Stop caching sysvars, instead load them ahead of time. (#21108)

This commit is contained in:
Alexander Meißner 2021-11-04 09:48:34 +01:00 committed by GitHub
parent 692cd5a2f8
commit 29ad081555
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 105 additions and 126 deletions

View File

@ -1400,9 +1400,9 @@ fn assert_instruction_count() {
("solana_bpf_rust_noop", 480), ("solana_bpf_rust_noop", 480),
("solana_bpf_rust_param_passing", 146), ("solana_bpf_rust_param_passing", 146),
("solana_bpf_rust_rand", 487), ("solana_bpf_rust_rand", 487),
("solana_bpf_rust_sanity", 8406), ("solana_bpf_rust_sanity", 8454),
("solana_bpf_rust_secp256k1_recover", 25216), ("solana_bpf_rust_secp256k1_recover", 25216),
("solana_bpf_rust_sha", 30704), ("solana_bpf_rust_sha", 30692),
]); ]);
} }

View File

@ -3284,10 +3284,8 @@ mod tests {
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]); let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
let mut data = vec![]; let mut data = vec![];
bincode::serialize_into(&mut data, &src_clock).unwrap(); bincode::serialize_into(&mut data, &src_clock).unwrap();
invoke_context let sysvars = &[(sysvar::clock::id(), data)];
.get_sysvars() invoke_context.sysvars = sysvars;
.borrow_mut()
.push((sysvar::clock::id(), Some(Rc::new(data))));
let mut syscall = SyscallGetClockSysvar { let mut syscall = SyscallGetClockSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)), invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
@ -3330,10 +3328,8 @@ mod tests {
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]); let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
let mut data = vec![]; let mut data = vec![];
bincode::serialize_into(&mut data, &src_epochschedule).unwrap(); bincode::serialize_into(&mut data, &src_epochschedule).unwrap();
invoke_context let sysvars = &[(sysvar::epoch_schedule::id(), data)];
.get_sysvars() invoke_context.sysvars = sysvars;
.borrow_mut()
.push((sysvar::epoch_schedule::id(), Some(Rc::new(data))));
let mut syscall = SyscallGetEpochScheduleSysvar { let mut syscall = SyscallGetEpochScheduleSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)), invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
@ -3383,10 +3379,8 @@ mod tests {
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]); let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
let mut data = vec![]; let mut data = vec![];
bincode::serialize_into(&mut data, &src_fees).unwrap(); bincode::serialize_into(&mut data, &src_fees).unwrap();
invoke_context let sysvars = &[(sysvar::fees::id(), data)];
.get_sysvars() invoke_context.sysvars = sysvars;
.borrow_mut()
.push((sysvar::fees::id(), Some(Rc::new(data))));
let mut syscall = SyscallGetFeesSysvar { let mut syscall = SyscallGetFeesSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)), invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
@ -3427,10 +3421,8 @@ mod tests {
let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]); let mut invoke_context = MockInvokeContext::new(&Pubkey::default(), vec![]);
let mut data = vec![]; let mut data = vec![];
bincode::serialize_into(&mut data, &src_rent).unwrap(); bincode::serialize_into(&mut data, &src_rent).unwrap();
invoke_context let sysvars = &[(sysvar::rent::id(), data)];
.get_sysvars() invoke_context.sysvars = sysvars;
.borrow_mut()
.push((sysvar::rent::id(), Some(Rc::new(data))));
let mut syscall = SyscallGetRentSysvar { let mut syscall = SyscallGetRentSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)), invoke_context: Rc::new(RefCell::new(&mut invoke_context)),

View File

