Skip to content

Commit

Permalink
SVM: Move sysvar_cache related functions and tests to SVM (#402)
Browse files Browse the repository at this point in the history
  • Loading branch information
pgarg66 authored Mar 23, 2024
1 parent 6e6acce commit 5cfb6e8
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 39 deletions.
26 changes: 19 additions & 7 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ use {
solana_accounts_db::accounts_db::{
ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
},
solana_program_runtime::loaded_programs::LoadedProgramsForTxBatch,
solana_program_runtime::{
loaded_programs::LoadedProgramsForTxBatch, sysvar_cache::SysvarCache,
},
};

/// params to `verify_accounts_hash`
Expand Down Expand Up @@ -1098,7 +1100,8 @@ impl Bank {
bank.update_epoch_schedule();
bank.update_recent_blockhashes();
bank.update_last_restart_slot();
bank.fill_missing_sysvar_cache_entries();
bank.transaction_processor
.fill_missing_sysvar_cache_entries(&bank);
bank
}

Expand Down Expand Up @@ -1457,7 +1460,9 @@ impl Bank {
new.update_last_restart_slot()
});

let (_, fill_sysvar_cache_time_us) = measure_us!(new.fill_missing_sysvar_cache_entries());
let (_, fill_sysvar_cache_time_us) = measure_us!(new
.transaction_processor
.fill_missing_sysvar_cache_entries(&new));
time.stop();

report_new_bank_metrics(
Expand Down Expand Up @@ -1793,7 +1798,8 @@ impl Bank {
new.inherit_specially_retained_account_fields(account),
)
});
new.fill_missing_sysvar_cache_entries();
new.transaction_processor
.fill_missing_sysvar_cache_entries(&new);
new.freeze();
new
}
Expand Down Expand Up @@ -1907,7 +1913,8 @@ impl Bank {
additional_builtins,
debug_do_not_add_builtins,
);
bank.fill_missing_sysvar_cache_entries();
bank.transaction_processor
.fill_missing_sysvar_cache_entries(&bank);
bank.rebuild_skipped_rewrites();

// Sanity assertions between bank snapshot and genesis config
Expand Down Expand Up @@ -2210,8 +2217,9 @@ impl Bank {
});
// Simply force fill sysvar cache rather than checking which sysvar was
// actually updated since tests don't need to be optimized for performance.
self.reset_sysvar_cache();
self.fill_missing_sysvar_cache_entries();
self.transaction_processor.reset_sysvar_cache();
self.transaction_processor
.fill_missing_sysvar_cache_entries(self);
}

fn update_slot_history(&self) {
Expand Down Expand Up @@ -7881,6 +7889,10 @@ impl Bank {
.wait_for_complete()
}

pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
self.transaction_processor.get_sysvar_cache_for_tests()
}

pub fn update_accounts_hash_for_tests(&self) -> AccountsHash {
self.update_accounts_hash(CalcAccountsHashDataSource::IndexForTests, false, false)
}
Expand Down
36 changes: 6 additions & 30 deletions runtime/src/bank/sysvar_cache.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,5 @@
use {
super::Bank, solana_program_runtime::sysvar_cache::SysvarCache,
solana_sdk::account::ReadableAccount,
};

impl Bank {
pub(crate) fn fill_missing_sysvar_cache_entries(&self) {
let mut sysvar_cache = self.transaction_processor.sysvar_cache.write().unwrap();
sysvar_cache.fill_missing_entries(|pubkey, callback| {
if let Some(account) = self.get_account_with_fixed_root(pubkey) {
callback(account.data());
}
});
}

pub(crate) fn reset_sysvar_cache(&self) {
let mut sysvar_cache = self.transaction_processor.sysvar_cache.write().unwrap();
sysvar_cache.reset();
}

pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
self.transaction_processor
.sysvar_cache
.read()
.unwrap()
.clone()
}
}
#[cfg(test)]
use super::Bank;

