diff --git a/banks-server/src/banks_server.rs b/banks-server/src/banks_server.rs index b3028c0132ed48..d6eec95d104089 100644 --- a/banks-server/src/banks_server.rs +++ b/banks-server/src/banks_server.rs @@ -178,6 +178,7 @@ fn simulate_transaction( MessageHash::Compute, Some(false), // is_simple_vote_tx bank, + bank.get_reserved_account_keys(), ) { Err(err) => { return BanksTransactionResultWithSimulation { @@ -332,6 +333,7 @@ impl Banks for BanksServer { MessageHash::Compute, Some(false), // is_simple_vote_tx bank.as_ref(), + bank.get_reserved_account_keys(), ) { Ok(tx) => tx, Err(err) => return Some(Err(err)), @@ -417,7 +419,9 @@ impl Banks for BanksServer { commitment: CommitmentLevel, ) -> Option { let bank = self.bank(commitment); - let sanitized_message = SanitizedMessage::try_from_legacy_message(message).ok()?; + let sanitized_message = + SanitizedMessage::try_from_legacy_message(message, bank.get_reserved_account_keys()) + .ok()?; bank.get_fee_for_message(&sanitized_message) } } diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs index 80363989c6c809..e916674c7c5de2 100644 --- a/core/src/banking_stage/consumer.rs +++ b/core/src/banking_stage/consumer.rs @@ -868,6 +868,7 @@ mod tests { nonce_account::verify_nonce_account, poh_config::PohConfig, pubkey::Pubkey, + reserved_account_keys::ReservedAccountKeys, signature::Keypair, signer::Signer, system_instruction, system_program, system_transaction, @@ -2026,6 +2027,7 @@ mod tests { MessageHash::Compute, Some(false), bank.as_ref(), + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); diff --git a/core/src/banking_stage/immutable_deserialized_packet.rs b/core/src/banking_stage/immutable_deserialized_packet.rs index 8e31f9cd462473..fba145f3088652 100644 --- a/core/src/banking_stage/immutable_deserialized_packet.rs +++ b/core/src/banking_stage/immutable_deserialized_packet.rs @@ -6,6 +6,7 @@ use { feature_set, hash::Hash, message::Message, + pubkey::Pubkey, sanitize::SanitizeError, saturating_add_assign, short_vec::decode_shortu16_len, @@ -15,7 +16,7 @@ use { VersionedTransaction, }, }, - std::{cmp::Ordering, mem::size_of, sync::Arc}, + std::{cmp::Ordering, collections::HashSet, mem::size_of, sync::Arc}, thiserror::Error, }; @@ -123,6 +124,7 @@ impl ImmutableDeserializedPacket { feature_set: &Arc, votes_only: bool, address_loader: impl AddressLoader, + reserved_account_keys: &HashSet, ) -> Option { if votes_only && !self.is_simple_vote() { return None; @@ -132,6 +134,7 @@ impl ImmutableDeserializedPacket { *self.message_hash(), self.is_simple_vote(), address_loader, + reserved_account_keys, ) .ok()?; tx.verify_precompiles(feature_set).ok()?; diff --git a/core/src/banking_stage/latest_unprocessed_votes.rs b/core/src/banking_stage/latest_unprocessed_votes.rs index 6498f4c81ec381..44ed870e3fb86b 100644 --- a/core/src/banking_stage/latest_unprocessed_votes.rs +++ b/core/src/banking_stage/latest_unprocessed_votes.rs @@ -283,6 +283,7 @@ impl LatestUnprocessedVotes { &bank.feature_set, bank.vote_only_bank(), bank.as_ref(), + bank.get_reserved_account_keys(), ) { if forward_packet_batches_by_accounts.try_add_packet( diff --git a/core/src/banking_stage/read_write_account_set.rs b/core/src/banking_stage/read_write_account_set.rs index dad1256f6e6f22..6d6b908249f168 100644 --- a/core/src/banking_stage/read_write_account_set.rs +++ b/core/src/banking_stage/read_write_account_set.rs @@ -138,6 +138,7 @@ mod tests { MessageHash::Compute, Some(false), bank, + bank.get_reserved_account_keys(), ) .unwrap() } diff --git a/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs b/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs index e608a3ba0699d3..8ca6594db6c971 100644 --- a/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs +++ b/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs @@ -381,7 +381,12 @@ impl SchedulerController { let (transactions, fee_budget_limits_vec): (Vec<_>, Vec<_>) = chunk .iter() .filter_map(|packet| { - packet.build_sanitized_transaction(feature_set, vote_only, bank.as_ref()) + packet.build_sanitized_transaction( + feature_set, + vote_only, + bank.as_ref(), + bank.get_reserved_account_keys(), + ) }) .inspect(|_| saturating_add_assign!(post_sanitization_count, 1)) .filter(|tx| { diff --git a/core/src/banking_stage/unprocessed_packet_batches.rs b/core/src/banking_stage/unprocessed_packet_batches.rs index b87cfef291b991..ebb91773c49923 100644 --- a/core/src/banking_stage/unprocessed_packet_batches.rs +++ b/core/src/banking_stage/unprocessed_packet_batches.rs @@ -310,6 +310,7 @@ mod tests { solana_sdk::{ compute_budget::ComputeBudgetInstruction, message::Message, + reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signer}, system_instruction, system_transaction, transaction::{SimpleAddressLoader, Transaction}, @@ -490,6 +491,7 @@ mod tests { &Arc::new(FeatureSet::default()), votes_only, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }); assert_eq!(2, txs.count()); @@ -500,6 +502,7 @@ mod tests { &Arc::new(FeatureSet::default()), votes_only, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }); assert_eq!(0, txs.count()); @@ -519,6 +522,7 @@ mod tests { &Arc::new(FeatureSet::default()), votes_only, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }); assert_eq!(3, txs.count()); @@ -529,6 +533,7 @@ mod tests { &Arc::new(FeatureSet::default()), votes_only, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }); assert_eq!(2, txs.count()); @@ -548,6 +553,7 @@ mod tests { &Arc::new(FeatureSet::default()), votes_only, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }); assert_eq!(3, txs.count()); @@ -558,6 +564,7 @@ mod tests { &Arc::new(FeatureSet::default()), votes_only, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }); assert_eq!(3, txs.count()); diff --git a/core/src/banking_stage/unprocessed_transaction_storage.rs b/core/src/banking_stage/unprocessed_transaction_storage.rs index 82ba08a3981532..c0c39276d63b2f 100644 --- a/core/src/banking_stage/unprocessed_transaction_storage.rs +++ b/core/src/banking_stage/unprocessed_transaction_storage.rs @@ -153,9 +153,13 @@ fn consume_scan_should_process_packet( } // Try to sanitize the packet - let (maybe_sanitized_transaction, sanitization_time_us) = measure_us!( - packet.build_sanitized_transaction(&bank.feature_set, bank.vote_only_bank(), bank) - ); + let (maybe_sanitized_transaction, sanitization_time_us) = measure_us!(packet + .build_sanitized_transaction( + &bank.feature_set, + bank.vote_only_bank(), + bank, + bank.get_reserved_account_keys(), + )); payload .slot_metrics_tracker @@ -770,7 +774,12 @@ impl ThreadLocalUnprocessedPackets { .enumerate() .filter_map(|(packet_index, deserialized_packet)| { deserialized_packet - .build_sanitized_transaction(&bank.feature_set, bank.vote_only_bank(), bank) + .build_sanitized_transaction( + &bank.feature_set, + bank.vote_only_bank(), + bank, + bank.get_reserved_account_keys(), + ) .map(|transaction| (transaction, packet_index)) }) .unzip(); diff --git a/cost-model/src/cost_tracker.rs b/cost-model/src/cost_tracker.rs index 64185edb6c77ca..a68e6c9d7dbde3 100644 --- a/cost-model/src/cost_tracker.rs +++ b/cost-model/src/cost_tracker.rs @@ -339,6 +339,7 @@ mod tests { crate::transaction_cost::*, solana_sdk::{ hash::Hash, + reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signer}, system_transaction, transaction::{ @@ -401,6 +402,7 @@ mod tests { MessageHash::Compute, Some(true), SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); diff --git a/cost-model/src/transaction_cost.rs b/cost-model/src/transaction_cost.rs index c92639676958ae..ee280c873312f9 100644 --- a/cost-model/src/transaction_cost.rs +++ b/cost-model/src/transaction_cost.rs @@ -203,6 +203,7 @@ mod tests { feature_set::FeatureSet, hash::Hash, message::SimpleAddressLoader, + reserved_account_keys::ReservedAccountKeys, signer::keypair::Keypair, transaction::{MessageHash, SanitizedTransaction, VersionedTransaction}, }, @@ -231,6 +232,7 @@ mod tests { MessageHash::Compute, Some(true), SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); @@ -240,6 +242,7 @@ mod tests { MessageHash::Compute, Some(false), SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); diff --git a/entry/benches/entry_sigverify.rs b/entry/benches/entry_sigverify.rs index 09adeb6cfd831a..d9b97b2dbfd91e 100644 --- a/entry/benches/entry_sigverify.rs +++ b/entry/benches/entry_sigverify.rs @@ -5,6 +5,7 @@ use { solana_perf::test_tx::test_tx, solana_sdk::{ hash::Hash, + reserved_account_keys::ReservedAccountKeys, transaction::{ Result, SanitizedTransaction, SimpleAddressLoader, TransactionVerificationMode, VersionedTransaction, @@ -41,6 +42,7 @@ fn bench_gpusigverify(bencher: &mut Bencher) { message_hash, None, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }?; @@ -84,6 +86,7 @@ fn bench_cpusigverify(bencher: &mut Bencher) { message_hash, None, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }?; diff --git a/entry/src/entry.rs b/entry/src/entry.rs index 7497f96d65980f..da4fda5914a363 100644 --- a/entry/src/entry.rs +++ b/entry/src/entry.rs @@ -982,6 +982,7 @@ mod tests { solana_sdk::{ hash::{hash, Hash}, pubkey::Pubkey, + reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signer}, system_transaction, transaction::{ @@ -1084,6 +1085,7 @@ mod tests { message_hash, None, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) }?; diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index ab859ff0a7e689..3c1e23f6dfabe6 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -67,6 +67,7 @@ use { native_token::{lamports_to_sol, sol_to_lamports, Sol}, pubkey::Pubkey, rent::Rent, + reserved_account_keys::ReservedAccountKeys, shred_version::compute_shred_version, stake::{self, state::StakeStateV2}, system_program, @@ -461,6 +462,9 @@ fn compute_slot_cost( let mut program_ids = HashMap::new(); let mut cost_tracker = CostTracker::default(); + let feature_set = FeatureSet::all_enabled(); + let reserved_account_keys = ReservedAccountKeys::new_all_activated(); + for entry in entries { num_transactions += entry.transactions.len(); entry @@ -472,6 +476,7 @@ fn compute_slot_cost( MessageHash::Compute, None, SimpleAddressLoader::Disabled, + &reserved_account_keys.active, ) .map_err(|err| { warn!("Failed to compute cost of transaction: {:?}", err); @@ -481,7 +486,7 @@ fn compute_slot_cost( .for_each(|transaction| { num_programs += transaction.message().instructions().len(); - let tx_cost = CostModel::calculate_cost(&transaction, &FeatureSet::all_enabled()); + let tx_cost = CostModel::calculate_cost(&transaction, &feature_set); let result = cost_tracker.try_add(&tx_cost); if result.is_err() { println!( diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index fa67dd11340f3f..0f45329c581905 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -81,6 +81,7 @@ use { message::Message, pubkey::Pubkey, rent::Rent, + reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signer}, system_program, transaction::{SanitizedTransaction, Transaction, TransactionError}, @@ -201,7 +202,11 @@ fn execute_transactions( } .expect("lamports_per_signature must be available"); let fee = bank.get_fee_for_message_with_lamports_per_signature( - &SanitizedMessage::try_from_legacy_message(tx.message().clone()).unwrap(), + &SanitizedMessage::try_from_legacy_message( + tx.message().clone(), + &ReservedAccountKeys::empty_key_set(), + ) + .unwrap(), lamports_per_signature, ); @@ -3706,7 +3711,11 @@ fn test_program_fees() { Some(&mint_keypair.pubkey()), ); - let sanitized_message = SanitizedMessage::try_from_legacy_message(message.clone()).unwrap(); + let sanitized_message = SanitizedMessage::try_from_legacy_message( + message.clone(), + &ReservedAccountKeys::empty_key_set(), + ) + .unwrap(); let expected_normal_fee = fee_structure.calculate_fee( &sanitized_message, congestion_multiplier, @@ -3730,7 +3739,11 @@ fn test_program_fees() { ], Some(&mint_keypair.pubkey()), ); - let sanitized_message = SanitizedMessage::try_from_legacy_message(message.clone()).unwrap(); + let sanitized_message = SanitizedMessage::try_from_legacy_message( + message.clone(), + &ReservedAccountKeys::empty_key_set(), + ) + .unwrap(); let expected_prioritized_fee = fee_structure.calculate_fee( &sanitized_message, congestion_multiplier, diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index c3b00fd9716410..6c41fb59d88cd8 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -3657,7 +3657,11 @@ pub mod rpc_full { min_context_slot, })?; - let transaction = sanitize_transaction(unsanitized_tx, preflight_bank)?; + let transaction = sanitize_transaction( + unsanitized_tx, + preflight_bank, + preflight_bank.get_reserved_account_keys(), + )?; let signature = *transaction.signature(); let mut last_valid_block_height = preflight_bank @@ -3789,7 +3793,8 @@ pub mod rpc_full { }); } - let transaction = sanitize_transaction(unsanitized_tx, bank)?; + let transaction = + sanitize_transaction(unsanitized_tx, bank, bank.get_reserved_account_keys())?; if sig_verify { verify_transaction(&transaction, &bank.feature_set)?; } @@ -4041,10 +4046,12 @@ pub mod rpc_full { .map_err(|err| { Error::invalid_params(format!("invalid transaction message: {err}")) })?; - let sanitized_message = SanitizedMessage::try_new(sanitized_versioned_message, bank) - .map_err(|err| { - Error::invalid_params(format!("invalid transaction message: {err}")) - })?; + let sanitized_message = SanitizedMessage::try_new( + sanitized_versioned_message, + bank, + bank.get_reserved_account_keys(), + ) + .map_err(|err| Error::invalid_params(format!("invalid transaction message: {err}")))?; let fee = bank.get_fee_for_message(&sanitized_message); Ok(new_response(bank, fee)) } @@ -4623,9 +4630,16 @@ where fn sanitize_transaction( transaction: VersionedTransaction, address_loader: impl AddressLoader, + reserved_account_keys: &HashSet, ) -> Result { - SanitizedTransaction::try_create(transaction, MessageHash::Compute, None, address_loader) - .map_err(|err| Error::invalid_params(format!("invalid transaction: {err}"))) + SanitizedTransaction::try_create( + transaction, + MessageHash::Compute, + None, + address_loader, + reserved_account_keys, + ) + .map_err(|err| Error::invalid_params(format!("invalid transaction: {err}"))) } pub fn create_validator_exit(exit: Arc) -> Arc> { @@ -4771,6 +4785,7 @@ pub mod tests { Message, MessageHeader, VersionedMessage, }, nonce::{self, state::DurableNonce}, + reserved_account_keys::ReservedAccountKeys, rpc_port, signature::{Keypair, Signer}, slot_hashes::SlotHashes, @@ -9049,8 +9064,12 @@ pub mod tests { .to_string(), ); assert_eq!( - sanitize_transaction(unsanitary_versioned_tx, SimpleAddressLoader::Disabled) - .unwrap_err(), + sanitize_transaction( + unsanitary_versioned_tx, + SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set() + ) + .unwrap_err(), expect58 ); } @@ -9070,7 +9089,12 @@ pub mod tests { }; assert_eq!( - sanitize_transaction(versioned_tx, SimpleAddressLoader::Disabled).unwrap_err(), + sanitize_transaction( + versioned_tx, + SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set() + ) + .unwrap_err(), Error::invalid_params( "invalid transaction: Transaction version is unsupported".to_string(), ) diff --git a/rpc/src/transaction_status_service.rs b/rpc/src/transaction_status_service.rs index 8730fb2ed0f3d8..f76c72102e3057 100644 --- a/rpc/src/transaction_status_service.rs +++ b/rpc/src/transaction_status_service.rs @@ -225,6 +225,7 @@ pub(crate) mod tests { nonce_info::{NonceFull, NoncePartial}, pubkey::Pubkey, rent_debits::RentDebits, + reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signature, Signer}, system_transaction, transaction::{ @@ -335,6 +336,7 @@ pub(crate) mod tests { MessageHash::Compute, None, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); @@ -364,7 +366,10 @@ pub(crate) mod tests { durable_nonce_fee: Some(DurableNonceFee::from( &NonceFull::from_partial( &rollback_partial, - &SanitizedMessage::Legacy(LegacyMessage::new(message)), + &SanitizedMessage::Legacy(LegacyMessage::new( + message, + &ReservedAccountKeys::empty_key_set(), + )), &[(pubkey, nonce_account)], &rent_debits, ) diff --git a/runtime-transaction/src/runtime_transaction.rs b/runtime-transaction/src/runtime_transaction.rs index 3ca7d4fb7920cd..d7fa7da0fbb3f9 100644 --- a/runtime-transaction/src/runtime_transaction.rs +++ b/runtime-transaction/src/runtime_transaction.rs @@ -17,10 +17,12 @@ use { solana_sdk::{ hash::Hash, message::{AddressLoader, SanitizedMessage, SanitizedVersionedMessage}, + pubkey::Pubkey, signature::Signature, simple_vote_transaction_checker::is_simple_vote_transaction, transaction::{Result, SanitizedVersionedTransaction}, }, + std::collections::HashSet, }; #[derive(Debug, Clone, Eq, PartialEq)] @@ -101,12 +103,14 @@ impl RuntimeTransaction { pub fn try_from( statically_loaded_runtime_tx: RuntimeTransaction, address_loader: impl AddressLoader, + reserved_account_keys: &HashSet, ) -> Result { let mut tx = Self { signatures: statically_loaded_runtime_tx.signatures, message: SanitizedMessage::try_new( statically_loaded_runtime_tx.message, address_loader, + reserved_account_keys, )?, meta: statically_loaded_runtime_tx.meta, }; @@ -132,6 +136,7 @@ mod tests { compute_budget::ComputeBudgetInstruction, instruction::Instruction, message::Message, + reserved_account_keys::ReservedAccountKeys, signer::{keypair::Keypair, Signer}, transaction::{SimpleAddressLoader, Transaction, VersionedTransaction}, }, @@ -256,6 +261,7 @@ mod tests { let dynamically_loaded_transaction = RuntimeTransaction::::try_from( statically_loaded_transaction, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ); let dynamically_loaded_transaction = dynamically_loaded_transaction.expect("created from statically loaded tx"); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 8411d7773b71f9..48bb64ff1a3bcd 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -3470,7 +3470,15 @@ impl Bank { pub fn prepare_entry_batch(&self, txs: Vec) -> Result { let sanitized_txs = txs .into_iter() - .map(|tx| SanitizedTransaction::try_create(tx, MessageHash::Compute, None, self)) + .map(|tx| { + SanitizedTransaction::try_create( + tx, + MessageHash::Compute, + None, + self, + self.get_reserved_account_keys(), + ) + }) .collect::>>()?; let tx_account_lock_limit = self.get_transaction_account_lock_limit(); let lock_results = self @@ -5901,7 +5909,13 @@ impl Bank { tx.message.hash() }; - SanitizedTransaction::try_create(tx, message_hash, None, self) + SanitizedTransaction::try_create( + tx, + message_hash, + None, + self, + self.get_reserved_account_keys(), + ) }?; if verification_mode == TransactionVerificationMode::HashAndVerifyPrecompiles diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 02c889d4b780f7..80deca7005cb97 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -189,7 +189,8 @@ pub(in crate::bank) fn create_genesis_config(lamports: u64) -> (GenesisConfig, K } fn new_sanitized_message(message: Message) -> SanitizedMessage { - SanitizedMessage::try_from_legacy_message(message).unwrap() + SanitizedMessage::try_from_legacy_message(message, &ReservedAccountKeys::empty_key_set()) + .unwrap() } #[test] diff --git a/runtime/src/bank_client.rs b/runtime/src/bank_client.rs index 22a1631085870f..634cb0e28b09ab 100644 --- a/runtime/src/bank_client.rs +++ b/runtime/src/bank_client.rs @@ -285,15 +285,15 @@ impl SyncClient for BankClient { } fn get_fee_for_message(&self, message: &Message) -> Result { - SanitizedMessage::try_from_legacy_message(message.clone()) - .ok() - .and_then(|sanitized_message| self.bank.get_fee_for_message(&sanitized_message)) - .ok_or_else(|| { - TransportError::IoError(io::Error::new( - io::ErrorKind::Other, - "Unable calculate fee", - )) - }) + SanitizedMessage::try_from_legacy_message( + message.clone(), + self.bank.get_reserved_account_keys(), + ) + .ok() + .and_then(|sanitized_message| self.bank.get_fee_for_message(&sanitized_message)) + .ok_or_else(|| { + TransportError::IoError(io::Error::new(io::ErrorKind::Other, "Unable calculate fee")) + }) } } diff --git a/sdk/benches/serialize_instructions.rs b/sdk/benches/serialize_instructions.rs index adf36497ec67d4..d5ab20cad92fe1 100644 --- a/sdk/benches/serialize_instructions.rs +++ b/sdk/benches/serialize_instructions.rs @@ -7,6 +7,7 @@ use { instruction::{AccountMeta, Instruction}, message::{Message, SanitizedMessage}, pubkey::{self, Pubkey}, + reserved_account_keys::ReservedAccountKeys, sysvar::instructions::{self, construct_instructions_data}, }, test::Bencher, @@ -29,10 +30,10 @@ fn bench_bincode_instruction_serialize(b: &mut Bencher) { #[bench] fn bench_construct_instructions_data(b: &mut Bencher) { let instructions = make_instructions(); - let message = SanitizedMessage::try_from_legacy_message(Message::new( - &instructions, - Some(&Pubkey::new_unique()), - )) + let message = SanitizedMessage::try_from_legacy_message( + Message::new(&instructions, Some(&Pubkey::new_unique())), + &ReservedAccountKeys::empty_key_set(), + ) .unwrap(); b.iter(|| { let instructions = message.decompile_instructions(); @@ -52,10 +53,10 @@ fn bench_bincode_instruction_deserialize(b: &mut Bencher) { #[bench] fn bench_manual_instruction_deserialize(b: &mut Bencher) { let instructions = make_instructions(); - let message = SanitizedMessage::try_from_legacy_message(Message::new( - &instructions, - Some(&Pubkey::new_unique()), - )) + let message = SanitizedMessage::try_from_legacy_message( + Message::new(&instructions, Some(&Pubkey::new_unique())), + &ReservedAccountKeys::empty_key_set(), + ) .unwrap(); let serialized = construct_instructions_data(&message.decompile_instructions()); b.iter(|| { @@ -69,10 +70,10 @@ fn bench_manual_instruction_deserialize(b: &mut Bencher) { #[bench] fn bench_manual_instruction_deserialize_single(b: &mut Bencher) { let instructions = make_instructions(); - let message = SanitizedMessage::try_from_legacy_message(Message::new( - &instructions, - Some(&Pubkey::new_unique()), - )) + let message = SanitizedMessage::try_from_legacy_message( + Message::new(&instructions, Some(&Pubkey::new_unique())), + &ReservedAccountKeys::empty_key_set(), + ) .unwrap(); let serialized = construct_instructions_data(&message.decompile_instructions()); b.iter(|| { diff --git a/sdk/program/src/message/legacy.rs b/sdk/program/src/message/legacy.rs index 780259cd07fca4..3d20e980828269 100644 --- a/sdk/program/src/message/legacy.rs +++ b/sdk/program/src/message/legacy.rs @@ -550,7 +550,7 @@ impl Message { /// Returns true if the account at the specified index was requested to be /// writable. This method should not be used directly. - fn is_writable_index(&self, i: usize) -> bool { + pub(super) fn is_writable_index(&self, i: usize) -> bool { i < (self.header.num_required_signatures - self.header.num_readonly_signed_accounts) as usize || (i >= self.header.num_required_signatures as usize @@ -558,10 +558,11 @@ impl Message { - self.header.num_readonly_unsigned_accounts as usize) } - /// Returns true if the account at the specified index should be write - /// locked when loaded for transaction processing in the runtime. This - /// method differs from `is_maybe_writable` because it is aware of the - /// latest reserved accounts which are not allowed to be write locked. + /// Returns true if the account at the specified index is writable by the + /// instructions in this message. Since the dynamic set of reserved accounts + /// isn't used here to demote write locks, this shouldn't be used in the + /// runtime. + #[deprecated(since = "2.0.0", note = "Please use `is_maybe_writable` instead")] pub fn is_writable(&self, i: usize) -> bool { (self.is_writable_index(i)) && !is_builtin_key_or_sysvar(&self.account_keys[i]) @@ -587,7 +588,7 @@ impl Message { let mut writable_keys = vec![]; let mut readonly_keys = vec![]; for (i, key) in self.account_keys.iter().enumerate() { - if self.is_writable(i) { + if self.is_maybe_writable(i) { writable_keys.push(key); } else { readonly_keys.push(key); diff --git a/sdk/program/src/message/sanitized.rs b/sdk/program/src/message/sanitized.rs index ce276a60ef69e7..3f7b49662546f5 100644 --- a/sdk/program/src/message/sanitized.rs +++ b/sdk/program/src/message/sanitized.rs @@ -17,7 +17,7 @@ use { solana_program::{system_instruction::SystemInstruction, system_program}, sysvar::instructions::{BorrowedAccountMeta, BorrowedInstruction}, }, - std::{borrow::Cow, convert::TryFrom}, + std::{borrow::Cow, collections::HashSet, convert::TryFrom}, thiserror::Error, }; @@ -31,12 +31,16 @@ pub struct LegacyMessage<'a> { } impl<'a> LegacyMessage<'a> { - pub fn new(message: legacy::Message) -> Self { + pub fn new(message: legacy::Message, reserved_account_keys: &HashSet) -> Self { let is_writable_account_cache = message .account_keys .iter() .enumerate() - .map(|(i, _key)| message.is_writable(i)) + .map(|(i, _key)| { + message.is_writable_index(i) + && !reserved_account_keys.contains(&message.account_keys[i]) + && !message.demote_program_id(i) + }) .collect::>(); Self { message: Cow::Owned(message), @@ -105,23 +109,34 @@ impl SanitizedMessage { pub fn try_new( sanitized_msg: SanitizedVersionedMessage, address_loader: impl AddressLoader, + reserved_account_keys: &HashSet, ) -> Result { Ok(match sanitized_msg.message { VersionedMessage::Legacy(message) => { - SanitizedMessage::Legacy(LegacyMessage::new(message)) + SanitizedMessage::Legacy(LegacyMessage::new(message, reserved_account_keys)) } VersionedMessage::V0(message) => { let loaded_addresses = address_loader.load_addresses(&message.address_table_lookups)?; - SanitizedMessage::V0(v0::LoadedMessage::new(message, loaded_addresses)) + SanitizedMessage::V0(v0::LoadedMessage::new( + message, + loaded_addresses, + reserved_account_keys, + )) } }) } /// Create a sanitized legacy message - pub fn try_from_legacy_message(message: legacy::Message) -> Result { + pub fn try_from_legacy_message( + message: legacy::Message, + reserved_account_keys: &HashSet, + ) -> Result { message.sanitize()?; - Ok(Self::Legacy(LegacyMessage::new(message))) + Ok(Self::Legacy(LegacyMessage::new( + message, + reserved_account_keys, + ))) } /// Return true if this message contains duplicate account keys @@ -431,7 +446,11 @@ mod tests { }; assert_eq!( - SanitizedMessage::try_from_legacy_message(legacy_message_with_no_signers).err(), + SanitizedMessage::try_from_legacy_message( + legacy_message_with_no_signers, + &HashSet::default(), + ) + .err(), Some(SanitizeMessageError::IndexOutOfBounds), ); } @@ -455,6 +474,7 @@ mod tests { Hash::default(), instructions, ), + &HashSet::default(), ) .unwrap(); @@ -472,15 +492,18 @@ mod tests { let key4 = Pubkey::new_unique(); let key5 = Pubkey::new_unique(); - let legacy_message = SanitizedMessage::try_from_legacy_message(legacy::Message { - header: MessageHeader { - num_required_signatures: 2, - num_readonly_signed_accounts: 1, - num_readonly_unsigned_accounts: 1, + let legacy_message = SanitizedMessage::try_from_legacy_message( + legacy::Message { + header: MessageHeader { + num_required_signatures: 2, + num_readonly_signed_accounts: 1, + num_readonly_unsigned_accounts: 1, + }, + account_keys: vec![key0, key1, key2, key3], + ..legacy::Message::default() }, - account_keys: vec![key0, key1, key2, key3], - ..legacy::Message::default() - }) + &HashSet::default(), + ) .unwrap(); assert_eq!(legacy_message.num_readonly_accounts(), 2); @@ -499,6 +522,7 @@ mod tests { writable: vec![key4], readonly: vec![key5], }, + &HashSet::default(), )); assert_eq!(v0_message.num_readonly_accounts(), 3); @@ -525,6 +549,7 @@ mod tests { Hash::default(), instructions, ), + &HashSet::default(), ) .unwrap(); @@ -556,15 +581,18 @@ mod tests { let key4 = Pubkey::new_unique(); let key5 = Pubkey::new_unique(); - let legacy_message = SanitizedMessage::try_from_legacy_message(legacy::Message { - header: MessageHeader { - num_required_signatures: 2, - num_readonly_signed_accounts: 1, - num_readonly_unsigned_accounts: 1, + let legacy_message = SanitizedMessage::try_from_legacy_message( + legacy::Message { + header: MessageHeader { + num_required_signatures: 2, + num_readonly_signed_accounts: 1, + num_readonly_unsigned_accounts: 1, + }, + account_keys: vec![key0, key1, key2, key3], + ..legacy::Message::default() }, - account_keys: vec![key0, key1, key2, key3], - ..legacy::Message::default() - }) + &HashSet::default(), + ) .unwrap(); match legacy_message { SanitizedMessage::Legacy(message) => { @@ -596,6 +624,7 @@ mod tests { writable: vec![key4], readonly: vec![key5], }, + &HashSet::default(), )); match v0_message { SanitizedMessage::V0(message) => { @@ -646,6 +675,7 @@ mod tests { mock_secp256k1_instr, ], ), + &HashSet::new(), ) .unwrap(); diff --git a/sdk/program/src/message/versions/v0/loaded.rs b/sdk/program/src/message/versions/v0/loaded.rs index c8edbff58b5522..1825c5e748e3f4 100644 --- a/sdk/program/src/message/versions/v0/loaded.rs +++ b/sdk/program/src/message/versions/v0/loaded.rs @@ -1,7 +1,7 @@ use { crate::{ bpf_loader_upgradeable, - message::{legacy::is_builtin_key_or_sysvar, v0, AccountKeys}, + message::{v0, AccountKeys}, pubkey::Pubkey, }, std::{borrow::Cow, collections::HashSet}, @@ -55,32 +55,40 @@ impl LoadedAddresses { } impl<'a> LoadedMessage<'a> { - pub fn new(message: v0::Message, loaded_addresses: LoadedAddresses) -> Self { + pub fn new( + message: v0::Message, + loaded_addresses: LoadedAddresses, + reserved_account_keys: &HashSet, + ) -> Self { let mut loaded_message = Self { message: Cow::Owned(message), loaded_addresses: Cow::Owned(loaded_addresses), is_writable_account_cache: Vec::default(), }; - loaded_message.set_is_writable_account_cache(); + loaded_message.set_is_writable_account_cache(reserved_account_keys); loaded_message } - pub fn new_borrowed(message: &'a v0::Message, loaded_addresses: &'a LoadedAddresses) -> Self { + pub fn new_borrowed( + message: &'a v0::Message, + loaded_addresses: &'a LoadedAddresses, + reserved_account_keys: &HashSet, + ) -> Self { let mut loaded_message = Self { message: Cow::Borrowed(message), loaded_addresses: Cow::Borrowed(loaded_addresses), is_writable_account_cache: Vec::default(), }; - loaded_message.set_is_writable_account_cache(); + loaded_message.set_is_writable_account_cache(reserved_account_keys); loaded_message } - fn set_is_writable_account_cache(&mut self) { + fn set_is_writable_account_cache(&mut self, reserved_account_keys: &HashSet) { let is_writable_account_cache = self .account_keys() .iter() .enumerate() - .map(|(i, _key)| self.is_writable_internal(i)) + .map(|(i, _key)| self.is_writable_internal(i, reserved_account_keys)) .collect::>(); let _ = std::mem::replace( &mut self.is_writable_account_cache, @@ -127,10 +135,14 @@ impl<'a> LoadedMessage<'a> { } /// Returns true if the account at the specified index was loaded as writable - fn is_writable_internal(&self, key_index: usize) -> bool { + fn is_writable_internal( + &self, + key_index: usize, + reserved_account_keys: &HashSet, + ) -> bool { if self.is_writable_index(key_index) { if let Some(key) = self.account_keys().get(key_index) { - return !(is_builtin_key_or_sysvar(key) || self.demote_program_id(key_index)); + return !(reserved_account_keys.contains(key) || self.demote_program_id(key_index)); } } false @@ -201,6 +213,7 @@ mod tests { writable: vec![key4], readonly: vec![key5], }, + &HashSet::default(), ); (message, [key0, key1, key2, key3, key4, key5]) @@ -225,6 +238,7 @@ mod tests { writable: keys.split_off(2), readonly: keys, }, + &HashSet::default(), ) }; @@ -257,6 +271,8 @@ mod tests { #[test] fn test_is_writable() { solana_logger::setup(); + + let reserved_account_keys = HashSet::from_iter([sysvar::clock::id(), system_program::id()]); let create_message_with_keys = |keys: Vec| { LoadedMessage::new( v0::Message { @@ -272,6 +288,7 @@ mod tests { writable: keys[2..=2].to_vec(), readonly: keys[3..].to_vec(), }, + &reserved_account_keys, ) }; @@ -321,6 +338,7 @@ mod tests { writable: vec![key1, key2], readonly: vec![], }, + &HashSet::default(), ); assert!(message.is_writable_index(2)); diff --git a/sdk/program/src/sysvar/instructions.rs b/sdk/program/src/sysvar/instructions.rs index 28d5674177b838..249b11b5f9452f 100644 --- a/sdk/program/src/sysvar/instructions.rs +++ b/sdk/program/src/sysvar/instructions.rs @@ -302,10 +302,11 @@ mod tests { message::{Message as LegacyMessage, SanitizedMessage}, pubkey::Pubkey, }, + std::collections::HashSet, }; fn new_sanitized_message(message: LegacyMessage) -> SanitizedMessage { - SanitizedMessage::try_from_legacy_message(message).unwrap() + SanitizedMessage::try_from_legacy_message(message, &HashSet::default()).unwrap() } #[test] diff --git a/sdk/src/nonce_info.rs b/sdk/src/nonce_info.rs index c29d3db6bdb944..2672174209f70e 100644 --- a/sdk/src/nonce_info.rs +++ b/sdk/src/nonce_info.rs @@ -124,6 +124,7 @@ mod tests { instruction::Instruction, message::Message, nonce::{self, state::DurableNonce}, + reserved_account_keys::ReservedAccountKeys, signature::{keypair_from_seed, Signer}, system_instruction, system_program, }, @@ -133,7 +134,11 @@ mod tests { instructions: &[Instruction], payer: Option<&Pubkey>, ) -> SanitizedMessage { - SanitizedMessage::try_from_legacy_message(Message::new(instructions, payer)).unwrap() + SanitizedMessage::try_from_legacy_message( + Message::new(instructions, payer), + &ReservedAccountKeys::empty_key_set(), + ) + .unwrap() } #[test] diff --git a/sdk/src/transaction/sanitized.rs b/sdk/src/transaction/sanitized.rs index b7383b4a0a454c..fe951c7ff57147 100644 --- a/sdk/src/transaction/sanitized.rs +++ b/sdk/src/transaction/sanitized.rs @@ -12,6 +12,7 @@ use { }, precompiles::verify_if_precompile, pubkey::Pubkey, + reserved_account_keys::ReservedAccountKeys, sanitize::Sanitize, signature::Signature, simple_vote_transaction_checker::is_simple_vote_transaction, @@ -19,6 +20,7 @@ use { transaction::{Result, Transaction, TransactionError, VersionedTransaction}, }, solana_program::message::SanitizedVersionedMessage, + std::collections::HashSet, }; /// Maximum number of accounts that a transaction may lock. @@ -66,17 +68,22 @@ impl SanitizedTransaction { message_hash: Hash, is_simple_vote_tx: bool, address_loader: impl AddressLoader, + reserved_account_keys: &HashSet, ) -> Result { let signatures = tx.signatures; let SanitizedVersionedMessage { message } = tx.message; let message = match message { VersionedMessage::Legacy(message) => { - SanitizedMessage::Legacy(LegacyMessage::new(message)) + SanitizedMessage::Legacy(LegacyMessage::new(message, reserved_account_keys)) } VersionedMessage::V0(message) => { let loaded_addresses = address_loader.load_addresses(&message.address_table_lookups)?; - SanitizedMessage::V0(v0::LoadedMessage::new(message, loaded_addresses)) + SanitizedMessage::V0(v0::LoadedMessage::new( + message, + loaded_addresses, + reserved_account_keys, + )) } }; @@ -96,6 +103,7 @@ impl SanitizedTransaction { message_hash: impl Into, is_simple_vote_tx: Option, address_loader: impl AddressLoader, + reserved_account_keys: &HashSet, ) -> Result { let sanitized_versioned_tx = SanitizedVersionedTransaction::try_from(tx)?; let is_simple_vote_tx = is_simple_vote_tx @@ -109,15 +117,23 @@ impl SanitizedTransaction { message_hash, is_simple_vote_tx, address_loader, + reserved_account_keys, ) } - pub fn try_from_legacy_transaction(tx: Transaction) -> Result { + /// Create a sanitized transaction from a legacy transaction + pub fn try_from_legacy_transaction( + tx: Transaction, + reserved_account_keys: &HashSet, + ) -> Result { tx.sanitize()?; Ok(Self { message_hash: tx.message.hash(), - message: SanitizedMessage::Legacy(LegacyMessage::new(tx.message)), + message: SanitizedMessage::Legacy(LegacyMessage::new( + tx.message, + reserved_account_keys, + )), is_simple_vote_tx: false, signatures: tx.signatures, }) @@ -125,7 +141,7 @@ impl SanitizedTransaction { /// Create a sanitized transaction from a legacy transaction. Used for tests only. pub fn from_transaction_for_tests(tx: Transaction) -> Self { - Self::try_from_legacy_transaction(tx).unwrap() + Self::try_from_legacy_transaction(tx, &ReservedAccountKeys::empty_key_set()).unwrap() } /// Return the first signature for this transaction. @@ -292,7 +308,10 @@ impl SanitizedTransaction { mod tests { use { super::*, - crate::signer::{keypair::Keypair, Signer}, + crate::{ + reserved_account_keys::ReservedAccountKeys, + signer::{keypair::Keypair, Signer}, + }, solana_program::vote::{self, state::Vote}, }; @@ -317,6 +336,7 @@ mod tests { MessageHash::Compute, None, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); assert!(vote_transaction.is_simple_vote_transaction()); @@ -329,6 +349,7 @@ mod tests { MessageHash::Compute, Some(false), SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); assert!(!vote_transaction.is_simple_vote_transaction()); @@ -343,6 +364,7 @@ mod tests { MessageHash::Compute, None, SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); assert!(!vote_transaction.is_simple_vote_transaction()); @@ -355,6 +377,7 @@ mod tests { MessageHash::Compute, Some(true), SimpleAddressLoader::Disabled, + &ReservedAccountKeys::empty_key_set(), ) .unwrap(); assert!(vote_transaction.is_simple_vote_transaction()); diff --git a/svm/src/account_loader.rs b/svm/src/account_loader.rs index 8911f28822fbae..f35252e896a5f6 100644 --- a/svm/src/account_loader.rs +++ b/svm/src/account_loader.rs @@ -491,6 +491,7 @@ mod tests { rent::Rent, rent_collector::{RentCollector, RENT_EXEMPT_RENT_EPOCH}, rent_debits::RentDebits, + reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signature, Signer}, system_program, system_transaction, sysvar, transaction::{Result, SanitizedTransaction, Transaction, TransactionError}, @@ -570,6 +571,18 @@ mod tests { features } + fn new_sanitized_message(message: Message) -> SanitizedMessage { + SanitizedMessage::try_from_legacy_message(message, &ReservedAccountKeys::empty_key_set()) + .unwrap() + } + + fn new_unchecked_sanitized_message(message: Message) -> SanitizedMessage { + SanitizedMessage::Legacy(LegacyMessage::new( + message, + &ReservedAccountKeys::empty_key_set(), + )) + } + fn load_accounts_with_fee( tx: Transaction, ka: &[TransactionAccount], @@ -689,7 +702,7 @@ mod tests { instructions, ); - let message = SanitizedMessage::try_from_legacy_message(tx.message().clone()).unwrap(); + let message = new_sanitized_message(tx.message().clone()); let fee = FeeStructure::default().calculate_fee( &message, lamports_per_signature, @@ -1217,7 +1230,7 @@ mod tests { Hash::default(), ); - let message = SanitizedMessage::try_from_legacy_message(tx.message().clone()).unwrap(); + let message = new_sanitized_message(tx.message().clone()); let fee = FeeStructure::default().calculate_fee( &message, lamports_per_signature, @@ -1441,8 +1454,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mock_bank = TestCallbacks::default(); let mut error_counter = TransactionErrorMetrics::default(); let loaded_programs = LoadedProgramsForTxBatch::default(); @@ -1479,8 +1491,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); mock_bank .accounts_map @@ -1548,8 +1559,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_lamports(200); @@ -1593,8 +1603,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_lamports(200); @@ -1637,8 +1646,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_lamports(200); @@ -1684,8 +1692,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_owner(native_loader::id()); @@ -1754,8 +1761,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_executable(true); @@ -1807,8 +1813,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_executable(true); @@ -1868,8 +1873,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_executable(true); @@ -1957,8 +1961,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_executable(true); @@ -2110,8 +2113,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); let mut account_data = AccountSharedData::default(); account_data.set_executable(true); @@ -2202,8 +2204,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let sanitized_transaction = SanitizedTransaction::new_for_tests( sanitized_message, vec![Signature::new_unique()], diff --git a/svm/src/message_processor.rs b/svm/src/message_processor.rs index 6e788b9c0f86e0..f6595b4450bce7 100644 --- a/svm/src/message_processor.rs +++ b/svm/src/message_processor.rs @@ -160,6 +160,7 @@ mod tests { native_loader::{self, create_loadable_account_for_test}, pubkey::Pubkey, rent::Rent, + reserved_account_keys::ReservedAccountKeys, secp256k1_instruction::new_secp256k1_instruction, secp256k1_program, system_program, transaction_context::TransactionContext, @@ -177,7 +178,8 @@ mod tests { } fn new_sanitized_message(message: Message) -> SanitizedMessage { - SanitizedMessage::try_from_legacy_message(message).unwrap() + SanitizedMessage::try_from_legacy_message(message, &ReservedAccountKeys::empty_key_set()) + .unwrap() } #[test] diff --git a/svm/src/transaction_account_state_info.rs b/svm/src/transaction_account_state_info.rs index 0631050fe0e765..74d898b81adc10 100644 --- a/svm/src/transaction_account_state_info.rs +++ b/svm/src/transaction_account_state_info.rs @@ -82,6 +82,7 @@ mod test { instruction::CompiledInstruction, message::{LegacyMessage, Message, MessageHeader, SanitizedMessage}, rent::Rent, + reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signer}, transaction::TransactionError, transaction_context::TransactionContext, @@ -114,8 +115,10 @@ mod test { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = SanitizedMessage::Legacy(LegacyMessage::new( + message, + &ReservedAccountKeys::empty_key_set(), + )); let transaction_accounts = vec![ (key1.pubkey(), AccountSharedData::default()), @@ -166,8 +169,10 @@ mod test { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = SanitizedMessage::Legacy(LegacyMessage::new( + message, + &ReservedAccountKeys::empty_key_set(), + )); let transaction_accounts = vec![ (key1.pubkey(), AccountSharedData::default()), diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index a069a6c74e6cd5..bc7cce7c778bdd 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -995,6 +995,7 @@ mod tests { fee_calculator::FeeCalculator, message::{LegacyMessage, Message, MessageHeader}, rent_debits::RentDebits, + reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signature}, sysvar::{self, rent::Rent}, transaction::{SanitizedTransaction, Transaction, TransactionError}, @@ -1007,6 +1008,13 @@ mod tests { }, }; + fn new_unchecked_sanitized_message(message: Message) -> SanitizedMessage { + SanitizedMessage::Legacy(LegacyMessage::new( + message, + &ReservedAccountKeys::empty_key_set(), + )) + } + struct TestForkGraph {} impl ForkGraph for TestForkGraph { @@ -1711,8 +1719,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let loaded_programs = LoadedProgramsForTxBatch::default(); let mock_bank = MockBankCallback::default(); let batch_processor = TransactionBatchProcessor::::default(); @@ -1836,8 +1843,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let loaded_programs = LoadedProgramsForTxBatch::default(); let mock_bank = MockBankCallback::default(); let batch_processor = TransactionBatchProcessor::::default(); @@ -1954,8 +1960,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let sanitized_transaction_1 = SanitizedTransaction::new_for_tests( sanitized_message, @@ -1985,8 +1990,7 @@ mod tests { recent_blockhash: Hash::default(), }; - let legacy = LegacyMessage::new(message); - let sanitized_message = SanitizedMessage::Legacy(legacy); + let sanitized_message = new_unchecked_sanitized_message(message); let sanitized_transaction_2 = SanitizedTransaction::new_for_tests( sanitized_message, diff --git a/svm/tests/transaction_builder.rs b/svm/tests/transaction_builder.rs index ca8ef79a9b73c9..7d880aa168e5f1 100644 --- a/svm/tests/transaction_builder.rs +++ b/svm/tests/transaction_builder.rs @@ -4,6 +4,7 @@ use { instruction::{AccountMeta, CompiledInstruction}, message::{Message, MessageHeader}, pubkey::Pubkey, + reserved_account_keys::ReservedAccountKeys, signature::Signature, transaction::{SanitizedTransaction, Transaction}, }, @@ -126,7 +127,11 @@ impl SanitizedTransactionBuilder { message, }; - SanitizedTransaction::try_from_legacy_transaction(transaction).unwrap() + SanitizedTransaction::try_from_legacy_transaction( + transaction, + &ReservedAccountKeys::new_all_activated().active, + ) + .unwrap() } } diff --git a/transaction-status/src/lib.rs b/transaction-status/src/lib.rs index 0eb13d36819c4a..4028ff14bb62bb 100644 --- a/transaction-status/src/lib.rs +++ b/transaction-status/src/lib.rs @@ -19,6 +19,7 @@ use { AccountKeys, Message, MessageHeader, VersionedMessage, }, pubkey::Pubkey, + reserved_account_keys::ReservedAccountKeys, signature::Signature, transaction::{ Result as TransactionResult, Transaction, TransactionError, TransactionVersion, @@ -980,12 +981,16 @@ impl VersionedTransactionWithStatusMeta { show_rewards: bool, ) -> Result { let version = self.validate_version(max_supported_transaction_version)?; + let reserved_account_keys = ReservedAccountKeys::new_all_activated(); let account_keys = match &self.transaction.message { VersionedMessage::Legacy(message) => parse_legacy_message_accounts(message), VersionedMessage::V0(message) => { - let loaded_message = - LoadedMessage::new_borrowed(message, &self.meta.loaded_addresses); + let loaded_message = LoadedMessage::new_borrowed( + message, + &self.meta.loaded_addresses, + &reserved_account_keys.active, + ); parse_v0_message_accounts(&loaded_message) } }; @@ -1228,8 +1233,13 @@ impl EncodableWithMeta for v0::Message { meta: &TransactionStatusMeta, ) -> Self::Encoded { if encoding == UiTransactionEncoding::JsonParsed { + let reserved_account_keys = ReservedAccountKeys::new_all_activated(); let account_keys = AccountKeys::new(&self.account_keys, Some(&meta.loaded_addresses)); - let loaded_message = LoadedMessage::new_borrowed(self, &meta.loaded_addresses); + let loaded_message = LoadedMessage::new_borrowed( + self, + &meta.loaded_addresses, + &reserved_account_keys.active, + ); UiMessage::Parsed(UiParsedMessage { account_keys: parse_v0_message_accounts(&loaded_message), recent_blockhash: self.recent_blockhash.to_string(), diff --git a/transaction-status/src/parse_accounts.rs b/transaction-status/src/parse_accounts.rs index 5388c15ecf858b..097cb50d716cc9 100644 --- a/transaction-status/src/parse_accounts.rs +++ b/transaction-status/src/parse_accounts.rs @@ -54,6 +54,7 @@ mod test { solana_sdk::{ message::{v0, v0::LoadedAddresses, MessageHeader}, pubkey::Pubkey, + reserved_account_keys::ReservedAccountKeys, }, }; @@ -126,6 +127,7 @@ mod test { writable: vec![pubkey4], readonly: vec![pubkey5], }, + &ReservedAccountKeys::empty_key_set(), ); assert_eq!(