diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index f4f06771af05a7..ca66f0d6f337a5 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -33,7 +33,7 @@ use { native_token::sol_to_lamports, poh_config::PohConfig, process_instruction::{ - stable_log, BpfComputeBudget, InvokeContext, ProcessInstructionWithContext, + self, stable_log, BpfComputeBudget, InvokeContext, ProcessInstructionWithContext, }, program_error::{ProgramError, ACCOUNT_BORROW_FAILED, UNSUPPORTED_SYSVAR}, pubkey::Pubkey, @@ -197,24 +197,6 @@ fn get_sysvar( var_addr: *mut u8, ) -> u64 { let invoke_context = get_invoke_context(); - - let sysvar_data = match invoke_context.get_sysvar_data(id).ok_or_else(|| { - ic_msg!(invoke_context, "Unable to get Sysvar {}", id); - UNSUPPORTED_SYSVAR - }) { - Ok(sysvar_data) => sysvar_data, - Err(err) => return err, - }; - - let var: T = match bincode::deserialize(&sysvar_data) { - Ok(sysvar_data) => sysvar_data, - Err(_) => return UNSUPPORTED_SYSVAR, - }; - - unsafe { - *(var_addr as *mut _ as *mut T) = var; - } - if invoke_context .get_compute_meter() .try_borrow_mut() @@ -225,8 +207,13 @@ fn get_sysvar( { panic!("Exceeded compute budget"); } - - SUCCESS + match process_instruction::get_sysvar::(invoke_context, id) { + Ok(sysvar_data) => unsafe { + *(var_addr as *mut _ as *mut T) = sysvar_data; + SUCCESS + }, + Err(_) => UNSUPPORTED_SYSVAR, + } } struct SyscallStubs {} diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index d8803dfc6e7ce7..d5caeeadc694c1 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -3650,9 +3650,7 @@ mod tests { let mut invoke_context = MockInvokeContext::new(vec![]); let mut data = vec![]; bincode::serialize_into(&mut data, &src_clock).unwrap(); - invoke_context - .sysvars - .push((sysvar::clock::id(), Some(Rc::new(data)))); + invoke_context.sysvars = vec![(sysvar::clock::id(), data)]; let mut syscall = SyscallGetClockSysvar { invoke_context: Rc::new(RefCell::new(&mut invoke_context)), @@ -3695,9 +3693,7 @@ mod tests { let mut invoke_context = MockInvokeContext::new(vec![]); let mut data = vec![]; bincode::serialize_into(&mut data, &src_epochschedule).unwrap(); - invoke_context - .sysvars - .push((sysvar::epoch_schedule::id(), Some(Rc::new(data)))); + invoke_context.sysvars = vec![(sysvar::epoch_schedule::id(), data)]; let mut syscall = SyscallGetEpochScheduleSysvar { invoke_context: Rc::new(RefCell::new(&mut invoke_context)), @@ -3746,9 +3742,7 @@ mod tests { let mut invoke_context = MockInvokeContext::new(vec![]); let mut data = vec![]; bincode::serialize_into(&mut data, &src_fees).unwrap(); - invoke_context - .sysvars - .push((sysvar::fees::id(), Some(Rc::new(data)))); + invoke_context.sysvars = vec![(sysvar::fees::id(), data)]; let mut syscall = SyscallGetFeesSysvar { invoke_context: Rc::new(RefCell::new(&mut invoke_context)), @@ -3789,9 +3783,7 @@ mod tests { let mut invoke_context = MockInvokeContext::new(vec![]); let mut data = vec![]; bincode::serialize_into(&mut data, &src_rent).unwrap(); - invoke_context - .sysvars - .push((sysvar::rent::id(), Some(Rc::new(data)))); + invoke_context.sysvars = vec![(sysvar::rent::id(), data)]; let mut syscall = SyscallGetRentSysvar { invoke_context: Rc::new(RefCell::new(&mut invoke_context)), diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index ae37c58059673e..74bd8398706b27 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -281,16 +281,16 @@ mod tests { account::{self, Account, AccountSharedData, WritableAccount}, instruction::{AccountMeta, Instruction}, keyed_account::KeyedAccount, - process_instruction::{mock_set_sysvar, MockInvokeContext}, + process_instruction::MockInvokeContext, rent::Rent, stake::{ config as stake_config, instruction::{self, LockupArgs}, state::{Authorized, Lockup, StakeAuthorize}, }, - sysvar::stake_history::StakeHistory, + sysvar::{stake_history::StakeHistory, Sysvar}, }, - std::{cell::RefCell, rc::Rc, str::FromStr}, + std::{cell::RefCell, str::FromStr}, }; fn create_default_account() -> RefCell { @@ -370,12 +370,9 @@ mod tests { .collect(); let mut invoke_context = MockInvokeContext::new(keyed_accounts); - mock_set_sysvar( - &mut invoke_context, - sysvar::clock::id(), - sysvar::clock::Clock::default(), - ) - .unwrap(); + let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of()); + bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap(); + invoke_context.sysvars = vec![(sysvar::clock::id(), data)]; super::process_instruction(&Pubkey::default(), &instruction.data, &mut invoke_context) } } @@ -1038,12 +1035,9 @@ mod tests { ]; let mut invoke_context = MockInvokeContext::new(keyed_accounts); - let clock = Clock::default(); - let mut data = vec![]; - bincode::serialize_into(&mut data, &clock).unwrap(); - invoke_context - .sysvars - .push((sysvar::clock::id(), Some(Rc::new(data)))); + let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of()); + bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap(); + invoke_context.sysvars = vec![(sysvar::clock::id(), data)]; assert_eq!( super::process_instruction( diff --git a/programs/vote/src/vote_instruction.rs b/programs/vote/src/vote_instruction.rs index 22b13bac6f1ea7..3af13d2e198710 100644 --- a/programs/vote/src/vote_instruction.rs +++ b/programs/vote/src/vote_instruction.rs @@ -402,8 +402,9 @@ mod tests { bincode::serialize, solana_sdk::{ account::{self, Account, AccountSharedData}, - process_instruction::{mock_set_sysvar, MockInvokeContext}, + process_instruction::MockInvokeContext, rent::Rent, + sysvar::Sysvar, }, std::{cell::RefCell, str::FromStr}, }; @@ -462,12 +463,9 @@ mod tests { .map(|(meta, account)| KeyedAccount::new(&meta.pubkey, meta.is_signer, account)) .collect(); let mut invoke_context = MockInvokeContext::new(keyed_accounts); - mock_set_sysvar( - &mut invoke_context, - sysvar::rent::id(), - sysvar::rent::Rent::default(), - ) - .unwrap(); + let mut data = Vec::with_capacity(sysvar::rent::Rent::size_of()); + bincode::serialize_into(&mut data, &sysvar::rent::Rent::default()).unwrap(); + invoke_context.sysvars = vec![(sysvar::rent::id(), data)]; super::process_instruction(&Pubkey::default(), &instruction.data, &mut invoke_context) } } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 21a0d7c482bf50..fa26de78d01a20 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -1158,6 +1158,8 @@ pub struct Bank { vote_only_bank: bool, pub cost_tracker: RwLock, + + sysvar_cache: RwLock)>>, } impl Default for BlockhashQueue { @@ -1290,6 +1292,7 @@ impl Bank { bank.update_rent(); bank.update_epoch_schedule(); bank.update_recent_blockhashes(); + bank.fill_sysvar_cache(); bank } @@ -1430,6 +1433,7 @@ impl Bank { )), freeze_started: AtomicBool::new(false), cost_tracker: RwLock::new(CostTracker::default()), + sysvar_cache: RwLock::new(Vec::new()), }; let mut ancestors = Vec::with_capacity(1 + new.parents().len()); @@ -1471,6 +1475,7 @@ impl Bank { if !new.fix_recent_blockhashes_sysvar_delay() { new.update_recent_blockhashes(); } + new.fill_sysvar_cache(); time.stop(); @@ -1605,6 +1610,7 @@ impl Bank { freeze_started: AtomicBool::new(fields.hash != Hash::default()), vote_only_bank: false, cost_tracker: RwLock::new(CostTracker::default()), + sysvar_cache: RwLock::new(Vec::new()), }; bank.finish_init( genesis_config, @@ -1780,6 +1786,14 @@ impl Bank { } self.store_account_and_update_capitalization(pubkey, &new_account); + + // Update the entry in the cache + let mut sysvar_cache = self.sysvar_cache.write().unwrap(); + if let Some(position) = sysvar_cache.iter().position(|(id, _data)| id == pubkey) { + sysvar_cache[position].1 = new_account.data().to_vec(); + } else { + sysvar_cache.push((*pubkey, new_account.data().to_vec())); + } } fn inherit_specially_retained_account_fields( @@ -1917,6 +1931,17 @@ impl Bank { }); } + fn fill_sysvar_cache(&mut self) { + let mut sysvar_cache = self.sysvar_cache.write().unwrap(); + for id in sysvar::ALL_IDS.iter() { + if !sysvar_cache.iter().any(|(key, _data)| key == id) { + if let Some(account) = self.get_account_with_fixed_root(id) { + sysvar_cache.push((*id, account.data().to_vec())); + } + } + } + } + pub fn get_slot_history(&self) -> SlotHistory { from_account(&self.get_account(&sysvar::slot_history::id()).unwrap()).unwrap() } @@ -3587,8 +3612,7 @@ impl Bank { bpf_compute_budget, compute_meter, timings, - self.rc.accounts.clone(), - &self.ancestors, + &*self.sysvar_cache.read().unwrap(), ); process_message_time.stop(); saturating_add_assign!( diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 9eee43e8ef2e06..2a77b9de86161e 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -1,8 +1,7 @@ use { crate::{ - accounts::Accounts, ancestors::Ancestors, bank::TransactionAccountRefCell, - instruction_recorder::InstructionRecorder, log_collector::LogCollector, - native_loader::NativeLoader, rent_collector::RentCollector, + bank::TransactionAccountRefCell, instruction_recorder::InstructionRecorder, + log_collector::LogCollector, native_loader::NativeLoader, rent_collector::RentCollector, }, log::*, serde::{Deserialize, Serialize}, @@ -278,6 +277,7 @@ pub struct ThisInvokeContext<'a> { pre_accounts: Vec, accounts: &'a [TransactionAccountRefCell], programs: &'a [(Pubkey, ProcessInstructionWithContext)], + sysvars: &'a [(Pubkey, Vec)], logger: Rc>, bpf_compute_budget: BpfComputeBudget, compute_meter: Rc>, @@ -285,10 +285,6 @@ pub struct ThisInvokeContext<'a> { instruction_recorder: Option, feature_set: Arc, pub timings: ExecuteDetailsTimings, - account_db: Arc, - ancestors: &'a Ancestors, - #[allow(clippy::type_complexity)] - sysvars: RefCell>>)>>, // return data and program_id that set it return_data: Option<(Pubkey, Vec)>, } @@ -302,14 +298,13 @@ impl<'a> ThisInvokeContext<'a> { executable_accounts: &'a [TransactionAccountRefCell], accounts: &'a [TransactionAccountRefCell], programs: &'a [(Pubkey, ProcessInstructionWithContext)], + sysvars: &'a [(Pubkey, Vec)], log_collector: Option>, bpf_compute_budget: BpfComputeBudget, compute_meter: Rc>, executors: Rc>, instruction_recorder: Option, feature_set: Arc, - account_db: Arc, - ancestors: &'a Ancestors, ) -> Self { let pre_accounts = MessageProcessor::create_pre_accounts(message, instruction, accounts); let keyed_accounts = MessageProcessor::create_keyed_accounts( @@ -332,6 +327,7 @@ impl<'a> ThisInvokeContext<'a> { pre_accounts, accounts, programs, + sysvars, logger: Rc::new(RefCell::new(ThisLogger { log_collector })), bpf_compute_budget, compute_meter, @@ -339,9 +335,6 @@ impl<'a> ThisInvokeContext<'a> { instruction_recorder, feature_set, timings: ExecuteDetailsTimings::default(), - account_db, - ancestors, - sysvars: RefCell::new(vec![]), return_data: None, }; invoke_context @@ -514,25 +507,8 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> { self.timings.execute_us += execute_us; self.timings.deserialize_us += deserialize_us; } - fn get_sysvar_data(&self, id: &Pubkey) -> Option>> { - if let Ok(mut sysvars) = self.sysvars.try_borrow_mut() { - // Try share from cache - let mut result = sysvars - .iter() - .find_map(|(key, sysvar)| if id == key { sysvar.clone() } else { None }); - if result.is_none() { - // Load it - result = self - .account_db - .load_with_fixed_root(self.ancestors, id) - .map(|(account, _)| Rc::new(account.data().to_vec())); - // Cache it - sysvars.push((*id, result.clone())); - } - result - } else { - None - } + fn get_sysvars(&self) -> &[(Pubkey, Vec)] { + self.sysvars } fn set_return_data(&mut self, return_data: Option<(Pubkey, Vec)>) { self.return_data = return_data; @@ -1208,6 +1184,7 @@ impl MessageProcessor { executable_accounts: &[TransactionAccountRefCell], accounts: &[TransactionAccountRefCell], rent_collector: &RentCollector, + sysvars: &[(Pubkey, Vec)], log_collector: Option>, executors: Rc>, instruction_recorder: Option, @@ -1216,8 +1193,6 @@ impl MessageProcessor { bpf_compute_budget: BpfComputeBudget, compute_meter: Rc>, timings: &mut ExecuteTimings, - account_db: Arc, - ancestors: &Ancestors, ) -> Result<(), InstructionError> { // Fixup the special instructions key if present // before the account pre-values are taken care of @@ -1259,14 +1234,13 @@ impl MessageProcessor { executable_accounts, accounts, &self.programs, + sysvars, log_collector, bpf_compute_budget, compute_meter, executors, instruction_recorder, feature_set, - account_db, - ancestors, ); let pre_remaining_units = invoke_context.get_compute_meter().borrow().get_remaining(); let mut time = Measure::start("execute_instruction"); @@ -1325,8 +1299,7 @@ impl MessageProcessor { bpf_compute_budget: BpfComputeBudget, compute_meter: Rc>, timings: &mut ExecuteTimings, - account_db: Arc, - ancestors: &Ancestors, + sysvars: &[(Pubkey, Vec)], ) -> Result<(), TransactionError> { for (instruction_index, instruction) in message.instructions.iter().enumerate() { let instruction_recorder = instruction_recorders @@ -1339,6 +1312,7 @@ impl MessageProcessor { &loaders[instruction_index], accounts, rent_collector, + sysvars, log_collector.clone(), executors.clone(), instruction_recorder, @@ -1347,8 +1321,6 @@ impl MessageProcessor { bpf_compute_budget, compute_meter.clone(), timings, - account_db.clone(), - ancestors, ) .map_err(|err| TransactionError::InstructionError(instruction_index as u8, err)); @@ -1406,7 +1378,6 @@ mod tests { &[Instruction::new_with_bytes(invoke_stack[0], &[0], metas)], None, ); - let ancestors = Ancestors::default(); let mut invoke_context = ThisInvokeContext::new( &invoke_stack[0], Rent::default(), @@ -1415,14 +1386,13 @@ mod tests { &[], &accounts, &[], + &[], None, BpfComputeBudget::default(), Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(Executors::default())), None, Arc::new(FeatureSet::all_enabled()), - Arc::new(Accounts::default()), - &ancestors, ); // Check call depth increases and has a limit @@ -2006,7 +1976,6 @@ mod tests { let loaders = vec![vec![(mock_system_program_id, account)]]; let executors = Rc::new(RefCell::new(Executors::default())); - let ancestors = Ancestors::default(); let account_metas = vec![ AccountMeta::new(accounts[0].0, true), @@ -2033,8 +2002,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!(result, Ok(())); assert_eq!(accounts[0].1.borrow().lamports(), 100); @@ -2061,8 +2029,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!( result, @@ -2093,8 +2060,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!( result, @@ -2188,7 +2154,6 @@ mod tests { let loaders = vec![vec![(mock_program_id, account)]]; let executors = Rc::new(RefCell::new(Executors::default())); - let ancestors = Ancestors::default(); let account_metas = vec![ AccountMeta::new(accounts[0].0, true), @@ -2217,8 +2182,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!( result, @@ -2249,8 +2213,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!(result, Ok(())); @@ -2266,7 +2229,6 @@ mod tests { )], Some(&accounts[0].0), ); - let ancestors = Ancestors::default(); let result = message_processor.process_message( &message, &loaders, @@ -2279,8 +2241,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!(result, Ok(())); assert_eq!(accounts[0].1.borrow().lamports(), 80); @@ -2381,7 +2342,6 @@ mod tests { let feature_set = FeatureSet::all_enabled(); let demote_program_write_locks = feature_set.is_active(&demote_program_write_locks::id()); - let ancestors = Ancestors::default(); let mut invoke_context = ThisInvokeContext::new( &caller_program_id, Rent::default(), @@ -2390,14 +2350,13 @@ mod tests { &executable_accounts, &accounts, programs.as_slice(), + &[], None, BpfComputeBudget::default(), Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(Executors::default())), None, Arc::new(feature_set), - Arc::new(Accounts::default()), - &ancestors, ); // not owned account modified by the caller (before the invoke) @@ -2452,7 +2411,6 @@ mod tests { Instruction::new_with_bincode(callee_program_id, &case.0, metas.clone()); let message = Message::new(&[callee_instruction], None); - let ancestors = Ancestors::default(); let mut invoke_context = ThisInvokeContext::new( &caller_program_id, Rent::default(), @@ -2461,14 +2419,13 @@ mod tests { &executable_accounts, &accounts, programs.as_slice(), + &[], None, BpfComputeBudget::default(), Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(Executors::default())), None, Arc::new(FeatureSet::all_enabled()), - Arc::new(Accounts::default()), - &ancestors, ); let caller_write_privileges = message @@ -2605,7 +2562,6 @@ mod tests { ); let message = Message::new(&[callee_instruction.clone()], None); - let ancestors = Ancestors::default(); let mut invoke_context = ThisInvokeContext::new( &caller_program_id, Rent::default(), @@ -2614,14 +2570,13 @@ mod tests { &executable_accounts, &accounts, programs.as_slice(), + &[], None, BpfComputeBudget::default(), Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(Executors::default())), None, Arc::new(FeatureSet::all_enabled()), - Arc::new(Accounts::default()), - &ancestors, ); // not owned account modified by the invoker @@ -2672,7 +2627,6 @@ mod tests { Instruction::new_with_bincode(callee_program_id, &case.0, metas.clone()); let message = Message::new(&[callee_instruction.clone()], None); - let ancestors = Ancestors::default(); let mut invoke_context = ThisInvokeContext::new( &caller_program_id, Rent::default(), @@ -2681,14 +2635,13 @@ mod tests { &executable_accounts, &accounts, programs.as_slice(), + &[], None, BpfComputeBudget::default(), Rc::new(RefCell::new(MockComputeMeter::default())), Rc::new(RefCell::new(Executors::default())), None, Arc::new(FeatureSet::all_enabled()), - Arc::new(Accounts::default()), - &ancestors, ); assert_eq!( diff --git a/sdk/program/src/sysvar/mod.rs b/sdk/program/src/sysvar/mod.rs index f6a539a373d1d5..0d6ea40dc6391d 100644 --- a/sdk/program/src/sysvar/mod.rs +++ b/sdk/program/src/sysvar/mod.rs @@ -1,6 +1,7 @@ //! named accounts for synthesized data accounts for bank state, etc. //! use crate::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; +use lazy_static::lazy_static; pub mod clock; pub mod epoch_schedule; @@ -13,17 +14,25 @@ pub mod slot_hashes; pub mod slot_history; pub mod stake_history; +lazy_static! { + pub static ref ALL_IDS: Vec = vec![ + clock::id(), + epoch_schedule::id(), + #[allow(deprecated)] + fees::id(), + #[allow(deprecated)] + recent_blockhashes::id(), + rent::id(), + rewards::id(), + slot_hashes::id(), + slot_history::id(), + stake_history::id(), + instructions::id(), + ]; +} + pub fn is_sysvar_id(id: &Pubkey) -> bool { - clock::check_id(id) - || epoch_schedule::check_id(id) - || fees::check_id(id) - || recent_blockhashes::check_id(id) - || rent::check_id(id) - || rewards::check_id(id) - || slot_hashes::check_id(id) - || slot_history::check_id(id) - || stake_history::check_id(id) - || instructions::check_id(id) + ALL_IDS.iter().any(|key| key == id) } #[macro_export] diff --git a/sdk/src/process_instruction.rs b/sdk/src/process_instruction.rs index 98c029be6af785..b39cfd552bcd19 100644 --- a/sdk/src/process_instruction.rs +++ b/sdk/src/process_instruction.rs @@ -104,8 +104,8 @@ pub trait InvokeContext { execute_us: u64, deserialize_us: u64, ); - /// Get sysvar data - fn get_sysvar_data(&self, id: &Pubkey) -> Option>>; + /// Get sysvars + fn get_sysvars(&self) -> &[(Pubkey, Vec)]; /// Set the return data fn set_return_data(&mut self, return_data: Option<(Pubkey, Vec)>); /// Get the return data @@ -148,15 +148,20 @@ pub fn get_sysvar( invoke_context: &dyn InvokeContext, id: &Pubkey, ) -> Result { - let sysvar_data = invoke_context.get_sysvar_data(id).ok_or_else(|| { - ic_msg!(invoke_context, "Unable to get sysvar {}", id); - InstructionError::UnsupportedSysvar - })?; - - bincode::deserialize(&sysvar_data).map_err(|err| { - ic_msg!(invoke_context, "Unable to get sysvar {}: {:?}", id, err); - InstructionError::UnsupportedSysvar - }) + invoke_context + .get_sysvars() + .iter() + .find_map(|(key, data)| { + if id == key { + bincode::deserialize(data).ok() + } else { + None + } + }) + .ok_or_else(|| { + ic_msg!(invoke_context, "Unable to get sysvar {}", id); + InstructionError::UnsupportedSysvar + }) } #[derive(Clone, Copy, Debug, AbiExample, PartialEq)] @@ -389,7 +394,7 @@ pub struct MockInvokeContext<'a> { pub compute_meter: MockComputeMeter, pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>, pub accounts: Vec<(Pubkey, Rc>)>, - pub sysvars: Vec<(Pubkey, Option>>)>, + pub sysvars: Vec<(Pubkey, Vec)>, pub disabled_features: HashSet, pub return_data: Option<(Pubkey, Vec)>, pub execute_timings: ExecuteDetailsTimings, @@ -422,21 +427,6 @@ impl<'a> MockInvokeContext<'a> { } } -pub fn mock_set_sysvar( - mock_invoke_context: &mut MockInvokeContext, - id: Pubkey, - sysvar: T, -) -> Result<(), InstructionError> { - let mut data = Vec::with_capacity(T::size_of()); - - bincode::serialize_into(&mut data, &sysvar).map_err(|err| { - ic_msg!(mock_invoke_context, "Unable to serialize sysvar: {:?}", err); - InstructionError::GenericError - })?; - mock_invoke_context.sysvars.push((id, Some(Rc::new(data)))); - Ok(()) -} - impl<'a> InvokeContext for MockInvokeContext<'a> { fn push( &mut self, @@ -524,10 +514,8 @@ impl<'a> InvokeContext for MockInvokeContext<'a> { _deserialize_us: u64, ) { } - fn get_sysvar_data(&self, id: &Pubkey) -> Option>> { - self.sysvars - .iter() - .find_map(|(key, sysvar)| if id == key { sysvar.clone() } else { None }) + fn get_sysvars(&self) -> &[(Pubkey, Vec)] { + &self.sysvars } fn set_return_data(&mut self, return_data: Option<(Pubkey, Vec)>) { self.return_data = return_data;