#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -132,7 +106,7 @@ mod tests {
assert!(bank1_cached_epoch_rewards.is_err());

drop(bank1_sysvar_cache);
bank1.reset_sysvar_cache();
bank1.transaction_processor.reset_sysvar_cache();

let bank1_sysvar_cache = bank1.transaction_processor.sysvar_cache.read().unwrap();
assert!(bank1_sysvar_cache.get_clock().is_err());
Expand All @@ -157,7 +131,9 @@ mod tests {
expected_epoch_rewards.distribution_complete_block_height,
);

bank1.fill_missing_sysvar_cache_entries();
bank1
.transaction_processor
.fill_missing_sysvar_cache_entries(&bank1);

let bank1_sysvar_cache = bank1.transaction_processor.sysvar_cache.read().unwrap();
assert_eq!(bank1_sysvar_cache.get_clock(), bank1_cached_clock);
Expand Down
179 changes: 177 additions & 2 deletions svm/src/transaction_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,27 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
}
outer_instructions
}

pub fn fill_missing_sysvar_cache_entries<CB: TransactionProcessingCallback>(
&self,
callbacks: &CB,
) {
let mut sysvar_cache = self.sysvar_cache.write().unwrap();
sysvar_cache.fill_missing_entries(|pubkey, set_sysvar| {
if let Some(account) = callbacks.get_account_shared_data(pubkey) {
set_sysvar(account.data());
}
});
}

pub fn reset_sysvar_cache(&self) {
let mut sysvar_cache = self.sysvar_cache.write().unwrap();
sysvar_cache.reset();
}

pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
self.sysvar_cache.read().unwrap().clone()
}
}

#[cfg(test)]
Expand All @@ -937,12 +958,13 @@ mod tests {
loaded_programs::BlockRelation, solana_rbpf::program::BuiltinProgram,
},
solana_sdk::{
account::WritableAccount,
account::{create_account_shared_data_for_test, WritableAccount},
bpf_loader,
fee_calculator::FeeCalculator,
message::{LegacyMessage, Message, MessageHeader},
rent_debits::RentDebits,
signature::{Keypair, Signature},
sysvar::rent::Rent,
sysvar::{self, rent::Rent},
transaction::{SanitizedTransaction, Transaction, TransactionError},
transaction_context::TransactionContext,
},
Expand Down Expand Up @@ -2102,4 +2124,157 @@ mod tests {
);
assert_eq!(lock_results[1].0, Err(TransactionError::BlockhashNotFound));
}

#[test]
#[allow(deprecated)]
fn test_sysvar_cache_initialization1() {
let mut mock_bank = MockBankCallback::default();

let clock = sysvar::clock::Clock {
slot: 1,
epoch_start_timestamp: 2,
epoch: 3,
leader_schedule_epoch: 4,
unix_timestamp: 5,
};
let clock_account = create_account_shared_data_for_test(&clock);
mock_bank
.account_shared_data
.insert(sysvar::clock::id(), clock_account);

let epoch_schedule = EpochSchedule::custom(64, 2, true);
let epoch_schedule_account = create_account_shared_data_for_test(&epoch_schedule);
mock_bank
.account_shared_data
.insert(sysvar::epoch_schedule::id(), epoch_schedule_account);

let fees = sysvar::fees::Fees {
fee_calculator: FeeCalculator {
lamports_per_signature: 123,
},
};
let fees_account = create_account_shared_data_for_test(&fees);
mock_bank
.account_shared_data
.insert(sysvar::fees::id(), fees_account);

let rent = Rent::with_slots_per_epoch(2048);
let rent_account = create_account_shared_data_for_test(&rent);
mock_bank
.account_shared_data
.insert(sysvar::rent::id(), rent_account);

let transaction_processor = TransactionBatchProcessor::<TestForkGraph>::default();
transaction_processor.fill_missing_sysvar_cache_entries(&mock_bank);

let sysvar_cache = transaction_processor.sysvar_cache.read().unwrap();
let cached_clock = sysvar_cache.get_clock();
let cached_epoch_schedule = sysvar_cache.get_epoch_schedule();
let cached_fees = sysvar_cache.get_fees();
let cached_rent = sysvar_cache.get_rent();

assert_eq!(
cached_clock.expect("clock sysvar missing in cache"),
clock.into()
);
assert_eq!(
cached_epoch_schedule.expect("epoch_schedule sysvar missing in cache"),
epoch_schedule.into()
);
assert_eq!(
cached_fees.expect("fees sysvar missing in cache"),
fees.into()
);
assert_eq!(
cached_rent.expect("rent sysvar missing in cache"),
rent.into()
);
assert!(sysvar_cache.get_slot_hashes().is_err());
assert!(sysvar_cache.get_epoch_rewards().is_err());
}