@ -340,7 +340,7 @@ mod tests {
}, },
sysvar::{stake_history::StakeHistory, Sysvar}, sysvar::{stake_history::StakeHistory, Sysvar},
}; };
use std::{cell::RefCell, rc::Rc, str::FromStr}; use std::{cell::RefCell, str::FromStr};
fn create_default_account() -> RefCell<AccountSharedData> { fn create_default_account() -> RefCell<AccountSharedData> {
RefCell::new(AccountSharedData::default()) RefCell::new(AccountSharedData::default())
@ -444,10 +444,8 @@ mod tests {
); );
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of()); let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap(); bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
invoke_context let sysvars = &[(sysvar::clock::id(), data)];
.get_sysvars() invoke_context.sysvars = sysvars;
.borrow_mut()
.push((sysvar::clock::id(), Some(Rc::new(data))));
super::process_instruction(1, &instruction.data, &mut invoke_context) super::process_instruction(1, &instruction.data, &mut invoke_context)
} }
} }
@ -1102,10 +1100,8 @@ mod tests {
MockInvokeContext::new(&id(), create_keyed_accounts_unified(&keyed_accounts)); MockInvokeContext::new(&id(), create_keyed_accounts_unified(&keyed_accounts));
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of()); let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap(); bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
invoke_context let sysvars = &[(sysvar::clock::id(), data)];
.get_sysvars() invoke_context.sysvars = sysvars;
.borrow_mut()
.push((sysvar::clock::id(), Some(Rc::new(data))));
assert_eq!( assert_eq!(
super::process_instruction( super::process_instruction(

View File

@ -1006,6 +1006,8 @@ pub struct Bank {
vote_only_bank: bool, vote_only_bank: bool,
pub cost_tracker: RwLock<CostTracker>, pub cost_tracker: RwLock<CostTracker>,
sysvar_cache: RwLock<Vec<(Pubkey, Vec<u8>)>>,
} }
impl Default for BlockhashQueue { impl Default for BlockhashQueue {
@ -1145,6 +1147,7 @@ impl Bank {
freeze_started: AtomicBool::default(), freeze_started: AtomicBool::default(),
vote_only_bank: false, vote_only_bank: false,
cost_tracker: RwLock::<CostTracker>::default(), cost_tracker: RwLock::<CostTracker>::default(),
sysvar_cache: RwLock::new(Vec::new()),
} }
} }
@ -1254,6 +1257,7 @@ impl Bank {
bank.update_rent(); bank.update_rent();
bank.update_epoch_schedule(); bank.update_epoch_schedule();
bank.update_recent_blockhashes(); bank.update_recent_blockhashes();
bank.fill_sysvar_cache();
bank bank
} }
@ -1402,6 +1406,7 @@ impl Bank {
)), )),
freeze_started: AtomicBool::new(false), freeze_started: AtomicBool::new(false),
cost_tracker: RwLock::new(CostTracker::default()), cost_tracker: RwLock::new(CostTracker::default()),
sysvar_cache: RwLock::new(Vec::new()),
}; };
datapoint_info!( datapoint_info!(
@ -1458,6 +1463,7 @@ impl Bank {
new.update_stake_history(Some(parent_epoch)); new.update_stake_history(Some(parent_epoch));
new.update_clock(Some(parent_epoch)); new.update_clock(Some(parent_epoch));
new.update_fees(); new.update_fees();
new.fill_sysvar_cache();
return new; return new;
} }
@ -1473,6 +1479,7 @@ impl Bank {
new.update_stake_history(Some(parent_epoch)); new.update_stake_history(Some(parent_epoch));
new.update_clock(Some(parent_epoch)); new.update_clock(Some(parent_epoch));
new.update_fees(); new.update_fees();
new.fill_sysvar_cache();
new new
} }
@ -1589,6 +1596,7 @@ impl Bank {
freeze_started: AtomicBool::new(fields.hash != Hash::default()), freeze_started: AtomicBool::new(fields.hash != Hash::default()),
vote_only_bank: false, vote_only_bank: false,
cost_tracker: RwLock::new(CostTracker::default()), cost_tracker: RwLock::new(CostTracker::default()),
sysvar_cache: RwLock::new(Vec::new()),
}; };
bank.finish_init( bank.finish_init(
genesis_config, genesis_config,
@ -1767,6 +1775,14 @@ impl Bank {
} }
self.store_account_and_update_capitalization(pubkey, &new_account); 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( fn inherit_specially_retained_account_fields(
@ -1904,6 +1920,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 { pub fn get_slot_history(&self) -> SlotHistory {
from_account(&self.get_account(&sysvar::slot_history::id()).unwrap()).unwrap() from_account(&self.get_account(&sysvar::slot_history::id()).unwrap()).unwrap()
} }
@ -3858,8 +3885,7 @@ impl Bank {
compute_budget, compute_budget,
compute_meter, compute_meter,
&mut timings.details, &mut timings.details,
self.rc.accounts.clone(), &*self.sysvar_cache.read().unwrap(),
&self.ancestors,
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
); );

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
accounts::Accounts, ancestors::Ancestors, instruction_recorder::InstructionRecorder, instruction_recorder::InstructionRecorder, log_collector::LogCollector,
log_collector::LogCollector, rent_collector::RentCollector, rent_collector::RentCollector,
}; };
use log::*; use log::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -80,6 +80,7 @@ pub struct ThisInvokeContext<'a> {
pre_accounts: Vec<PreAccount>, pre_accounts: Vec<PreAccount>,
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)], accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
programs: &'a [(Pubkey, ProcessInstructionWithContext)], programs: &'a [(Pubkey, ProcessInstructionWithContext)],
sysvars: &'a [(Pubkey, Vec<u8>)],
logger: Rc<RefCell<dyn Logger>>, logger: Rc<RefCell<dyn Logger>>,
compute_budget: ComputeBudget, compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
@ -87,10 +88,6 @@ pub struct ThisInvokeContext<'a> {
instruction_recorders: Option<&'a [InstructionRecorder]>, instruction_recorders: Option<&'a [InstructionRecorder]>,
feature_set: Arc<FeatureSet>, feature_set: Arc<FeatureSet>,
pub timings: ExecuteDetailsTimings, pub timings: ExecuteDetailsTimings,
account_db: Arc<Accounts>,
ancestors: Option<&'a Ancestors>,
#[allow(clippy::type_complexity)]
sysvars: RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>>,
blockhash: Hash, blockhash: Hash,
lamports_per_signature: u64, lamports_per_signature: u64,
return_data: (Pubkey, Vec<u8>), return_data: (Pubkey, Vec<u8>),
@ -101,14 +98,13 @@ impl<'a> ThisInvokeContext<'a> {
rent: Rent, rent: Rent,
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)], accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
programs: &'a [(Pubkey, ProcessInstructionWithContext)], programs: &'a [(Pubkey, ProcessInstructionWithContext)],
sysvars: &'a [(Pubkey, Vec<u8>)],
log_collector: Option<Rc<LogCollector>>, log_collector: Option<Rc<LogCollector>>,
compute_budget: ComputeBudget, compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
executors: Rc<RefCell<Executors>>, executors: Rc<RefCell<Executors>>,
instruction_recorders: Option<&'a [InstructionRecorder]>, instruction_recorders: Option<&'a [InstructionRecorder]>,
feature_set: Arc<FeatureSet>, feature_set: Arc<FeatureSet>,
account_db: Arc<Accounts>,
ancestors: Option<&'a Ancestors>,
blockhash: Hash, blockhash: Hash,
lamports_per_signature: u64, lamports_per_signature: u64,
) -> Self { ) -> Self {
@ -119,6 +115,7 @@ impl<'a> ThisInvokeContext<'a> {
pre_accounts: Vec::new(), pre_accounts: Vec::new(),
accounts, accounts,
programs, programs,
sysvars,
logger: ThisLogger::new_ref(log_collector), logger: ThisLogger::new_ref(log_collector),
compute_budget, compute_budget,
compute_meter, compute_meter,
@ -126,32 +123,29 @@ impl<'a> ThisInvokeContext<'a> {
instruction_recorders, instruction_recorders,
feature_set, feature_set,
timings: ExecuteDetailsTimings::default(), timings: ExecuteDetailsTimings::default(),
account_db,
ancestors,
sysvars: RefCell::new(Vec::new()),
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
return_data: (Pubkey::default(), Vec::new()), return_data: (Pubkey::default(), Vec::new()),
} }
} }
pub fn new_mock_with_features( pub fn new_mock_with_sysvars_and_features(
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)], accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
programs: &'a [(Pubkey, ProcessInstructionWithContext)], programs: &'a [(Pubkey, ProcessInstructionWithContext)],
sysvars: &'a [(Pubkey, Vec<u8>)],
feature_set: Arc<FeatureSet>, feature_set: Arc<FeatureSet>,
) -> Self { ) -> Self {
Self::new( Self::new(
Rent::default(), Rent::default(),
accounts, accounts,
programs, programs,
sysvars,
None, None,
ComputeBudget::default(), ComputeBudget::default(),
ThisComputeMeter::new_ref(std::i64::MAX as u64), ThisComputeMeter::new_ref(std::i64::MAX as u64),
Rc::new(RefCell::new(Executors::default())), Rc::new(RefCell::new(Executors::default())),
None, None,
feature_set, feature_set,
Arc::new(Accounts::default_for_tests()),
None,
Hash::default(), Hash::default(),
0, 0,
) )
@ -161,7 +155,12 @@ impl<'a> ThisInvokeContext<'a> {
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)], accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
programs: &'a [(Pubkey, ProcessInstructionWithContext)], programs: &'a [(Pubkey, ProcessInstructionWithContext)],
) -> Self { ) -> Self {
Self::new_mock_with_features(accounts, programs, Arc::new(FeatureSet::all_enabled())) Self::new_mock_with_sysvars_and_features(
accounts,
programs,
&[],
Arc::new(FeatureSet::all_enabled()),
)
} }
} }
impl<'a> InvokeContext for ThisInvokeContext<'a> { impl<'a> InvokeContext for ThisInvokeContext<'a> {
@ -452,31 +451,8 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
self.timings.execute_us += execute_us; self.timings.execute_us += execute_us;
self.timings.deserialize_us += deserialize_us; self.timings.deserialize_us += deserialize_us;
} }
#[allow(clippy::type_complexity)] fn get_sysvars(&self) -> &[(Pubkey, Vec<u8>)] {
fn get_sysvars(&self) -> &RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>> { self.sysvars
&self.sysvars
}
fn get_sysvar_data(&self, id: &Pubkey) -> Option<Rc<Vec<u8>>> {
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() {
if let Some(ancestors) = self.ancestors {
// Load it
result = self
.account_db
.load_with_fixed_root(ancestors, id)
.map(|(account, _)| Rc::new(account.data().to_vec()));
// Cache it
sysvars.push((*id, result.clone()));
}
}
result
} else {
None
}
} }
fn get_compute_budget(&self) -> &ComputeBudget { fn get_compute_budget(&self) -> &ComputeBudget {
&self.compute_budget &self.compute_budget
@ -604,7 +580,6 @@ impl MessageProcessor {
/// the call does not violate the bank's accounting rules. /// the call does not violate the bank's accounting rules.
/// The accounts are committed back to the bank only if every instruction succeeds. /// The accounts are committed back to the bank only if every instruction succeeds.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[allow(clippy::type_complexity)]
pub fn process_message( pub fn process_message(
instruction_processor: &InstructionProcessor, instruction_processor: &InstructionProcessor,
message: &Message, message: &Message,
@ -618,8 +593,7 @@ impl MessageProcessor {
compute_budget: ComputeBudget, compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
timings: &mut ExecuteDetailsTimings, timings: &mut ExecuteDetailsTimings,
account_db: Arc<Accounts>, sysvars: &[(Pubkey, Vec<u8>)],
ancestors: &Ancestors,
blockhash: Hash, blockhash: Hash,
lamports_per_signature: u64, lamports_per_signature: u64,
) -> Result<(), TransactionError> { ) -> Result<(), TransactionError> {
@ -627,14 +601,13 @@ impl MessageProcessor {
rent_collector.rent, rent_collector.rent,
accounts, accounts,
instruction_processor.programs(), instruction_processor.programs(),
sysvars,
log_collector, log_collector,
compute_budget, compute_budget,
compute_meter, compute_meter,
executors, executors,
instruction_recorders, instruction_recorders,
feature_set, feature_set,
account_db,
Some(ancestors),
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
); );
@ -979,7 +952,6 @@ mod tests {
let program_indices = vec![vec![2]]; let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default())); let executors = Rc::new(RefCell::new(Executors::default()));
let ancestors = Ancestors::default();
let account_metas = vec![ let account_metas = vec![
AccountMeta::new(accounts[0].0, true), AccountMeta::new(accounts[0].0, true),
@ -1007,8 +979,7 @@ mod tests {
ComputeBudget::new(), ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64), ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()), &[],
&ancestors,
Hash::default(), Hash::default(),
0, 0,
); );
@ -1038,8 +1009,7 @@ mod tests {
ComputeBudget::new(), ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64), ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()), &[],
&ancestors,
Hash::default(), Hash::default(),
0, 0,
); );
@ -1073,8 +1043,7 @@ mod tests {
ComputeBudget::new(), ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64), ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()), &[],
&ancestors,
Hash::default(), Hash::default(),
0, 0,
); );
@ -1188,7 +1157,6 @@ mod tests {
let program_indices = vec![vec![2]]; let program_indices = vec![vec![2]];
let executors = Rc::new(RefCell::new(Executors::default())); let executors = Rc::new(RefCell::new(Executors::default()));
let ancestors = Ancestors::default();
let account_metas = vec![ let account_metas = vec![
AccountMeta::new(accounts[0].0, true), AccountMeta::new(accounts[0].0, true),
@ -1218,8 +1186,7 @@ mod tests {
ComputeBudget::new(), ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64), ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()), &[],
&ancestors,
Hash::default(), Hash::default(),
0, 0,
); );
@ -1253,8 +1220,7 @@ mod tests {
ComputeBudget::new(), ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64), ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()), &[],
&ancestors,
Hash::default(), Hash::default(),
0, 0,
); );
@ -1272,7 +1238,6 @@ mod tests {
)], )],
Some(&accounts[0].0), Some(&accounts[0].0),
); );
let ancestors = Ancestors::default();
let result = MessageProcessor::process_message( let result = MessageProcessor::process_message(
&instruction_processor, &instruction_processor,
&message, &message,
@ -1286,8 +1251,7 @@ mod tests {
ComputeBudget::new(), ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64), ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()), &[],
&ancestors,
Hash::default(), Hash::default(),
0, 0,
); );
@ -1578,8 +1542,7 @@ mod tests {
ComputeBudget::new(), ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64), ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(), &mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()), &[],
&Ancestors::default(),
Hash::default(), Hash::default(),
0, 0,
); );

