Make BPF Loader static (#11516)
This commit is contained in:
@ -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) {
|
||||
|
@ -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
39
runtime/src/builtins.rs
Normal 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
|
||||
}
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user