Refactor - `BuiltinPrograms` (#31324)
* Moves BuiltinProgram of the program runtime into its own file. * Unifies the runtimes Builtin and program runtimes BuiltinProgram definitions. * Moves BuiltinPrograms from bank.rs into the program runtime.
This commit is contained in:
parent
1b08d01a80
commit
4b0e16d06f
|
@ -1,13 +1,20 @@
|
||||||
use solana_runtime::builtins::{Builtin, BuiltinFeatureTransition, Builtins};
|
use {
|
||||||
|
solana_program_runtime::builtin_program::BuiltinProgram,
|
||||||
|
solana_runtime::builtins::{BuiltinFeatureTransition, Builtins},
|
||||||
|
};
|
||||||
|
|
||||||
macro_rules! to_builtin {
|
macro_rules! to_builtin {
|
||||||
($b:expr) => {
|
($b:expr) => {
|
||||||
Builtin::new(&$b.0, $b.1, $b.2)
|
BuiltinProgram {
|
||||||
|
name: $b.0.to_string(),
|
||||||
|
program_id: $b.1,
|
||||||
|
process_instruction: $b.2,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builtin programs that are always available
|
/// Builtin programs that are always available
|
||||||
fn genesis_builtins(bpf_jit: bool) -> Vec<Builtin> {
|
fn genesis_builtins(bpf_jit: bool) -> Vec<BuiltinProgram> {
|
||||||
// Currently JIT is not supported on the SBF VM:
|
// Currently JIT is not supported on the SBF VM:
|
||||||
// !x86_64: https://github.com/qmonnet/rbpf/issues/48
|
// !x86_64: https://github.com/qmonnet/rbpf/issues/48
|
||||||
// Windows: https://github.com/solana-labs/rbpf/issues/217
|
// Windows: https://github.com/solana-labs/rbpf/issues/217
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||||
|
use {crate::declare_process_instruction, solana_frozen_abi::abi_example::AbiExample};
|
||||||
|
use {
|
||||||
|
crate::invoke_context::InvokeContext, solana_rbpf::vm::BuiltInFunction,
|
||||||
|
solana_sdk::pubkey::Pubkey,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub type ProcessInstructionWithContext = BuiltInFunction<InvokeContext<'static>>;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct BuiltinProgram {
|
||||||
|
pub name: String,
|
||||||
|
pub program_id: Pubkey,
|
||||||
|
pub process_instruction: ProcessInstructionWithContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for BuiltinProgram {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "Builtin [name={}, id={}]", self.name, self.program_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||||
|
impl AbiExample for BuiltinProgram {
|
||||||
|
fn example() -> Self {
|
||||||
|
declare_process_instruction!(empty_mock_process_instruction, 1, |_invoke_context| {
|
||||||
|
// Do nothing
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
name: String::default(),
|
||||||
|
program_id: Pubkey::default(),
|
||||||
|
process_instruction: empty_mock_process_instruction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct BuiltinPrograms {
|
||||||
|
pub vec: Vec<BuiltinProgram>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||||
|
impl AbiExample for BuiltinPrograms {
|
||||||
|
fn example() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuiltinPrograms {
|
||||||
|
pub fn new_mock(
|
||||||
|
program_id: Pubkey,
|
||||||
|
process_instruction: ProcessInstructionWithContext,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
vec: vec![BuiltinProgram {
|
||||||
|
name: "mock instruction processor".to_string(),
|
||||||
|
program_id,
|
||||||
|
process_instruction,
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
accounts_data_meter::AccountsDataMeter,
|
accounts_data_meter::AccountsDataMeter,
|
||||||
|
builtin_program::{BuiltinPrograms, ProcessInstructionWithContext},
|
||||||
compute_budget::ComputeBudget,
|
compute_budget::ComputeBudget,
|
||||||
executor_cache::TransactionExecutorCache,
|
executor_cache::TransactionExecutorCache,
|
||||||
ic_logger_msg, ic_msg,
|
ic_logger_msg, ic_msg,
|
||||||
|
@ -14,7 +15,7 @@ use {
|
||||||
solana_rbpf::{
|
solana_rbpf::{
|
||||||
ebpf::MM_HEAP_START,
|
ebpf::MM_HEAP_START,
|
||||||
memory_region::MemoryMapping,
|
memory_region::MemoryMapping,
|
||||||
vm::{BuiltInFunction, Config, ContextObject, ProgramResult},
|
vm::{Config, ContextObject, ProgramResult},
|
||||||
},
|
},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
account::{AccountSharedData, ReadableAccount},
|
account::{AccountSharedData, ReadableAccount},
|
||||||
|
@ -82,24 +83,6 @@ macro_rules! declare_process_instruction {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ProcessInstructionWithContext = BuiltInFunction<InvokeContext<'static>>;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct BuiltinProgram {
|
|
||||||
pub program_id: Pubkey,
|
|
||||||
pub process_instruction: ProcessInstructionWithContext,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for BuiltinProgram {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}: {:p}",
|
|
||||||
self.program_id, self.process_instruction as *const ProcessInstructionWithContext,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ContextObject for InvokeContext<'a> {
|
impl<'a> ContextObject for InvokeContext<'a> {
|
||||||
fn trace(&mut self, state: [u64; 12]) {
|
fn trace(&mut self, state: [u64; 12]) {
|
||||||
self.syscall_context
|
self.syscall_context
|
||||||
|
@ -169,7 +152,7 @@ pub struct InvokeContext<'a> {
|
||||||
pub transaction_context: &'a mut TransactionContext,
|
pub transaction_context: &'a mut TransactionContext,
|
||||||
rent: Rent,
|
rent: Rent,
|
||||||
pre_accounts: Vec<PreAccount>,
|
pre_accounts: Vec<PreAccount>,
|
||||||
builtin_programs: &'a [BuiltinProgram],
|
builtin_programs: &'a BuiltinPrograms,
|
||||||
sysvar_cache: &'a SysvarCache,
|
sysvar_cache: &'a SysvarCache,
|
||||||
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
||||||
compute_budget: ComputeBudget,
|
compute_budget: ComputeBudget,
|
||||||
|
@ -189,7 +172,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
transaction_context: &'a mut TransactionContext,
|
transaction_context: &'a mut TransactionContext,
|
||||||
rent: Rent,
|
rent: Rent,
|
||||||
builtin_programs: &'a [BuiltinProgram],
|
builtin_programs: &'a BuiltinPrograms,
|
||||||
sysvar_cache: &'a SysvarCache,
|
sysvar_cache: &'a SysvarCache,
|
||||||
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
||||||
compute_budget: ComputeBudget,
|
compute_budget: ComputeBudget,
|
||||||
|
@ -731,7 +714,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for entry in self.builtin_programs {
|
for entry in self.builtin_programs.vec.iter() {
|
||||||
if entry.program_id == builtin_id {
|
if entry.program_id == builtin_id {
|
||||||
let program_id =
|
let program_id =
|
||||||
*instruction_context.get_last_program_key(self.transaction_context)?;
|
*instruction_context.get_last_program_key(self.transaction_context)?;
|
||||||
|
@ -894,9 +877,9 @@ macro_rules! with_mock_invoke_context {
|
||||||
},
|
},
|
||||||
std::{cell::RefCell, rc::Rc, sync::Arc},
|
std::{cell::RefCell, rc::Rc, sync::Arc},
|
||||||
$crate::{
|
$crate::{
|
||||||
compute_budget::ComputeBudget, executor_cache::TransactionExecutorCache,
|
builtin_program::BuiltinPrograms, compute_budget::ComputeBudget,
|
||||||
invoke_context::InvokeContext, log_collector::LogCollector,
|
executor_cache::TransactionExecutorCache, invoke_context::InvokeContext,
|
||||||
sysvar_cache::SysvarCache,
|
log_collector::LogCollector, sysvar_cache::SysvarCache,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let compute_budget = ComputeBudget::default();
|
let compute_budget = ComputeBudget::default();
|
||||||
|
@ -907,6 +890,7 @@ macro_rules! with_mock_invoke_context {
|
||||||
compute_budget.max_instruction_trace_length,
|
compute_budget.max_instruction_trace_length,
|
||||||
);
|
);
|
||||||
$transaction_context.enable_cap_accounts_data_allocations_per_transaction();
|
$transaction_context.enable_cap_accounts_data_allocations_per_transaction();
|
||||||
|
let builtin_programs = BuiltinPrograms::default();
|
||||||
let mut sysvar_cache = SysvarCache::default();
|
let mut sysvar_cache = SysvarCache::default();
|
||||||
sysvar_cache.fill_missing_entries(|pubkey, callback| {
|
sysvar_cache.fill_missing_entries(|pubkey, callback| {
|
||||||
for index in 0..$transaction_context.get_number_of_accounts() {
|
for index in 0..$transaction_context.get_number_of_accounts() {
|
||||||
|
@ -928,7 +912,7 @@ macro_rules! with_mock_invoke_context {
|
||||||
let mut $invoke_context = InvokeContext::new(
|
let mut $invoke_context = InvokeContext::new(
|
||||||
&mut $transaction_context,
|
&mut $transaction_context,
|
||||||
Rent::default(),
|
Rent::default(),
|
||||||
&[],
|
&builtin_programs,
|
||||||
&sysvar_cache,
|
&sysvar_cache,
|
||||||
Some(LogCollector::new_ref()),
|
Some(LogCollector::new_ref()),
|
||||||
compute_budget,
|
compute_budget,
|
||||||
|
@ -980,11 +964,8 @@ pub fn mock_process_instruction<F: FnMut(&mut InvokeContext), G: FnMut(&mut Invo
|
||||||
let processor_account = AccountSharedData::new(0, 0, &native_loader::id());
|
let processor_account = AccountSharedData::new(0, 0, &native_loader::id());
|
||||||
transaction_accounts.push((*loader_id, processor_account));
|
transaction_accounts.push((*loader_id, processor_account));
|
||||||
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
|
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
|
||||||
let builtin_programs = &[BuiltinProgram {
|
let builtin_programs = BuiltinPrograms::new_mock(*loader_id, process_instruction);
|
||||||
program_id: *loader_id,
|
invoke_context.builtin_programs = &builtin_programs;
|
||||||
process_instruction,
|
|
||||||
}];
|
|
||||||
invoke_context.builtin_programs = builtin_programs;
|
|
||||||
pre_adjustments(&mut invoke_context);
|
pre_adjustments(&mut invoke_context);
|
||||||
let result = invoke_context.process_instruction(
|
let result = invoke_context.process_instruction(
|
||||||
instruction_data,
|
instruction_data,
|
||||||
|
@ -1233,11 +1214,8 @@ mod tests {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
|
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
|
||||||
let builtin_programs = &[BuiltinProgram {
|
let builtin_programs = BuiltinPrograms::new_mock(callee_program_id, process_instruction);
|
||||||
program_id: callee_program_id,
|
invoke_context.builtin_programs = &builtin_programs;
|
||||||
process_instruction,
|
|
||||||
}];
|
|
||||||
invoke_context.builtin_programs = builtin_programs;
|
|
||||||
|
|
||||||
// Account modification tests
|
// Account modification tests
|
||||||
let cases = vec![
|
let cases = vec![
|
||||||
|
@ -1378,11 +1356,8 @@ mod tests {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
|
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
|
||||||
let builtin_programs = &[BuiltinProgram {
|
let builtin_programs = BuiltinPrograms::new_mock(program_key, process_instruction);
|
||||||
program_id: program_key,
|
invoke_context.builtin_programs = &builtin_programs;
|
||||||
process_instruction,
|
|
||||||
}];
|
|
||||||
invoke_context.builtin_programs = builtin_programs;
|
|
||||||
|
|
||||||
// Test: Resize the account to *the same size*, so not consuming any additional size; this must succeed
|
// Test: Resize the account to *the same size*, so not consuming any additional size; this must succeed
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@ extern crate solana_metrics;
|
||||||
|
|
||||||
pub use solana_rbpf;
|
pub use solana_rbpf;
|
||||||
pub mod accounts_data_meter;
|
pub mod accounts_data_meter;
|
||||||
|
pub mod builtin_program;
|
||||||
pub mod compute_budget;
|
pub mod compute_budget;
|
||||||
pub mod executor_cache;
|
pub mod executor_cache;
|
||||||
pub mod invoke_context;
|
pub mod invoke_context;
|
||||||
|
|
|
@ -11,14 +11,15 @@ use {
|
||||||
solana_banks_server::banks_server::start_local_server,
|
solana_banks_server::banks_server::start_local_server,
|
||||||
solana_bpf_loader_program::serialization::serialize_parameters,
|
solana_bpf_loader_program::serialization::serialize_parameters,
|
||||||
solana_program_runtime::{
|
solana_program_runtime::{
|
||||||
compute_budget::ComputeBudget, ic_msg, invoke_context::ProcessInstructionWithContext,
|
builtin_program::{BuiltinProgram, BuiltinPrograms, ProcessInstructionWithContext},
|
||||||
stable_log, timings::ExecuteTimings,
|
compute_budget::ComputeBudget,
|
||||||
|
ic_msg, stable_log,
|
||||||
|
timings::ExecuteTimings,
|
||||||
},
|
},
|
||||||
solana_runtime::{
|
solana_runtime::{
|
||||||
accounts_background_service::{AbsRequestSender, SnapshotRequestType},
|
accounts_background_service::{AbsRequestSender, SnapshotRequestType},
|
||||||
bank::Bank,
|
bank::Bank,
|
||||||
bank_forks::BankForks,
|
bank_forks::BankForks,
|
||||||
builtins::Builtin,
|
|
||||||
commitment::BlockCommitmentCache,
|
commitment::BlockCommitmentCache,
|
||||||
epoch_accounts_hash::EpochAccountsHash,
|
epoch_accounts_hash::EpochAccountsHash,
|
||||||
genesis_utils::{create_genesis_config_with_leader_ex, GenesisConfigInfo},
|
genesis_utils::{create_genesis_config_with_leader_ex, GenesisConfigInfo},
|
||||||
|
@ -436,7 +437,7 @@ pub fn read_file<P: AsRef<Path>>(path: P) -> Vec<u8> {
|
||||||
|
|
||||||
pub struct ProgramTest {
|
pub struct ProgramTest {
|
||||||
accounts: Vec<(Pubkey, AccountSharedData)>,
|
accounts: Vec<(Pubkey, AccountSharedData)>,
|
||||||
builtins: Vec<Builtin>,
|
builtin_programs: BuiltinPrograms,
|
||||||
compute_max_units: Option<u64>,
|
compute_max_units: Option<u64>,
|
||||||
prefer_bpf: bool,
|
prefer_bpf: bool,
|
||||||
use_bpf_jit: bool,
|
use_bpf_jit: bool,
|
||||||
|
@ -474,7 +475,7 @@ impl Default for ProgramTest {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
accounts: vec![],
|
accounts: vec![],
|
||||||
builtins: vec![],
|
builtin_programs: BuiltinPrograms::default(),
|
||||||
compute_max_units: None,
|
compute_max_units: None,
|
||||||
prefer_bpf,
|
prefer_bpf,
|
||||||
use_bpf_jit: false,
|
use_bpf_jit: false,
|
||||||
|
@ -628,12 +629,6 @@ impl ProgramTest {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let add_native = |this: &mut ProgramTest, process_fn: ProcessInstructionWithContext| {
|
|
||||||
info!("\"{}\" program loaded as native code", program_name);
|
|
||||||
this.builtins
|
|
||||||
.push(Builtin::new(program_name, program_id, process_fn));
|
|
||||||
};
|
|
||||||
|
|
||||||
let warn_invalid_program_name = || {
|
let warn_invalid_program_name = || {
|
||||||
let valid_program_names = default_shared_object_dirs()
|
let valid_program_names = default_shared_object_dirs()
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -679,7 +674,9 @@ impl ProgramTest {
|
||||||
// processor function as is.
|
// processor function as is.
|
||||||
//
|
//
|
||||||
// TODO: figure out why tests hang if a processor panics when running native code.
|
// TODO: figure out why tests hang if a processor panics when running native code.
|
||||||
(false, _, Some(process)) => add_native(self, process),
|
(false, _, Some(process)) => {
|
||||||
|
self.add_builtin_program(program_name, program_id, process)
|
||||||
|
}
|
||||||
|
|
||||||
// Invalid: `test-sbf` invocation with no matching SBF shared object.
|
// Invalid: `test-sbf` invocation with no matching SBF shared object.
|
||||||
(true, None, _) => {
|
(true, None, _) => {
|
||||||
|
@ -704,8 +701,11 @@ impl ProgramTest {
|
||||||
process_instruction: ProcessInstructionWithContext,
|
process_instruction: ProcessInstructionWithContext,
|
||||||
) {
|
) {
|
||||||
info!("\"{}\" builtin program", program_name);
|
info!("\"{}\" builtin program", program_name);
|
||||||
self.builtins
|
self.builtin_programs.vec.push(BuiltinProgram {
|
||||||
.push(Builtin::new(program_name, program_id, process_instruction));
|
name: program_name.to_string(),
|
||||||
|
program_id,
|
||||||
|
process_instruction,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deactivate a runtime feature.
|
/// Deactivate a runtime feature.
|
||||||
|
@ -816,11 +816,11 @@ impl ProgramTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
// User-supplied additional builtins
|
// User-supplied additional builtins
|
||||||
for builtin in self.builtins.iter() {
|
for builtin in self.builtin_programs.vec.iter() {
|
||||||
bank.add_builtin(
|
bank.add_builtin(
|
||||||
&builtin.name,
|
&builtin.name,
|
||||||
&builtin.id,
|
&builtin.program_id,
|
||||||
builtin.process_instruction_with_context,
|
builtin.process_instruction,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,9 +94,9 @@ use {
|
||||||
solana_perf::perf_libs,
|
solana_perf::perf_libs,
|
||||||
solana_program_runtime::{
|
solana_program_runtime::{
|
||||||
accounts_data_meter::MAX_ACCOUNTS_DATA_LEN,
|
accounts_data_meter::MAX_ACCOUNTS_DATA_LEN,
|
||||||
|
builtin_program::{BuiltinProgram, BuiltinPrograms, ProcessInstructionWithContext},
|
||||||
compute_budget::{self, ComputeBudget},
|
compute_budget::{self, ComputeBudget},
|
||||||
executor_cache::{BankExecutorCache, TransactionExecutorCache, MAX_CACHED_EXECUTORS},
|
executor_cache::{BankExecutorCache, TransactionExecutorCache, MAX_CACHED_EXECUTORS},
|
||||||
invoke_context::{BuiltinProgram, ProcessInstructionWithContext},
|
|
||||||
loaded_programs::{LoadedProgram, LoadedProgramType, LoadedPrograms, WorkingSlot},
|
loaded_programs::{LoadedProgram, LoadedProgramType, LoadedPrograms, WorkingSlot},
|
||||||
log_collector::LogCollector,
|
log_collector::LogCollector,
|
||||||
sysvar_cache::SysvarCache,
|
sysvar_cache::SysvarCache,
|
||||||
|
@ -887,18 +887,6 @@ impl AbiExample for OptionalDropCallback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
|
||||||
pub struct BuiltinPrograms {
|
|
||||||
pub vec: Vec<BuiltinProgram>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
|
||||||
impl AbiExample for BuiltinPrograms {
|
|
||||||
fn example() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Manager for the state of all accounts and programs after processing its entries.
|
/// Manager for the state of all accounts and programs after processing its entries.
|
||||||
/// AbiExample is needed even without Serialize/Deserialize; actual (de-)serialization
|
/// AbiExample is needed even without Serialize/Deserialize; actual (de-)serialization
|
||||||
/// are implemented elsewhere for versioning
|
/// are implemented elsewhere for versioning
|
||||||
|
@ -4282,7 +4270,7 @@ impl Bank {
|
||||||
|
|
||||||
let mut process_message_time = Measure::start("process_message_time");
|
let mut process_message_time = Measure::start("process_message_time");
|
||||||
let process_result = MessageProcessor::process_message(
|
let process_result = MessageProcessor::process_message(
|
||||||
&self.builtin_programs.vec,
|
&self.builtin_programs,
|
||||||
tx.message(),
|
tx.message(),
|
||||||
&loaded_transaction.program_indices,
|
&loaded_transaction.program_indices,
|
||||||
&mut transaction_context,
|
&mut transaction_context,
|
||||||
|
@ -6631,8 +6619,8 @@ impl Bank {
|
||||||
for builtin in builtins.genesis_builtins {
|
for builtin in builtins.genesis_builtins {
|
||||||
self.add_builtin(
|
self.add_builtin(
|
||||||
&builtin.name,
|
&builtin.name,
|
||||||
&builtin.id,
|
&builtin.program_id,
|
||||||
builtin.process_instruction_with_context,
|
builtin.process_instruction,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for precompile in get_precompiles() {
|
for precompile in get_precompiles() {
|
||||||
|
@ -7674,6 +7662,7 @@ impl Bank {
|
||||||
entry.process_instruction = process_instruction;
|
entry.process_instruction = process_instruction;
|
||||||
} else {
|
} else {
|
||||||
self.builtin_programs.vec.push(BuiltinProgram {
|
self.builtin_programs.vec.push(BuiltinProgram {
|
||||||
|
name: name.to_string(),
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
process_instruction,
|
process_instruction,
|
||||||
});
|
});
|
||||||
|
@ -7944,8 +7933,8 @@ impl Bank {
|
||||||
match builtin_action {
|
match builtin_action {
|
||||||
BuiltinAction::Add(builtin) => self.add_builtin(
|
BuiltinAction::Add(builtin) => self.add_builtin(
|
||||||
&builtin.name,
|
&builtin.name,
|
||||||
&builtin.id,
|
&builtin.program_id,
|
||||||
builtin.process_instruction_with_context,
|
builtin.process_instruction,
|
||||||
),
|
),
|
||||||
BuiltinAction::Remove(program_id) => self.remove_builtin(&program_id),
|
BuiltinAction::Remove(program_id) => self.remove_builtin(&program_id),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +1,12 @@
|
||||||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
|
||||||
use {
|
use {
|
||||||
solana_frozen_abi::abi_example::AbiExample, solana_program_runtime::declare_process_instruction,
|
solana_program_runtime::builtin_program::BuiltinProgram,
|
||||||
};
|
|
||||||
use {
|
|
||||||
solana_program_runtime::invoke_context::ProcessInstructionWithContext,
|
|
||||||
solana_sdk::{feature_set, pubkey::Pubkey, stake},
|
solana_sdk::{feature_set, pubkey::Pubkey, stake},
|
||||||
std::fmt,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Builtin {
|
|
||||||
pub name: String,
|
|
||||||
pub id: Pubkey,
|
|
||||||
pub process_instruction_with_context: ProcessInstructionWithContext,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Builtin {
|
|
||||||
pub fn new(
|
|
||||||
name: &str,
|
|
||||||
id: Pubkey,
|
|
||||||
process_instruction_with_context: ProcessInstructionWithContext,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
id,
|
|
||||||
process_instruction_with_context,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Builtin {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "Builtin [name={}, id={}]", self.name, self.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
|
||||||
impl AbiExample for Builtin {
|
|
||||||
fn example() -> Self {
|
|
||||||
declare_process_instruction!(process_instruction, 1, |_invoke_context| {
|
|
||||||
// Do nothing
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
|
||||||
name: String::default(),
|
|
||||||
id: Pubkey::default(),
|
|
||||||
process_instruction_with_context: process_instruction,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Builtins {
|
pub struct Builtins {
|
||||||
/// Builtin programs that are always available
|
/// Builtin programs that are always available
|
||||||
pub genesis_builtins: Vec<Builtin>,
|
pub genesis_builtins: Vec<BuiltinProgram>,
|
||||||
|
|
||||||
/// Dynamic feature transitions for builtin programs
|
/// Dynamic feature transitions for builtin programs
|
||||||
pub feature_transitions: Vec<BuiltinFeatureTransition>,
|
pub feature_transitions: Vec<BuiltinFeatureTransition>,
|
||||||
|
@ -63,7 +15,7 @@ pub struct Builtins {
|
||||||
/// Actions taken by a bank when managing the list of active builtin programs.
|
/// Actions taken by a bank when managing the list of active builtin programs.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum BuiltinAction {
|
pub enum BuiltinAction {
|
||||||
Add(Builtin),
|
Add(BuiltinProgram),
|
||||||
Remove(Pubkey),
|
Remove(Pubkey),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,13 +25,13 @@ pub enum BuiltinAction {
|
||||||
pub enum BuiltinFeatureTransition {
|
pub enum BuiltinFeatureTransition {
|
||||||
/// Add a builtin program if a feature is activated.
|
/// Add a builtin program if a feature is activated.
|
||||||
Add {
|
Add {
|
||||||
builtin: Builtin,
|
builtin: BuiltinProgram,
|
||||||
feature_id: Pubkey,
|
feature_id: Pubkey,
|
||||||
},
|
},
|
||||||
/// Remove a builtin program if a feature is activated or
|
/// Remove a builtin program if a feature is activated or
|
||||||
/// retain a previously added builtin.
|
/// retain a previously added builtin.
|
||||||
RemoveOrRetain {
|
RemoveOrRetain {
|
||||||
previously_added_builtin: Builtin,
|
previously_added_builtin: BuiltinProgram,
|
||||||
addition_feature_id: Pubkey,
|
addition_feature_id: Pubkey,
|
||||||
removal_feature_id: Pubkey,
|
removal_feature_id: Pubkey,
|
||||||
},
|
},
|
||||||
|
@ -107,7 +59,7 @@ impl BuiltinFeatureTransition {
|
||||||
removal_feature_id,
|
removal_feature_id,
|
||||||
} => {
|
} => {
|
||||||
if should_apply_action_for_feature(removal_feature_id) {
|
if should_apply_action_for_feature(removal_feature_id) {
|
||||||
Some(BuiltinAction::Remove(previously_added_builtin.id))
|
Some(BuiltinAction::Remove(previously_added_builtin.program_id))
|
||||||
} else if should_apply_action_for_feature(addition_feature_id) {
|
} else if should_apply_action_for_feature(addition_feature_id) {
|
||||||
// Retaining is no different from adding a new builtin.
|
// Retaining is no different from adding a new builtin.
|
||||||
Some(BuiltinAction::Add(previously_added_builtin.clone()))
|
Some(BuiltinAction::Add(previously_added_builtin.clone()))
|
||||||
|
@ -119,29 +71,29 @@ impl BuiltinFeatureTransition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builtin programs that are always available
|
/// Built-in programs that are always available
|
||||||
fn genesis_builtins() -> Vec<Builtin> {
|
fn genesis_builtins() -> Vec<BuiltinProgram> {
|
||||||
vec![
|
vec![
|
||||||
Builtin::new(
|
BuiltinProgram {
|
||||||
"system_program",
|
name: "system_program".to_string(),
|
||||||
solana_system_program::id(),
|
program_id: solana_system_program::id(),
|
||||||
solana_system_program::system_processor::process_instruction,
|
process_instruction: solana_system_program::system_processor::process_instruction,
|
||||||
),
|
},
|
||||||
Builtin::new(
|
BuiltinProgram {
|
||||||
"vote_program",
|
name: "vote_program".to_string(),
|
||||||
solana_vote_program::id(),
|
program_id: solana_vote_program::id(),
|
||||||
solana_vote_program::vote_processor::process_instruction,
|
process_instruction: solana_vote_program::vote_processor::process_instruction,
|
||||||
),
|
},
|
||||||
Builtin::new(
|
BuiltinProgram {
|
||||||
"stake_program",
|
name: "stake_program".to_string(),
|
||||||
stake::program::id(),
|
program_id: stake::program::id(),
|
||||||
solana_stake_program::stake_instruction::process_instruction,
|
process_instruction: solana_stake_program::stake_instruction::process_instruction,
|
||||||
),
|
},
|
||||||
Builtin::new(
|
BuiltinProgram {
|
||||||
"config_program",
|
name: "config_program".to_string(),
|
||||||
solana_config_program::id(),
|
program_id: solana_config_program::id(),
|
||||||
solana_config_program::config_processor::process_instruction,
|
process_instruction: solana_config_program::config_processor::process_instruction,
|
||||||
),
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,27 +101,28 @@ fn genesis_builtins() -> Vec<Builtin> {
|
||||||
fn builtin_feature_transitions() -> Vec<BuiltinFeatureTransition> {
|
fn builtin_feature_transitions() -> Vec<BuiltinFeatureTransition> {
|
||||||
vec![
|
vec![
|
||||||
BuiltinFeatureTransition::Add {
|
BuiltinFeatureTransition::Add {
|
||||||
builtin: Builtin::new(
|
builtin: BuiltinProgram {
|
||||||
"compute_budget_program",
|
name: "compute_budget_program".to_string(),
|
||||||
solana_sdk::compute_budget::id(),
|
program_id: solana_sdk::compute_budget::id(),
|
||||||
solana_compute_budget_program::process_instruction,
|
process_instruction: solana_compute_budget_program::process_instruction,
|
||||||
),
|
},
|
||||||
feature_id: feature_set::add_compute_budget_program::id(),
|
feature_id: feature_set::add_compute_budget_program::id(),
|
||||||
},
|
},
|
||||||
BuiltinFeatureTransition::Add {
|
BuiltinFeatureTransition::Add {
|
||||||
builtin: Builtin::new(
|
builtin: BuiltinProgram {
|
||||||
"address_lookup_table_program",
|
name: "address_lookup_table_program".to_string(),
|
||||||
solana_address_lookup_table_program::id(),
|
program_id: solana_address_lookup_table_program::id(),
|
||||||
solana_address_lookup_table_program::processor::process_instruction,
|
process_instruction:
|
||||||
),
|
solana_address_lookup_table_program::processor::process_instruction,
|
||||||
|
},
|
||||||
feature_id: feature_set::versioned_tx_message_enabled::id(),
|
feature_id: feature_set::versioned_tx_message_enabled::id(),
|
||||||
},
|
},
|
||||||
BuiltinFeatureTransition::Add {
|
BuiltinFeatureTransition::Add {
|
||||||
builtin: Builtin::new(
|
builtin: BuiltinProgram {
|
||||||
"zk_token_proof_program",
|
name: "zk_token_proof_program".to_string(),
|
||||||
solana_zk_token_sdk::zk_token_proof_program::id(),
|
program_id: solana_zk_token_sdk::zk_token_proof_program::id(),
|
||||||
solana_zk_token_proof_program::process_instruction,
|
process_instruction: solana_zk_token_proof_program::process_instruction,
|
||||||
),
|
},
|
||||||
feature_id: feature_set::zk_token_sdk_enabled::id(),
|
feature_id: feature_set::zk_token_sdk_enabled::id(),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -187,9 +140,9 @@ pub fn get_pubkeys() -> Vec<Pubkey> {
|
||||||
let builtins = get();
|
let builtins = get();
|
||||||
|
|
||||||
let mut pubkeys = Vec::new();
|
let mut pubkeys = Vec::new();
|
||||||
pubkeys.extend(builtins.genesis_builtins.iter().map(|b| b.id));
|
pubkeys.extend(builtins.genesis_builtins.iter().map(|b| b.program_id));
|
||||||
pubkeys.extend(builtins.feature_transitions.iter().filter_map(|f| match f {
|
pubkeys.extend(builtins.feature_transitions.iter().filter_map(|f| match f {
|
||||||
BuiltinFeatureTransition::Add { builtin, .. } => Some(builtin.id),
|
BuiltinFeatureTransition::Add { builtin, .. } => Some(builtin.program_id),
|
||||||
BuiltinFeatureTransition::RemoveOrRetain { .. } => None,
|
BuiltinFeatureTransition::RemoveOrRetain { .. } => None,
|
||||||
}));
|
}));
|
||||||
pubkeys
|
pubkeys
|
||||||
|
|
|
@ -2,9 +2,10 @@ use {
|
||||||
serde::{Deserialize, Serialize},
|
serde::{Deserialize, Serialize},
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
solana_program_runtime::{
|
solana_program_runtime::{
|
||||||
|
builtin_program::BuiltinPrograms,
|
||||||
compute_budget::ComputeBudget,
|
compute_budget::ComputeBudget,
|
||||||
executor_cache::TransactionExecutorCache,
|
executor_cache::TransactionExecutorCache,
|
||||||
invoke_context::{BuiltinProgram, InvokeContext},
|
invoke_context::InvokeContext,
|
||||||
log_collector::LogCollector,
|
log_collector::LogCollector,
|
||||||
sysvar_cache::SysvarCache,
|
sysvar_cache::SysvarCache,
|
||||||
timings::{ExecuteDetailsTimings, ExecuteTimings},
|
timings::{ExecuteDetailsTimings, ExecuteTimings},
|
||||||
|
@ -51,7 +52,7 @@ impl MessageProcessor {
|
||||||
/// The accounts are committed back to the bank only if every instruction succeeds.
|
/// The accounts are committed back to the bank only if every instruction succeeds.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn process_message(
|
pub fn process_message(
|
||||||
builtin_programs: &[BuiltinProgram],
|
builtin_programs: &BuiltinPrograms,
|
||||||
message: &SanitizedMessage,
|
message: &SanitizedMessage,
|
||||||
program_indices: &[Vec<IndexOfAccount>],
|
program_indices: &[Vec<IndexOfAccount>],
|
||||||
transaction_context: &mut TransactionContext,
|
transaction_context: &mut TransactionContext,
|
||||||
|
@ -251,10 +252,8 @@ mod tests {
|
||||||
let mock_system_program_id = Pubkey::new_unique();
|
let mock_system_program_id = Pubkey::new_unique();
|
||||||
|
|
||||||
let rent_collector = RentCollector::default();
|
let rent_collector = RentCollector::default();
|
||||||
let builtin_programs = &[BuiltinProgram {
|
let builtin_programs =
|
||||||
program_id: mock_system_program_id,
|
BuiltinPrograms::new_mock(mock_system_program_id, process_instruction);
|
||||||
process_instruction,
|
|
||||||
}];
|
|
||||||
|
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
(
|
(
|
||||||
|
@ -303,7 +302,7 @@ mod tests {
|
||||||
)));
|
)));
|
||||||
let sysvar_cache = SysvarCache::default();
|
let sysvar_cache = SysvarCache::default();
|
||||||
let result = MessageProcessor::process_message(
|
let result = MessageProcessor::process_message(
|
||||||
builtin_programs,
|
&builtin_programs,
|
||||||
&message,
|
&message,
|
||||||
&program_indices,
|
&program_indices,
|
||||||
&mut transaction_context,
|
&mut transaction_context,
|
||||||
|
@ -353,7 +352,7 @@ mod tests {
|
||||||
]),
|
]),
|
||||||
)));
|
)));
|
||||||
let result = MessageProcessor::process_message(
|
let result = MessageProcessor::process_message(
|
||||||
builtin_programs,
|
&builtin_programs,
|
||||||
&message,
|
&message,
|
||||||
&program_indices,
|
&program_indices,
|
||||||
&mut transaction_context,
|
&mut transaction_context,
|
||||||
|
@ -393,7 +392,7 @@ mod tests {
|
||||||
]),
|
]),
|
||||||
)));
|
)));
|
||||||
let result = MessageProcessor::process_message(
|
let result = MessageProcessor::process_message(
|
||||||
builtin_programs,
|
&builtin_programs,
|
||||||
&message,
|
&message,
|
||||||
&program_indices,
|
&program_indices,
|
||||||
&mut transaction_context,
|
&mut transaction_context,
|
||||||
|
@ -478,10 +477,7 @@ mod tests {
|
||||||
|
|
||||||
let mock_program_id = Pubkey::from([2u8; 32]);
|
let mock_program_id = Pubkey::from([2u8; 32]);
|
||||||
let rent_collector = RentCollector::default();
|
let rent_collector = RentCollector::default();
|
||||||
let builtin_programs = &[BuiltinProgram {
|
let builtin_programs = BuiltinPrograms::new_mock(mock_program_id, process_instruction);
|
||||||
program_id: mock_program_id,
|
|
||||||
process_instruction,
|
|
||||||
}];
|
|
||||||
|
|
||||||
let accounts = vec![
|
let accounts = vec![
|
||||||
(
|
(
|
||||||
|
@ -527,7 +523,7 @@ mod tests {
|
||||||
)));
|
)));
|
||||||
let sysvar_cache = SysvarCache::default();
|
let sysvar_cache = SysvarCache::default();
|
||||||
let result = MessageProcessor::process_message(
|
let result = MessageProcessor::process_message(
|
||||||
builtin_programs,
|
&builtin_programs,
|
||||||
&message,
|
&message,
|
||||||
&program_indices,
|
&program_indices,
|
||||||
&mut transaction_context,
|
&mut transaction_context,
|
||||||
|
@ -561,7 +557,7 @@ mod tests {
|
||||||
Some(transaction_context.get_key_of_account_at_index(0).unwrap()),
|
Some(transaction_context.get_key_of_account_at_index(0).unwrap()),
|
||||||
)));
|
)));
|
||||||
let result = MessageProcessor::process_message(
|
let result = MessageProcessor::process_message(
|
||||||
builtin_programs,
|
&builtin_programs,
|
||||||
&message,
|
&message,
|
||||||
&program_indices,
|
&program_indices,
|
||||||
&mut transaction_context,
|
&mut transaction_context,
|
||||||
|
@ -592,7 +588,7 @@ mod tests {
|
||||||
Some(transaction_context.get_key_of_account_at_index(0).unwrap()),
|
Some(transaction_context.get_key_of_account_at_index(0).unwrap()),
|
||||||
)));
|
)));
|
||||||
let result = MessageProcessor::process_message(
|
let result = MessageProcessor::process_message(
|
||||||
builtin_programs,
|
&builtin_programs,
|
||||||
&message,
|
&message,
|
||||||
&program_indices,
|
&program_indices,
|
||||||
&mut transaction_context,
|
&mut transaction_context,
|
||||||
|
@ -641,10 +637,7 @@ mod tests {
|
||||||
declare_process_instruction!(process_instruction, 1, |_invoke_context| {
|
declare_process_instruction!(process_instruction, 1, |_invoke_context| {
|
||||||
Err(InstructionError::Custom(0xbabb1e))
|
Err(InstructionError::Custom(0xbabb1e))
|
||||||
});
|
});
|
||||||
let builtin_programs = &[BuiltinProgram {
|
let builtin_programs = BuiltinPrograms::new_mock(mock_program_id, process_instruction);
|
||||||
program_id: mock_program_id,
|
|
||||||
process_instruction,
|
|
||||||
}];
|
|
||||||
|
|
||||||
let mut secp256k1_account = AccountSharedData::new(1, 0, &native_loader::id());
|
let mut secp256k1_account = AccountSharedData::new(1, 0, &native_loader::id());
|
||||||
secp256k1_account.set_executable(true);
|
secp256k1_account.set_executable(true);
|
||||||
|
@ -669,7 +662,7 @@ mod tests {
|
||||||
)));
|
)));
|
||||||
let sysvar_cache = SysvarCache::default();
|
let sysvar_cache = SysvarCache::default();
|
||||||
let result = MessageProcessor::process_message(
|
let result = MessageProcessor::process_message(
|
||||||
builtin_programs,
|
&builtin_programs,
|
||||||
&message,
|
&message,
|
||||||
&[vec![0], vec![1]],
|
&[vec![0], vec![1]],
|
||||||
&mut transaction_context,
|
&mut transaction_context,
|
||||||
|
|
Loading…
Reference in New Issue