diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index ca6cfa7d3d..cf02a6e355 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -32,7 +32,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, @@ -196,24 +196,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() @@ -224,8 +206,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 d8803dfc6e..d5caeeadc6 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 ae37c58059..74bd839870 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 22b13bac6f..3af13d2e19 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 f951d29403..7cf44e0cad 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -1184,6 +1184,8 @@ pub struct Bank { vote_only_bank: bool, pub cost_tracker: RwLock, + + sysvar_cache: RwLock)>>, } impl Default for BlockhashQueue { @@ -1316,6 +1318,7 @@ impl Bank { bank.update_rent(); bank.update_epoch_schedule(); bank.update_recent_blockhashes(); + bank.fill_sysvar_cache(); bank } @@ -1456,6 +1459,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()); @@ -1497,6 +1501,7 @@ impl Bank { if !new.fix_recent_blockhashes_sysvar_delay() { new.update_recent_blockhashes(); } + new.fill_sysvar_cache(); time.stop(); @@ -1631,6 +1636,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, @@ -1806,6 +1812,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( @@ -1943,6 +1957,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() } @@ -3598,8 +3623,7 @@ impl Bank { bpf_compute_budget, compute_meter, &mut timings.details, - self.rc.accounts.clone(), - &self.ancestors, + &*self.sysvar_cache.read().unwrap(), ); transaction_log_messages.push(Self::collect_log_messages(log_collector)); diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index aabc1ac3f8..c4cc89404f 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}, @@ -371,6 +370,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>, @@ -378,10 +378,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)>, } @@ -395,14 +391,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( @@ -425,6 +420,7 @@ impl<'a> ThisInvokeContext<'a> { pre_accounts, accounts, programs, + sysvars, logger: Rc::new(RefCell::new(ThisLogger { log_collector })), bpf_compute_budget, compute_meter, @@ -432,9 +428,6 @@ impl<'a> ThisInvokeContext<'a> { instruction_recorder, feature_set, timings: ExecuteDetailsTimings::default(), - account_db, - ancestors, - sysvars: RefCell::new(vec![]), return_data: None, }; invoke_context @@ -607,25 +600,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; @@ -1298,6 +1274,7 @@ impl MessageProcessor { executable_accounts: &[TransactionAccountRefCell], accounts: &[TransactionAccountRefCell], rent_collector: &RentCollector, + sysvars: &[(Pubkey, Vec)], log_collector: Option>, executors: Rc>, instruction_recorder: Option, @@ -1306,8 +1283,6 @@ impl MessageProcessor { bpf_compute_budget: BpfComputeBudget, compute_meter: Rc>, timings: &mut ExecuteDetailsTimings, - account_db: Arc, - ancestors: &Ancestors, ) -> Result<(), InstructionError> { // Fixup the special instructions key if present // before the account pre-values are taken care of @@ -1349,14 +1324,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"); @@ -1411,8 +1385,7 @@ impl MessageProcessor { bpf_compute_budget: BpfComputeBudget, compute_meter: Rc>, timings: &mut ExecuteDetailsTimings, - account_db: Arc, - ancestors: &Ancestors, + sysvars: &[(Pubkey, Vec)], ) -> Result<(), TransactionError> { for (instruction_index, instruction) in message.instructions.iter().enumerate() { let instruction_recorder = instruction_recorders @@ -1425,6 +1398,7 @@ impl MessageProcessor { &loaders[instruction_index], accounts, rent_collector, + sysvars, log_collector.clone(), executors.clone(), instruction_recorder, @@ -1433,8 +1407,6 @@ impl MessageProcessor { bpf_compute_budget, compute_meter.clone(), timings, - account_db.clone(), - ancestors, ) .map_err(|err| TransactionError::InstructionError(instruction_index as u8, err)); @@ -1492,7 +1464,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(), @@ -1501,14 +1472,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 @@ -2092,7 +2062,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), @@ -2119,8 +2088,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!(result, Ok(())); assert_eq!(accounts[0].1.borrow().lamports(), 100); @@ -2147,8 +2115,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!( result, @@ -2179,8 +2146,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!( result, @@ -2274,7 +2240,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), @@ -2303,8 +2268,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!( result, @@ -2335,8 +2299,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!(result, Ok(())); @@ -2352,7 +2315,6 @@ mod tests { )], Some(&accounts[0].0), ); - let ancestors = Ancestors::default(); let result = message_processor.process_message( &message, &loaders, @@ -2365,8 +2327,7 @@ mod tests { BpfComputeBudget::new(), Rc::new(RefCell::new(MockComputeMeter::default())), &mut ExecuteDetailsTimings::default(), - Arc::new(Accounts::default()), - &ancestors, + &[], ); assert_eq!(result, Ok(())); assert_eq!(accounts[0].1.borrow().lamports(), 80); @@ -2467,7 +2428,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(), @@ -2476,14 +2436,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) @@ -2538,7 +2497,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(), @@ -2547,14 +2505,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 @@ -2691,7 +2648,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(), @@ -2700,14 +2656,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 @@ -2758,7 +2713,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(), @@ -2767,14 +2721,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 f6a539a373..0d6ea40dc6 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 d479c93231..18823ced01 100644 --- a/sdk/src/process_instruction.rs +++ b/sdk/src/process_instruction.rs @@ -103,8 +103,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 @@ -145,15 +145,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)] @@ -386,7 +391,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)>, } @@ -417,21 +422,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, @@ -519,10 +509,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;