#[test]
#[allow(deprecated)]
fn test_reset_and_fill_sysvar_cache() {
let mut mock_bank = MockBankCallback::default();

let clock = sysvar::clock::Clock {
slot: 1,
epoch_start_timestamp: 2,
epoch: 3,
leader_schedule_epoch: 4,
unix_timestamp: 5,
};
let clock_account = create_account_shared_data_for_test(&clock);
mock_bank
.account_shared_data
.insert(sysvar::clock::id(), clock_account);

let epoch_schedule = EpochSchedule::custom(64, 2, true);
let epoch_schedule_account = create_account_shared_data_for_test(&epoch_schedule);
mock_bank
.account_shared_data
.insert(sysvar::epoch_schedule::id(), epoch_schedule_account);

let fees = sysvar::fees::Fees {
fee_calculator: FeeCalculator {
lamports_per_signature: 123,
},
};
let fees_account = create_account_shared_data_for_test(&fees);
mock_bank
.account_shared_data
.insert(sysvar::fees::id(), fees_account);

let rent = Rent::with_slots_per_epoch(2048);
let rent_account = create_account_shared_data_for_test(&rent);
mock_bank
.account_shared_data
.insert(sysvar::rent::id(), rent_account);

let transaction_processor = TransactionBatchProcessor::<TestForkGraph>::default();
// Fill the sysvar cache
transaction_processor.fill_missing_sysvar_cache_entries(&mock_bank);
// Reset the sysvar cache
transaction_processor.reset_sysvar_cache();

{
let sysvar_cache = transaction_processor.sysvar_cache.read().unwrap();
// Test that sysvar cache is empty and none of the values are found
assert!(sysvar_cache.get_clock().is_err());
assert!(sysvar_cache.get_epoch_schedule().is_err());
assert!(sysvar_cache.get_fees().is_err());
assert!(sysvar_cache.get_epoch_rewards().is_err());
assert!(sysvar_cache.get_rent().is_err());
assert!(sysvar_cache.get_epoch_rewards().is_err());
}

// Refill the cache and test the values are available.
transaction_processor.fill_missing_sysvar_cache_entries(&mock_bank);

let sysvar_cache = transaction_processor.sysvar_cache.read().unwrap();
let cached_clock = sysvar_cache.get_clock();
let cached_epoch_schedule = sysvar_cache.get_epoch_schedule();
let cached_fees = sysvar_cache.get_fees();
let cached_rent = sysvar_cache.get_rent();

assert_eq!(
cached_clock.expect("clock sysvar missing in cache"),
clock.into()
);
assert_eq!(
cached_epoch_schedule.expect("epoch_schedule sysvar missing in cache"),
epoch_schedule.into()
);
assert_eq!(
cached_fees.expect("fees sysvar missing in cache"),
fees.into()
);
assert_eq!(
cached_rent.expect("rent sysvar missing in cache"),
rent.into()
);
assert!(sysvar_cache.get_slot_hashes().is_err());
assert!(sysvar_cache.get_epoch_rewards().is_err());
}
}

0 comments on commit 5cfb6e8

Please sign in to comment.