Make BPF Loader static (#11516)

This commit is contained in:
Jack May
2020-08-14 12:32:45 -07:00
committed by GitHub
parent 346e982e28
commit 7c736f71fe
21 changed files with 756 additions and 577 deletions

View File

@ -10,7 +10,7 @@ use crate::{
accounts_db::{ErrorCounters, SnapshotStorages},
accounts_index::Ancestors,
blockhash_queue::BlockhashQueue,
builtin_programs::{get_builtin_programs, get_epoch_activated_builtin_programs},
builtins::{get_builtins, get_epoch_activated_builtins},
epoch_stakes::{EpochStakes, NodeVoteAccounts},
log_collector::LogCollector,
message_processor::MessageProcessor,
@ -35,7 +35,7 @@ use solana_sdk::{
Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND,
MAX_PROCESSING_AGE, MAX_RECENT_BLOCKHASHES, SECONDS_PER_DAY,
},
entrypoint_native::ProcessInstruction,
entrypoint_native::{ProcessInstruction, ProcessInstructionWithContext},
epoch_info::EpochInfo,
epoch_schedule::EpochSchedule,
fee_calculator::{FeeCalculator, FeeRateGovernor},
@ -98,6 +98,26 @@ type RentCollectionCycleParams = (
type EpochCount = u64;
#[derive(Copy, Clone)]
pub enum Entrypoint {
Program(ProcessInstruction),
Loader(ProcessInstructionWithContext),
}
pub struct Builtin {
pub name: String,
pub id: Pubkey,
pub entrypoint: Entrypoint,
}
impl Builtin {
pub fn new(name: &str, id: Pubkey, entrypoint: Entrypoint) -> Self {
Self {
name: name.to_string(),
id,
entrypoint,
}
}
}
#[derive(Default)]
pub struct BankRc {
/// where all the Accounts are stored
@ -544,11 +564,9 @@ impl Bank {
entered_epoch_callback(&mut new)
}
if let Some(builtin_programs) =
get_epoch_activated_builtin_programs(new.operating_mode(), new.epoch)
{
for program in builtin_programs.iter() {
new.add_builtin_program(&program.name, program.id, program.process_instruction);
if let Some(builtins) = get_epoch_activated_builtins(new.operating_mode(), new.epoch) {
for program in builtins.iter() {
new.add_builtin(&program.name, program.id, program.entrypoint);
}
}
}
@ -2575,9 +2593,9 @@ impl Bank {
}
pub fn finish_init(&mut self) {
let builtin_programs = get_builtin_programs(self.operating_mode(), self.epoch);
for program in builtin_programs.iter() {
self.add_builtin_program(&program.name, program.id, program.process_instruction);
let builtins = get_builtins();
for program in builtins.iter() {
self.add_builtin(&program.name, program.id, program.entrypoint);
}
}
@ -3021,19 +3039,36 @@ impl Bank {
!self.is_delta.load(Ordering::Relaxed)
}
/// Add an instruction processor to intercept instructions before the dynamic loader.
pub fn add_builtin_program(
&mut self,
name: &str,
program_id: Pubkey,
process_instruction: ProcessInstruction,
) {
self.add_builtin(name, program_id, Entrypoint::Program(process_instruction));
}
pub fn add_builtin_loader(
&mut self,
name: &str,
program_id: Pubkey,
process_instruction_with_context: ProcessInstructionWithContext,
) {
self.add_builtin(
name,
program_id,
Entrypoint::Loader(process_instruction_with_context),
);
}
/// Add an instruction processor to intercept instructions before the dynamic loader.
pub fn add_builtin(&mut self, name: &str, program_id: Pubkey, entrypoint: Entrypoint) {
match self.get_account(&program_id) {
Some(account) => {
assert_eq!(
account.owner,
native_loader::id(),
"Cannot overwrite non-native loader account"
"Cannot overwrite non-native account"
);
}
None => {
@ -3042,9 +3077,18 @@ impl Bank {
self.store_account(&program_id, &account);
}
}
self.message_processor
.add_program(program_id, process_instruction);
debug!("Added static program {} under {:?}", name, program_id);
match entrypoint {
Entrypoint::Program(process_instruction) => {
self.message_processor
.add_program(program_id, process_instruction);
debug!("Added builtin program {} under {:?}", name, program_id);
}
Entrypoint::Loader(process_instruction_with_context) => {
self.message_processor
.add_loader(program_id, process_instruction_with_context);
debug!("Added builtin loader {} under {:?}", name, program_id);
}
}
}
pub fn compare_bank(&self, dbank: &Bank) {

View File

@ -1,54 +0,0 @@
use crate::system_instruction_processor;
use solana_sdk::{
clock::Epoch, entrypoint_native::ProcessInstruction, genesis_config::OperatingMode,
pubkey::Pubkey, system_program,
};
pub struct BuiltinProgram {
pub name: String,
pub id: Pubkey,
pub process_instruction: ProcessInstruction,
}
impl BuiltinProgram {
pub fn new(name: &str, id: Pubkey, process_instruction: ProcessInstruction) -> Self {
Self {
name: name.to_string(),
id,
process_instruction,
}
}
}
/// All builtin programs that should be active at the given (operating_mode, epoch)
pub fn get_builtin_programs(_operating_mode: OperatingMode, _epoch: Epoch) -> Vec<BuiltinProgram> {
vec![
BuiltinProgram::new(
"system_program",
system_program::id(),
system_instruction_processor::process_instruction,
),
BuiltinProgram::new(
"config_program",
solana_config_program::id(),
solana_config_program::config_processor::process_instruction,
),
BuiltinProgram::new(
"stake_program",
solana_stake_program::id(),
solana_stake_program::stake_instruction::process_instruction,
),
BuiltinProgram::new(
"vote_program",
solana_vote_program::id(),
solana_vote_program::vote_instruction::process_instruction,
),
]
}
/// Builtin programs that activate at the given (operating_mode, epoch)
pub fn get_epoch_activated_builtin_programs(
_operating_mode: OperatingMode,
_epoch: Epoch,
) -> Option<Vec<BuiltinProgram>> {
None
}

39
runtime/src/builtins.rs Normal file
View File

@ -0,0 +1,39 @@
use crate::{
bank::{Builtin, Entrypoint},
system_instruction_processor,
};
use solana_sdk::{clock::Epoch, genesis_config::OperatingMode, system_program};
/// All builtin programs that should be active at the given (operating_mode, epoch)
pub fn get_builtins() -> Vec<Builtin> {
vec![
Builtin::new(
"system_program",
system_program::id(),
Entrypoint::Program(system_instruction_processor::process_instruction),
),
Builtin::new(
"config_program",
solana_config_program::id(),
Entrypoint::Program(solana_config_program::config_processor::process_instruction),
),
Builtin::new(
"stake_program",
solana_stake_program::id(),
Entrypoint::Program(solana_stake_program::stake_instruction::process_instruction),
),
Builtin::new(
"vote_program",
solana_vote_program::id(),
Entrypoint::Program(solana_vote_program::vote_instruction::process_instruction),
),
]
}
/// Builtin programs that activate at the given (operating_mode, epoch)
pub fn get_epoch_activated_builtins(
_operating_mode: OperatingMode,
_epoch: Epoch,
) -> Option<Vec<Builtin>> {
None
}

View File

@ -9,7 +9,7 @@ pub mod bank_forks;
pub mod bank_utils;
mod blockhash_queue;
pub mod bloom;
pub mod builtin_programs;
pub mod builtins;
pub mod commitment;
pub mod epoch_stakes;
pub mod genesis_utils;

View File

@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use solana_sdk::{
account::{create_keyed_readonly_accounts, Account, KeyedAccount},
clock::Epoch,
entrypoint_native::{InvokeContext, Logger, ProcessInstruction},
entrypoint_native::{InvokeContext, Logger, ProcessInstruction, ProcessInstructionWithContext},
instruction::{CompiledInstruction, InstructionError},
message::Message,
native_loader,
@ -247,9 +247,6 @@ impl Logger for ThisLogger {
}
}
pub type ProcessInstructionWithContext =
fn(&Pubkey, &[KeyedAccount], &[u8], &mut dyn InvokeContext) -> Result<(), InstructionError>;
#[derive(Deserialize, Serialize)]
pub struct MessageProcessor {
#[serde(skip)]
@ -353,6 +350,17 @@ impl MessageProcessor {
) -> Result<(), InstructionError> {
if native_loader::check_id(&keyed_accounts[0].owner()?) {
let root_id = keyed_accounts[0].unsigned_key();
for (id, process_instruction) in &self.loaders {
if id == root_id {
// Call the program via a builtin loader
return process_instruction(
&root_id,
&keyed_accounts[1..],
instruction_data,
invoke_context,
);
}
}
for (id, process_instruction) in &self.programs {
if id == root_id {
// Call the builtin program
@ -367,9 +375,9 @@ impl MessageProcessor {
invoke_context,
);
} else {
let owner_id = keyed_accounts[0].owner()?;
let owner_id = &keyed_accounts[0].owner()?;
for (id, process_instruction) in &self.loaders {
if *id == owner_id {
if id == owner_id {
// Call the program via a builtin loader
return process_instruction(
&owner_id,