From 51f6be25fe91c8eae97c55bcca4733797bc72d82 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 8 Jan 2024 11:11:26 +0000 Subject: [PATCH] don't serialize executable accounts --- ledger-tool/src/program.rs | 3 ++ program-runtime/src/loaded_programs.rs | 40 ++++++++++++++- programs/bpf_loader/src/lib.rs | 29 +++++++++-- programs/loader-v4/src/lib.rs | 8 ++- programs/sbf/tests/programs.rs | 1 + sdk/src/feature_set.rs | 10 ++++ sdk/src/transaction_context.rs | 47 +++++++++++++++++ svm/src/account_loader.rs | 70 ++++++++++++++++++++++---- svm/src/transaction_processor.rs | 12 +++++ 9 files changed, 204 insertions(+), 16 deletions(-) diff --git a/ledger-tool/src/program.rs b/ledger-tool/src/program.rs index af50d59bca0255..12cd8ee44602b8 100644 --- a/ledger-tool/src/program.rs +++ b/ledger-tool/src/program.rs @@ -25,6 +25,7 @@ use { account_utils::StateMut, bpf_loader_upgradeable::{self, UpgradeableLoaderState}, pubkey::Pubkey, + rent_collector::RENT_EXEMPT_RENT_EPOCH, slot_history::Slot, transaction_context::{IndexOfAccount, InstructionAccount}, }, @@ -337,6 +338,8 @@ fn load_program<'a>( &contents, &loader_key, account_size, + RENT_EXEMPT_RENT_EPOCH, + 1, slot, Arc::new(program_runtime_environment), false, diff --git a/program-runtime/src/loaded_programs.rs b/program-runtime/src/loaded_programs.rs index 2739d44c36f4cd..017603613692f0 100644 --- a/program-runtime/src/loaded_programs.rs +++ b/program-runtime/src/loaded_programs.rs @@ -18,6 +18,7 @@ use { clock::{Epoch, Slot}, loader_v4, pubkey::Pubkey, + rent_collector::RENT_EXEMPT_RENT_EPOCH, saturating_add_assign, }, std::{ @@ -133,6 +134,10 @@ pub struct LoadedProgram { pub program: LoadedProgramType, /// Size of account that stores the program and program data pub account_size: usize, + /// lamoports for the program account + pub lamports: u64, + /// rent epoch for the program account + pub rent_epoch: u64, /// Slot in which the program was (re)deployed pub deployment_slot: Slot, /// Slot in which this entry will become active (can be in the future) @@ -282,6 +287,8 @@ impl LoadedProgram { effective_slot: Slot, elf_bytes: &[u8], account_size: usize, + rent_epoch: u64, + lamports: u64, metrics: &mut LoadProgramMetrics, ) -> Result> { Self::new_internal( @@ -291,6 +298,8 @@ impl LoadedProgram { effective_slot, elf_bytes, account_size, + rent_epoch, + lamports, metrics, false, /* reloading */ ) @@ -311,6 +320,8 @@ impl LoadedProgram { effective_slot: Slot, elf_bytes: &[u8], account_size: usize, + rent_epoch: u64, + lamports: u64, metrics: &mut LoadProgramMetrics, ) -> Result> { Self::new_internal( @@ -320,11 +331,14 @@ impl LoadedProgram { effective_slot, elf_bytes, account_size, + rent_epoch, + lamports, metrics, true, /* reloading */ ) } + #[allow(clippy::too_many_arguments)] fn new_internal( loader_key: &Pubkey, program_runtime_environment: Arc>>, @@ -332,6 +346,8 @@ impl LoadedProgram { effective_slot: Slot, elf_bytes: &[u8], account_size: usize, + rent_epoch: u64, + lamports: u64, metrics: &mut LoadProgramMetrics, reloading: bool, ) -> Result> { @@ -371,6 +387,8 @@ impl LoadedProgram { Ok(Self { deployment_slot, account_size, + rent_epoch, + lamports, effective_slot, tx_usage_counter: AtomicU64::new(0), program, @@ -402,6 +420,8 @@ impl LoadedProgram { tx_usage_counter: AtomicU64::new(self.tx_usage_counter.load(Ordering::Relaxed)), ix_usage_counter: AtomicU64::new(self.ix_usage_counter.load(Ordering::Relaxed)), latest_access_slot: AtomicU64::new(self.latest_access_slot.load(Ordering::Relaxed)), + rent_epoch: self.rent_epoch, + lamports: self.lamports, }) } @@ -423,6 +443,8 @@ impl LoadedProgram { program: LoadedProgramType::Builtin(BuiltinProgram::new_builtin(function_registry)), ix_usage_counter: AtomicU64::new(0), latest_access_slot: AtomicU64::new(0), + lamports: 0, + rent_epoch: RENT_EXEMPT_RENT_EPOCH, } } @@ -435,6 +457,8 @@ impl LoadedProgram { tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), latest_access_slot: AtomicU64::new(0), + lamports: 0, + rent_epoch: 0, }; debug_assert!(tombstone.is_tombstone()); tombstone @@ -449,6 +473,10 @@ impl LoadedProgram { ) } + pub fn is_builtin(&self) -> bool { + matches!(self.program, LoadedProgramType::Builtin(..)) + } + fn is_implicit_delay_visibility_tombstone(&self, slot: Slot) -> bool { !matches!(self.program, LoadedProgramType::Builtin(_)) && self.effective_slot.saturating_sub(self.deployment_slot) @@ -1143,7 +1171,7 @@ mod tests { assert_matches::assert_matches, percentage::Percentage, solana_rbpf::program::BuiltinProgram, - solana_sdk::{clock::Slot, pubkey::Pubkey}, + solana_sdk::{clock::Slot, pubkey::Pubkey, rent_collector::RENT_EXEMPT_RENT_EPOCH}, std::{ ops::ControlFlow, sync::{ @@ -1182,6 +1210,8 @@ mod tests { tx_usage_counter: usage_counter, ix_usage_counter: AtomicU64::default(), latest_access_slot: AtomicU64::new(deployment_slot), + rent_epoch: 0, + lamports: 0, }) } @@ -1194,6 +1224,8 @@ mod tests { tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), latest_access_slot: AtomicU64::default(), + rent_epoch: RENT_EXEMPT_RENT_EPOCH, + lamports: 0, }) } @@ -1224,6 +1256,8 @@ mod tests { tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), latest_access_slot: AtomicU64::default(), + rent_epoch: 0, + lamports: 0, } .to_unloaded() .expect("Failed to unload the program"), @@ -1856,6 +1890,8 @@ mod tests { tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), latest_access_slot: AtomicU64::default(), + rent_epoch: RENT_EXEMPT_RENT_EPOCH, + lamports: 0, }); cache.assign_program(program1, updated_program.clone()); @@ -2392,6 +2428,8 @@ mod tests { account_size: 0, deployment_slot: 0, effective_slot: 0, + lamports: 0, + rent_epoch: 0, tx_usage_counter: AtomicU64::default(), ix_usage_counter: AtomicU64::default(), latest_access_slot: AtomicU64::default(), diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 5ba8b26e086c69..855588e89c66b7 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -42,6 +42,7 @@ use { native_loader, program_utils::limited_deserialize, pubkey::Pubkey, + rent_collector::RENT_EXEMPT_RENT_EPOCH, saturating_add_assign, system_instruction::{self, MAX_PERMITTED_DATA_LENGTH}, transaction_context::{IndexOfAccount, InstructionContext, TransactionContext}, @@ -66,6 +67,8 @@ pub fn load_program_from_bytes( programdata: &[u8], loader_key: &Pubkey, account_size: usize, + rent_epoch: u64, + lamports: u64, deployment_slot: Slot, program_runtime_environment: Arc>>, reloading: bool, @@ -81,6 +84,8 @@ pub fn load_program_from_bytes( effective_slot, programdata, account_size, + rent_epoch, + lamports, load_program_metrics, ) } @@ -92,6 +97,8 @@ pub fn load_program_from_bytes( effective_slot, programdata, account_size, + rent_epoch, + lamports, load_program_metrics, ) } @@ -104,7 +111,8 @@ pub fn load_program_from_bytes( macro_rules! deploy_program { ($invoke_context:expr, $program_id:expr, $loader_key:expr, - $account_size:expr, $slot:expr, $drop:expr, $new_programdata:expr $(,)?) => {{ + $account_size:expr, $lamports:expr, + $slot:expr, $drop:expr, $new_programdata:expr $(,)?) => {{ let mut load_program_metrics = LoadProgramMetrics::default(); let mut register_syscalls_time = Measure::start("register_syscalls_time"); let deployment_program_runtime_environment = create_program_runtime_environment_v1( @@ -143,6 +151,8 @@ macro_rules! deploy_program { $new_programdata, $loader_key, $account_size, + RENT_EXEMPT_RENT_EPOCH, + $lamports, $slot, $invoke_context.programs_modified_by_tx.environments.program_runtime_v1.clone(), true, @@ -526,7 +536,8 @@ fn process_loader_upgradeable_instruction( ic_logger_msg!(log_collector, "Program account too small"); return Err(InstructionError::AccountDataTooSmall); } - if program.get_lamports() < rent.minimum_balance(program.get_data().len()) { + let lamports = program.get_lamports(); + if lamports < rent.minimum_balance(program.get_data().len()) { ic_logger_msg!(log_collector, "Program account not rent-exempt"); return Err(InstructionError::ExecutableAccountNotRentExempt); } @@ -626,6 +637,7 @@ fn process_loader_upgradeable_instruction( new_program_id, &owner_id, UpgradeableLoaderState::size_of_program().saturating_add(programdata_len), + lamports, clock.slot, { drop(buffer); @@ -734,6 +746,7 @@ fn process_loader_upgradeable_instruction( return Err(InstructionError::InvalidAccountData); } let new_program_id = *program.get_key(); + let lamports = program.get_lamports(); drop(program); // Verify Buffer account @@ -822,6 +835,7 @@ fn process_loader_upgradeable_instruction( new_program_id, program_id, UpgradeableLoaderState::size_of_program().saturating_add(programdata_len), + lamports, clock.slot, { drop(buffer); @@ -1187,6 +1201,7 @@ fn process_loader_upgradeable_instruction( return Err(InstructionError::InvalidAccountOwner); } let program_key = *program_account.get_key(); + let lamports = program_account.get_lamports(); match program_account.get_state()? { UpgradeableLoaderState::Program { programdata_address, @@ -1285,6 +1300,7 @@ fn process_loader_upgradeable_instruction( program_key, &program_id, UpgradeableLoaderState::size_of_program().saturating_add(new_len), + lamports, clock_slot, { drop(programdata_account); @@ -1558,6 +1574,8 @@ pub mod test_utils { account.data(), owner, account.data().len(), + account.rent_epoch(), + account.lamports(), 0, program_runtime_environment.clone(), false, @@ -3779,9 +3797,10 @@ mod tests { program_id, &bpf_loader_upgradeable::id(), elf.len(), + 102, 2, {}, - &elf + &elf, ); Ok(()) } @@ -3800,6 +3819,8 @@ mod tests { tx_usage_counter: AtomicU64::new(100), ix_usage_counter: AtomicU64::new(100), latest_access_slot: AtomicU64::new(0), + rent_epoch: 0, + lamports: 0, }; invoke_context .programs_modified_by_tx @@ -3840,6 +3861,8 @@ mod tests { tx_usage_counter: AtomicU64::new(100), ix_usage_counter: AtomicU64::new(100), latest_access_slot: AtomicU64::new(0), + rent_epoch: 0, + lamports: 0, }; invoke_context .programs_modified_by_tx diff --git a/programs/loader-v4/src/lib.rs b/programs/loader-v4/src/lib.rs index 4764b23fe65e50..1278b11fa48c44 100644 --- a/programs/loader-v4/src/lib.rs +++ b/programs/loader-v4/src/lib.rs @@ -26,6 +26,7 @@ use { loader_v4_instruction::LoaderV4Instruction, program_utils::limited_deserialize, pubkey::Pubkey, + rent_collector::RENT_EXEMPT_RENT_EPOCH, saturating_add_assign, transaction_context::{BorrowedAccount, InstructionContext}, }, @@ -410,7 +411,7 @@ pub fn process_instruction_deploy( program_id: buffer.get_key().to_string(), ..LoadProgramMetrics::default() }; - let executor = LoadedProgram::new( + let mut executor = LoadedProgram::new( &loader_v4::id(), invoke_context .programs_modified_by_tx @@ -421,6 +422,8 @@ pub fn process_instruction_deploy( effective_slot, programdata, buffer.get_data().len(), + RENT_EXEMPT_RENT_EPOCH, + program.get_lamports(), &mut load_program_metrics, ) .map_err(|err| { @@ -436,6 +439,7 @@ pub fn process_instruction_deploy( source_program.set_data_length(0, &invoke_context.feature_set)?; source_program.checked_sub_lamports(transfer_lamports, &invoke_context.feature_set)?; program.checked_add_lamports(transfer_lamports, &invoke_context.feature_set)?; + executor.lamports = program.get_lamports(); } let state = get_state_mut(program.get_data_mut(&invoke_context.feature_set)?)?; state.slot = current_slot; @@ -661,6 +665,8 @@ mod tests { 0, programdata, account.data().len(), + account.rent_epoch(), + account.lamports(), &mut load_program_metrics, ) { invoke_context.programs_modified_by_tx.set_slot_for_tests(0); diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index 1635850bb2a9c5..843dd663f7c9a2 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -4434,6 +4434,7 @@ fn test_deny_executable_write() { if !direct_mapping { feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id()); } + feature_set.deactivate(&feature_set::dont_load_executable_accounts::id()); let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests(); let mut bank_client = BankClient::new_shared(bank); let authority_keypair = Keypair::new(); diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index abecf4fafb6b1d..c392e6cc2ffcd9 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -784,6 +784,14 @@ pub mod remove_rounding_in_fee_calculation { solana_sdk::declare_id!("BtVN7YjDzNE6Dk7kTT7YTDgMNUZTNgiSJgsdzAeTg2jF"); } +pub mod dont_load_executable_accounts { + solana_sdk::declare_id!("SeanGLG9chXD7bUF42nxUkyhhasZ38RauPFSK5txEkE"); +} + +pub mod dont_load_executable_accounts_no_exceptions { + solana_sdk::declare_id!("Seanx5tafZesNtxNeayrDHj5WFyzfCnsDse2ucj6ATz"); +} + lazy_static! { /// Map of feature identifiers to user-visible description pub static ref FEATURE_NAMES: HashMap = [ @@ -975,6 +983,8 @@ lazy_static! { (enable_gossip_duplicate_proof_ingestion::id(), "enable gossip duplicate proof ingestion #32963"), (enable_chained_merkle_shreds::id(), "Enable chained Merkle shreds #34916"), (remove_rounding_in_fee_calculation::id(), "Removing unwanted rounding in fee calculation #34982"), + (dont_load_executable_accounts::id(), "executable ro accounts should do not need to be loaded"), + (dont_load_executable_accounts_no_exceptions::id(), "executable ro accounts should not be loaded program_id exceptions"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter() diff --git a/sdk/src/transaction_context.rs b/sdk/src/transaction_context.rs index 981f64870f6063..dac1e3396c1aca 100644 --- a/sdk/src/transaction_context.rs +++ b/sdk/src/transaction_context.rs @@ -712,6 +712,53 @@ pub struct BorrowedAccount<'a> { account: RefMut<'a, AccountSharedData>, } +// Mainnet-beta program_ids that cannot deal with serializing executable accounts zero-length +solana_sdk::pubkeys!( + program_ids_exe_zero_length_exceptions, + [ + "7K3UpbZViPnQDLn2DAM853B9J5GBxd1L1rLHy4KqSmWG", + "5mpjDRgoRYRmSnAXZTfB2bBkbpwvRjobXUjb4WYjF225", + "SRDmexy38YTqtCmh7xU2eMFkWweYWF1pqdPyatTF1qP", // NO ELF MAGIC + /* + "Program log: Instruction: CykuraSwap", + "Program cysPXAjehMpVKUapzbMCCnpFxUFFryEWEaLgnb9NrR8 invoke [3]", + "Program log: Instruction: ExactInputSingle", + "Program log: ProgramError caused by account: core_program. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid.", + */ + "cysPXAjehMpVKUapzbMCCnpFxUFFryEWEaLgnb9NrR8", + /* + "Program 6e84wdHBa1joDWcyL7FZG9Fi2BtYTmvDNKfW2f8fNXnc invoke [1]", + "Program log: TestMode : 0", + "Program log: [from bot] Profitability : 1.036820375 Slot : 237528550 Dropped Slot : 0", + "Program log: panicked at 'index out of bounds: the len is 0 but the index is 291', src/exchange/orca.rs:41:22", + */ + "6e84wdHBa1joDWcyL7FZG9Fi2BtYTmvDNKfW2f8fNXnc", + /* + "Program log: ProgramError caused by account: mine_program. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid." + */ + "SPQR4kT3q2oUKEJes2L6NNSBCiPW9SfuhkuqC9bp6Sx", // NO ELF MAGIC + /* + *Program SCPv1LabixHirZbX6s7Zj3oiBogadWZvGUKRvXD3Zec failed: invalid account data for instruction + */ + "SCPv1LabixHirZbX6s7Zj3oiBogadWZvGUKRvXD3Zec", // NO ELF MAGIC + // "Program log: panicked at 'index out of bounds: the len is 4 but the index is 291', src/exchange/orca.rs:41:22", + "8nbexi4ReN1u6iTBkuEExXKGisgjFkY6AjChF1k19aFU", + // "Program log: ProgramError caused by account: gem_bank. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid.", + "DyziFCftH7CpoSLvXmtqyeMD2HBZVEqWk7xkRF1vcNqt", + // "Program log: Instruction: WithdrawFromPool", + // "Program log: An account's data contents was invalid", + "D83mNLnWHX1DmFTWFTG2zJXxjEnwX2dVTWNitExRJTsE", + // Program log: ProgramError caused by account: gem_bank. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid. + "GzYDEAKs7vTsqAxBWrbUEpMMH5xRRazRPGdd6Kp3e7Rh", + //"Program log: ProgramError caused by account: gem_bank. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid.", + "Dp8bcStZSpR4EyKuzcAJUFjnZKfoNo9iYM93BAxtDLve", + //"Program log: ProgramError occurred. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid.", + "BsKyUMNe1jXxiv3Y57H6UfkeodUYgHKuafaN4HSWdXj1", + //"Program log: ProgramError caused by account: gem_bank. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid.", + "7NryUmAmy8hMbawRNUs9UdkgAGEiHFxghSfve31dC7xh", + ] +); + impl<'a> BorrowedAccount<'a> { /// Returns the transaction context pub fn transaction_context(&self) -> &TransactionContext { diff --git a/svm/src/account_loader.rs b/svm/src/account_loader.rs index 334ad7679561ee..a6ef3a9f5eda4f 100644 --- a/svm/src/account_loader.rs +++ b/svm/src/account_loader.rs @@ -8,7 +8,7 @@ use { log::warn, solana_program_runtime::{ compute_budget_processor::process_compute_budget_instructions, - loaded_programs::LoadedProgramsForTxBatch, + loaded_programs::{LoadedProgram, LoadedProgramsForTxBatch}, }, solana_sdk::{ account::{ @@ -16,8 +16,9 @@ use { ReadableAccount, WritableAccount, }, feature_set::{ - self, include_loaded_accounts_data_size_in_fee_calculation, - remove_rounding_in_fee_calculation, + self, dont_load_executable_accounts, dont_load_executable_accounts_no_exceptions, + include_loaded_accounts_data_size_in_fee_calculation, + remove_rounding_in_fee_calculation, FeatureSet, }, fee::FeeStructure, message::SanitizedMessage, @@ -31,10 +32,12 @@ use { saturating_add_assign, sysvar::{self, instructions::construct_instructions_data}, transaction::{self, Result, SanitizedTransaction, TransactionError}, - transaction_context::{IndexOfAccount, TransactionAccount}, + transaction_context::{ + program_ids_exe_zero_length_exceptions, IndexOfAccount, TransactionAccount, + }, }, solana_system_program::{get_system_account_kind, SystemAccountKind}, - std::{collections::HashMap, num::NonZeroUsize}, + std::{collections::HashMap, num::NonZeroUsize, sync::Arc}, }; // for the load instructions @@ -173,14 +176,17 @@ fn load_transaction_accounts( account_overrides.and_then(|overrides| overrides.get(key)) { (account_override.data().len(), account_override.clone(), 0) - } else if let Some(program) = (!instruction_account && !message.is_writable(i)) - .then_some(()) - .and_then(|_| loaded_programs.find(key)) - { + } else if let Some(program) = elide_loading_program( + key, + message.is_writable(i), + instruction_account, + &feature_set, + loaded_programs, + ) { // Optimization to skip loading of accounts which are only used as // programs in top-level instructions and not passed as instruction accounts. - account_shared_data_from_program(key, program_accounts) - .map(|program_account| (program.account_size, program_account, 0))? + account_shared_data_from_program(key, program, program_accounts) + .map(|program_account| (program_account.data().len(), program_account, 0))? } else { callbacks .get_account_shared_data(key) @@ -341,6 +347,44 @@ fn load_transaction_accounts( }) } +fn elide_loading_program( + key: &Pubkey, + writable: bool, + instruction_account: bool, + feature_set: &Arc, + loaded_programs: &LoadedProgramsForTxBatch, +) -> Option> { + // if the account is writable, we have to load it + if writable { + return None; + } + + // It has to be an executable program account + let program = loaded_programs.find(key)?; + + // If the account is not passed as instruction accounts, we can simply avoid loading it + if !instruction_account { + // previous code used correct account size here; not sure this actually matters + Some(program) + } else if feature_set.is_active(&dont_load_executable_accounts::id()) { + if program.is_builtin() { + return None; + } + + // Serialize programs as zero-length if the feature is enabled + // Set of programs that do not handle executables serialized as zero length + if feature_set.is_active(&dont_load_executable_accounts_no_exceptions::id()) + || !program_ids_exe_zero_length_exceptions().contains(key) + { + Some(program) + } else { + None + } + } else { + None + } +} + /// Total accounts data a transaction can load is limited to /// if `set_tx_loaded_accounts_data_size` instruction is not activated or not used, then /// default value of 64MiB to not break anyone in Mainnet-beta today @@ -365,6 +409,7 @@ fn get_requested_loaded_accounts_data_size_limit( fn account_shared_data_from_program( key: &Pubkey, + program: Arc, program_accounts: &HashMap, ) -> Result { // It's an executable program account. The program is already loaded in the cache. @@ -377,6 +422,9 @@ fn account_shared_data_from_program( program_account.set_owner(**program_owner); program_account.set_executable(true); program_account.set_data_from_slice(create_executable_meta(program_owner)); + program_account.set_rent_epoch(program.rent_epoch); + program_account.set_lamports(program.lamports); + Ok(program_account) } diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index 0c456c918d68ff..7cd0970b935e90 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -675,6 +675,8 @@ impl TransactionBatchProcessor { program_account.data(), program_account.owner(), program_account.data().len(), + program_account.rent_epoch(), + program_account.lamports(), 0, environments.program_runtime_v1.clone(), reload, @@ -699,6 +701,8 @@ impl TransactionBatchProcessor { .data() .len() .saturating_add(programdata_account.data().len()), + program_account.rent_epoch(), + program_account.lamports(), slot, environments.program_runtime_v1.clone(), reload, @@ -717,6 +721,8 @@ impl TransactionBatchProcessor { elf_bytes, &loader_v4::id(), program_account.data().len(), + program_account.rent_epoch(), + program_account.lamports(), slot, environments.program_runtime_v2.clone(), reload, @@ -755,6 +761,8 @@ impl TransactionBatchProcessor { programdata: &[u8], loader_key: &Pubkey, account_size: usize, + rent_epoch: u64, + lamports: u64, deployment_slot: Slot, program_runtime_environment: ProgramRuntimeEnvironment, reloading: bool, @@ -769,6 +777,8 @@ impl TransactionBatchProcessor { deployment_slot.saturating_add(DELAY_VISIBILITY_SLOT_OFFSET), programdata, account_size, + rent_epoch, + lamports, load_program_metrics, ) } @@ -780,6 +790,8 @@ impl TransactionBatchProcessor { deployment_slot.saturating_add(DELAY_VISIBILITY_SLOT_OFFSET), programdata, account_size, + rent_epoch, + lamports, load_program_metrics, ) }