Refactoring - Remove redundant definition of `BuiltinProgram` (#31429)
* Replaces BuiltinProgram in the program-runtime with the one from solana_rbpf. * Adjusts the runtimes built-ins to use Arc<LoadedProgram>. * Adjusts the tests and benchmarks.
This commit is contained in:
parent
9b547fe9f8
commit
ae75c7cb3f
|
@ -1809,7 +1809,7 @@ pub mod tests {
|
|||
matches::assert_matches,
|
||||
rand::{thread_rng, Rng},
|
||||
solana_entry::entry::{create_ticks, next_entry, next_entry_mut},
|
||||
solana_program_runtime::declare_process_instruction,
|
||||
solana_program_runtime::{builtin_program::create_builtin, declare_process_instruction},
|
||||
solana_runtime::{
|
||||
genesis_utils::{
|
||||
self, create_genesis_config_with_vote_accounts, ValidatorVoteKeypairs,
|
||||
|
@ -2971,7 +2971,10 @@ pub mod tests {
|
|||
let mock_program_id = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
bank.add_builtin("mock_processor", &mock_program_id, mock_processor_ok);
|
||||
bank.add_builtin(
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), mock_processor_ok),
|
||||
);
|
||||
|
||||
let tx = Transaction::new_signed_with_payer(
|
||||
&[Instruction::new_with_bincode(
|
||||
|
@ -3012,7 +3015,10 @@ pub mod tests {
|
|||
|
||||
(0..get_instruction_errors().len()).for_each(|err| {
|
||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
bank.add_builtin("mock_processor", &mock_program_id, mock_processor_err);
|
||||
bank.add_builtin(
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), mock_processor_err),
|
||||
);
|
||||
|
||||
let tx = Transaction::new_signed_with_payer(
|
||||
&[Instruction::new_with_bincode(
|
||||
|
|
|
@ -1,44 +1,28 @@
|
|||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||
use {crate::declare_process_instruction, solana_frozen_abi::abi_example::AbiExample};
|
||||
use solana_frozen_abi::abi_example::AbiExample;
|
||||
use {
|
||||
crate::invoke_context::InvokeContext, solana_rbpf::vm::BuiltInFunction,
|
||||
crate::{invoke_context::InvokeContext, loaded_programs::LoadedProgram},
|
||||
solana_rbpf::vm::{BuiltInFunction, BuiltInProgram},
|
||||
solana_sdk::pubkey::Pubkey,
|
||||
std::sync::Arc,
|
||||
};
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
pub fn create_builtin(
|
||||
name: String,
|
||||
process_instruction: ProcessInstructionWithContext,
|
||||
) -> Arc<LoadedProgram> {
|
||||
let mut program = BuiltInProgram::default();
|
||||
program
|
||||
.register_function_by_name("entrypoint", process_instruction)
|
||||
.unwrap();
|
||||
Arc::new(LoadedProgram::new_builtin(name, 0, program))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct BuiltinPrograms {
|
||||
pub vec: Vec<BuiltinProgram>,
|
||||
pub vec: Vec<(Pubkey, Arc<LoadedProgram>)>,
|
||||
}
|
||||
|
||||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||
|
@ -54,11 +38,10 @@ impl BuiltinPrograms {
|
|||
process_instruction: ProcessInstructionWithContext,
|
||||
) -> Self {
|
||||
Self {
|
||||
vec: vec![BuiltinProgram {
|
||||
name: "mock instruction processor".to_string(),
|
||||
vec: vec![(
|
||||
program_id,
|
||||
process_instruction,
|
||||
}],
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
)],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use {
|
|||
compute_budget::ComputeBudget,
|
||||
executor_cache::TransactionExecutorCache,
|
||||
ic_logger_msg, ic_msg,
|
||||
loaded_programs::LoadedProgramType,
|
||||
log_collector::LogCollector,
|
||||
pre_account::PreAccount,
|
||||
stable_log,
|
||||
|
@ -40,7 +41,7 @@ use {
|
|||
cell::RefCell,
|
||||
fmt::{self, Debug},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
sync::{atomic::Ordering, Arc},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -719,19 +720,29 @@ impl<'a> InvokeContext<'a> {
|
|||
};
|
||||
|
||||
for entry in self.builtin_programs.vec.iter() {
|
||||
if entry.program_id == builtin_id {
|
||||
if entry.0 == builtin_id {
|
||||
// The Murmur3 hash value (used by RBPF) of the string "entrypoint"
|
||||
const ENTRYPOINT_KEY: u32 = 0x71E3CF81;
|
||||
let process_instruction = match &entry.1.program {
|
||||
LoadedProgramType::Builtin(_name, program) => program
|
||||
.lookup_function(ENTRYPOINT_KEY)
|
||||
.map(|(_name, process_instruction)| process_instruction),
|
||||
_ => None,
|
||||
}
|
||||
.ok_or(InstructionError::GenericError)?;
|
||||
entry.1.usage_counter.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
let program_id =
|
||||
*instruction_context.get_last_program_key(self.transaction_context)?;
|
||||
self.transaction_context
|
||||
.set_return_data(program_id, Vec::new())?;
|
||||
|
||||
let logger = self.get_log_collector();
|
||||
stable_log::program_invoke(&logger, &program_id, self.get_stack_height());
|
||||
let pre_remaining_units = self.get_remaining();
|
||||
let mock_config = Config::default();
|
||||
let mut mock_memory_mapping = MemoryMapping::new(Vec::new(), &mock_config).unwrap();
|
||||
let mut result = ProgramResult::Ok(0);
|
||||
(entry.process_instruction)(
|
||||
process_instruction(
|
||||
// Removes lifetime tracking
|
||||
unsafe { std::mem::transmute::<&mut InvokeContext, &mut InvokeContext>(self) },
|
||||
0,
|
||||
|
|
|
@ -72,7 +72,7 @@ pub enum LoadedProgramType {
|
|||
Typed(VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>),
|
||||
#[cfg(test)]
|
||||
TestLoaded,
|
||||
BuiltIn(BuiltInProgram<InvokeContext<'static>>),
|
||||
Builtin(String, BuiltInProgram<InvokeContext<'static>>),
|
||||
}
|
||||
|
||||
impl Debug for LoadedProgramType {
|
||||
|
@ -89,7 +89,9 @@ impl Debug for LoadedProgramType {
|
|||
LoadedProgramType::Typed(_) => write!(f, "LoadedProgramType::Typed"),
|
||||
#[cfg(test)]
|
||||
LoadedProgramType::TestLoaded => write!(f, "LoadedProgramType::TestLoaded"),
|
||||
LoadedProgramType::BuiltIn(_) => write!(f, "LoadedProgramType::BuiltIn"),
|
||||
LoadedProgramType::Builtin(name, _) => {
|
||||
write!(f, "LoadedProgramType::Builtin({name})")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -215,7 +217,8 @@ impl LoadedProgram {
|
|||
}
|
||||
|
||||
/// Creates a new built-in program
|
||||
pub fn new_built_in(
|
||||
pub fn new_builtin(
|
||||
name: String,
|
||||
deployment_slot: Slot,
|
||||
program: BuiltInProgram<InvokeContext<'static>>,
|
||||
) -> Self {
|
||||
|
@ -225,7 +228,7 @@ impl LoadedProgram {
|
|||
effective_slot: deployment_slot.saturating_add(1),
|
||||
maybe_expiration_slot: None,
|
||||
usage_counter: AtomicU64::new(0),
|
||||
program: LoadedProgramType::BuiltIn(program),
|
||||
program: LoadedProgramType::Builtin(name, program),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,16 +297,6 @@ impl LoadedProgramsForTxBatch {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||
impl solana_frozen_abi::abi_example::AbiExample for LoadedPrograms {
|
||||
fn example() -> Self {
|
||||
// Delegate AbiExample impl to Default before going deep and stuck with
|
||||
// not easily impl-able Arc<dyn Executor> due to rust's coherence issue
|
||||
// This is safe because LoadedPrograms isn't serializable by definition.
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum LoadedProgramMatchCriteria {
|
||||
DeployedOnOrAfterSlot(Slot),
|
||||
Closed,
|
||||
|
@ -474,7 +467,7 @@ impl LoadedPrograms {
|
|||
LoadedProgramType::FailedVerification
|
||||
| LoadedProgramType::Closed
|
||||
| LoadedProgramType::DelayVisibility
|
||||
| LoadedProgramType::BuiltIn(_) => None,
|
||||
| LoadedProgramType::Builtin(_, _) => None,
|
||||
})
|
||||
})
|
||||
.sorted_by_cached_key(|(order, (_id, program))| {
|
||||
|
@ -561,6 +554,22 @@ impl LoadedPrograms {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||
impl solana_frozen_abi::abi_example::AbiExample for LoadedProgram {
|
||||
fn example() -> Self {
|
||||
// LoadedProgram isn't serializable by definition.
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||
impl solana_frozen_abi::abi_example::AbiExample for LoadedPrograms {
|
||||
fn example() -> Self {
|
||||
// LoadedPrograms isn't serializable by definition.
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {
|
||||
|
@ -582,7 +591,7 @@ mod tests {
|
|||
|
||||
fn new_test_builtin_program(deployment_slot: Slot, effective_slot: Slot) -> Arc<LoadedProgram> {
|
||||
Arc::new(LoadedProgram {
|
||||
program: LoadedProgramType::BuiltIn(BuiltInProgram::default()),
|
||||
program: LoadedProgramType::Builtin("mockup".to_string(), BuiltInProgram::default()),
|
||||
account_size: 0,
|
||||
deployment_slot,
|
||||
effective_slot,
|
||||
|
|
|
@ -11,7 +11,7 @@ use {
|
|||
solana_banks_server::banks_server::start_local_server,
|
||||
solana_bpf_loader_program::serialization::serialize_parameters,
|
||||
solana_program_runtime::{
|
||||
builtin_program::{BuiltinProgram, BuiltinPrograms, ProcessInstructionWithContext},
|
||||
builtin_program::{create_builtin, BuiltinPrograms, ProcessInstructionWithContext},
|
||||
compute_budget::ComputeBudget,
|
||||
ic_msg, stable_log,
|
||||
timings::ExecuteTimings,
|
||||
|
@ -692,11 +692,10 @@ impl ProgramTest {
|
|||
process_instruction: ProcessInstructionWithContext,
|
||||
) {
|
||||
info!("\"{}\" builtin program", program_name);
|
||||
self.builtin_programs.vec.push(BuiltinProgram {
|
||||
name: program_name.to_string(),
|
||||
self.builtin_programs.vec.push((
|
||||
program_id,
|
||||
process_instruction,
|
||||
});
|
||||
create_builtin(program_name.to_string(), process_instruction),
|
||||
));
|
||||
}
|
||||
|
||||
/// Deactivate a runtime feature.
|
||||
|
@ -791,12 +790,8 @@ impl ProgramTest {
|
|||
}
|
||||
|
||||
// User-supplied additional builtins
|
||||
for builtin in self.builtin_programs.vec.iter() {
|
||||
bank.add_builtin(
|
||||
&builtin.name,
|
||||
&builtin.program_id,
|
||||
builtin.process_instruction,
|
||||
);
|
||||
for (program_id, builtin) in self.builtin_programs.vec.iter() {
|
||||
bank.add_builtin(*program_id, builtin.clone());
|
||||
}
|
||||
|
||||
for (address, account) in self.accounts.iter() {
|
||||
|
|
|
@ -5,7 +5,7 @@ extern crate test;
|
|||
|
||||
use {
|
||||
log::*,
|
||||
solana_program_runtime::declare_process_instruction,
|
||||
solana_program_runtime::{builtin_program::create_builtin, declare_process_instruction},
|
||||
solana_runtime::{
|
||||
bank::{test_utils::goto_end_of_slot, *},
|
||||
bank_client::BankClient,
|
||||
|
@ -132,9 +132,8 @@ fn do_bench_transactions(
|
|||
|
||||
let mut bank = Bank::new_from_parent(&Arc::new(bank), &Pubkey::default(), 1);
|
||||
bank.add_builtin(
|
||||
"builtin_program",
|
||||
&Pubkey::from(BUILTIN_PROGRAM_ID),
|
||||
process_instruction,
|
||||
Pubkey::from(BUILTIN_PROGRAM_ID),
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
bank.add_builtin_account("solana_noop_program", &Pubkey::from(NOOP_PROGRAM_ID), false);
|
||||
let bank = Arc::new(bank);
|
||||
|
|
|
@ -94,7 +94,7 @@ use {
|
|||
solana_perf::perf_libs,
|
||||
solana_program_runtime::{
|
||||
accounts_data_meter::MAX_ACCOUNTS_DATA_LEN,
|
||||
builtin_program::{BuiltinProgram, BuiltinPrograms, ProcessInstructionWithContext},
|
||||
builtin_program::BuiltinPrograms,
|
||||
compute_budget::{self, ComputeBudget},
|
||||
executor_cache::{BankExecutorCache, TransactionExecutorCache, MAX_CACHED_EXECUTORS},
|
||||
loaded_programs::{
|
||||
|
@ -6350,12 +6350,8 @@ impl Bank {
|
|||
.extend_from_slice(&additional_builtins.feature_transitions);
|
||||
}
|
||||
if !debug_do_not_add_builtins {
|
||||
for builtin in builtins.genesis_builtins {
|
||||
self.add_builtin(
|
||||
&builtin.name,
|
||||
&builtin.program_id,
|
||||
builtin.process_instruction,
|
||||
);
|
||||
for (program_id, builtin) in builtins.genesis_builtins {
|
||||
self.add_builtin(program_id, builtin);
|
||||
}
|
||||
for precompile in get_precompiles() {
|
||||
if precompile.feature.is_none() {
|
||||
|
@ -7379,27 +7375,24 @@ impl Bank {
|
|||
}
|
||||
|
||||
/// Add an instruction processor to intercept instructions before the dynamic loader.
|
||||
pub fn add_builtin(
|
||||
&mut self,
|
||||
name: &str,
|
||||
program_id: &Pubkey,
|
||||
process_instruction: ProcessInstructionWithContext,
|
||||
) {
|
||||
pub fn add_builtin(&mut self, program_id: Pubkey, builtin: Arc<LoadedProgram>) {
|
||||
let name = match &builtin.program {
|
||||
LoadedProgramType::Builtin(name, _) => name,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
debug!("Adding program {} under {:?}", name, program_id);
|
||||
self.add_builtin_account(name, program_id, false);
|
||||
self.add_builtin_account(name.as_str(), &program_id, false);
|
||||
if let Some(entry) = self
|
||||
.builtin_programs
|
||||
.vec
|
||||
.iter_mut()
|
||||
.find(|entry| entry.program_id == *program_id)
|
||||
.find(|entry| entry.0 == program_id)
|
||||
{
|
||||
entry.process_instruction = process_instruction;
|
||||
entry.1 = builtin.clone();
|
||||
} else {
|
||||
self.builtin_programs.vec.push(BuiltinProgram {
|
||||
name: name.to_string(),
|
||||
program_id: *program_id,
|
||||
process_instruction,
|
||||
});
|
||||
self.builtin_programs
|
||||
.vec
|
||||
.push((program_id, builtin.clone()));
|
||||
}
|
||||
debug!("Added program {} under {:?}", name, program_id);
|
||||
}
|
||||
|
@ -7413,7 +7406,7 @@ impl Bank {
|
|||
.builtin_programs
|
||||
.vec
|
||||
.iter()
|
||||
.position(|entry| entry.program_id == *program_id)
|
||||
.position(|entry| entry.0 == *program_id)
|
||||
{
|
||||
self.builtin_programs.vec.remove(position);
|
||||
}
|
||||
|
@ -7665,11 +7658,9 @@ impl Bank {
|
|||
transition.to_action(&should_apply_action_for_feature_transition)
|
||||
{
|
||||
match builtin_action {
|
||||
BuiltinAction::Add(builtin) => self.add_builtin(
|
||||
&builtin.name,
|
||||
&builtin.program_id,
|
||||
builtin.process_instruction,
|
||||
),
|
||||
BuiltinAction::Add(program_id, builtin) => {
|
||||
self.add_builtin(program_id, builtin)
|
||||
}
|
||||
BuiltinAction::Remove(program_id) => self.remove_builtin(&program_id),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ use {
|
|||
serde::{Deserialize, Serialize},
|
||||
solana_logger,
|
||||
solana_program_runtime::{
|
||||
builtin_program::create_builtin,
|
||||
compute_budget::{self, ComputeBudget, MAX_COMPUTE_UNIT_LIMIT},
|
||||
declare_process_instruction,
|
||||
executor_cache::TransactionExecutorCache,
|
||||
|
@ -1380,7 +1381,10 @@ fn test_rent_complex() {
|
|||
root_bank.restore_old_behavior_for_fragile_tests();
|
||||
let root_bank = Arc::new(root_bank);
|
||||
let mut bank = create_child_bank_for_rent_test(&root_bank, &genesis_config);
|
||||
bank.add_builtin("mock_program", &mock_program_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
assert_eq!(bank.last_blockhash(), genesis_config.hash());
|
||||
|
||||
|
@ -4817,9 +4821,8 @@ fn test_add_builtin() {
|
|||
|
||||
assert!(bank.get_account(&mock_vote_program_id()).is_none());
|
||||
bank.add_builtin(
|
||||
"mock_vote_program",
|
||||
&mock_vote_program_id(),
|
||||
process_instruction,
|
||||
mock_vote_program_id(),
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
assert!(bank.get_account(&mock_vote_program_id()).is_some());
|
||||
|
||||
|
@ -4894,9 +4897,8 @@ fn test_add_duplicate_static_program() {
|
|||
|
||||
let vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap();
|
||||
bank.add_builtin(
|
||||
"solana_vote_program",
|
||||
&solana_vote_program::id(),
|
||||
process_instruction,
|
||||
solana_vote_program::id(),
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
let new_vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap();
|
||||
// Vote loader account should not be updated since it was included in the genesis config.
|
||||
|
@ -4948,8 +4950,14 @@ fn test_add_instruction_processor_for_existing_unrelated_accounts() {
|
|||
continue;
|
||||
}
|
||||
|
||||
bank.add_builtin("mock_program1", &vote_id, process_instruction);
|
||||
bank.add_builtin("mock_program2", &stake_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
vote_id,
|
||||
create_builtin("mock_program1".to_string(), process_instruction),
|
||||
);
|
||||
bank.add_builtin(
|
||||
stake_id,
|
||||
create_builtin("mock_program2".to_string(), process_instruction),
|
||||
);
|
||||
{
|
||||
let stakes = bank.stakes_cache.stakes();
|
||||
assert!(stakes.vote_accounts().as_ref().is_empty());
|
||||
|
@ -4972,8 +4980,14 @@ fn test_add_instruction_processor_for_existing_unrelated_accounts() {
|
|||
// Re-adding builtin programs should be no-op
|
||||
bank.update_accounts_hash_for_tests();
|
||||
let old_hash = bank.get_accounts_hash().unwrap();
|
||||
bank.add_builtin("mock_program1", &vote_id, process_instruction);
|
||||
bank.add_builtin("mock_program2", &stake_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
vote_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
bank.add_builtin(
|
||||
stake_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
add_root_and_flush_write_cache(&bank);
|
||||
bank.update_accounts_hash_for_tests();
|
||||
let new_hash = bank.get_accounts_hash().unwrap();
|
||||
|
@ -6224,7 +6238,10 @@ fn test_transaction_with_duplicate_accounts_in_instruction() {
|
|||
});
|
||||
|
||||
let mock_program_id = Pubkey::from([2u8; 32]);
|
||||
bank.add_builtin("mock_program", &mock_program_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let from_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let to_pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
@ -6260,7 +6277,10 @@ fn test_transaction_with_program_ids_passed_to_programs() {
|
|||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
|
||||
let mock_program_id = Pubkey::from([2u8; 32]);
|
||||
bank.add_builtin("mock_program", &mock_program_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let from_pubkey = solana_sdk::pubkey::new_rand();
|
||||
let to_pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
@ -6312,7 +6332,10 @@ fn test_account_ids_after_program_ids() {
|
|||
|
||||
tx.message.account_keys.push(solana_sdk::pubkey::new_rand());
|
||||
|
||||
bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction);
|
||||
bank.add_builtin(
|
||||
solana_vote_program::id(),
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
let result = bank.process_transaction(&tx);
|
||||
assert_eq!(result, Ok(()));
|
||||
let account = bank.get_account(&solana_vote_program::id()).unwrap();
|
||||
|
@ -6362,7 +6385,10 @@ fn test_duplicate_account_key() {
|
|||
AccountMeta::new(to_pubkey, false),
|
||||
];
|
||||
|
||||
bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction);
|
||||
bank.add_builtin(
|
||||
solana_vote_program::id(),
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
|
||||
let mut tx = Transaction::new_signed_with_payer(
|
||||
|
@ -6391,7 +6417,10 @@ fn test_process_transaction_with_too_many_account_locks() {
|
|||
AccountMeta::new(to_pubkey, false),
|
||||
];
|
||||
|
||||
bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction);
|
||||
bank.add_builtin(
|
||||
solana_vote_program::id(),
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
|
||||
let mut tx = Transaction::new_signed_with_payer(
|
||||
|
@ -6424,7 +6453,10 @@ fn test_program_id_as_payer() {
|
|||
AccountMeta::new(to_pubkey, false),
|
||||
];
|
||||
|
||||
bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction);
|
||||
bank.add_builtin(
|
||||
solana_vote_program::id(),
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
|
||||
let mut tx = Transaction::new_signed_with_payer(
|
||||
|
@ -6467,7 +6499,10 @@ fn test_ref_account_key_after_program_id() {
|
|||
AccountMeta::new(to_pubkey, false),
|
||||
];
|
||||
|
||||
bank.add_builtin("mock_vote", &solana_vote_program::id(), process_instruction);
|
||||
bank.add_builtin(
|
||||
solana_vote_program::id(),
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let instruction = Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
|
||||
let mut tx = Transaction::new_signed_with_payer(
|
||||
|
@ -6498,7 +6533,7 @@ fn test_fuzz_instructions() {
|
|||
.map(|i| {
|
||||
let key = solana_sdk::pubkey::new_rand();
|
||||
let name = format!("program{i:?}");
|
||||
bank.add_builtin(&name, &key, process_instruction);
|
||||
bank.add_builtin(key, create_builtin(name.clone(), process_instruction));
|
||||
(key, name.as_bytes().to_vec())
|
||||
})
|
||||
.collect();
|
||||
|
@ -6704,7 +6739,10 @@ fn test_same_program_id_uses_unqiue_executable_accounts() {
|
|||
|
||||
// Add a new program
|
||||
let program1_pubkey = solana_sdk::pubkey::new_rand();
|
||||
bank.add_builtin("program", &program1_pubkey, process_instruction);
|
||||
bank.add_builtin(
|
||||
program1_pubkey,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
// Add a new program owned by the first
|
||||
let program2_pubkey = solana_sdk::pubkey::new_rand();
|
||||
|
@ -6919,15 +6957,17 @@ fn test_add_builtin_no_overwrite() {
|
|||
));
|
||||
assert_eq!(bank.get_account_modified_slot(&program_id), None);
|
||||
|
||||
Arc::get_mut(&mut bank)
|
||||
.unwrap()
|
||||
.add_builtin("mock_program", &program_id, process_instruction);
|
||||
Arc::get_mut(&mut bank).unwrap().add_builtin(
|
||||
program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
|
||||
|
||||
let mut bank = Arc::new(new_from_parent(&bank));
|
||||
Arc::get_mut(&mut bank)
|
||||
.unwrap()
|
||||
.add_builtin("mock_program", &program_id, process_instruction);
|
||||
Arc::get_mut(&mut bank).unwrap().add_builtin(
|
||||
program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
|
||||
}
|
||||
|
||||
|
@ -6943,15 +6983,17 @@ fn test_add_builtin_loader_no_overwrite() {
|
|||
));
|
||||
assert_eq!(bank.get_account_modified_slot(&loader_id), None);
|
||||
|
||||
Arc::get_mut(&mut bank)
|
||||
.unwrap()
|
||||
.add_builtin("mock_program", &loader_id, process_instruction);
|
||||
Arc::get_mut(&mut bank).unwrap().add_builtin(
|
||||
loader_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot);
|
||||
|
||||
let mut bank = Arc::new(new_from_parent(&bank));
|
||||
Arc::get_mut(&mut bank)
|
||||
.unwrap()
|
||||
.add_builtin("mock_program", &loader_id, process_instruction);
|
||||
Arc::get_mut(&mut bank).unwrap().add_builtin(
|
||||
loader_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot);
|
||||
}
|
||||
|
||||
|
@ -9694,7 +9736,10 @@ fn test_tx_return_data() {
|
|||
|
||||
let mock_program_id = Pubkey::from([2u8; 32]);
|
||||
let blockhash = bank.last_blockhash();
|
||||
bank.add_builtin("mock_program", &mock_program_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
for index in [
|
||||
None,
|
||||
|
@ -9883,7 +9928,10 @@ fn test_transfer_sysvar() {
|
|||
});
|
||||
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
bank.add_builtin("mock_program1", &program_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let blockhash = bank.last_blockhash();
|
||||
#[allow(deprecated)]
|
||||
|
@ -10095,7 +10143,10 @@ fn test_compute_budget_program_noop() {
|
|||
Ok(())
|
||||
});
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
bank.add_builtin("mock_program", &program_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let message = Message::new(
|
||||
&[
|
||||
|
@ -10138,7 +10189,10 @@ fn test_compute_request_instruction() {
|
|||
Ok(())
|
||||
});
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
bank.add_builtin("mock_program", &program_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
let message = Message::new(
|
||||
&[
|
||||
|
@ -10188,7 +10242,10 @@ fn test_failed_compute_request_instruction() {
|
|||
Ok(())
|
||||
});
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
bank.add_builtin("mock_program", &program_id, process_instruction);
|
||||
bank.add_builtin(
|
||||
program_id,
|
||||
create_builtin("mockup".to_string(), process_instruction),
|
||||
);
|
||||
|
||||
// This message will not be executed because the compute budget request is invalid
|
||||
let message0 = Message::new(
|
||||
|
@ -10863,9 +10920,8 @@ fn test_invalid_rent_state_changes_existing_accounts() {
|
|||
|
||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
bank.add_builtin(
|
||||
"mock_program",
|
||||
&mock_program_id,
|
||||
mock_transfer_process_instruction,
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), mock_transfer_process_instruction),
|
||||
);
|
||||
let recent_blockhash = bank.last_blockhash();
|
||||
|
||||
|
@ -10950,9 +11006,8 @@ fn test_invalid_rent_state_changes_new_accounts() {
|
|||
|
||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
bank.add_builtin(
|
||||
"mock_program",
|
||||
&mock_program_id,
|
||||
mock_transfer_process_instruction,
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), mock_transfer_process_instruction),
|
||||
);
|
||||
let recent_blockhash = bank.last_blockhash();
|
||||
|
||||
|
@ -11013,9 +11068,8 @@ fn test_drained_created_account() {
|
|||
|
||||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
bank.add_builtin(
|
||||
"mock_program",
|
||||
&mock_program_id,
|
||||
mock_transfer_process_instruction,
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), mock_transfer_process_instruction),
|
||||
);
|
||||
let recent_blockhash = bank.last_blockhash();
|
||||
|
||||
|
@ -11668,9 +11722,8 @@ fn test_resize_and_rent() {
|
|||
|
||||
let mock_program_id = Pubkey::new_unique();
|
||||
bank.add_builtin(
|
||||
"mock_realloc_program",
|
||||
&mock_program_id,
|
||||
mock_realloc_process_instruction,
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), mock_realloc_process_instruction),
|
||||
);
|
||||
let recent_blockhash = bank.last_blockhash();
|
||||
|
||||
|
@ -11943,9 +11996,8 @@ fn test_accounts_data_size_and_resize_transactions() {
|
|||
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||
let mock_program_id = Pubkey::new_unique();
|
||||
bank.add_builtin(
|
||||
"mock_realloc_program",
|
||||
&mock_program_id,
|
||||
mock_realloc_process_instruction,
|
||||
mock_program_id,
|
||||
create_builtin("mockup".to_string(), mock_realloc_process_instruction),
|
||||
);
|
||||
|
||||
let recent_blockhash = bank.last_blockhash();
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use {
|
||||
solana_program_runtime::builtin_program::BuiltinProgram,
|
||||
solana_program_runtime::{builtin_program::create_builtin, loaded_programs::LoadedProgram},
|
||||
solana_sdk::{
|
||||
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, feature_set, pubkey::Pubkey,
|
||||
},
|
||||
std::sync::Arc,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Builtins {
|
||||
/// Builtin programs that are always available
|
||||
pub genesis_builtins: Vec<BuiltinProgram>,
|
||||
pub genesis_builtins: Vec<(Pubkey, Arc<LoadedProgram>)>,
|
||||
|
||||
/// Dynamic feature transitions for builtin programs
|
||||
pub feature_transitions: Vec<BuiltinFeatureTransition>,
|
||||
|
@ -17,7 +18,7 @@ pub struct Builtins {
|
|||
/// Actions taken by a bank when managing the list of active builtin programs.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum BuiltinAction {
|
||||
Add(BuiltinProgram),
|
||||
Add(Pubkey, Arc<LoadedProgram>),
|
||||
Remove(Pubkey),
|
||||
}
|
||||
|
||||
|
@ -27,13 +28,15 @@ pub enum BuiltinAction {
|
|||
pub enum BuiltinFeatureTransition {
|
||||
/// Add a builtin program if a feature is activated.
|
||||
Add {
|
||||
builtin: BuiltinProgram,
|
||||
program_id: Pubkey,
|
||||
builtin: Arc<LoadedProgram>,
|
||||
feature_id: Pubkey,
|
||||
},
|
||||
/// Remove a builtin program if a feature is activated or
|
||||
/// retain a previously added builtin.
|
||||
RemoveOrRetain {
|
||||
previously_added_builtin: BuiltinProgram,
|
||||
program_id: Pubkey,
|
||||
previously_added_builtin: Arc<LoadedProgram>,
|
||||
addition_feature_id: Pubkey,
|
||||
removal_feature_id: Pubkey,
|
||||
},
|
||||
|
@ -46,25 +49,30 @@ impl BuiltinFeatureTransition {
|
|||
) -> Option<BuiltinAction> {
|
||||
match self {
|
||||
Self::Add {
|
||||
program_id,
|
||||
builtin,
|
||||
feature_id,
|
||||
} => {
|
||||
if should_apply_action_for_feature(feature_id) {
|
||||
Some(BuiltinAction::Add(builtin.clone()))
|
||||
Some(BuiltinAction::Add(*program_id, builtin.clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::RemoveOrRetain {
|
||||
program_id,
|
||||
previously_added_builtin,
|
||||
addition_feature_id,
|
||||
removal_feature_id,
|
||||
} => {
|
||||
if should_apply_action_for_feature(removal_feature_id) {
|
||||
Some(BuiltinAction::Remove(previously_added_builtin.program_id))
|
||||
Some(BuiltinAction::Remove(*program_id))
|
||||
} else if should_apply_action_for_feature(addition_feature_id) {
|
||||
// Retaining is no different from adding a new builtin.
|
||||
Some(BuiltinAction::Add(previously_added_builtin.clone()))
|
||||
Some(BuiltinAction::Add(
|
||||
*program_id,
|
||||
previously_added_builtin.clone(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -74,43 +82,57 @@ impl BuiltinFeatureTransition {
|
|||
}
|
||||
|
||||
/// Built-in programs that are always available
|
||||
fn genesis_builtins() -> Vec<BuiltinProgram> {
|
||||
fn genesis_builtins() -> Vec<(Pubkey, Arc<LoadedProgram>)> {
|
||||
vec![
|
||||
BuiltinProgram {
|
||||
name: "system_program".to_string(),
|
||||
program_id: solana_system_program::id(),
|
||||
process_instruction: solana_system_program::system_processor::process_instruction,
|
||||
},
|
||||
BuiltinProgram {
|
||||
name: "vote_program".to_string(),
|
||||
program_id: solana_vote_program::id(),
|
||||
process_instruction: solana_vote_program::vote_processor::process_instruction,
|
||||
},
|
||||
BuiltinProgram {
|
||||
name: "stake_program".to_string(),
|
||||
program_id: solana_stake_program::id(),
|
||||
process_instruction: solana_stake_program::stake_instruction::process_instruction,
|
||||
},
|
||||
BuiltinProgram {
|
||||
name: "config_program".to_string(),
|
||||
program_id: solana_config_program::id(),
|
||||
process_instruction: solana_config_program::config_processor::process_instruction,
|
||||
},
|
||||
BuiltinProgram {
|
||||
name: "solana_bpf_loader_deprecated_program".to_string(),
|
||||
program_id: bpf_loader_deprecated::id(),
|
||||
process_instruction: solana_bpf_loader_program::process_instruction,
|
||||
},
|
||||
BuiltinProgram {
|
||||
name: "solana_bpf_loader_program".to_string(),
|
||||
program_id: bpf_loader::id(),
|
||||
process_instruction: solana_bpf_loader_program::process_instruction,
|
||||
},
|
||||
BuiltinProgram {
|
||||
name: "solana_bpf_loader_upgradeable_program".to_string(),
|
||||
program_id: bpf_loader_upgradeable::id(),
|
||||
process_instruction: solana_bpf_loader_program::process_instruction,
|
||||
},
|
||||
(
|
||||
solana_system_program::id(),
|
||||
create_builtin(
|
||||
"system_program".to_string(),
|
||||
solana_system_program::system_processor::process_instruction,
|
||||
),
|
||||
),
|
||||
(
|
||||
solana_vote_program::id(),
|
||||
create_builtin(
|
||||
"vote_program".to_string(),
|
||||
solana_vote_program::vote_processor::process_instruction,
|
||||
),
|
||||
),
|
||||
(
|
||||
solana_stake_program::id(),
|
||||
create_builtin(
|
||||
"stake_program".to_string(),
|
||||
solana_stake_program::stake_instruction::process_instruction,
|
||||
),
|
||||
),
|
||||
(
|
||||
solana_config_program::id(),
|
||||
create_builtin(
|
||||
"config_program".to_string(),
|
||||
solana_config_program::config_processor::process_instruction,
|
||||
),
|
||||
),
|
||||
(
|
||||
bpf_loader_deprecated::id(),
|
||||
create_builtin(
|
||||
"solana_bpf_loader_deprecated_program".to_string(),
|
||||
solana_bpf_loader_program::process_instruction,
|
||||
),
|
||||
),
|
||||
(
|
||||
bpf_loader::id(),
|
||||
create_builtin(
|
||||
"solana_bpf_loader_program".to_string(),
|
||||
solana_bpf_loader_program::process_instruction,
|
||||
),
|
||||
),
|
||||
(
|
||||
bpf_loader_upgradeable::id(),
|
||||
create_builtin(
|
||||
"solana_bpf_loader_upgradeable_program".to_string(),
|
||||
solana_bpf_loader_program::process_instruction,
|
||||
),
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -118,28 +140,27 @@ fn genesis_builtins() -> Vec<BuiltinProgram> {
|
|||
fn builtin_feature_transitions() -> Vec<BuiltinFeatureTransition> {
|
||||
vec![
|
||||
BuiltinFeatureTransition::Add {
|
||||
builtin: BuiltinProgram {
|
||||
name: "compute_budget_program".to_string(),
|
||||
program_id: solana_sdk::compute_budget::id(),
|
||||
process_instruction: solana_compute_budget_program::process_instruction,
|
||||
},
|
||||
builtin: create_builtin(
|
||||
"compute_budget_program".to_string(),
|
||||
solana_compute_budget_program::process_instruction,
|
||||
),
|
||||
feature_id: feature_set::add_compute_budget_program::id(),
|
||||
},
|
||||
BuiltinFeatureTransition::Add {
|
||||
builtin: BuiltinProgram {
|
||||
name: "address_lookup_table_program".to_string(),
|
||||
program_id: solana_address_lookup_table_program::id(),
|
||||
process_instruction:
|
||||
builtin: create_builtin(
|
||||
"address_lookup_table_program".to_string(),
|
||||
solana_address_lookup_table_program::processor::process_instruction,
|
||||
},
|
||||
),
|
||||
feature_id: feature_set::versioned_tx_message_enabled::id(),
|
||||
},
|
||||
BuiltinFeatureTransition::Add {
|
||||
builtin: BuiltinProgram {
|
||||
name: "zk_token_proof_program".to_string(),
|
||||
program_id: solana_zk_token_sdk::zk_token_proof_program::id(),
|
||||
process_instruction: solana_zk_token_proof_program::process_instruction,
|
||||
},
|
||||
builtin: create_builtin(
|
||||
"zk_token_proof_program".to_string(),
|
||||
solana_zk_token_proof_program::process_instruction,
|
||||
),
|
||||
feature_id: feature_set::zk_token_sdk_enabled::id(),
|
||||
},
|
||||
]
|
||||
|
@ -157,9 +178,14 @@ pub fn get_pubkeys() -> Vec<Pubkey> {
|
|||
let builtins = get();
|
||||
|
||||
let mut pubkeys = Vec::new();
|
||||
pubkeys.extend(builtins.genesis_builtins.iter().map(|b| b.program_id));
|
||||
pubkeys.extend(
|
||||
builtins
|
||||
.genesis_builtins
|
||||
.iter()
|
||||
.map(|(program_id, _builtin)| program_id),
|
||||
);
|
||||
pubkeys.extend(builtins.feature_transitions.iter().filter_map(|f| match f {
|
||||
BuiltinFeatureTransition::Add { builtin, .. } => Some(builtin.program_id),
|
||||
BuiltinFeatureTransition::Add { program_id, .. } => Some(program_id),
|
||||
BuiltinFeatureTransition::RemoveOrRetain { .. } => None,
|
||||
}));
|
||||
pubkeys
|
||||
|
|
Loading…
Reference in New Issue