Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions program-runtime/src/invoke_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use {
pubkey::Pubkey,
rent::Rent,
saturating_add_assign,
sysvar::Sysvar,
transaction_context::{InstructionAccount, TransactionAccount, TransactionContext},
},
std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc, sync::Arc},
Expand Down Expand Up @@ -988,21 +987,9 @@ impl<'a> InvokeContext<'a> {
&self.current_compute_budget
}

/// Get the value of a sysvar by its id
pub fn get_sysvar<T: Sysvar>(&self, id: &Pubkey) -> Result<T, InstructionError> {
self.sysvar_cache
.iter()
.find_map(|(key, data)| {
if id == key {
bincode::deserialize(data).ok()
} else {
None
}
})
.ok_or_else(|| {
ic_msg!(self, "Unable to get sysvar {}", id);
InstructionError::UnsupportedSysvar
})
/// Get cached sysvars
pub fn get_sysvar_cache(&self) -> &SysvarCache {
&self.sysvar_cache
}
}

Expand Down
78 changes: 60 additions & 18 deletions program-runtime/src/sysvar_cache.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#[allow(deprecated)]
use solana_sdk::sysvar::fees::Fees;
use {
solana_sdk::{
account::{AccountSharedData, ReadableAccount},
pubkey::Pubkey,
instruction::InstructionError,
sysvar::{
clock::Clock, epoch_schedule::EpochSchedule, rent::Rent, slot_hashes::SlotHashes,
},
},
std::ops::Deref,
std::sync::Arc,
};

#[cfg(RUSTC_WITH_SPECIALIZATION)]
Expand All @@ -15,25 +19,63 @@ impl ::solana_frozen_abi::abi_example::AbiExample for SysvarCache {
}

#[derive(Default, Clone, Debug)]
pub struct SysvarCache(Vec<(Pubkey, Vec<u8>)>);

