From 5775d0b0b701636a15dfe762d960792d09831f3b Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Thu, 13 Jan 2022 13:36:21 +0800 Subject: [PATCH 1/3] Perf: Store deserialized sysvars in the sysvars cache (#22455) --- program-test/src/lib.rs | 38 ++++- programs/bpf_loader/src/syscalls.rs | 115 ++++++++++++-- programs/stake/src/stake_instruction.rs | 66 +++++++- programs/vote/src/vote_instruction.rs | 108 +++++++++++++- programs/vote/src/vote_state/mod.rs | 10 +- runtime/benches/bank.rs | 67 ++++++++- runtime/src/bank.rs | 191 +++++++++++++++++++++++- runtime/src/bank/sysvar_cache.rs | 151 ++++++++++++++++++- sdk/src/sysvar_cache.rs | 78 +++++++--- 9 files changed, 765 insertions(+), 59 deletions(-) diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index ca66f0d6f33..27e07a1a22d 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -1,8 +1,11 @@ //! The solana-program-test provides a BanksClient-based test framework BPF programs #![allow(clippy::integer_arithmetic)] +<<<<<<< HEAD // Export types so test clients can limit their solana crate dependencies pub use solana_banks_client::BanksClient; +======= +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) // Export tokio for test clients pub use tokio; use { @@ -20,11 +23,17 @@ use { solana_sdk::{ account::{Account, AccountSharedData, ReadableAccount, WritableAccount}, account_info::AccountInfo, +<<<<<<< HEAD clock::{Clock, Slot}, entrypoint::{ProgramResult, SUCCESS}, epoch_schedule::EpochSchedule, execute_timings::ExecuteTimings, feature_set::demote_program_write_locks, +======= + clock::Slot, + compute_budget::ComputeBudget, + entrypoint::{ProgramResult, SUCCESS}, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) fee_calculator::{FeeCalculator, FeeRateGovernor}, genesis_config::{ClusterType, GenesisConfig}, hash::Hash, @@ -39,11 +48,15 @@ use { pubkey::Pubkey, rent::Rent, signature::{Keypair, Signer}, +<<<<<<< HEAD sysvar::{ clock, epoch_schedule, fees::{self, Fees}, rent, Sysvar, }, +======= + sysvar::{Sysvar, SysvarId}, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) }, solana_vote_program::vote_state::{VoteState, VoteStateVersions}, std::{ @@ -192,8 +205,8 @@ macro_rules! processor { }; } -fn get_sysvar( - id: &Pubkey, +fn get_sysvar( + sysvar: Result, InstructionError>, var_addr: *mut u8, ) -> u64 { let invoke_context = get_invoke_context(); @@ -207,9 +220,14 @@ fn get_sysvar( { panic!("Exceeded compute budget"); } +<<<<<<< HEAD match process_instruction::get_sysvar::(invoke_context, id) { +======= + + match sysvar { +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) 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, @@ -368,19 +386,25 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs { } fn sol_get_clock_sysvar(&self, var_addr: *mut u8) -> u64 { - get_sysvar::(&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::(&epoch_schedule::id(), var_addr) + get_sysvar( + get_invoke_context().get_sysvar_cache().get_epoch_schedule(), + var_addr, + ) } fn sol_get_fees_sysvar(&self, var_addr: *mut u8) -> u64 { - get_sysvar::(&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::id(), var_addr) + get_sysvar(get_invoke_context().get_sysvar_cache().get_rent(), var_addr) } } diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 601431ab60d..b89c7c9a75a 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -13,12 +13,15 @@ use { solana_sdk::{ account::{Account, AccountSharedData, ReadableAccount}, account_info::AccountInfo, +<<<<<<< HEAD account_utils::StateMut, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable::{self, UpgradeableLoaderState}, clock::Clock, +======= + blake3, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) entrypoint::{BPF_ALIGN_OF_U128, MAX_PERMITTED_DATA_INCREASE, SUCCESS}, - epoch_schedule::EpochSchedule, feature_set::{ allow_native_ids, check_seed_length, close_upgradeable_program_accounts, cpi_data_cost, demote_program_write_locks, enforce_aligned_host_addrs, keccak256_syscall_enabled, @@ -36,11 +39,15 @@ use { process_instruction::{self, stable_log, ComputeMeter, InvokeContext, Logger}, program::MAX_RETURN_DATA, pubkey::{Pubkey, PubkeyError, MAX_SEEDS, MAX_SEED_LEN}, - rent::Rent, secp256k1_recover::{ Secp256k1RecoverError, SECP256K1_PUBLIC_KEY_LENGTH, SECP256K1_SIGNATURE_LENGTH, }, +<<<<<<< HEAD sysvar::{self, fees::Fees, Sysvar, SysvarId}, +======= + sysvar::{Sysvar, SysvarId}, + transaction_context::InstructionAccount, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) }, std::{ alloc::Layout, @@ -50,6 +57,7 @@ use { rc::Rc, slice::from_raw_parts_mut, str::{from_utf8, Utf8Error}, + sync::Arc, }, thiserror::Error as ThisError, }; @@ -1142,8 +1150,8 @@ impl<'a> SyscallObject for SyscallSha256<'a> { } } -fn get_sysvar( - id: &Pubkey, +fn get_sysvar( + sysvar: Result, InstructionError>, var_addr: u64, loader_id: &Pubkey, memory_mapping: &MemoryMapping, @@ -1153,6 +1161,7 @@ fn get_sysvar( .try_borrow() .map_err(|_| SyscallError::InvokeContextBorrowFailed)?; +<<<<<<< HEAD invoke_context.get_compute_meter().consume( invoke_context.get_bpf_compute_budget().sysvar_base_cost + size_of::() as u64, )?; @@ -1165,6 +1174,10 @@ fn get_sysvar( *var = process_instruction::get_sysvar::(*invoke_context, id) .map_err(SyscallError::InstructionError)?; +======= + let sysvar: Arc = sysvar.map_err(SyscallError::InstructionError)?; + *var = T::clone(sysvar.as_ref()); +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) Ok(SUCCESS) } @@ -1185,8 +1198,26 @@ impl<'a> SyscallObject for SyscallGetClockSysvar<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { +<<<<<<< HEAD *result = get_sysvar::( &sysvar::clock::id(), +======= + let mut invoke_context = question_mark!( + self.invoke_context + .try_borrow_mut() + .map_err(|_| SyscallError::InvokeContextBorrowFailed), + result + ); + let loader_id = question_mark!( + invoke_context + .transaction_context + .get_loader_key() + .map_err(SyscallError::InstructionError), + result + ); + *result = get_sysvar( + invoke_context.get_sysvar_cache().get_clock(), +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) var_addr, self.loader_id, memory_mapping, @@ -1210,8 +1241,26 @@ impl<'a> SyscallObject for SyscallGetEpochScheduleSysvar<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { +<<<<<<< HEAD *result = get_sysvar::( &sysvar::epoch_schedule::id(), +======= + let mut invoke_context = question_mark!( + self.invoke_context + .try_borrow_mut() + .map_err(|_| SyscallError::InvokeContextBorrowFailed), + result + ); + let loader_id = question_mark!( + invoke_context + .transaction_context + .get_loader_key() + .map_err(SyscallError::InstructionError), + result + ); + *result = get_sysvar( + invoke_context.get_sysvar_cache().get_epoch_schedule(), +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) var_addr, self.loader_id, memory_mapping, @@ -1235,8 +1284,26 @@ impl<'a> SyscallObject for SyscallGetFeesSysvar<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { +<<<<<<< HEAD *result = get_sysvar::( &sysvar::fees::id(), +======= + let mut invoke_context = question_mark!( + self.invoke_context + .try_borrow_mut() + .map_err(|_| SyscallError::InvokeContextBorrowFailed), + result + ); + let loader_id = question_mark!( + invoke_context + .transaction_context + .get_loader_key() + .map_err(SyscallError::InstructionError), + result + ); + *result = get_sysvar( + invoke_context.get_sysvar_cache().get_fees(), +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) var_addr, self.loader_id, memory_mapping, @@ -1260,8 +1327,26 @@ impl<'a> SyscallObject for SyscallGetRentSysvar<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { +<<<<<<< HEAD *result = get_sysvar::( &sysvar::rent::id(), +======= + let mut invoke_context = question_mark!( + self.invoke_context + .try_borrow_mut() + .map_err(|_| SyscallError::InvokeContextBorrowFailed), + result + ); + let loader_id = question_mark!( + invoke_context + .transaction_context + .get_loader_key() + .map_err(SyscallError::InstructionError), + result + ); + *result = get_sysvar( + invoke_context.get_sysvar_cache().get_rent(), +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) var_addr, self.loader_id, memory_mapping, @@ -2764,17 +2849,28 @@ impl<'a> SyscallObject for SyscallLogData<'a> { #[cfg(test)] mod tests { + #[allow(deprecated)] + use solana_sdk::sysvar::fees::Fees; use { super::*, solana_rbpf::{ ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config, }, solana_sdk::{ +<<<<<<< HEAD bpf_loader, fee_calculator::FeeCalculator, hash::hashv, process_instruction::{MockComputeMeter, MockInvokeContext, MockLogger}, sysvar_cache::SysvarCache, +======= + account::AccountSharedData, + bpf_loader, + fee_calculator::FeeCalculator, + hash::hashv, + sysvar::{clock::Clock, epoch_schedule::EpochSchedule, rent::Rent}, + transaction_context::TransactionContext, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) }, std::{borrow::Cow, str::FromStr}, }; @@ -3647,13 +3743,10 @@ mod tests { }; let mut sysvar_cache = SysvarCache::default(); - sysvar_cache.push_entry(sysvar::clock::id(), bincode::serialize(&src_clock).unwrap()); - sysvar_cache.push_entry( - sysvar::epoch_schedule::id(), - bincode::serialize(&src_epochschedule).unwrap(), - ); - sysvar_cache.push_entry(sysvar::fees::id(), bincode::serialize(&src_fees).unwrap()); - sysvar_cache.push_entry(sysvar::rent::id(), bincode::serialize(&src_rent).unwrap()); + sysvar_cache.set_clock(src_clock.clone()); + sysvar_cache.set_epoch_schedule(src_epochschedule); + sysvar_cache.set_fees(src_fees.clone()); + sysvar_cache.set_rent(src_rent); // Test clock sysvar { diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index 62a73352894..85288e926ea 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -18,7 +18,7 @@ use { program::id, state::{Authorized, Lockup}, }, - sysvar::{self, clock::Clock, rent::Rent, stake_history::StakeHistory}, + sysvar::{clock::Clock, rent::Rent, stake_history::StakeHistory}, }, }; @@ -166,12 +166,20 @@ pub fn process_instruction( &signers, ), StakeInstruction::SetLockup(lockup) => { +<<<<<<< HEAD let clock = if invoke_context.is_feature_active(&feature_set::stake_program_v4::id()) { Some(get_sysvar::(invoke_context, &sysvar::clock::id())?) +======= + let clock = if invoke_context + .feature_set + .is_active(&feature_set::stake_program_v4::id()) + { + Some(invoke_context.get_sysvar_cache().get_clock()?) +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } else { None }; - me.set_lockup(&lockup, &signers, clock.as_ref()) + me.set_lockup(&lockup, &signers, clock.as_deref()) } StakeInstruction::InitializeChecked => { if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id()) @@ -262,8 +270,13 @@ pub fn process_instruction( epoch: lockup_checked.epoch, custodian, }; +<<<<<<< HEAD let clock = Some(get_sysvar::(invoke_context, &sysvar::clock::id())?); me.set_lockup(&lockup, &signers, clock.as_ref()) +======= + let clock = Some(invoke_context.get_sysvar_cache().get_clock()?); + me.set_lockup(&lockup, &signers, clock.as_deref()) +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } else { Err(InstructionError::InvalidInstructionData) } @@ -288,8 +301,12 @@ mod tests { instruction::{self, LockupArgs}, state::{Authorized, Lockup, StakeAuthorize}, }, +<<<<<<< HEAD sysvar::stake_history::StakeHistory, sysvar_cache::SysvarCache, +======= + sysvar::{self, stake_history::StakeHistory}, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) }, std::{borrow::Cow, cell::RefCell, str::FromStr}, }; @@ -361,6 +378,7 @@ mod tests { }) }) .collect(); +<<<<<<< HEAD { let keyed_accounts: Vec<_> = instruction @@ -379,6 +397,20 @@ mod tests { invoke_context.sysvar_cache = Cow::Owned(sysvar_cache); super::process_instruction(&Pubkey::default(), &instruction.data, &mut invoke_context) } +======= + let mut sysvar_cache = SysvarCache::default(); + sysvar_cache.set_clock(Clock::default()); + mock_process_instruction_with_sysvars( + &id(), + Vec::new(), + &instruction.data, + transaction_accounts, + instruction.accounts.clone(), + expected_result, + &sysvar_cache, + super::process_instruction, + ) +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } #[test] @@ -1040,6 +1072,7 @@ mod tests { let mut invoke_context = MockInvokeContext::new(keyed_accounts); let mut sysvar_cache = SysvarCache::default(); +<<<<<<< HEAD sysvar_cache.push_entry( sysvar::clock::id(), bincode::serialize(&Clock::default()).unwrap(), @@ -1056,6 +1089,35 @@ mod tests { .unwrap(), &mut invoke_context ), +======= + sysvar_cache.set_clock(Clock::default()); + mock_process_instruction_with_sysvars( + &id(), + Vec::new(), + &instruction.data, + vec![ + (stake_address, stake_account), + (withdrawer, withdrawer_account), + (custodian, custodian_account), + ], + vec![ + AccountMeta { + pubkey: stake_address, + is_signer: false, + is_writable: false, + }, + AccountMeta { + pubkey: withdrawer, + is_signer: true, + is_writable: false, + }, + AccountMeta { + pubkey: custodian, + is_signer: true, + is_writable: false, + }, + ], +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) Ok(()), ); } diff --git a/programs/vote/src/vote_instruction.rs b/programs/vote/src/vote_instruction.rs index f213201b599..cb29b8d20d9 100644 --- a/programs/vote/src/vote_instruction.rs +++ b/programs/vote/src/vote_instruction.rs @@ -23,9 +23,9 @@ use { program_utils::limited_deserialize, pubkey::Pubkey, system_instruction, - sysvar::{self, clock::Clock, rent::Rent, slot_hashes::SlotHashes, Sysvar}, + sysvar::{self, clock::Clock, rent::Rent, slot_hashes::SlotHashes}, }, - std::collections::HashSet, + std::{collections::HashSet, sync::Arc}, thiserror::Error, }; @@ -311,17 +311,46 @@ fn verify_rent_exemption( } } -/// This method facilitates a transition from fetching sysvars from keyed +/// These methods facilitate a transition from fetching sysvars from keyed /// accounts to fetching from the sysvar cache without breaking consensus. In -/// order to keep consistent behavior, it continues to enforce the same checks +/// order to keep consistent behavior, they continue to enforce the same checks /// as `solana_sdk::keyed_account::from_keyed_account` despite dynamically /// loading them instead of deserializing from account data. +<<<<<<< HEAD fn get_sysvar_with_keyed_account_check( keyed_account: &KeyedAccount, invoke_context: &dyn InvokeContext, ) -> Result { check_sysvar_keyed_account::(keyed_account)?; get_sysvar(invoke_context, keyed_account.unsigned_key()) +======= +mod get_sysvar_with_keyed_account_check { + use super::*; + + pub fn clock( + keyed_account: &KeyedAccount, + invoke_context: &InvokeContext, + ) -> Result, InstructionError> { + check_sysvar_keyed_account::(keyed_account)?; + invoke_context.get_sysvar_cache().get_clock() + } + + pub fn rent( + keyed_account: &KeyedAccount, + invoke_context: &InvokeContext, + ) -> Result, InstructionError> { + check_sysvar_keyed_account::(keyed_account)?; + invoke_context.get_sysvar_cache().get_rent() + } + + pub fn slot_hashes( + keyed_account: &KeyedAccount, + invoke_context: &InvokeContext, + ) -> Result, InstructionError> { + check_sysvar_keyed_account::(keyed_account)?; + invoke_context.get_sysvar_cache().get_slot_hashes() + } +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } pub fn process_instruction( @@ -346,6 +375,7 @@ pub fn process_instruction( match limited_deserialize(data)? { VoteInstruction::InitializeAccount(vote_init) => { +<<<<<<< HEAD let rent: Rent = get_sysvar_with_keyed_account_check( keyed_account_at_index(keyed_accounts, 1)?, invoke_context, @@ -353,13 +383,27 @@ pub fn process_instruction( verify_rent_exemption(me, &rent)?; let clock: Clock = get_sysvar_with_keyed_account_check( keyed_account_at_index(keyed_accounts, 2)?, +======= + let rent = get_sysvar_with_keyed_account_check::rent( + keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?, + invoke_context, + )?; + verify_rent_exemption(me, &rent)?; + let clock = get_sysvar_with_keyed_account_check::clock( + keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) invoke_context, )?; vote_state::initialize_account(me, &vote_init, &signers, &clock) } VoteInstruction::Authorize(voter_pubkey, vote_authorize) => { +<<<<<<< HEAD let clock: Clock = get_sysvar_with_keyed_account_check( keyed_account_at_index(keyed_accounts, 1)?, +======= + let clock = get_sysvar_with_keyed_account_check::clock( + keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) invoke_context, )?; vote_state::authorize(me, &voter_pubkey, vote_authorize, &signers, &clock) @@ -374,26 +418,63 @@ pub fn process_instruction( } VoteInstruction::Vote(vote) | VoteInstruction::VoteSwitch(vote, _) => { inc_new_counter_info!("vote-native", 1); +<<<<<<< HEAD let slot_hashes: SlotHashes = get_sysvar_with_keyed_account_check( keyed_account_at_index(keyed_accounts, 1)?, invoke_context, )?; let clock: Clock = get_sysvar_with_keyed_account_check( keyed_account_at_index(keyed_accounts, 2)?, +======= + let slot_hashes = get_sysvar_with_keyed_account_check::slot_hashes( + keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?, + invoke_context, + )?; + let clock = get_sysvar_with_keyed_account_check::clock( + keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) invoke_context, )?; vote_state::process_vote(me, &slot_hashes, &clock, &vote, &signers) } +<<<<<<< HEAD +======= + VoteInstruction::UpdateVoteState(vote_state_update) + | VoteInstruction::UpdateVoteStateSwitch(vote_state_update, _) => { + if invoke_context + .feature_set + .is_active(&feature_set::allow_votes_to_directly_update_vote_state::id()) + { + inc_new_counter_info!("vote-state-native", 1); + let sysvar_cache = invoke_context.get_sysvar_cache(); + let slot_hashes = sysvar_cache.get_slot_hashes()?; + let clock = sysvar_cache.get_clock()?; + vote_state::process_vote_state_update( + me, + slot_hashes.slot_hashes(), + &clock, + vote_state_update, + &signers, + ) + } else { + Err(InstructionError::InvalidInstructionData) + } + } +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) VoteInstruction::Withdraw(lamports) => { let to = keyed_account_at_index(keyed_accounts, 1)?; let rent_sysvar = if invoke_context .is_feature_active(&feature_set::reject_non_rent_exempt_vote_withdraws::id()) { +<<<<<<< HEAD Some(get_sysvar(invoke_context, &sysvar::rent::id())?) +======= + Some(invoke_context.get_sysvar_cache().get_rent()?) +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } else { None }; - vote_state::withdraw(me, lamports, to, &signers, rent_sysvar) + vote_state::withdraw(me, lamports, to, &signers, rent_sysvar.as_deref()) } VoteInstruction::AuthorizeChecked(vote_authorize) => { if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id()) @@ -471,6 +552,7 @@ mod tests { }) }) .collect(); +<<<<<<< HEAD for _ in 0..instruction.accounts.len() { accounts.push(RefCell::new(AccountSharedData::default())); @@ -499,6 +581,22 @@ mod tests { invoke_context.sysvar_cache = Cow::Owned(sysvar_cache); super::process_instruction(&Pubkey::default(), &instruction.data, &mut invoke_context) } +======= + let mut sysvar_cache = SysvarCache::default(); + sysvar_cache.set_rent(Rent::free()); + sysvar_cache.set_clock(Clock::default()); + sysvar_cache.set_slot_hashes(SlotHashes::default()); + mock_process_instruction_with_sysvars( + &id(), + Vec::new(), + &instruction.data, + transaction_accounts, + instruction.accounts.clone(), + expected_result, + &sysvar_cache, + super::process_instruction, + ) +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } fn invalid_vote_state_pubkey() -> Pubkey { diff --git a/programs/vote/src/vote_state/mod.rs b/programs/vote/src/vote_state/mod.rs index 60fc8987a94..32ed74f1872 100644 --- a/programs/vote/src/vote_state/mod.rs +++ b/programs/vote/src/vote_state/mod.rs @@ -681,7 +681,7 @@ pub fn withdraw( lamports: u64, to_account: &KeyedAccount, signers: &HashSet, - rent_sysvar: Option, + rent_sysvar: Option<&Rent>, ) -> Result<(), InstructionError> { let vote_state: VoteState = State::::state(vote_account)?.convert_to_current(); @@ -1742,7 +1742,7 @@ mod tests { &RefCell::new(AccountSharedData::default()), ), &signers, - Some(rent_sysvar), + Some(&rent_sysvar), ); assert_eq!(res, Err(InstructionError::InsufficientFunds)); } @@ -1765,7 +1765,7 @@ mod tests { withdraw_lamports, &KeyedAccount::new(&solana_sdk::pubkey::new_rand(), false, &to_account), &signers, - Some(rent_sysvar), + Some(&rent_sysvar), ); assert_eq!(res, Ok(())); assert_eq!( @@ -1778,7 +1778,11 @@ mod tests { // full withdraw, before/after activation { let rent_sysvar = Rent::default(); +<<<<<<< HEAD for rent_sysvar in &[None, Some(rent_sysvar)] { +======= + for rent_sysvar in [None, Some(&rent_sysvar)] { +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) let to_account = RefCell::new(AccountSharedData::default()); let (vote_pubkey, vote_account) = create_test_account(); let lamports = vote_account.borrow().lamports(); diff --git a/runtime/benches/bank.rs b/runtime/benches/bank.rs index ffc58e99ef6..15856df5d07 100644 --- a/runtime/benches/bank.rs +++ b/runtime/benches/bank.rs @@ -17,6 +17,10 @@ use { signature::{Keypair, Signer}, transaction::Transaction, }, + solana_vote_program::{ + vote_instruction, + vote_state::{Vote, VoteInit}, + }, std::{sync::Arc, thread::sleep, time::Duration}, test::Bencher, }; @@ -62,6 +66,52 @@ pub fn create_builtin_transactions( .collect() } +pub fn create_vote_transactions( + bank_client: &BankClient, + mint_keypair: &Keypair, +) -> Vec { + let blockhash = bank_client.get_latest_blockhash().unwrap(); + (0..4096) + .map(|_| { + // Seed the signer account + let payer_keypair = Keypair::new(); + bank_client + .transfer_and_confirm(27_000_000, mint_keypair, &payer_keypair.pubkey()) + .unwrap_or_else(|_| panic!("{}:{}", line!(), file!())); + + // Setup vote + let vote_keypair = Keypair::new(); + let instructions = vote_instruction::create_account( + &payer_keypair.pubkey(), + &vote_keypair.pubkey(), + &VoteInit { + node_pubkey: payer_keypair.pubkey(), + authorized_voter: payer_keypair.pubkey(), + authorized_withdrawer: payer_keypair.pubkey(), + commission: 100u8, + }, + 26_858_640, + ); + let message = Message::new(&instructions, Some(&payer_keypair.pubkey())); + bank_client + .send_and_confirm_message(&[&payer_keypair, &vote_keypair], message) + .unwrap(); + + let vote_ix = vote_instruction::vote( + &vote_keypair.pubkey(), + &payer_keypair.pubkey(), + Vote { + slots: vec![0], + hash: blockhash, + timestamp: None, + }, + ); + let message = Message::new(&[vote_ix], Some(&payer_keypair.pubkey())); + Transaction::new(&[&payer_keypair], message, blockhash) + }) + .collect() +} + pub fn create_native_loader_transactions( bank_client: &BankClient, mint_keypair: &Keypair, @@ -123,9 +173,18 @@ fn do_bench_transactions( ) { solana_logger::setup(); let ns_per_s = 1_000_000_000; - let (mut genesis_config, mint_keypair) = create_genesis_config(100_000_000); + let (mut genesis_config, mint_keypair) = create_genesis_config(100_000_000_000_000); genesis_config.ticks_per_slot = 100; +<<<<<<< HEAD let mut bank = Bank::new(&genesis_config); +======= + + let bank = Bank::new_for_benches(&genesis_config); + // freeze bank so that slot hashes is populated + bank.freeze(); + + let mut bank = Bank::new_from_parent(&Arc::new(bank), &Pubkey::default(), 1); +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) bank.add_builtin( "builtin_program", Pubkey::new(&BUILTIN_PROGRAM_ID), @@ -166,6 +225,12 @@ fn bench_bank_sync_process_native_loader_transactions(bencher: &mut Bencher) { do_bench_transactions(bencher, &sync_bencher, &create_native_loader_transactions); } +#[bench] +#[ignore] +fn bench_bank_sync_process_vote_transactions(bencher: &mut Bencher) { + do_bench_transactions(bencher, &sync_bencher, &create_vote_transactions); +} + #[bench] #[ignore] fn bench_bank_async_process_builtin_transactions(bencher: &mut Bencher) { diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index b02b0f986a2..0a9c3b6eb43 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -1295,7 +1295,7 @@ impl Bank { bank.update_rent(); bank.update_epoch_schedule(); bank.update_recent_blockhashes(); - bank.fill_sysvar_cache(); + bank.fill_missing_sysvar_cache_entries(); bank } @@ -1475,10 +1475,14 @@ impl Bank { new.update_stake_history(Some(parent_epoch)); new.update_clock(Some(parent_epoch)); new.update_fees(); +<<<<<<< HEAD if !new.fix_recent_blockhashes_sysvar_delay() { new.update_recent_blockhashes(); } new.fill_sysvar_cache(); +======= + new.fill_missing_sysvar_cache_entries(); +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) time.stop(); @@ -1537,7 +1541,7 @@ impl Bank { new.inherit_specially_retained_account_fields(account), ) }); - + new.fill_missing_sysvar_cache_entries(); new.freeze(); new } @@ -1789,10 +1793,6 @@ 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(); - sysvar_cache.update_entry(pubkey, &new_account); } fn inherit_specially_retained_account_fields( @@ -1902,6 +1902,25 @@ impl Bank { }); } +<<<<<<< HEAD +======= + pub fn set_sysvar_for_tests(&self, sysvar: &T) + where + T: Sysvar + SysvarId, + { + self.update_sysvar_account(&T::id(), |account| { + create_account( + sysvar, + self.inherit_specially_retained_account_fields(account), + ) + }); + // 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(); + } + +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) fn update_slot_history(&self) { self.update_sysvar_account(&sysvar::slot_history::id(), |account| { let mut slot_history = account @@ -3454,6 +3473,166 @@ impl Bank { Arc::make_mut(&mut cache).remove(pubkey); } +<<<<<<< HEAD +======= + pub fn load_lookup_table_addresses( + &self, + address_table_lookups: &[MessageAddressTableLookup], + ) -> Result { + if !self.versioned_tx_message_enabled() { + return Err(TransactionError::UnsupportedVersion); + } + + let slot_hashes = self + .sysvar_cache + .read() + .unwrap() + .get_slot_hashes() + .map_err(|_| TransactionError::AccountNotFound)?; + + Ok(address_table_lookups + .iter() + .map(|address_table_lookup| { + self.rc.accounts.load_lookup_table_addresses( + &self.ancestors, + address_table_lookup, + &slot_hashes, + ) + }) + .collect::>()?) + } + + /// Execute a transaction using the provided loaded accounts and update + /// the executors cache if the transaction was successful. + fn execute_loaded_transaction( + &self, + tx: &SanitizedTransaction, + loaded_transaction: &mut LoadedTransaction, + compute_budget: ComputeBudget, + durable_nonce_fee: Option, + enable_cpi_recording: bool, + enable_log_recording: bool, + timings: &mut ExecuteTimings, + error_counters: &mut ErrorCounters, + ) -> TransactionExecutionResult { + let mut get_executors_time = Measure::start("get_executors_time"); + let executors = self.get_executors( + tx.message(), + &loaded_transaction.accounts, + &loaded_transaction.program_indices, + ); + get_executors_time.stop(); + saturating_add_assign!( + timings.execute_accessories.get_executors_us, + get_executors_time.as_us() + ); + + let mut transaction_accounts = Vec::new(); + std::mem::swap(&mut loaded_transaction.accounts, &mut transaction_accounts); + let mut transaction_context = TransactionContext::new( + transaction_accounts, + compute_budget.max_invoke_depth.saturating_add(1), + ); + + let pre_account_state_info = + self.get_transaction_account_state_info(&transaction_context, tx.message()); + + let instruction_recorder = if enable_cpi_recording { + Some(InstructionRecorder::new_ref( + tx.message().instructions().len(), + )) + } else { + None + }; + + let log_collector = if enable_log_recording { + Some(LogCollector::new_ref()) + } else { + None + }; + + let (blockhash, lamports_per_signature) = self.last_blockhash_and_lamports_per_signature(); + + let mut process_message_time = Measure::start("process_message_time"); + let process_result = MessageProcessor::process_message( + &self.builtin_programs.vec, + tx.message(), + &loaded_transaction.program_indices, + &mut transaction_context, + self.rent_collector.rent, + log_collector.clone(), + executors.clone(), + instruction_recorder.clone(), + self.feature_set.clone(), + compute_budget, + timings, + &*self.sysvar_cache.read().unwrap(), + blockhash, + lamports_per_signature, + self.load_accounts_data_len(), + ); + process_message_time.stop(); + saturating_add_assign!( + timings.execute_accessories.process_message_us, + process_message_time.as_us() + ); + + let mut update_executors_time = Measure::start("update_executors_time"); + self.update_executors(process_result.is_ok(), executors); + update_executors_time.stop(); + saturating_add_assign!( + timings.execute_accessories.update_executors_us, + update_executors_time.as_us() + ); + + let status = process_result + .and_then(|info| { + let post_account_state_info = + self.get_transaction_account_state_info(&transaction_context, tx.message()); + self.verify_transaction_account_state_changes( + &pre_account_state_info, + &post_account_state_info, + &transaction_context, + ) + .map(|_| info) + }) + .map(|info| { + self.store_accounts_data_len(info.accounts_data_len); + }) + .map_err(|err| { + match err { + TransactionError::InvalidRentPayingAccount => { + error_counters.invalid_rent_paying_account += 1; + } + _ => { + error_counters.instruction_error += 1; + } + } + err + }); + + let log_messages: Option = + log_collector.and_then(|log_collector| { + Rc::try_unwrap(log_collector) + .map(|log_collector| log_collector.into_inner().into()) + .ok() + }); + + let inner_instructions = instruction_recorder + .and_then(|instruction_recorder| Rc::try_unwrap(instruction_recorder).ok()) + .map(|instruction_recorder| instruction_recorder.into_inner().deconstruct()); + + loaded_transaction.accounts = transaction_context.deconstruct(); + + TransactionExecutionResult::Executed(TransactionExecutionDetails { + status, + log_messages, + inner_instructions, + durable_nonce_fee, + }) + } + +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) #[allow(clippy::type_complexity)] pub fn load_and_execute_transactions( &self, diff --git a/runtime/src/bank/sysvar_cache.rs b/runtime/src/bank/sysvar_cache.rs index d6e3d42291d..d5c5cd3e9f2 100644 --- a/runtime/src/bank/sysvar_cache.rs +++ b/runtime/src/bank/sysvar_cache.rs @@ -1,17 +1,156 @@ use { super::Bank, +<<<<<<< HEAD solana_sdk::{account::ReadableAccount, sysvar}, +======= + solana_program_runtime::sysvar_cache::SysvarCache, + solana_sdk::{account::ReadableAccount, sysvar::Sysvar}, +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) }; impl Bank { - pub(crate) fn fill_sysvar_cache(&mut self) { + pub(crate) fn fill_missing_sysvar_cache_entries(&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_entry(*id, account.data().to_vec()); - } + if sysvar_cache.get_clock().is_err() { + if let Some(clock) = self.load_sysvar_account() { + sysvar_cache.set_clock(clock); } } + if sysvar_cache.get_epoch_schedule().is_err() { + if let Some(epoch_schedule) = self.load_sysvar_account() { + sysvar_cache.set_epoch_schedule(epoch_schedule); + } + } + #[allow(deprecated)] + if sysvar_cache.get_fees().is_err() { + if let Some(fees) = self.load_sysvar_account() { + sysvar_cache.set_fees(fees); + } + } + if sysvar_cache.get_rent().is_err() { + if let Some(rent) = self.load_sysvar_account() { + sysvar_cache.set_rent(rent); + } + } + if sysvar_cache.get_slot_hashes().is_err() { + if let Some(slot_hashes) = self.load_sysvar_account() { + sysvar_cache.set_slot_hashes(slot_hashes); + } + } + } +<<<<<<< HEAD +======= + + pub(crate) fn reset_sysvar_cache(&self) { + let mut sysvar_cache = self.sysvar_cache.write().unwrap(); + *sysvar_cache = SysvarCache::default(); + } + + fn load_sysvar_account(&self) -> Option { + if let Some(account) = self.get_account_with_fixed_root(&T::id()) { + bincode::deserialize(account.data()).ok() + } else { + None + } + } +} + +#[cfg(test)] +mod tests { + use { + super::*, + solana_sdk::{genesis_config::create_genesis_config, pubkey::Pubkey}, + std::sync::Arc, + }; + + #[test] + #[allow(deprecated)] + fn test_sysvar_cache_initialization() { + let (genesis_config, _mint_keypair) = create_genesis_config(100_000); + let bank0 = Arc::new(Bank::new_for_tests(&genesis_config)); + + let bank0_sysvar_cache = bank0.sysvar_cache.read().unwrap(); + let bank0_cached_clock = bank0_sysvar_cache.get_clock(); + let bank0_cached_epoch_schedule = bank0_sysvar_cache.get_epoch_schedule(); + let bank0_cached_fees = bank0_sysvar_cache.get_fees(); + let bank0_cached_rent = bank0_sysvar_cache.get_rent(); + + assert!(bank0_cached_clock.is_ok()); + assert!(bank0_cached_epoch_schedule.is_ok()); + assert!(bank0_cached_fees.is_ok()); + assert!(bank0_cached_rent.is_ok()); + assert!(bank0 + .sysvar_cache + .read() + .unwrap() + .get_slot_hashes() + .is_err()); + + let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), bank0.slot() + 1); + + let bank1_sysvar_cache = bank1.sysvar_cache.read().unwrap(); + let bank1_cached_clock = bank1_sysvar_cache.get_clock(); + let bank1_cached_epoch_schedule = bank0_sysvar_cache.get_epoch_schedule(); + let bank1_cached_fees = bank0_sysvar_cache.get_fees(); + let bank1_cached_rent = bank0_sysvar_cache.get_rent(); + + assert!(bank1_cached_clock.is_ok()); + assert!(bank1_cached_epoch_schedule.is_ok()); + assert!(bank1_cached_fees.is_ok()); + assert!(bank1_cached_rent.is_ok()); + assert!(bank1.sysvar_cache.read().unwrap().get_slot_hashes().is_ok()); + + assert_ne!(bank0_cached_clock, bank1_cached_clock); + assert_eq!(bank0_cached_epoch_schedule, bank1_cached_epoch_schedule); + assert_eq!(bank0_cached_fees, bank1_cached_fees); + assert_eq!(bank0_cached_rent, bank1_cached_rent); + } + + #[test] + #[allow(deprecated)] + fn test_reset_and_fill_sysvar_cache() { + let (genesis_config, _mint_keypair) = create_genesis_config(100_000); + let bank0 = Arc::new(Bank::new_for_tests(&genesis_config)); + let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), bank0.slot() + 1); + + let bank1_sysvar_cache = bank1.sysvar_cache.read().unwrap(); + let bank1_cached_clock = bank1_sysvar_cache.get_clock(); + let bank1_cached_epoch_schedule = bank1_sysvar_cache.get_epoch_schedule(); + let bank1_cached_fees = bank1_sysvar_cache.get_fees(); + let bank1_cached_rent = bank1_sysvar_cache.get_rent(); + let bank1_cached_slot_hashes = bank1_sysvar_cache.get_slot_hashes(); + + assert!(bank1_cached_clock.is_ok()); + assert!(bank1_cached_epoch_schedule.is_ok()); + assert!(bank1_cached_fees.is_ok()); + assert!(bank1_cached_rent.is_ok()); + assert!(bank1_cached_slot_hashes.is_ok()); + + drop(bank1_sysvar_cache); + bank1.reset_sysvar_cache(); + + let bank1_sysvar_cache = bank1.sysvar_cache.read().unwrap(); + assert!(bank1_sysvar_cache.get_clock().is_err()); + assert!(bank1_sysvar_cache.get_epoch_schedule().is_err()); + assert!(bank1_sysvar_cache.get_fees().is_err()); + assert!(bank1_sysvar_cache.get_rent().is_err()); + assert!(bank1_sysvar_cache.get_slot_hashes().is_err()); + + drop(bank1_sysvar_cache); + bank1.fill_missing_sysvar_cache_entries(); + + let bank1_sysvar_cache = bank1.sysvar_cache.read().unwrap(); + assert_eq!(bank1_sysvar_cache.get_clock(), bank1_cached_clock); + assert_eq!( + bank1_sysvar_cache.get_epoch_schedule(), + bank1_cached_epoch_schedule + ); + assert_eq!(bank1_sysvar_cache.get_fees(), bank1_cached_fees); + assert_eq!(bank1_sysvar_cache.get_rent(), bank1_cached_rent); + assert_eq!( + bank1_sysvar_cache.get_slot_hashes(), + bank1_cached_slot_hashes + ); } +>>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } diff --git a/sdk/src/sysvar_cache.rs b/sdk/src/sysvar_cache.rs index ba9629c9924..6bc744b63b2 100644 --- a/sdk/src/sysvar_cache.rs +++ b/sdk/src/sysvar_cache.rs @@ -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)] @@ -15,25 +19,63 @@ impl ::solana_frozen_abi::abi_example::AbiExample for SysvarCache { } #[derive(Default, Clone, Debug)] -pub struct SysvarCache(Vec<(Pubkey, Vec)>); - -impl Deref for SysvarCache { - type Target = Vec<(Pubkey, Vec)>; - fn deref(&self) -> &Self::Target { - &self.0 - } +pub struct SysvarCache { + clock: Option>, + epoch_schedule: Option>, + #[allow(deprecated)] + fees: Option>, + rent: Option>, + slot_hashes: Option>, } impl SysvarCache { - pub fn push_entry(&mut self, pubkey: Pubkey, data: Vec) { - self.0.push((pubkey, data)); + pub fn get_clock(&self) -> Result, 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, 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, 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, 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, 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)); } } From 6f9156c3a44b5c228d985207198fe93ef4a7a08d Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Fri, 21 Jan 2022 17:37:57 +0800 Subject: [PATCH 2/3] resolve conflicts --- program-test/src/lib.rs | 28 +--- programs/bpf_loader/src/syscalls.rs | 112 +++----------- programs/stake/src/stake_instruction.rs | 76 +--------- programs/vote/src/vote_instruction.rs | 111 ++------------ programs/vote/src/vote_state/mod.rs | 6 +- runtime/benches/bank.rs | 6 +- runtime/src/bank.rs | 186 +----------------------- runtime/src/bank/sysvar_cache.rs | 31 ++-- sdk/src/process_instruction.rs | 21 --- sdk/src/sysvar_cache.rs | 10 +- 10 files changed, 55 insertions(+), 532 deletions(-) diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index 27e07a1a22d..83fed811293 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -1,11 +1,8 @@ //! The solana-program-test provides a BanksClient-based test framework BPF programs #![allow(clippy::integer_arithmetic)] -<<<<<<< HEAD // Export types so test clients can limit their solana crate dependencies pub use solana_banks_client::BanksClient; -======= ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) // Export tokio for test clients pub use tokio; use { @@ -23,17 +20,10 @@ use { solana_sdk::{ account::{Account, AccountSharedData, ReadableAccount, WritableAccount}, account_info::AccountInfo, -<<<<<<< HEAD - clock::{Clock, Slot}, + clock::Slot, entrypoint::{ProgramResult, SUCCESS}, - epoch_schedule::EpochSchedule, execute_timings::ExecuteTimings, feature_set::demote_program_write_locks, -======= - clock::Slot, - compute_budget::ComputeBudget, - entrypoint::{ProgramResult, SUCCESS}, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) fee_calculator::{FeeCalculator, FeeRateGovernor}, genesis_config::{ClusterType, GenesisConfig}, hash::Hash, @@ -42,21 +32,13 @@ use { native_token::sol_to_lamports, poh_config::PohConfig, process_instruction::{ - self, stable_log, BpfComputeBudget, InvokeContext, ProcessInstructionWithContext, + stable_log, BpfComputeBudget, InvokeContext, ProcessInstructionWithContext, }, program_error::{ProgramError, ACCOUNT_BORROW_FAILED, UNSUPPORTED_SYSVAR}, pubkey::Pubkey, rent::Rent, signature::{Keypair, Signer}, -<<<<<<< HEAD - sysvar::{ - clock, epoch_schedule, - fees::{self, Fees}, - rent, Sysvar, - }, -======= - sysvar::{Sysvar, SysvarId}, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) + sysvar::Sysvar, }, solana_vote_program::vote_state::{VoteState, VoteStateVersions}, std::{ @@ -220,12 +202,8 @@ fn get_sysvar { panic!("Exceeded compute budget"); } -<<<<<<< HEAD - match process_instruction::get_sysvar::(invoke_context, id) { -======= match sysvar { ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) Ok(sysvar_data) => unsafe { *(var_addr as *mut _ as *mut T) = T::clone(&sysvar_data); SUCCESS diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index b89c7c9a75a..3e9e2cf5ae9 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -13,14 +13,9 @@ use { solana_sdk::{ account::{Account, AccountSharedData, ReadableAccount}, account_info::AccountInfo, -<<<<<<< HEAD account_utils::StateMut, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable::{self, UpgradeableLoaderState}, - clock::Clock, -======= - blake3, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) entrypoint::{BPF_ALIGN_OF_U128, MAX_PERMITTED_DATA_INCREASE, SUCCESS}, feature_set::{ allow_native_ids, check_seed_length, close_upgradeable_program_accounts, cpi_data_cost, @@ -36,18 +31,13 @@ use { keccak, keyed_account::KeyedAccount, native_loader, - process_instruction::{self, stable_log, ComputeMeter, InvokeContext, Logger}, + process_instruction::{stable_log, ComputeMeter, InvokeContext, Logger}, program::MAX_RETURN_DATA, pubkey::{Pubkey, PubkeyError, MAX_SEEDS, MAX_SEED_LEN}, secp256k1_recover::{ Secp256k1RecoverError, SECP256K1_PUBLIC_KEY_LENGTH, SECP256K1_SIGNATURE_LENGTH, }, -<<<<<<< HEAD - sysvar::{self, fees::Fees, Sysvar, SysvarId}, -======= - sysvar::{Sysvar, SysvarId}, - transaction_context::InstructionAccount, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) + sysvar::{self, Sysvar, SysvarId}, }, std::{ alloc::Layout, @@ -1155,13 +1145,8 @@ fn get_sysvar( var_addr: u64, loader_id: &Pubkey, memory_mapping: &MemoryMapping, - invoke_context: Rc>, + invoke_context: &dyn InvokeContext, ) -> Result> { - let invoke_context = invoke_context - .try_borrow() - .map_err(|_| SyscallError::InvokeContextBorrowFailed)?; - -<<<<<<< HEAD invoke_context.get_compute_meter().consume( invoke_context.get_bpf_compute_budget().sysvar_base_cost + size_of::() as u64, )?; @@ -1172,12 +1157,8 @@ fn get_sysvar( invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()), )?; - *var = process_instruction::get_sysvar::(*invoke_context, id) - .map_err(SyscallError::InstructionError)?; -======= let sysvar: Arc = sysvar.map_err(SyscallError::InstructionError)?; *var = T::clone(sysvar.as_ref()); ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) Ok(SUCCESS) } @@ -1198,30 +1179,18 @@ impl<'a> SyscallObject for SyscallGetClockSysvar<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { -<<<<<<< HEAD - *result = get_sysvar::( - &sysvar::clock::id(), -======= - let mut invoke_context = question_mark!( + let invoke_context = question_mark!( self.invoke_context - .try_borrow_mut() + .try_borrow() .map_err(|_| SyscallError::InvokeContextBorrowFailed), result ); - let loader_id = question_mark!( - invoke_context - .transaction_context - .get_loader_key() - .map_err(SyscallError::InstructionError), - result - ); *result = get_sysvar( invoke_context.get_sysvar_cache().get_clock(), ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) var_addr, self.loader_id, memory_mapping, - self.invoke_context.clone(), + *invoke_context, ); } } @@ -1241,30 +1210,18 @@ impl<'a> SyscallObject for SyscallGetEpochScheduleSysvar<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { -<<<<<<< HEAD - *result = get_sysvar::( - &sysvar::epoch_schedule::id(), -======= - let mut invoke_context = question_mark!( + let invoke_context = question_mark!( self.invoke_context - .try_borrow_mut() + .try_borrow() .map_err(|_| SyscallError::InvokeContextBorrowFailed), result ); - let loader_id = question_mark!( - invoke_context - .transaction_context - .get_loader_key() - .map_err(SyscallError::InstructionError), - result - ); *result = get_sysvar( invoke_context.get_sysvar_cache().get_epoch_schedule(), ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) var_addr, self.loader_id, memory_mapping, - self.invoke_context.clone(), + *invoke_context, ); } } @@ -1284,30 +1241,18 @@ impl<'a> SyscallObject for SyscallGetFeesSysvar<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { -<<<<<<< HEAD - *result = get_sysvar::( - &sysvar::fees::id(), -======= - let mut invoke_context = question_mark!( + let invoke_context = question_mark!( self.invoke_context - .try_borrow_mut() + .try_borrow() .map_err(|_| SyscallError::InvokeContextBorrowFailed), result ); - let loader_id = question_mark!( - invoke_context - .transaction_context - .get_loader_key() - .map_err(SyscallError::InstructionError), - result - ); *result = get_sysvar( invoke_context.get_sysvar_cache().get_fees(), ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) var_addr, self.loader_id, memory_mapping, - self.invoke_context.clone(), + *invoke_context, ); } } @@ -1327,30 +1272,18 @@ impl<'a> SyscallObject for SyscallGetRentSysvar<'a> { memory_mapping: &MemoryMapping, result: &mut Result>, ) { -<<<<<<< HEAD - *result = get_sysvar::( - &sysvar::rent::id(), -======= - let mut invoke_context = question_mark!( + let invoke_context = question_mark!( self.invoke_context - .try_borrow_mut() + .try_borrow() .map_err(|_| SyscallError::InvokeContextBorrowFailed), result ); - let loader_id = question_mark!( - invoke_context - .transaction_context - .get_loader_key() - .map_err(SyscallError::InstructionError), - result - ); *result = get_sysvar( invoke_context.get_sysvar_cache().get_rent(), ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) var_addr, self.loader_id, memory_mapping, - self.invoke_context.clone(), + *invoke_context, ); } } @@ -2849,28 +2782,21 @@ impl<'a> SyscallObject for SyscallLogData<'a> { #[cfg(test)] mod tests { - #[allow(deprecated)] - use solana_sdk::sysvar::fees::Fees; use { super::*, solana_rbpf::{ ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config, }, solana_sdk::{ -<<<<<<< HEAD bpf_loader, + clock::Clock, + epoch_schedule::EpochSchedule, fee_calculator::FeeCalculator, hash::hashv, process_instruction::{MockComputeMeter, MockInvokeContext, MockLogger}, + rent::Rent, + sysvar::fees::Fees, sysvar_cache::SysvarCache, -======= - account::AccountSharedData, - bpf_loader, - fee_calculator::FeeCalculator, - hash::hashv, - sysvar::{clock::Clock, epoch_schedule::EpochSchedule, rent::Rent}, - transaction_context::TransactionContext, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) }, std::{borrow::Cow, str::FromStr}, }; diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index 85288e926ea..1189e8ba1b5 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -10,7 +10,7 @@ use { feature_set, instruction::InstructionError, keyed_account::{from_keyed_account, get_signers, keyed_account_at_index}, - process_instruction::{get_sysvar, InvokeContext}, + process_instruction::InvokeContext, program_utils::limited_deserialize, pubkey::Pubkey, stake::{ @@ -166,16 +166,8 @@ pub fn process_instruction( &signers, ), StakeInstruction::SetLockup(lockup) => { -<<<<<<< HEAD let clock = if invoke_context.is_feature_active(&feature_set::stake_program_v4::id()) { - Some(get_sysvar::(invoke_context, &sysvar::clock::id())?) -======= - let clock = if invoke_context - .feature_set - .is_active(&feature_set::stake_program_v4::id()) - { Some(invoke_context.get_sysvar_cache().get_clock()?) ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } else { None }; @@ -270,13 +262,8 @@ pub fn process_instruction( epoch: lockup_checked.epoch, custodian, }; -<<<<<<< HEAD - let clock = Some(get_sysvar::(invoke_context, &sysvar::clock::id())?); - me.set_lockup(&lockup, &signers, clock.as_ref()) -======= let clock = Some(invoke_context.get_sysvar_cache().get_clock()?); me.set_lockup(&lockup, &signers, clock.as_deref()) ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } else { Err(InstructionError::InvalidInstructionData) } @@ -301,12 +288,8 @@ mod tests { instruction::{self, LockupArgs}, state::{Authorized, Lockup, StakeAuthorize}, }, -<<<<<<< HEAD - sysvar::stake_history::StakeHistory, - sysvar_cache::SysvarCache, -======= sysvar::{self, stake_history::StakeHistory}, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) + sysvar_cache::SysvarCache, }, std::{borrow::Cow, cell::RefCell, str::FromStr}, }; @@ -378,7 +361,6 @@ mod tests { }) }) .collect(); -<<<<<<< HEAD { let keyed_accounts: Vec<_> = instruction @@ -390,27 +372,10 @@ mod tests { let mut invoke_context = MockInvokeContext::new(keyed_accounts); let mut sysvar_cache = SysvarCache::default(); - sysvar_cache.push_entry( - sysvar::clock::id(), - bincode::serialize(&Clock::default()).unwrap(), - ); + sysvar_cache.set_clock(Clock::default()); invoke_context.sysvar_cache = Cow::Owned(sysvar_cache); super::process_instruction(&Pubkey::default(), &instruction.data, &mut invoke_context) } -======= - let mut sysvar_cache = SysvarCache::default(); - sysvar_cache.set_clock(Clock::default()); - mock_process_instruction_with_sysvars( - &id(), - Vec::new(), - &instruction.data, - transaction_accounts, - instruction.accounts.clone(), - expected_result, - &sysvar_cache, - super::process_instruction, - ) ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } #[test] @@ -1072,11 +1037,7 @@ mod tests { let mut invoke_context = MockInvokeContext::new(keyed_accounts); let mut sysvar_cache = SysvarCache::default(); -<<<<<<< HEAD - sysvar_cache.push_entry( - sysvar::clock::id(), - bincode::serialize(&Clock::default()).unwrap(), - ); + sysvar_cache.set_clock(Clock::default()); invoke_context.sysvar_cache = Cow::Owned(sysvar_cache); assert_eq!( @@ -1089,35 +1050,6 @@ mod tests { .unwrap(), &mut invoke_context ), -======= - sysvar_cache.set_clock(Clock::default()); - mock_process_instruction_with_sysvars( - &id(), - Vec::new(), - &instruction.data, - vec![ - (stake_address, stake_account), - (withdrawer, withdrawer_account), - (custodian, custodian_account), - ], - vec![ - AccountMeta { - pubkey: stake_address, - is_signer: false, - is_writable: false, - }, - AccountMeta { - pubkey: withdrawer, - is_signer: true, - is_writable: false, - }, - AccountMeta { - pubkey: custodian, - is_signer: true, - is_writable: false, - }, - ], ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) Ok(()), ); } diff --git a/programs/vote/src/vote_instruction.rs b/programs/vote/src/vote_instruction.rs index cb29b8d20d9..028f4ee9af1 100644 --- a/programs/vote/src/vote_instruction.rs +++ b/programs/vote/src/vote_instruction.rs @@ -19,7 +19,7 @@ use { check_sysvar_keyed_account, from_keyed_account, get_signers, keyed_account_at_index, KeyedAccount, }, - process_instruction::{get_sysvar, InvokeContext}, + process_instruction::InvokeContext, program_utils::limited_deserialize, pubkey::Pubkey, system_instruction, @@ -316,20 +316,12 @@ fn verify_rent_exemption( /// order to keep consistent behavior, they continue to enforce the same checks /// as `solana_sdk::keyed_account::from_keyed_account` despite dynamically /// loading them instead of deserializing from account data. -<<<<<<< HEAD -fn get_sysvar_with_keyed_account_check( - keyed_account: &KeyedAccount, - invoke_context: &dyn InvokeContext, -) -> Result { - check_sysvar_keyed_account::(keyed_account)?; - get_sysvar(invoke_context, keyed_account.unsigned_key()) -======= mod get_sysvar_with_keyed_account_check { use super::*; pub fn clock( keyed_account: &KeyedAccount, - invoke_context: &InvokeContext, + invoke_context: &dyn InvokeContext, ) -> Result, InstructionError> { check_sysvar_keyed_account::(keyed_account)?; invoke_context.get_sysvar_cache().get_clock() @@ -337,7 +329,7 @@ mod get_sysvar_with_keyed_account_check { pub fn rent( keyed_account: &KeyedAccount, - invoke_context: &InvokeContext, + invoke_context: &dyn InvokeContext, ) -> Result, InstructionError> { check_sysvar_keyed_account::(keyed_account)?; invoke_context.get_sysvar_cache().get_rent() @@ -345,12 +337,11 @@ mod get_sysvar_with_keyed_account_check { pub fn slot_hashes( keyed_account: &KeyedAccount, - invoke_context: &InvokeContext, + invoke_context: &dyn InvokeContext, ) -> Result, InstructionError> { check_sysvar_keyed_account::(keyed_account)?; invoke_context.get_sysvar_cache().get_slot_hashes() } ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } pub fn process_instruction( @@ -375,35 +366,20 @@ pub fn process_instruction( match limited_deserialize(data)? { VoteInstruction::InitializeAccount(vote_init) => { -<<<<<<< HEAD - let rent: Rent = get_sysvar_with_keyed_account_check( - keyed_account_at_index(keyed_accounts, 1)?, - invoke_context, - )?; - verify_rent_exemption(me, &rent)?; - let clock: Clock = get_sysvar_with_keyed_account_check( - keyed_account_at_index(keyed_accounts, 2)?, -======= let rent = get_sysvar_with_keyed_account_check::rent( - keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?, + keyed_account_at_index(keyed_accounts, 1)?, invoke_context, )?; verify_rent_exemption(me, &rent)?; let clock = get_sysvar_with_keyed_account_check::clock( - keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) + keyed_account_at_index(keyed_accounts, 2)?, invoke_context, )?; vote_state::initialize_account(me, &vote_init, &signers, &clock) } VoteInstruction::Authorize(voter_pubkey, vote_authorize) => { -<<<<<<< HEAD - let clock: Clock = get_sysvar_with_keyed_account_check( - keyed_account_at_index(keyed_accounts, 1)?, -======= let clock = get_sysvar_with_keyed_account_check::clock( - keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) + keyed_account_at_index(keyed_accounts, 1)?, invoke_context, )?; vote_state::authorize(me, &voter_pubkey, vote_authorize, &signers, &clock) @@ -418,59 +394,22 @@ pub fn process_instruction( } VoteInstruction::Vote(vote) | VoteInstruction::VoteSwitch(vote, _) => { inc_new_counter_info!("vote-native", 1); -<<<<<<< HEAD - let slot_hashes: SlotHashes = get_sysvar_with_keyed_account_check( - keyed_account_at_index(keyed_accounts, 1)?, - invoke_context, - )?; - let clock: Clock = get_sysvar_with_keyed_account_check( - keyed_account_at_index(keyed_accounts, 2)?, -======= let slot_hashes = get_sysvar_with_keyed_account_check::slot_hashes( - keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?, + keyed_account_at_index(keyed_accounts, 1)?, invoke_context, )?; let clock = get_sysvar_with_keyed_account_check::clock( - keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) + keyed_account_at_index(keyed_accounts, 2)?, invoke_context, )?; vote_state::process_vote(me, &slot_hashes, &clock, &vote, &signers) } -<<<<<<< HEAD -======= - VoteInstruction::UpdateVoteState(vote_state_update) - | VoteInstruction::UpdateVoteStateSwitch(vote_state_update, _) => { - if invoke_context - .feature_set - .is_active(&feature_set::allow_votes_to_directly_update_vote_state::id()) - { - inc_new_counter_info!("vote-state-native", 1); - let sysvar_cache = invoke_context.get_sysvar_cache(); - let slot_hashes = sysvar_cache.get_slot_hashes()?; - let clock = sysvar_cache.get_clock()?; - vote_state::process_vote_state_update( - me, - slot_hashes.slot_hashes(), - &clock, - vote_state_update, - &signers, - ) - } else { - Err(InstructionError::InvalidInstructionData) - } - } ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) VoteInstruction::Withdraw(lamports) => { let to = keyed_account_at_index(keyed_accounts, 1)?; let rent_sysvar = if invoke_context .is_feature_active(&feature_set::reject_non_rent_exempt_vote_withdraws::id()) { -<<<<<<< HEAD - Some(get_sysvar(invoke_context, &sysvar::rent::id())?) -======= Some(invoke_context.get_sysvar_cache().get_rent()?) ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } else { None }; @@ -552,7 +491,6 @@ mod tests { }) }) .collect(); -<<<<<<< HEAD for _ in 0..instruction.accounts.len() { accounts.push(RefCell::new(AccountSharedData::default())); @@ -566,37 +504,12 @@ mod tests { .collect(); let mut invoke_context = MockInvokeContext::new(keyed_accounts); let mut sysvar_cache = SysvarCache::default(); - sysvar_cache.push_entry( - sysvar::rent::id(), - bincode::serialize(&Rent::free()).unwrap(), - ); - sysvar_cache.push_entry( - sysvar::clock::id(), - bincode::serialize(&Clock::default()).unwrap(), - ); - sysvar_cache.push_entry( - sysvar::slot_hashes::id(), - bincode::serialize(&SlotHashes::default()).unwrap(), - ); + sysvar_cache.set_rent(Rent::free()); + sysvar_cache.set_clock(Clock::default()); + sysvar_cache.set_slot_hashes(SlotHashes::default()); invoke_context.sysvar_cache = Cow::Owned(sysvar_cache); super::process_instruction(&Pubkey::default(), &instruction.data, &mut invoke_context) } -======= - let mut sysvar_cache = SysvarCache::default(); - sysvar_cache.set_rent(Rent::free()); - sysvar_cache.set_clock(Clock::default()); - sysvar_cache.set_slot_hashes(SlotHashes::default()); - mock_process_instruction_with_sysvars( - &id(), - Vec::new(), - &instruction.data, - transaction_accounts, - instruction.accounts.clone(), - expected_result, - &sysvar_cache, - super::process_instruction, - ) ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } fn invalid_vote_state_pubkey() -> Pubkey { diff --git a/programs/vote/src/vote_state/mod.rs b/programs/vote/src/vote_state/mod.rs index 32ed74f1872..754888e44d0 100644 --- a/programs/vote/src/vote_state/mod.rs +++ b/programs/vote/src/vote_state/mod.rs @@ -1778,11 +1778,7 @@ mod tests { // full withdraw, before/after activation { let rent_sysvar = Rent::default(); -<<<<<<< HEAD for rent_sysvar in &[None, Some(rent_sysvar)] { -======= - for rent_sysvar in [None, Some(&rent_sysvar)] { ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) let to_account = RefCell::new(AccountSharedData::default()); let (vote_pubkey, vote_account) = create_test_account(); let lamports = vote_account.borrow().lamports(); @@ -1793,7 +1789,7 @@ mod tests { lamports, &KeyedAccount::new(&solana_sdk::pubkey::new_rand(), false, &to_account), &signers, - *rent_sysvar, + rent_sysvar.as_ref(), ); assert_eq!(res, Ok(())); assert_eq!(vote_account.borrow().lamports(), 0); diff --git a/runtime/benches/bank.rs b/runtime/benches/bank.rs index 15856df5d07..0e6bac9f28c 100644 --- a/runtime/benches/bank.rs +++ b/runtime/benches/bank.rs @@ -175,16 +175,12 @@ fn do_bench_transactions( let ns_per_s = 1_000_000_000; let (mut genesis_config, mint_keypair) = create_genesis_config(100_000_000_000_000); genesis_config.ticks_per_slot = 100; -<<<<<<< HEAD - let mut bank = Bank::new(&genesis_config); -======= - let bank = Bank::new_for_benches(&genesis_config); + let bank = Bank::new(&genesis_config); // freeze bank so that slot hashes is populated bank.freeze(); let mut bank = Bank::new_from_parent(&Arc::new(bank), &Pubkey::default(), 1); ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) bank.add_builtin( "builtin_program", Pubkey::new(&BUILTIN_PROGRAM_ID), diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 0a9c3b6eb43..e7c49808dc8 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -114,8 +114,7 @@ use { signature::{Keypair, Signature}, slot_hashes::SlotHashes, slot_history::SlotHistory, - system_transaction, - sysvar::{self}, + system_transaction, sysvar, sysvar_cache::SysvarCache, timing::years_as_slots, transaction::{self, Result, Transaction, TransactionError}, @@ -1475,14 +1474,10 @@ impl Bank { new.update_stake_history(Some(parent_epoch)); new.update_clock(Some(parent_epoch)); new.update_fees(); -<<<<<<< HEAD if !new.fix_recent_blockhashes_sysvar_delay() { new.update_recent_blockhashes(); } - new.fill_sysvar_cache(); -======= new.fill_missing_sysvar_cache_entries(); ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) time.stop(); @@ -1902,25 +1897,6 @@ impl Bank { }); } -<<<<<<< HEAD -======= - pub fn set_sysvar_for_tests(&self, sysvar: &T) - where - T: Sysvar + SysvarId, - { - self.update_sysvar_account(&T::id(), |account| { - create_account( - sysvar, - self.inherit_specially_retained_account_fields(account), - ) - }); - // 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(); - } - ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) fn update_slot_history(&self) { self.update_sysvar_account(&sysvar::slot_history::id(), |account| { let mut slot_history = account @@ -3473,166 +3449,6 @@ impl Bank { Arc::make_mut(&mut cache).remove(pubkey); } -<<<<<<< HEAD -======= - pub fn load_lookup_table_addresses( - &self, - address_table_lookups: &[MessageAddressTableLookup], - ) -> Result { - if !self.versioned_tx_message_enabled() { - return Err(TransactionError::UnsupportedVersion); - } - - let slot_hashes = self - .sysvar_cache - .read() - .unwrap() - .get_slot_hashes() - .map_err(|_| TransactionError::AccountNotFound)?; - - Ok(address_table_lookups - .iter() - .map(|address_table_lookup| { - self.rc.accounts.load_lookup_table_addresses( - &self.ancestors, - address_table_lookup, - &slot_hashes, - ) - }) - .collect::>()?) - } - - /// Execute a transaction using the provided loaded accounts and update - /// the executors cache if the transaction was successful. - fn execute_loaded_transaction( - &self, - tx: &SanitizedTransaction, - loaded_transaction: &mut LoadedTransaction, - compute_budget: ComputeBudget, - durable_nonce_fee: Option, - enable_cpi_recording: bool, - enable_log_recording: bool, - timings: &mut ExecuteTimings, - error_counters: &mut ErrorCounters, - ) -> TransactionExecutionResult { - let mut get_executors_time = Measure::start("get_executors_time"); - let executors = self.get_executors( - tx.message(), - &loaded_transaction.accounts, - &loaded_transaction.program_indices, - ); - get_executors_time.stop(); - saturating_add_assign!( - timings.execute_accessories.get_executors_us, - get_executors_time.as_us() - ); - - let mut transaction_accounts = Vec::new(); - std::mem::swap(&mut loaded_transaction.accounts, &mut transaction_accounts); - let mut transaction_context = TransactionContext::new( - transaction_accounts, - compute_budget.max_invoke_depth.saturating_add(1), - ); - - let pre_account_state_info = - self.get_transaction_account_state_info(&transaction_context, tx.message()); - - let instruction_recorder = if enable_cpi_recording { - Some(InstructionRecorder::new_ref( - tx.message().instructions().len(), - )) - } else { - None - }; - - let log_collector = if enable_log_recording { - Some(LogCollector::new_ref()) - } else { - None - }; - - let (blockhash, lamports_per_signature) = self.last_blockhash_and_lamports_per_signature(); - - let mut process_message_time = Measure::start("process_message_time"); - let process_result = MessageProcessor::process_message( - &self.builtin_programs.vec, - tx.message(), - &loaded_transaction.program_indices, - &mut transaction_context, - self.rent_collector.rent, - log_collector.clone(), - executors.clone(), - instruction_recorder.clone(), - self.feature_set.clone(), - compute_budget, - timings, - &*self.sysvar_cache.read().unwrap(), - blockhash, - lamports_per_signature, - self.load_accounts_data_len(), - ); - process_message_time.stop(); - saturating_add_assign!( - timings.execute_accessories.process_message_us, - process_message_time.as_us() - ); - - let mut update_executors_time = Measure::start("update_executors_time"); - self.update_executors(process_result.is_ok(), executors); - update_executors_time.stop(); - saturating_add_assign!( - timings.execute_accessories.update_executors_us, - update_executors_time.as_us() - ); - - let status = process_result - .and_then(|info| { - let post_account_state_info = - self.get_transaction_account_state_info(&transaction_context, tx.message()); - self.verify_transaction_account_state_changes( - &pre_account_state_info, - &post_account_state_info, - &transaction_context, - ) - .map(|_| info) - }) - .map(|info| { - self.store_accounts_data_len(info.accounts_data_len); - }) - .map_err(|err| { - match err { - TransactionError::InvalidRentPayingAccount => { - error_counters.invalid_rent_paying_account += 1; - } - _ => { - error_counters.instruction_error += 1; - } - } - err - }); - - let log_messages: Option = - log_collector.and_then(|log_collector| { - Rc::try_unwrap(log_collector) - .map(|log_collector| log_collector.into_inner().into()) - .ok() - }); - - let inner_instructions = instruction_recorder - .and_then(|instruction_recorder| Rc::try_unwrap(instruction_recorder).ok()) - .map(|instruction_recorder| instruction_recorder.into_inner().deconstruct()); - - loaded_transaction.accounts = transaction_context.deconstruct(); - - TransactionExecutionResult::Executed(TransactionExecutionDetails { - status, - log_messages, - inner_instructions, - durable_nonce_fee, - }) - } - ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) #[allow(clippy::type_complexity)] pub fn load_and_execute_transactions( &self, diff --git a/runtime/src/bank/sysvar_cache.rs b/runtime/src/bank/sysvar_cache.rs index d5c5cd3e9f2..4b9950ec795 100644 --- a/runtime/src/bank/sysvar_cache.rs +++ b/runtime/src/bank/sysvar_cache.rs @@ -1,11 +1,6 @@ use { super::Bank, -<<<<<<< HEAD - solana_sdk::{account::ReadableAccount, sysvar}, -======= - solana_program_runtime::sysvar_cache::SysvarCache, solana_sdk::{account::ReadableAccount, sysvar::Sysvar}, ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) }; impl Bank { @@ -21,7 +16,6 @@ impl Bank { sysvar_cache.set_epoch_schedule(epoch_schedule); } } - #[allow(deprecated)] if sysvar_cache.get_fees().is_err() { if let Some(fees) = self.load_sysvar_account() { sysvar_cache.set_fees(fees); @@ -38,13 +32,6 @@ impl Bank { } } } -<<<<<<< HEAD -======= - - pub(crate) fn reset_sysvar_cache(&self) { - let mut sysvar_cache = self.sysvar_cache.write().unwrap(); - *sysvar_cache = SysvarCache::default(); - } fn load_sysvar_account(&self) -> Option { if let Some(account) = self.get_account_with_fixed_root(&T::id()) { @@ -59,15 +46,23 @@ impl Bank { mod tests { use { super::*, - solana_sdk::{genesis_config::create_genesis_config, pubkey::Pubkey}, + solana_sdk::{ + genesis_config::create_genesis_config, pubkey::Pubkey, sysvar_cache::SysvarCache, + }, std::sync::Arc, }; + impl Bank { + pub(crate) fn reset_sysvar_cache(&self) { + let mut sysvar_cache = self.sysvar_cache.write().unwrap(); + *sysvar_cache = SysvarCache::default(); + } + } + #[test] - #[allow(deprecated)] fn test_sysvar_cache_initialization() { let (genesis_config, _mint_keypair) = create_genesis_config(100_000); - let bank0 = Arc::new(Bank::new_for_tests(&genesis_config)); + let bank0 = Arc::new(Bank::new(&genesis_config)); let bank0_sysvar_cache = bank0.sysvar_cache.read().unwrap(); let bank0_cached_clock = bank0_sysvar_cache.get_clock(); @@ -107,10 +102,9 @@ mod tests { } #[test] - #[allow(deprecated)] fn test_reset_and_fill_sysvar_cache() { let (genesis_config, _mint_keypair) = create_genesis_config(100_000); - let bank0 = Arc::new(Bank::new_for_tests(&genesis_config)); + let bank0 = Arc::new(Bank::new(&genesis_config)); let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), bank0.slot() + 1); let bank1_sysvar_cache = bank1.sysvar_cache.read().unwrap(); @@ -152,5 +146,4 @@ mod tests { bank1_cached_slot_hashes ); } ->>>>>>> 2370e61431 (Perf: Store deserialized sysvars in the sysvars cache (#22455)) } diff --git a/sdk/src/process_instruction.rs b/sdk/src/process_instruction.rs index 061fb6933d6..2c26a7a94c3 100644 --- a/sdk/src/process_instruction.rs +++ b/sdk/src/process_instruction.rs @@ -7,7 +7,6 @@ use { instruction::{CompiledInstruction, Instruction, InstructionError}, keyed_account::{create_keyed_accounts_unified, KeyedAccount}, pubkey::Pubkey, - sysvar::Sysvar, }, std::{borrow::Cow, cell::RefCell, collections::HashSet, fmt::Debug, rc::Rc, sync::Arc}, }; @@ -145,26 +144,6 @@ macro_rules! ic_msg { }; } -pub fn get_sysvar( - invoke_context: &dyn InvokeContext, - id: &Pubkey, -) -> Result { - invoke_context - .get_sysvar_cache() - .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)] pub struct BpfComputeBudget { /// Number of compute units that an instruction is allowed. Compute units diff --git a/sdk/src/sysvar_cache.rs b/sdk/src/sysvar_cache.rs index 6bc744b63b2..71e69b7ca53 100644 --- a/sdk/src/sysvar_cache.rs +++ b/sdk/src/sysvar_cache.rs @@ -1,10 +1,9 @@ -#[allow(deprecated)] -use solana_sdk::sysvar::fees::Fees; use { solana_sdk::{ instruction::InstructionError, sysvar::{ - clock::Clock, epoch_schedule::EpochSchedule, rent::Rent, slot_hashes::SlotHashes, + clock::Clock, epoch_schedule::EpochSchedule, fees::Fees, rent::Rent, + slot_hashes::SlotHashes, }, }, std::sync::Arc, @@ -22,7 +21,6 @@ impl ::solana_frozen_abi::abi_example::AbiExample for SysvarCache { pub struct SysvarCache { clock: Option>, epoch_schedule: Option>, - #[allow(deprecated)] fees: Option>, rent: Option>, slot_hashes: Option>, @@ -49,14 +47,10 @@ impl SysvarCache { self.epoch_schedule = Some(Arc::new(epoch_schedule)); } - #[deprecated] - #[allow(deprecated)] pub fn get_fees(&self) -> Result, 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)); } From b1fb18e54c1c760c0a84ce7304859d2de83fbf5c Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Sat, 22 Jan 2022 11:30:18 +0800 Subject: [PATCH 3/3] remove bench --- runtime/benches/bank.rs | 65 ++--------------------------------------- 1 file changed, 2 insertions(+), 63 deletions(-) diff --git a/runtime/benches/bank.rs b/runtime/benches/bank.rs index 0e6bac9f28c..ffc58e99ef6 100644 --- a/runtime/benches/bank.rs +++ b/runtime/benches/bank.rs @@ -17,10 +17,6 @@ use { signature::{Keypair, Signer}, transaction::Transaction, }, - solana_vote_program::{ - vote_instruction, - vote_state::{Vote, VoteInit}, - }, std::{sync::Arc, thread::sleep, time::Duration}, test::Bencher, }; @@ -66,52 +62,6 @@ pub fn create_builtin_transactions( .collect() } -pub fn create_vote_transactions( - bank_client: &BankClient, - mint_keypair: &Keypair, -) -> Vec { - let blockhash = bank_client.get_latest_blockhash().unwrap(); - (0..4096) - .map(|_| { - // Seed the signer account - let payer_keypair = Keypair::new(); - bank_client - .transfer_and_confirm(27_000_000, mint_keypair, &payer_keypair.pubkey()) - .unwrap_or_else(|_| panic!("{}:{}", line!(), file!())); - - // Setup vote - let vote_keypair = Keypair::new(); - let instructions = vote_instruction::create_account( - &payer_keypair.pubkey(), - &vote_keypair.pubkey(), - &VoteInit { - node_pubkey: payer_keypair.pubkey(), - authorized_voter: payer_keypair.pubkey(), - authorized_withdrawer: payer_keypair.pubkey(), - commission: 100u8, - }, - 26_858_640, - ); - let message = Message::new(&instructions, Some(&payer_keypair.pubkey())); - bank_client - .send_and_confirm_message(&[&payer_keypair, &vote_keypair], message) - .unwrap(); - - let vote_ix = vote_instruction::vote( - &vote_keypair.pubkey(), - &payer_keypair.pubkey(), - Vote { - slots: vec![0], - hash: blockhash, - timestamp: None, - }, - ); - let message = Message::new(&[vote_ix], Some(&payer_keypair.pubkey())); - Transaction::new(&[&payer_keypair], message, blockhash) - }) - .collect() -} - pub fn create_native_loader_transactions( bank_client: &BankClient, mint_keypair: &Keypair, @@ -173,14 +123,9 @@ fn do_bench_transactions( ) { solana_logger::setup(); let ns_per_s = 1_000_000_000; - let (mut genesis_config, mint_keypair) = create_genesis_config(100_000_000_000_000); + let (mut genesis_config, mint_keypair) = create_genesis_config(100_000_000); genesis_config.ticks_per_slot = 100; - - let bank = Bank::new(&genesis_config); - // freeze bank so that slot hashes is populated - bank.freeze(); - - let mut bank = Bank::new_from_parent(&Arc::new(bank), &Pubkey::default(), 1); + let mut bank = Bank::new(&genesis_config); bank.add_builtin( "builtin_program", Pubkey::new(&BUILTIN_PROGRAM_ID), @@ -221,12 +166,6 @@ fn bench_bank_sync_process_native_loader_transactions(bencher: &mut Bencher) { do_bench_transactions(bencher, &sync_bencher, &create_native_loader_transactions); } -#[bench] -#[ignore] -fn bench_bank_sync_process_vote_transactions(bencher: &mut Bencher) { - do_bench_transactions(bencher, &sync_bencher, &create_vote_transactions); -} - #[bench] #[ignore] fn bench_bank_async_process_builtin_transactions(bencher: &mut Bencher) {