View File

@ -1,6 +1,7 @@
//! named accounts for synthesized data accounts for bank state, etc. //! named accounts for synthesized data accounts for bank state, etc.
//! //!
use crate::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; use crate::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey};
use lazy_static::lazy_static;
pub mod clock; pub mod clock;
pub mod epoch_schedule; pub mod epoch_schedule;
@ -13,18 +14,25 @@ pub mod slot_hashes;
pub mod slot_history; pub mod slot_history;
pub mod stake_history; pub mod stake_history;
#[allow(deprecated)] lazy_static! {
pub static ref ALL_IDS: Vec<Pubkey> = 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 { pub fn is_sysvar_id(id: &Pubkey) -> bool {
clock::check_id(id) ALL_IDS.iter().any(|key| key == 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)
} }
#[macro_export] #[macro_export]

View File

@ -121,10 +121,7 @@ pub trait InvokeContext {
deserialize_us: u64, deserialize_us: u64,
); );
/// Get sysvars /// Get sysvars
#[allow(clippy::type_complexity)] fn get_sysvars(&self) -> &[(Pubkey, Vec<u8>)];
fn get_sysvars(&self) -> &RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>>;
/// Get sysvar data
fn get_sysvar_data(&self, id: &Pubkey) -> Option<Rc<Vec<u8>>>;
/// Get this invocation's compute budget /// Get this invocation's compute budget
fn get_compute_budget(&self) -> &ComputeBudget; fn get_compute_budget(&self) -> &ComputeBudget;
/// Set this invocation's blockhash /// Set this invocation's blockhash
@ -175,15 +172,20 @@ pub fn get_sysvar<T: Sysvar>(
invoke_context: &dyn InvokeContext, invoke_context: &dyn InvokeContext,
id: &Pubkey, id: &Pubkey,
) -> Result<T, InstructionError> { ) -> Result<T, InstructionError> {
let sysvar_data = invoke_context.get_sysvar_data(id).ok_or_else(|| { invoke_context
ic_msg!(invoke_context, "Unable to get sysvar {}", id); .get_sysvars()
InstructionError::UnsupportedSysvar .iter()
})?; .find_map(|(key, data)| {
if id == key {
bincode::deserialize(&sysvar_data).map_err(|err| { bincode::deserialize(data).ok()
ic_msg!(invoke_context, "Unable to get sysvar {}: {:?}", id, err); } else {
InstructionError::UnsupportedSysvar None
}) }
})
.ok_or_else(|| {
ic_msg!(invoke_context, "Unable to get sysvar {}", id);
InstructionError::UnsupportedSysvar
})
} }
/// Compute meter /// Compute meter
@ -356,8 +358,7 @@ pub struct MockInvokeContext<'a> {
pub compute_meter: Rc<RefCell<dyn ComputeMeter>>, pub compute_meter: Rc<RefCell<dyn ComputeMeter>>,
pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>, pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>,
pub accounts: Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>, pub accounts: Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>,
#[allow(clippy::type_complexity)] pub sysvars: &'a [(Pubkey, Vec<u8>)],
pub sysvars: RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>>,
pub disabled_features: HashSet<Pubkey>, pub disabled_features: HashSet<Pubkey>,
pub blockhash: Hash, pub blockhash: Hash,
pub lamports_per_signature: u64, pub lamports_per_signature: u64,
@ -376,7 +377,7 @@ impl<'a> MockInvokeContext<'a> {
})), })),
programs: vec![], programs: vec![],
accounts: vec![], accounts: vec![],
sysvars: RefCell::new(Vec::new()), sysvars: &[],
disabled_features: HashSet::default(), disabled_features: HashSet::default(),
blockhash: Hash::default(), blockhash: Hash::default(),
lamports_per_signature: 0, lamports_per_signature: 0,
@ -490,15 +491,8 @@ impl<'a> InvokeContext for MockInvokeContext<'a> {
_deserialize_us: u64, _deserialize_us: u64,
) { ) {
} }
#[allow(clippy::type_complexity)] fn get_sysvars(&self) -> &[(Pubkey, Vec<u8>)] {
fn get_sysvars(&self) -> &RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>> {
&self.sysvars
}
fn get_sysvar_data(&self, id: &Pubkey) -> Option<Rc<Vec<u8>>> {
self.sysvars self.sysvars
.borrow()
.iter()
.find_map(|(key, sysvar)| if id == key { sysvar.clone() } else { None })
} }
fn get_compute_budget(&self) -> &ComputeBudget { fn get_compute_budget(&self) -> &ComputeBudget {
&self.compute_budget &self.compute_budget