impl Deref for SysvarCache {
type Target = Vec<(Pubkey, Vec<u8>)>;
fn deref(&self) -> &Self::Target {
&self.0
}
pub struct SysvarCache {
clock: Option<Arc<Clock>>,
epoch_schedule: Option<Arc<EpochSchedule>>,
#[allow(deprecated)]
fees: Option<Arc<Fees>>,
rent: Option<Arc<Rent>>,
slot_hashes: Option<Arc<SlotHashes>>,
}

impl SysvarCache {
pub fn push_entry(&mut self, pubkey: Pubkey, data: Vec<u8>) {
self.0.push((pubkey, data));
pub fn get_clock(&self) -> Result<Arc<Clock>, InstructionError> {
self.clock
.clone()
.ok_or(InstructionError::UnsupportedSysvar)
}

pub fn set_clock(&mut self, clock: Clock) {
self.clock = Some(Arc::new(clock));
}

pub fn get_epoch_schedule(&self) -> Result<Arc<EpochSchedule>, InstructionError> {
self.epoch_schedule
.clone()
.ok_or(InstructionError::UnsupportedSysvar)
}

pub fn set_epoch_schedule(&mut self, epoch_schedule: EpochSchedule) {
self.epoch_schedule = Some(Arc::new(epoch_schedule));
}

#[deprecated]
#[allow(deprecated)]
pub fn get_fees(&self) -> Result<Arc<Fees>, InstructionError> {
self.fees.clone().ok_or(InstructionError::UnsupportedSysvar)
}

#[deprecated]
#[allow(deprecated)]
pub fn set_fees(&mut self, fees: Fees) {
self.fees = Some(Arc::new(fees));
}

pub fn get_rent(&self) -> Result<Arc<Rent>, InstructionError> {
self.rent.clone().ok_or(InstructionError::UnsupportedSysvar)
}

pub fn set_rent(&mut self, rent: Rent) {
self.rent = Some(Arc::new(rent));
}

pub fn get_slot_hashes(&self) -> Result<Arc<SlotHashes>, InstructionError> {
self.slot_hashes
.clone()
.ok_or(InstructionError::UnsupportedSysvar)
}

pub fn update_entry(&mut self, pubkey: &Pubkey, new_account: &AccountSharedData) {
if let Some(position) = self.iter().position(|(id, _data)| id == pubkey) {
self.0[position].1 = new_account.data().to_vec();
} else {
self.0.push((*pubkey, new_account.data().to_vec()));
}
pub fn set_slot_hashes(&mut self, slot_hashes: SlotHashes) {
self.slot_hashes = Some(Arc::new(slot_hashes));
}
}
33 changes: 16 additions & 17 deletions program-test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! The solana-program-test provides a BanksClient-based test framework BPF programs
#![allow(clippy::integer_arithmetic)]

#[allow(deprecated)]
use solana_sdk::sysvar::fees::Fees;
// Export tokio for test clients
pub use tokio;
use {
Expand All @@ -24,10 +22,9 @@ use {
solana_sdk::{
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
account_info::AccountInfo,
clock::{Clock, Slot},
clock::Slot,
compute_budget::ComputeBudget,
entrypoint::{ProgramResult, SUCCESS},
epoch_schedule::EpochSchedule,
fee_calculator::{FeeCalculator, FeeRateGovernor},
genesis_config::{ClusterType, GenesisConfig},
hash::Hash,
Expand All @@ -38,11 +35,7 @@ use {
pubkey::Pubkey,
rent::Rent,
signature::{Keypair, Signer},
sysvar::{
clock, epoch_schedule,
fees::{self},
rent, Sysvar, SysvarId,
},
sysvar::{Sysvar, SysvarId},
},
solana_vote_program::vote_state::{VoteState, VoteStateVersions},
std::{
Expand Down Expand Up @@ -209,8 +202,8 @@ macro_rules! processor {
};
}

fn get_sysvar<T: Default + Sysvar + Sized + serde::de::DeserializeOwned>(
id: &Pubkey,
fn get_sysvar<T: Default + Sysvar + Sized + serde::de::DeserializeOwned + Clone>(
sysvar: Result<Arc<T>, InstructionError>,
var_addr: *mut u8,
) -> u64 {
let invoke_context = get_invoke_context();
Expand All @@ -225,9 +218,9 @@ fn get_sysvar<T: Default + Sysvar + Sized + serde::de::DeserializeOwned>(
panic!("Exceeded compute budget");
}

match invoke_context.get_sysvar::<T>(id) {
match sysvar {
Ok(sysvar_data) => unsafe {
*(var_addr as *mut _ as *mut T) = sysvar_data;
*(var_addr as *mut _ as *mut T) = T::clone(&sysvar_data);
SUCCESS
},
Err(_) => UNSUPPORTED_SYSVAR,
Expand Down Expand Up @@ -341,20 +334,26 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
}

fn sol_get_clock_sysvar(&self, var_addr: *mut u8) -> u64 {
get_sysvar::<Clock>(&clock::id(), var_addr)
get_sysvar(
get_invoke_context().get_sysvar_cache().get_clock(),
var_addr,
)
}

fn sol_get_epoch_schedule_sysvar(&self, var_addr: *mut u8) -> u64 {
get_sysvar::<EpochSchedule>(&epoch_schedule::id(), var_addr)
get_sysvar(
get_invoke_context().get_sysvar_cache().get_epoch_schedule(),
var_addr,
)
}

#[allow(deprecated)]
fn sol_get_fees_sysvar(&self, var_addr: *mut u8) -> u64 {
get_sysvar::<Fees>(&fees::id(), var_addr)
get_sysvar(get_invoke_context().get_sysvar_cache().get_fees(), var_addr)
}

fn sol_get_rent_sysvar(&self, var_addr: *mut u8) -> u64 {
get_sysvar::<Rent>(&rent::id(), var_addr)
get_sysvar(get_invoke_context().get_sysvar_cache().get_rent(), var_addr)
}
}

Expand Down
21 changes: 8 additions & 13 deletions programs/address-lookup-table/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ use {
keyed_account::keyed_account_at_index,
program_utils::limited_deserialize,
pubkey::{Pubkey, PUBKEY_BYTES},
slot_hashes::SlotHashes,
system_instruction,
sysvar::{
clock::{self, Clock},
rent::{self, Rent},
slot_hashes,
},
},
std::convert::TryFrom,
};
Expand Down Expand Up @@ -92,7 +86,7 @@ impl Processor {
})?;

let derivation_slot = {
let slot_hashes: SlotHashes = invoke_context.get_sysvar(&slot_hashes::id())?;
let slot_hashes = invoke_context.get_sysvar_cache().get_slot_hashes()?;
if slot_hashes.get(&untrusted_recent_slot).is_some() {
Ok(untrusted_recent_slot)
} else {
Expand Down Expand Up @@ -127,7 +121,7 @@ impl Processor {
}

let table_account_data_len = LOOKUP_TABLE_META_SIZE;
let rent: Rent = invoke_context.get_sysvar(&rent::id())?;
let rent = invoke_context.get_sysvar_cache().get_rent()?;
let required_lamports = rent
.minimum_balance(table_account_data_len)
.max(1)
Expand Down Expand Up @@ -281,7 +275,7 @@ impl Processor {
return Err(InstructionError::InvalidInstructionData);
}

let clock: Clock = invoke_context.get_sysvar(&clock::id())?;
let clock = invoke_context.get_sysvar_cache().get_clock()?;
if clock.slot != lookup_table.meta.last_extended_slot {
lookup_table.meta.last_extended_slot = clock.slot;
lookup_table.meta.last_extended_slot_start_index =
Expand Down Expand Up @@ -313,7 +307,7 @@ impl Processor {
}
}

let rent: Rent = invoke_context.get_sysvar(&rent::id())?;
let rent = invoke_context.get_sysvar_cache().get_rent()?;
let required_lamports = rent
.minimum_balance(new_table_data_len)
.max(1)
Expand Down Expand Up @@ -367,7 +361,7 @@ impl Processor {
let mut lookup_table_meta = lookup_table.meta;
drop(lookup_table_account_ref);

let clock: Clock = invoke_context.get_sysvar(&clock::id())?;
let clock = invoke_context.get_sysvar_cache().get_clock()?;
lookup_table_meta.deactivation_slot = clock.slot;

AddressLookupTable::overwrite_meta_data(
Expand Down Expand Up @@ -420,8 +414,9 @@ impl Processor {
return Err(InstructionError::IncorrectAuthority);
}

let clock: Clock = invoke_context.get_sysvar(&clock::id())?;
let slot_hashes: SlotHashes = invoke_context.get_sysvar(&slot_hashes::id())?;
let sysvar_cache = invoke_context.get_sysvar_cache();
let clock = sysvar_cache.get_clock()?;
let slot_hashes = sysvar_cache.get_slot_hashes()?;

match lookup_table.meta.status(clock.slot, &slot_hashes) {
LookupTableStatus::Activated => {
Expand Down
Loading