From b74fbdf7eb408d61386f53de79d2c3f3258d9e84 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 8 Oct 2020 18:18:51 +0000 Subject: [PATCH] Pipe FeatureSet though InvokeContext (bp #12536) (#12730) * Pipe FeatureSet though InvokeContext (#12536) * Pipe FeatureSet though InvokeContext * gate program size cap * nit (cherry picked from commit 74fcb184b266cbbc519b8476e070944f301ba31e) # Conflicts: # runtime/src/bank.rs # runtime/src/feature_set.rs * fix conflicts Co-authored-by: Jack May --- programs/bpf/benches/bpf_loader.rs | 13 ++-- programs/bpf/tests/programs.rs | 12 ++-- programs/bpf_loader/src/bpf_verifier.rs | 8 +-- programs/bpf_loader/src/lib.rs | 49 +++++++++----- programs/bpf_loader/src/syscalls.rs | 57 ++++++++-------- runtime/src/bank.rs | 59 +---------------- runtime/src/feature_set.rs | 14 ++-- runtime/src/message_processor.rs | 86 +++++++++++-------------- runtime/src/process_instruction.rs | 6 +- 9 files changed, 124 insertions(+), 180 deletions(-) diff --git a/programs/bpf/benches/bpf_loader.rs b/programs/bpf/benches/bpf_loader.rs index b134451e5c..6d99366208 100644 --- a/programs/bpf/benches/bpf_loader.rs +++ b/programs/bpf/benches/bpf_loader.rs @@ -218,7 +218,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { "Tuner must consume the whole budget" ); println!( - "{:?} Consumed compute budget took {:?} us ({:?} instructions)", + "{:?} compute units took {:?} us ({:?} instructions)", BUDGET - instruction_meter.get_remaining(), measure.as_us(), vm.get_total_instruction_count(), @@ -229,6 +229,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { pub struct MockInvokeContext { key: Pubkey, logger: MockLogger, + compute_budget: ComputeBudget, compute_meter: Rc>, } impl InvokeContext for MockInvokeContext { @@ -253,11 +254,8 @@ impl InvokeContext for MockInvokeContext { fn get_logger(&self) -> Rc> { Rc::new(RefCell::new(self.logger.clone())) } - fn is_cross_program_supported(&self) -> bool { - true - } - fn get_compute_budget(&self) -> ComputeBudget { - ComputeBudget::default() + fn get_compute_budget(&self) -> &ComputeBudget { + &self.compute_budget } fn get_compute_meter(&self) -> Rc> { self.compute_meter.clone() @@ -267,6 +265,9 @@ impl InvokeContext for MockInvokeContext { None } fn record_instruction(&self, _instruction: &Instruction) {} + fn is_feature_active(&self, _feature_id: &Pubkey) -> bool { + true + } } #[derive(Debug, Default, Clone)] pub struct MockLogger { diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 8b867d3555..54dca17455 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -23,7 +23,6 @@ use solana_sdk::{ client::SyncClient, clock::{DEFAULT_SLOTS_PER_EPOCH, MAX_PROCESSING_AGE}, entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS}, - instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError}, message::Message, pubkey::Pubkey, @@ -688,6 +687,7 @@ fn assert_instruction_count() { struct MockInvokeContext { pub key: Pubkey, pub logger: MockLogger, + pub compute_budget: ComputeBudget, pub compute_meter: MockComputeMeter, } impl InvokeContext for MockInvokeContext { @@ -712,11 +712,8 @@ impl InvokeContext for MockInvokeContext { fn get_logger(&self) -> Rc> { Rc::new(RefCell::new(self.logger.clone())) } - fn is_cross_program_supported(&self) -> bool { - true - } - fn get_compute_budget(&self) -> ComputeBudget { - ComputeBudget::default() + fn get_compute_budget(&self) -> &ComputeBudget { + &self.compute_budget } fn get_compute_meter(&self) -> Rc> { Rc::new(RefCell::new(self.compute_meter.clone())) @@ -726,6 +723,9 @@ impl InvokeContext for MockInvokeContext { None } fn record_instruction(&self, _instruction: &Instruction) {} + fn is_feature_active(&self, _feature_id: &Pubkey) -> bool { + true + } } #[derive(Debug, Default, Clone)] diff --git a/programs/bpf_loader/src/bpf_verifier.rs b/programs/bpf_loader/src/bpf_verifier.rs index a3261b2844..816bdafe47 100644 --- a/programs/bpf_loader/src/bpf_verifier.rs +++ b/programs/bpf_loader/src/bpf_verifier.rs @@ -54,11 +54,11 @@ pub enum VerifierError { InvalidRegister(usize), } -fn check_prog_len(prog: &[u8]) -> Result<(), BPFError> { +fn check_prog_len(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> { if prog.len() % ebpf::INSN_SIZE != 0 { return Err(VerifierError::ProgramLengthNotMultiple.into()); } - if prog.len() > ebpf::PROG_MAX_SIZE { + if is_program_size_cap && prog.len() > ebpf::PROG_MAX_SIZE { return Err(VerifierError::ProgramTooLarge(prog.len() / ebpf::INSN_SIZE).into()); } @@ -139,8 +139,8 @@ fn check_imm_register(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), Verifier } #[rustfmt::skip] -pub fn check(prog: &[u8]) -> Result<(), BPFError> { - check_prog_len(prog)?; +pub fn check(prog: &[u8], is_program_size_cap: bool) -> Result<(), BPFError> { + check_prog_len(prog, is_program_size_cap)?; let mut insn_ptr: usize = 0; while insn_ptr * ebpf::INSN_SIZE < prog.len() { diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index ff133a6c56..afa8b86161 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -16,7 +16,10 @@ use solana_rbpf::{ memory_region::MemoryRegion, vm::{EbpfVm, Executable, InstructionMeter}, }; -use solana_runtime::process_instruction::{ComputeMeter, Executor, InvokeContext}; +use solana_runtime::{ + feature_set::compute_budget_config2, + process_instruction::{ComputeMeter, Executor, InvokeContext}, +}; use solana_sdk::{ account::{is_executable, next_keyed_account, KeyedAccount}, bpf_loader, bpf_loader_deprecated, @@ -78,19 +81,29 @@ macro_rules! log{ }; } +fn map_ebpf_error( + invoke_context: &mut dyn InvokeContext, + e: EbpfError, +) -> InstructionError { + let logger = invoke_context.get_logger(); + log!(logger, "{}", e); + InstructionError::InvalidAccountData +} + pub fn create_and_cache_executor( program: &KeyedAccount, invoke_context: &mut dyn InvokeContext, ) -> Result, InstructionError> { - let executable = EbpfVm::create_executable_from_elf( - &program.try_account_ref()?.data, - Some(bpf_verifier::check), + let executable = EbpfVm::create_executable_from_elf(&program.try_account_ref()?.data, None) + .map_err(|e| map_ebpf_error(invoke_context, e))?; + let (_, elf_bytes) = executable + .get_text_bytes() + .map_err(|e| map_ebpf_error(invoke_context, e))?; + bpf_verifier::check( + elf_bytes, + !invoke_context.is_feature_active(&compute_budget_config2::id()), ) - .map_err(|e| { - let logger = invoke_context.get_logger(); - log!(logger, "{}", e); - InstructionError::InvalidAccountData - })?; + .map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e)))?; let executor = Arc::new(BPFExecutor { executable }); invoke_context.add_executor(program.unsigned_key(), executor.clone()); Ok(executor) @@ -271,6 +284,7 @@ mod tests { use super::*; use rand::Rng; use solana_runtime::{ + feature_set::FeatureSet, message_processor::{Executors, ThisInvokeContext}, process_instruction::{ComputeBudget, Logger, ProcessInstruction}, }; @@ -313,6 +327,7 @@ mod tests { pub struct MockInvokeContext { pub key: Pubkey, pub logger: MockLogger, + pub compute_budget: ComputeBudget, pub compute_meter: MockComputeMeter, } impl Default for MockInvokeContext { @@ -320,6 +335,7 @@ mod tests { MockInvokeContext { key: Pubkey::default(), logger: MockLogger::default(), + compute_budget: ComputeBudget::default(), compute_meter: MockComputeMeter { remaining: std::u64::MAX, }, @@ -348,11 +364,8 @@ mod tests { fn get_logger(&self) -> Rc> { Rc::new(RefCell::new(self.logger.clone())) } - fn is_cross_program_supported(&self) -> bool { - true - } - fn get_compute_budget(&self) -> ComputeBudget { - ComputeBudget::default() + fn get_compute_budget(&self) -> &ComputeBudget { + &self.compute_budget } fn get_compute_meter(&self) -> Rc> { Rc::new(RefCell::new(self.compute_meter.clone())) @@ -362,6 +375,9 @@ mod tests { None } fn record_instruction(&self, _instruction: &Instruction) {} + fn is_feature_active(&self, _feature_id: &Pubkey) -> bool { + true + } } struct TestInstructionMeter { @@ -387,8 +403,7 @@ mod tests { ]; let input = &mut [0x00]; - let executable = - EbpfVm::create_executable_from_text_bytes(program, Some(bpf_verifier::check)).unwrap(); + let executable = EbpfVm::create_executable_from_text_bytes(program, None).unwrap(); let mut vm = EbpfVm::::new(executable.as_ref()).unwrap(); let instruction_meter = TestInstructionMeter { remaining: 10 }; vm.execute_program_metered(input, &[], &[], instruction_meter) @@ -579,7 +594,6 @@ mod tests { vec![], vec![], None, - true, ComputeBudget { max_units: 1, log_units: 100, @@ -590,6 +604,7 @@ mod tests { }, Rc::new(RefCell::new(Executors::default())), None, + Arc::new(FeatureSet::default()), ); assert_eq!( Err(InstructionError::Custom(194969602)), diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index afd47b92e1..18486ff67e 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -94,6 +94,7 @@ pub fn register_syscalls<'a>( invoke_context: &'a mut dyn InvokeContext, ) -> Result> { let compute_budget = invoke_context.get_compute_budget(); + // Syscall functions common across languages vm.register_syscall_ex("abort", syscall_abort)?; @@ -115,36 +116,35 @@ pub fn register_syscalls<'a>( logger: invoke_context.get_logger(), }), )?; - if invoke_context.is_cross_program_supported() { - vm.register_syscall_with_context_ex( - "sol_create_program_address", - Box::new(SyscallCreateProgramAddress { - cost: compute_budget.create_program_address_units, - compute_meter: invoke_context.get_compute_meter(), - loader_id, - }), - )?; - // Cross-program invocation syscalls + vm.register_syscall_with_context_ex( + "sol_create_program_address", + Box::new(SyscallCreateProgramAddress { + cost: compute_budget.create_program_address_units, + compute_meter: invoke_context.get_compute_meter(), + loader_id, + }), + )?; - let invoke_context = Rc::new(RefCell::new(invoke_context)); - vm.register_syscall_with_context_ex( - "sol_invoke_signed_c", - Box::new(SyscallInvokeSignedC { - callers_keyed_accounts, - invoke_context: invoke_context.clone(), - loader_id, - }), - )?; - vm.register_syscall_with_context_ex( - "sol_invoke_signed_rust", - Box::new(SyscallInvokeSignedRust { - callers_keyed_accounts, - invoke_context: invoke_context.clone(), - loader_id, - }), - )?; - } + // Cross-program invocation syscalls + + let invoke_context = Rc::new(RefCell::new(invoke_context)); + vm.register_syscall_with_context_ex( + "sol_invoke_signed_c", + Box::new(SyscallInvokeSignedC { + callers_keyed_accounts, + invoke_context: invoke_context.clone(), + loader_id, + }), + )?; + vm.register_syscall_with_context_ex( + "sol_invoke_signed_rust", + Box::new(SyscallInvokeSignedRust { + callers_keyed_accounts, + invoke_context: invoke_context.clone(), + loader_id, + }), + )?; // Memory allocator let heap = vec![0_u8; DEFAULT_HEAP_SIZE]; @@ -1049,7 +1049,6 @@ fn call<'a>( } message_processor.add_loader(bpf_loader::id(), crate::process_instruction); message_processor.add_loader(bpf_loader_deprecated::id(), crate::process_instruction); - message_processor.set_cross_program_support(invoke_context.is_cross_program_supported()); #[allow(clippy::deref_addrof)] match message_processor.process_cross_program_instruction( diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index a995532477..246cd7e580 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -17,9 +17,7 @@ use crate::{ instruction_recorder::InstructionRecorder, log_collector::LogCollector, message_processor::{Executors, MessageProcessor}, - process_instruction::{ - ComputeBudget, Executor, ProcessInstruction, ProcessInstructionWithContext, - }, + process_instruction::{Executor, ProcessInstruction, ProcessInstructionWithContext}, rent_collector::RentCollector, stakes::Stakes, status_cache::{SlotDelta, StatusCache}, @@ -1527,15 +1525,6 @@ impl Bank { debug!("Added native program {} under {:?}", name, program_id); } - pub fn set_cross_program_support(&mut self, is_supported: bool) { - self.message_processor - .set_cross_program_support(is_supported); - } - - pub fn set_compute_budget(&mut self, budget: ComputeBudget) { - self.message_processor.set_compute_budget(budget); - } - pub fn set_rent_burn_percentage(&mut self, burn_percent: u8) { self.rent_collector.rent.burn_percent = burn_percent; } @@ -2206,7 +2195,7 @@ impl Bank { log_collector.clone(), executors.clone(), instruction_recorders.as_deref(), - &self.feature_set, + self.feature_set.clone(), ); Self::compile_recorded_instructions( @@ -3717,8 +3706,6 @@ impl Bank { } self.ensure_feature_builtins(init_finish_or_warp, &new_feature_activations); - self.recheck_cross_program_support(); - self.recheck_compute_budget(); self.reconfigure_token2_native_mint(); self.ensure_no_storage_rewards_pool(); } @@ -3782,35 +3769,6 @@ impl Bank { } } - fn recheck_cross_program_support(&mut self) { - if ClusterType::MainnetBeta == self.cluster_type() { - self.set_cross_program_support(self.epoch() >= 63); - } else { - self.set_cross_program_support(true); - } - } - - fn recheck_compute_budget(&mut self) { - let compute_budget = if ClusterType::MainnetBeta == self.cluster_type() { - if self.epoch() >= u64::MAX - 1 { - ComputeBudget::default() - } else { - // Original - ComputeBudget { - max_units: 100_000, - log_units: 0, - log_64_units: 0, - create_program_address_units: 0, - invoke_units: 0, - max_invoke_depth: 2, - } - } - } else { - ComputeBudget::default() - }; - self.set_compute_budget(compute_budget); - } - fn apply_spl_token_v2_multisig_fix(&mut self) { if let Some(mut account) = self.get_account(&inline_spl_token_v2_0::id()) { self.capitalization @@ -8871,19 +8829,6 @@ mod tests { assert_eq!(bank.get_balance(&mint_keypair.pubkey()), 496); // no transaction fee charged } - #[test] - fn test_finish_init() { - let (genesis_config, _mint_keypair) = create_genesis_config(100_000); - let mut bank = Bank::new(&genesis_config); - bank.message_processor = MessageProcessor::default(); - bank.message_processor.set_cross_program_support(false); - - // simulate bank is just after deserialized from snapshot - bank.finish_init(&genesis_config, None); - - assert_eq!(bank.message_processor.get_cross_program_support(), true); - } - #[test] fn test_add_builtin_program_no_overwrite() { let (genesis_config, _mint_keypair) = create_genesis_config(100_000); diff --git a/runtime/src/feature_set.rs b/runtime/src/feature_set.rs index f2dd6d65d7..58d6bddc78 100644 --- a/runtime/src/feature_set.rs +++ b/runtime/src/feature_set.rs @@ -33,6 +33,10 @@ pub mod no_overflow_rent_distribution { solana_sdk::declare_id!("4kpdyrcj5jS47CZb2oJGfVxjYbsMm2Kx97gFyZrxxwXz"); } +pub mod compute_budget_config2 { + solana_sdk::declare_id!("HxvjqDSiF5sYdSYuCXsUnS8UeAoWsMT9iGoFP8pgV1mB"); +} + lazy_static! { /// Map of feature identifiers to user-visible description pub static ref FEATURE_NAMES: HashMap = [ @@ -43,6 +47,7 @@ lazy_static! { (spl_token_v2_multisig_fix::id(), "spl-token multisig fix"), (bpf_loader2_program::id(), "bpf_loader2 program"), (no_overflow_rent_distribution::id(), "no overflow rent distribution"), + (compute_budget_config2::id(), "1ms compute budget"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter() @@ -83,12 +88,3 @@ impl Default for FeatureSet { } } } - -impl FeatureSet { - pub fn enabled() -> Self { - Self { - active: FEATURE_NAMES.keys().cloned().collect(), - inactive: HashSet::new(), - } - } -} diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 64d657a72f..43141b072f 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -1,5 +1,5 @@ use crate::{ - feature_set::{self, FeatureSet}, + feature_set::{compute_budget_config2, instructions_sysvar_enabled, FeatureSet}, instruction_recorder::InstructionRecorder, log_collector::LogCollector, native_loader::NativeLoader, @@ -206,11 +206,11 @@ pub struct ThisInvokeContext { pre_accounts: Vec, programs: Vec<(Pubkey, ProcessInstruction)>, logger: Rc>, - is_cross_program_supported: bool, compute_budget: ComputeBudget, compute_meter: Rc>, executors: Rc>, instruction_recorder: Option, + feature_set: Arc, } impl ThisInvokeContext { pub fn new( @@ -219,10 +219,10 @@ impl ThisInvokeContext { pre_accounts: Vec, programs: Vec<(Pubkey, ProcessInstruction)>, log_collector: Option>, - is_cross_program_supported: bool, compute_budget: ComputeBudget, executors: Rc>, instruction_recorder: Option, + feature_set: Arc, ) -> Self { let mut program_ids = Vec::with_capacity(compute_budget.max_invoke_depth); program_ids.push(*program_id); @@ -232,13 +232,13 @@ impl ThisInvokeContext { pre_accounts, programs, logger: Rc::new(RefCell::new(ThisLogger { log_collector })), - is_cross_program_supported, compute_budget, compute_meter: Rc::new(RefCell::new(ThisComputeMeter { remaining: compute_budget.max_units, })), executors, instruction_recorder, + feature_set, } } } @@ -286,11 +286,8 @@ impl InvokeContext for ThisInvokeContext { fn get_logger(&self) -> Rc> { self.logger.clone() } - fn is_cross_program_supported(&self) -> bool { - self.is_cross_program_supported - } - fn get_compute_budget(&self) -> ComputeBudget { - self.compute_budget + fn get_compute_budget(&self) -> &ComputeBudget { + &self.compute_budget } fn get_compute_meter(&self) -> Rc> { self.compute_meter.clone() @@ -306,6 +303,9 @@ impl InvokeContext for ThisInvokeContext { recorder.record_instruction(instruction.clone()); } } + fn is_feature_active(&self, feature_id: &Pubkey) -> bool { + self.feature_set.is_active(feature_id) + } } pub struct ThisLogger { log_collector: Option>, @@ -330,10 +330,6 @@ pub struct MessageProcessor { loaders: Vec<(Pubkey, ProcessInstructionWithContext)>, #[serde(skip)] native_loader: NativeLoader, - #[serde(skip)] - is_cross_program_supported: bool, - #[serde(skip)] - compute_budget: ComputeBudget, } impl std::fmt::Debug for MessageProcessor { @@ -343,8 +339,6 @@ impl std::fmt::Debug for MessageProcessor { programs: Vec, loaders: Vec, native_loader: &'a NativeLoader, - is_cross_program_supported: bool, - compute_budget: ComputeBudget, } // rustc doesn't compile due to bug without this work around // https://github.com/rust-lang/rust/issues/50280 @@ -367,8 +361,6 @@ impl std::fmt::Debug for MessageProcessor { }) .collect::>(), native_loader: &self.native_loader, - is_cross_program_supported: self.is_cross_program_supported, - compute_budget: self.compute_budget, }; write!(f, "{:?}", processor) @@ -381,8 +373,6 @@ impl Default for MessageProcessor { programs: vec![], loaders: vec![], native_loader: NativeLoader::default(), - is_cross_program_supported: true, - compute_budget: ComputeBudget::default(), } } } @@ -392,7 +382,6 @@ impl Clone for MessageProcessor { programs: self.programs.clone(), loaders: self.loaders.clone(), native_loader: NativeLoader::default(), - ..*self } } } @@ -426,17 +415,20 @@ impl MessageProcessor { } } - pub fn set_cross_program_support(&mut self, is_supported: bool) { - self.is_cross_program_supported = is_supported; - } - - pub fn set_compute_budget(&mut self, compute_budget: ComputeBudget) { - self.compute_budget = compute_budget; - } - - #[cfg(test)] - pub fn get_cross_program_support(&mut self) -> bool { - self.is_cross_program_supported + fn get_compute_budget(feature_set: &FeatureSet) -> ComputeBudget { + if feature_set.is_active(&compute_budget_config2::id()) { + ComputeBudget::default() + } else { + // Original + ComputeBudget { + max_units: 100_000, + log_units: 0, + log_64_units: 0, + create_program_address_units: 0, + invoke_units: 0, + max_invoke_depth: 2, + } + } } /// Create the KeyedAccounts that will be passed to the program @@ -526,10 +518,6 @@ impl MessageProcessor { accounts: &[Rc>], invoke_context: &mut dyn InvokeContext, ) -> Result<(), InstructionError> { - if !self.is_cross_program_supported { - return Err(InstructionError::ReentrancyNotAllowed); - } - let instruction = &message.instructions[0]; // Verify the calling program hasn't misbehaved @@ -680,11 +668,11 @@ impl MessageProcessor { executors: Rc>, instruction_recorder: Option, instruction_index: usize, - feature_set: &FeatureSet, + feature_set: Arc, ) -> Result<(), InstructionError> { // Fixup the special instructions key if present // before the account pre-values are taken care of - if feature_set.is_active(&feature_set::instructions_sysvar_enabled::id()) { + if feature_set.is_active(&instructions_sysvar_enabled::id()) { for (i, key) in message.account_keys.iter().enumerate() { if solana_sdk::sysvar::instructions::check_id(key) { let mut mut_account_ref = accounts[i].borrow_mut(); @@ -704,10 +692,10 @@ impl MessageProcessor { pre_accounts, self.programs.clone(), // get rid of clone log_collector, - self.is_cross_program_supported, - self.compute_budget, + Self::get_compute_budget(&feature_set), executors, instruction_recorder, + feature_set, ); let keyed_accounts = Self::create_keyed_accounts(message, instruction, executable_accounts, accounts)?; @@ -736,7 +724,7 @@ impl MessageProcessor { log_collector: Option>, executors: Rc>, instruction_recorders: Option<&[InstructionRecorder]>, - feature_set: &FeatureSet, + feature_set: Arc, ) -> Result<(), TransactionError> { for (instruction_index, instruction) in message.instructions.iter().enumerate() { let instruction_recorder = instruction_recorders @@ -752,7 +740,7 @@ impl MessageProcessor { executors.clone(), instruction_recorder, instruction_index, - feature_set, + feature_set.clone(), ) .map_err(|err| TransactionError::InstructionError(instruction_index as u8, err))?; } @@ -797,10 +785,10 @@ mod tests { pre_accounts, vec![], None, - true, ComputeBudget::default(), Rc::new(RefCell::new(Executors::default())), None, + Arc::new(FeatureSet::default()), ); // Check call depth increases and has a limit @@ -1337,7 +1325,7 @@ mod tests { None, executors.clone(), None, - &FeatureSet::default(), + Arc::new(FeatureSet::default()), ); assert_eq!(result, Ok(())); assert_eq!(accounts[0].borrow().lamports, 100); @@ -1360,7 +1348,7 @@ mod tests { None, executors.clone(), None, - &FeatureSet::default(), + Arc::new(FeatureSet::default()), ); assert_eq!( result, @@ -1387,7 +1375,7 @@ mod tests { None, executors, None, - &FeatureSet::default(), + Arc::new(FeatureSet::default()), ); assert_eq!( result, @@ -1497,7 +1485,7 @@ mod tests { None, executors.clone(), None, - &FeatureSet::default(), + Arc::new(FeatureSet::default()), ); assert_eq!( result, @@ -1524,7 +1512,7 @@ mod tests { None, executors.clone(), None, - &FeatureSet::default(), + Arc::new(FeatureSet::default()), ); assert_eq!(result, Ok(())); @@ -1548,7 +1536,7 @@ mod tests { None, executors, None, - &FeatureSet::default(), + Arc::new(FeatureSet::default()), ); assert_eq!(result, Ok(())); assert_eq!(accounts[0].borrow().lamports, 80); @@ -1622,10 +1610,10 @@ mod tests { vec![owned_preaccount, not_owned_preaccount], vec![], None, - true, ComputeBudget::default(), Rc::new(RefCell::new(Executors::default())), None, + Arc::new(FeatureSet::default()), ); let metas = vec![ AccountMeta::new(owned_key, false), diff --git a/runtime/src/process_instruction.rs b/runtime/src/process_instruction.rs index d57945c8af..a15131fd7c 100644 --- a/runtime/src/process_instruction.rs +++ b/runtime/src/process_instruction.rs @@ -56,10 +56,8 @@ pub trait InvokeContext { fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)]; /// Get this invocation's logger fn get_logger(&self) -> Rc>; - /// Are cross program invocations supported - fn is_cross_program_supported(&self) -> bool; /// Get this invocation's compute budget - fn get_compute_budget(&self) -> ComputeBudget; + fn get_compute_budget(&self) -> &ComputeBudget; /// Get this invocation's compute meter fn get_compute_meter(&self) -> Rc>; /// Loaders may need to do work in order to execute a program. Cache @@ -69,6 +67,8 @@ pub trait InvokeContext { fn get_executor(&mut self, pubkey: &Pubkey) -> Option>; /// Record invoked instruction fn record_instruction(&self, instruction: &Instruction); + /// Get the bank's active feature set + fn is_feature_active(&self, feature_id: &Pubkey) -> bool; } #[derive(Clone, Copy, Debug)]