diff --git a/Cargo.lock b/Cargo.lock index cfa0233ba5a205..bba4a76258c48d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6658,9 +6658,13 @@ name = "solana-feature-set" version = "2.1.0" dependencies = [ "lazy_static", + "solana-clock", + "solana-epoch-schedule", "solana-frozen-abi", "solana-frozen-abi-macro", - "solana-program", + "solana-hash", + "solana-pubkey", + "solana-sha256-hasher", ] [[package]] @@ -6842,7 +6846,7 @@ name = "solana-inline-spl" version = "2.1.0" dependencies = [ "bytemuck", - "solana-program", + "solana-pubkey", ] [[package]] @@ -6872,6 +6876,7 @@ dependencies = [ "clap 3.2.23", "dirs-next", "num_cpus", + "serde_json", "solana-clap-v3-utils", "solana-cli-config", "solana-derivation-path", @@ -7037,6 +7042,7 @@ dependencies = [ "byte-unit", "clap 3.2.23", "serde", + "serde_derive", "serde_json", "solana-logger", "solana-version", @@ -7112,6 +7118,10 @@ dependencies = [ "solana-define-syscall", ] +[[package]] +name = "solana-native-token" +version = "2.1.0" + [[package]] name = "solana-net-shaper" version = "2.1.0" @@ -7312,6 +7322,7 @@ dependencies = [ "solana-instruction", "solana-logger", "solana-msg", + "solana-native-token", "solana-program-error", "solana-program-memory", "solana-program-option", @@ -7892,6 +7903,7 @@ dependencies = [ "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", + "solana-native-token", "solana-program", "solana-program-memory", "solana-pubkey", diff --git a/Cargo.toml b/Cargo.toml index 5ec30da8b2c460..8339070f9bbf39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,7 +99,6 @@ members = [ "rpc-test", "runtime", "runtime-transaction", - "sanitize", "sdk", "sdk/account", "sdk/account-info", @@ -117,6 +116,7 @@ members = [ "sdk/instruction", "sdk/macro", "sdk/msg", + "sdk/native-token", "sdk/package-metadata", "sdk/package-metadata-macro", "sdk/program", @@ -126,6 +126,7 @@ members = [ "sdk/program-pack", "sdk/pubkey", "sdk/rent", + "sdk/sanitize", "sdk/serde-varint", "sdk/serialize-utils", "sdk/sha256-hasher", @@ -432,6 +433,7 @@ solana-measure = { path = "measure", version = "=2.1.0" } solana-merkle-tree = { path = "merkle-tree", version = "=2.1.0" } solana-metrics = { path = "metrics", version = "=2.1.0" } solana-msg = { path = "sdk/msg", version = "=2.1.0" } +solana-native-token = { path = "sdk/native-token", version = "=2.1.0" } solana-net-utils = { path = "net-utils", version = "=2.1.0" } solana-nohash-hasher = "0.2.1" solana-notifier = { path = "notifier", version = "=2.1.0" } @@ -453,7 +455,7 @@ solana-quic-client = { path = "quic-client", version = "=2.1.0" } solana-rayon-threadlimit = { path = "rayon-threadlimit", version = "=2.1.0" } solana-remote-wallet = { path = "remote-wallet", version = "=2.1.0", default-features = false } solana-rent = { path = "sdk/rent", version = "=2.1.0", default-features = false } -solana-sanitize = { path = "sanitize", version = "=2.1.0" } +solana-sanitize = { path = "sdk/sanitize", version = "=2.1.0" } solana-serde-varint = { path = "sdk/serde-varint", version = "=2.1.0" } solana-serialize-utils = { path = "sdk/serialize-utils", version = "=2.1.0" } solana-sha256-hasher = { path = "sdk/sha256-hasher", version = "=2.1.0" } diff --git a/accounts-db/src/accounts.rs b/accounts-db/src/accounts.rs index 2584f900edbc49..cce35988aff69d 100644 --- a/accounts-db/src/accounts.rs +++ b/accounts-db/src/accounts.rs @@ -81,12 +81,14 @@ impl Accounts { } } + /// Return loaded addresses and the deactivation slot. + /// If the table hasn't been deactivated, the deactivation slot is `u64::MAX`. pub fn load_lookup_table_addresses( &self, ancestors: &Ancestors, address_table_lookup: SVMMessageAddressTableLookup, slot_hashes: &SlotHashes, - ) -> std::result::Result { + ) -> std::result::Result<(LoadedAddresses, Slot), AddressLookupError> { let table_account = self .accounts_db .load_with_fixed_root(ancestors, address_table_lookup.account_key) @@ -98,18 +100,21 @@ impl Accounts { let lookup_table = AddressLookupTable::deserialize(table_account.data()) .map_err(|_ix_err| AddressLookupError::InvalidAccountData)?; - Ok(LoadedAddresses { - writable: lookup_table.lookup( - current_slot, - address_table_lookup.writable_indexes, - slot_hashes, - )?, - readonly: lookup_table.lookup( - current_slot, - address_table_lookup.readonly_indexes, - slot_hashes, - )?, - }) + Ok(( + LoadedAddresses { + writable: lookup_table.lookup( + current_slot, + address_table_lookup.writable_indexes, + slot_hashes, + )?, + readonly: lookup_table.lookup( + current_slot, + address_table_lookup.readonly_indexes, + slot_hashes, + )?, + }, + lookup_table.meta.deactivation_slot, + )) } else { Err(AddressLookupError::InvalidAccountOwner) } @@ -806,10 +811,13 @@ mod tests { SVMMessageAddressTableLookup::from(&address_table_lookup), &SlotHashes::default(), ), - Ok(LoadedAddresses { - writable: vec![table_addresses[0]], - readonly: vec![table_addresses[1]], - }), + Ok(( + LoadedAddresses { + writable: vec![table_addresses[0]], + readonly: vec![table_addresses[1]], + }, + u64::MAX + )), ); } diff --git a/bucket_map/src/bucket_storage.rs b/bucket_map/src/bucket_storage.rs index a55923c142d850..95f05cfdfaa679 100644 --- a/bucket_map/src/bucket_storage.rs +++ b/bucket_map/src/bucket_storage.rs @@ -433,6 +433,10 @@ impl BucketStorage { std::env::current_dir(), ); }); + // Access to the disk bucket files are random (excluding the linear search on collisions), + // so advise the kernel to treat the mmaps as such. + #[cfg(unix)] + mmap.advise(memmap2::Advice::Random).unwrap(); measure_mmap.stop(); stats .new_file_us diff --git a/core/src/banking_stage/consume_worker.rs b/core/src/banking_stage/consume_worker.rs index b676168bb04d4d..787901ffa521f8 100644 --- a/core/src/banking_stage/consume_worker.rs +++ b/core/src/banking_stage/consume_worker.rs @@ -107,7 +107,7 @@ impl ConsumeWorker { let output = self.consumer.process_and_record_aged_transactions( bank, &work.transactions, - &work.max_age_slots, + &work.max_ages, ); self.metrics.update_for_consume(&output); @@ -694,7 +694,7 @@ mod tests { crate::banking_stage::{ committer::Committer, qos_service::QosService, - scheduler_messages::{TransactionBatchId, TransactionId}, + scheduler_messages::{MaxAge, TransactionBatchId, TransactionId}, tests::{create_slow_genesis_config, sanitize_transactions, simulate_poh}, }, crossbeam_channel::unbounded, @@ -708,10 +708,25 @@ mod tests { vote_sender_types::ReplayVoteReceiver, }, solana_sdk::{ - genesis_config::GenesisConfig, poh_config::PohConfig, pubkey::Pubkey, - signature::Keypair, system_transaction, + address_lookup_table::AddressLookupTableAccount, + clock::{Slot, MAX_PROCESSING_AGE}, + genesis_config::GenesisConfig, + message::{ + v0::{self, LoadedAddresses}, + SimpleAddressLoader, VersionedMessage, + }, + poh_config::PohConfig, + pubkey::Pubkey, + signature::Keypair, + signer::Signer, + system_instruction, system_transaction, + transaction::{ + MessageHash, SanitizedTransaction, TransactionError, VersionedTransaction, + }, }, + solana_svm_transaction::svm_message::SVMMessage, std::{ + collections::HashSet, sync::{atomic::AtomicBool, RwLock}, thread::JoinHandle, }, @@ -742,6 +757,7 @@ mod tests { .. } = create_slow_genesis_config(10_000); let (bank, bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config); + let bank = Arc::new(Bank::new_from_parent(bank, &Pubkey::new_unique(), 1)); let ledger_path = get_tmp_ledger_path_auto_delete!(); let blockstore = Blockstore::open(ledger_path.path()) @@ -820,17 +836,21 @@ mod tests { )]); let bid = TransactionBatchId::new(0); let id = TransactionId::new(0); + let max_age = MaxAge { + epoch_invalidation_slot: bank.slot(), + alt_invalidation_slot: bank.slot(), + }; let work = ConsumeWork { batch_id: bid, ids: vec![id], transactions, - max_age_slots: vec![bank.slot()], + max_ages: vec![max_age], }; consume_sender.send(work).unwrap(); let consumed = consumed_receiver.recv().unwrap(); assert_eq!(consumed.work.batch_id, bid); assert_eq!(consumed.work.ids, vec![id]); - assert_eq!(consumed.work.max_age_slots, vec![bank.slot()]); + assert_eq!(consumed.work.max_ages, vec![max_age]); assert_eq!(consumed.retryable_indexes, vec![0]); drop(test_frame); @@ -865,17 +885,21 @@ mod tests { )]); let bid = TransactionBatchId::new(0); let id = TransactionId::new(0); + let max_age = MaxAge { + epoch_invalidation_slot: bank.slot(), + alt_invalidation_slot: bank.slot(), + }; let work = ConsumeWork { batch_id: bid, ids: vec![id], transactions, - max_age_slots: vec![bank.slot()], + max_ages: vec![max_age], }; consume_sender.send(work).unwrap(); let consumed = consumed_receiver.recv().unwrap(); assert_eq!(consumed.work.batch_id, bid); assert_eq!(consumed.work.ids, vec![id]); - assert_eq!(consumed.work.max_age_slots, vec![bank.slot()]); + assert_eq!(consumed.work.max_ages, vec![max_age]); assert_eq!(consumed.retryable_indexes, Vec::::new()); drop(test_frame); @@ -911,19 +935,23 @@ mod tests { let bid = TransactionBatchId::new(0); let id1 = TransactionId::new(1); let id2 = TransactionId::new(0); + let max_age = MaxAge { + epoch_invalidation_slot: bank.slot(), + alt_invalidation_slot: bank.slot(), + }; consume_sender .send(ConsumeWork { batch_id: bid, ids: vec![id1, id2], transactions: txs, - max_age_slots: vec![bank.slot(), bank.slot()], + max_ages: vec![max_age, max_age], }) .unwrap(); let consumed = consumed_receiver.recv().unwrap(); assert_eq!(consumed.work.batch_id, bid); assert_eq!(consumed.work.ids, vec![id1, id2]); - assert_eq!(consumed.work.max_age_slots, vec![bank.slot(), bank.slot()]); + assert_eq!(consumed.work.max_ages, vec![max_age, max_age]); assert_eq!(consumed.retryable_indexes, vec![1]); // id2 is retryable since lock conflict drop(test_frame); @@ -968,12 +996,16 @@ mod tests { let bid2 = TransactionBatchId::new(1); let id1 = TransactionId::new(1); let id2 = TransactionId::new(0); + let max_age = MaxAge { + epoch_invalidation_slot: bank.slot(), + alt_invalidation_slot: bank.slot(), + }; consume_sender .send(ConsumeWork { batch_id: bid1, ids: vec![id1], transactions: txs1, - max_age_slots: vec![bank.slot()], + max_ages: vec![max_age], }) .unwrap(); @@ -982,22 +1014,185 @@ mod tests { batch_id: bid2, ids: vec![id2], transactions: txs2, - max_age_slots: vec![bank.slot()], + max_ages: vec![max_age], }) .unwrap(); let consumed = consumed_receiver.recv().unwrap(); assert_eq!(consumed.work.batch_id, bid1); assert_eq!(consumed.work.ids, vec![id1]); - assert_eq!(consumed.work.max_age_slots, vec![bank.slot()]); + assert_eq!(consumed.work.max_ages, vec![max_age]); assert_eq!(consumed.retryable_indexes, Vec::::new()); let consumed = consumed_receiver.recv().unwrap(); assert_eq!(consumed.work.batch_id, bid2); assert_eq!(consumed.work.ids, vec![id2]); - assert_eq!(consumed.work.max_age_slots, vec![bank.slot()]); + assert_eq!(consumed.work.max_ages, vec![max_age]); assert_eq!(consumed.retryable_indexes, Vec::::new()); drop(test_frame); let _ = worker_thread.join().unwrap(); } + + #[test] + fn test_worker_ttl() { + let (test_frame, worker) = setup_test_frame(); + let TestFrame { + mint_keypair, + genesis_config, + bank, + poh_recorder, + consume_sender, + consumed_receiver, + .. + } = &test_frame; + let worker_thread = std::thread::spawn(move || worker.run()); + poh_recorder + .write() + .unwrap() + .set_bank_for_test(bank.clone()); + assert!(bank.slot() > 0); + + // No conflicts between transactions. Test 6 cases. + // 1. Epoch expiration, before slot => still succeeds due to resanitizing + // 2. Epoch expiration, on slot => succeeds normally + // 3. Epoch expiration, after slot => succeeds normally + // 4. ALT expiration, before slot => fails + // 5. ALT expiration, on slot => succeeds normally + // 6. ALT expiration, after slot => succeeds normally + let simple_transfer = || { + system_transaction::transfer( + &Keypair::new(), + &Pubkey::new_unique(), + 1, + genesis_config.hash(), + ) + }; + let simple_v0_transfer = || { + let payer = Keypair::new(); + let to_pubkey = Pubkey::new_unique(); + let loaded_addresses = LoadedAddresses { + writable: vec![to_pubkey], + readonly: vec![], + }; + let loader = SimpleAddressLoader::Enabled(loaded_addresses); + SanitizedTransaction::try_create( + VersionedTransaction::try_new( + VersionedMessage::V0( + v0::Message::try_compile( + &payer.pubkey(), + &[system_instruction::transfer(&payer.pubkey(), &to_pubkey, 1)], + &[AddressLookupTableAccount { + key: Pubkey::new_unique(), // will fail if using **bank** to lookup + addresses: vec![to_pubkey], + }], + genesis_config.hash(), + ) + .unwrap(), + ), + &[&payer], + ) + .unwrap(), + MessageHash::Compute, + None, + loader, + &HashSet::default(), + ) + .unwrap() + }; + + let mut txs = sanitize_transactions(vec![ + simple_transfer(), + simple_transfer(), + simple_transfer(), + ]); + txs.push(simple_v0_transfer()); + txs.push(simple_v0_transfer()); + txs.push(simple_v0_transfer()); + let sanitized_txs = txs.clone(); + + // Fund the keypairs. + for tx in &txs { + bank.process_transaction(&system_transaction::transfer( + mint_keypair, + &tx.account_keys()[0], + 2, + genesis_config.hash(), + )) + .unwrap(); + } + + consume_sender + .send(ConsumeWork { + batch_id: TransactionBatchId::new(1), + ids: vec![ + TransactionId::new(0), + TransactionId::new(1), + TransactionId::new(2), + TransactionId::new(3), + TransactionId::new(4), + TransactionId::new(5), + ], + transactions: txs, + max_ages: vec![ + MaxAge { + epoch_invalidation_slot: bank.slot() - 1, + alt_invalidation_slot: Slot::MAX, + }, + MaxAge { + epoch_invalidation_slot: bank.slot(), + alt_invalidation_slot: Slot::MAX, + }, + MaxAge { + epoch_invalidation_slot: bank.slot() + 1, + alt_invalidation_slot: Slot::MAX, + }, + MaxAge { + epoch_invalidation_slot: u64::MAX, + alt_invalidation_slot: bank.slot() - 1, + }, + MaxAge { + epoch_invalidation_slot: u64::MAX, + alt_invalidation_slot: bank.slot(), + }, + MaxAge { + epoch_invalidation_slot: u64::MAX, + alt_invalidation_slot: bank.slot() + 1, + }, + ], + }) + .unwrap(); + + let consumed = consumed_receiver.recv().unwrap(); + assert_eq!(consumed.retryable_indexes, Vec::::new()); + // all but one succeed. 6 for initial funding + assert_eq!(bank.transaction_count(), 6 + 5); + + let already_processed_results = bank + .check_transactions( + &sanitized_txs, + &vec![Ok(()); sanitized_txs.len()], + MAX_PROCESSING_AGE, + &mut TransactionErrorMetrics::default(), + ) + .into_iter() + .map(|r| match r { + Ok(_) => Ok(()), + Err(err) => Err(err), + }) + .collect::>(); + assert_eq!( + already_processed_results, + vec![ + Err(TransactionError::AlreadyProcessed), + Err(TransactionError::AlreadyProcessed), + Err(TransactionError::AlreadyProcessed), + Ok(()), // <--- this transaction was not processed + Err(TransactionError::AlreadyProcessed), + Err(TransactionError::AlreadyProcessed) + ] + ); + + drop(test_frame); + let _ = worker_thread.join().unwrap(); + } } diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs index 57f1b1958b152c..ae04cc30ff0167 100644 --- a/core/src/banking_stage/consumer.rs +++ b/core/src/banking_stage/consumer.rs @@ -7,6 +7,7 @@ use { }, leader_slot_timing_metrics::LeaderExecuteAndCommitTimings, qos_service::QosService, + scheduler_messages::MaxAge, unprocessed_transaction_storage::{ConsumeScannerPayload, UnprocessedTransactionStorage}, BankingStageStats, }, @@ -25,12 +26,12 @@ use { }, solana_runtime_transaction::instructions_processor::process_compute_budget_instructions, solana_sdk::{ - clock::{Slot, FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE}, + clock::{FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE}, fee::FeeBudgetLimits, message::SanitizedMessage, saturating_add_assign, timing::timestamp, - transaction::{self, AddressLoader, SanitizedTransaction, TransactionError}, + transaction::{self, SanitizedTransaction, TransactionError}, }, solana_svm::{ account_loader::{validate_fee_payer, TransactionCheckResult}, @@ -429,7 +430,7 @@ impl Consumer { &self, bank: &Arc, txs: &[SanitizedTransaction], - max_slot_ages: &[Slot], + max_ages: &[MaxAge], ) -> ProcessTransactionBatchOutput { let move_precompile_verification_to_svm = bank .feature_set @@ -438,8 +439,9 @@ impl Consumer { // Need to filter out transactions since they were sanitized earlier. // This means that the transaction may cross and epoch boundary (not allowed), // or account lookup tables may have been closed. - let pre_results = txs.iter().zip(max_slot_ages).map(|(tx, max_slot_age)| { - if *max_slot_age < bank.slot() { + let pre_results = txs.iter().zip(max_ages).map(|(tx, max_age)| { + if bank.slot() > max_age.epoch_invalidation_slot { + // Epoch has rolled over. Need to fully re-verify the transaction. // Pre-compiles are verified here. // Attempt re-sanitization after epoch-cross. // Re-sanitized transaction should be equal to the original transaction, @@ -451,18 +453,24 @@ impl Consumer { return Err(TransactionError::ResanitizationNeeded); } } else { + if bank.slot() > max_age.alt_invalidation_slot { + // The address table lookup **may** have expired, but the + // expiration is not guaranteed since there may have been + // skipped slot. + // If the addresses still resolve here, then the transaction is still + // valid, and we can continue with processing. + // If they do not, then the ATL has expired and the transaction + // can be dropped. + let (_addresses, _deactivation_slot) = + bank.load_addresses_from_ref(tx.message_address_table_lookups())?; + } + // Verify pre-compiles. if !move_precompile_verification_to_svm { verify_precompiles(tx, &bank.feature_set)?; } - - // Any transaction executed between sanitization time and now may have closed the lookup table(s). - // Above re-sanitization already loads addresses, so don't need to re-check in that case. - let lookup_tables = tx.message().message_address_table_lookups(); - if !lookup_tables.is_empty() { - bank.load_addresses(lookup_tables)?; - } } + Ok(()) }); self.process_and_record_transactions_with_pre_results(bank, txs, 0, pre_results) diff --git a/core/src/banking_stage/immutable_deserialized_packet.rs b/core/src/banking_stage/immutable_deserialized_packet.rs index b03f3d5d64d4e8..978e4f9b935c7e 100644 --- a/core/src/banking_stage/immutable_deserialized_packet.rs +++ b/core/src/banking_stage/immutable_deserialized_packet.rs @@ -2,20 +2,21 @@ use { super::packet_filter::PacketFilterFailure, solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, solana_perf::packet::Packet, + solana_runtime::bank::Bank, solana_runtime_transaction::instructions_processor::process_compute_budget_instructions, solana_sanitize::SanitizeError, solana_sdk::{ + clock::Slot, hash::Hash, - message::Message, + message::{v0::LoadedAddresses, AddressLoaderError, Message, SimpleAddressLoader}, pubkey::Pubkey, signature::Signature, - transaction::{ - AddressLoader, SanitizedTransaction, SanitizedVersionedTransaction, - VersionedTransaction, - }, + transaction::{SanitizedTransaction, SanitizedVersionedTransaction, VersionedTransaction}, }, solana_short_vec::decode_shortu16_len, - solana_svm_transaction::instruction::SVMInstruction, + solana_svm_transaction::{ + instruction::SVMInstruction, message_address_table_lookup::SVMMessageAddressTableLookup, + }, std::{cmp::Ordering, collections::HashSet, mem::size_of}, thiserror::Error, }; @@ -111,15 +112,22 @@ impl ImmutableDeserializedPacket { // This function deserializes packets into transactions, computes the blake3 hash of transaction // messages. + // Additionally, this returns the minimum deactivation slot of the resolved addresses. pub fn build_sanitized_transaction( &self, votes_only: bool, - address_loader: impl AddressLoader, + bank: &Bank, reserved_account_keys: &HashSet, - ) -> Option { + ) -> Option<(SanitizedTransaction, Slot)> { if votes_only && !self.is_simple_vote() { return None; } + + // Resolve the lookup addresses and retrieve the min deactivation slot + let (loaded_addresses, deactivation_slot) = + Self::resolve_addresses_with_deactivation(self.transaction(), bank).ok()?; + let address_loader = SimpleAddressLoader::Enabled(loaded_addresses); + let tx = SanitizedTransaction::try_new( self.transaction().clone(), *self.message_hash(), @@ -128,7 +136,23 @@ impl ImmutableDeserializedPacket { reserved_account_keys, ) .ok()?; - Some(tx) + Some((tx, deactivation_slot)) + } + + fn resolve_addresses_with_deactivation( + transaction: &SanitizedVersionedTransaction, + bank: &Bank, + ) -> Result<(LoadedAddresses, Slot), AddressLoaderError> { + let Some(address_table_lookups) = transaction.get_message().message.address_table_lookups() + else { + return Ok((LoadedAddresses::default(), Slot::MAX)); + }; + + bank.load_addresses_from_ref( + address_table_lookups + .iter() + .map(SVMMessageAddressTableLookup::from), + ) } } diff --git a/core/src/banking_stage/latest_unprocessed_votes.rs b/core/src/banking_stage/latest_unprocessed_votes.rs index bb97142bda5e81..ae13c37caa5a0e 100644 --- a/core/src/banking_stage/latest_unprocessed_votes.rs +++ b/core/src/banking_stage/latest_unprocessed_votes.rs @@ -420,7 +420,7 @@ impl LatestUnprocessedVotes { } let deserialized_vote_packet = vote.vote.as_ref().unwrap().clone(); - let Some(sanitized_vote_transaction) = deserialized_vote_packet + let Some((sanitized_vote_transaction, _deactivation_slot)) = deserialized_vote_packet .build_sanitized_transaction( bank.vote_only_bank(), bank.as_ref(), diff --git a/core/src/banking_stage/scheduler_messages.rs b/core/src/banking_stage/scheduler_messages.rs index d93d2d6dbb6c52..29e9b99f50588a 100644 --- a/core/src/banking_stage/scheduler_messages.rs +++ b/core/src/banking_stage/scheduler_messages.rs @@ -35,13 +35,19 @@ impl Display for TransactionId { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct MaxAge { + pub epoch_invalidation_slot: Slot, + pub alt_invalidation_slot: Slot, +} + /// Message: [Scheduler -> Worker] /// Transactions to be consumed (i.e. executed, recorded, and committed) pub struct ConsumeWork { pub batch_id: TransactionBatchId, pub ids: Vec, pub transactions: Vec, - pub max_age_slots: Vec, + pub max_ages: Vec, } /// Message: [Worker -> Scheduler] diff --git a/core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs b/core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs index 59ce92173ed26e..9f6fcc8388a364 100644 --- a/core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs +++ b/core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs @@ -9,7 +9,9 @@ use { crate::banking_stage::{ consumer::TARGET_NUM_TRANSACTIONS_PER_BATCH, read_write_account_set::ReadWriteAccountSet, - scheduler_messages::{ConsumeWork, FinishedConsumeWork, TransactionBatchId, TransactionId}, + scheduler_messages::{ + ConsumeWork, FinishedConsumeWork, MaxAge, TransactionBatchId, TransactionId, + }, transaction_scheduler::{ transaction_priority_id::TransactionPriorityId, transaction_state::TransactionState, }, @@ -19,10 +21,7 @@ use { prio_graph::{AccessKind, PrioGraph}, solana_cost_model::block_cost_limits::MAX_BLOCK_UNITS, solana_measure::measure_us, - solana_sdk::{ - pubkey::Pubkey, saturating_add_assign, slot_history::Slot, - transaction::SanitizedTransaction, - }, + solana_sdk::{pubkey::Pubkey, saturating_add_assign, transaction::SanitizedTransaction}, }; pub(crate) struct PrioGraphScheduler { @@ -202,13 +201,13 @@ impl PrioGraphScheduler { Ok(TransactionSchedulingInfo { thread_id, transaction, - max_age_slot, + max_age, cost, }) => { saturating_add_assign!(num_scheduled, 1); batches.transactions[thread_id].push(transaction); batches.ids[thread_id].push(id.id); - batches.max_age_slots[thread_id].push(max_age_slot); + batches.max_ages[thread_id].push(max_age); saturating_add_assign!(batches.total_cus[thread_id], cost); // If target batch size is reached, send only this batch. @@ -309,7 +308,7 @@ impl PrioGraphScheduler { batch_id, ids, transactions, - max_age_slots, + max_ages, }, retryable_indexes, }) => { @@ -321,8 +320,8 @@ impl PrioGraphScheduler { // Retryable transactions should be inserted back into the container let mut retryable_iter = retryable_indexes.into_iter().peekable(); - for (index, (id, transaction, max_age_slot)) in - izip!(ids, transactions, max_age_slots).enumerate() + for (index, (id, transaction, max_age)) in + izip!(ids, transactions, max_ages).enumerate() { if let Some(retryable_index) = retryable_iter.peek() { if *retryable_index == index { @@ -330,7 +329,7 @@ impl PrioGraphScheduler { id, SanitizedTransactionTTL { transaction, - max_age_slot, + max_age, }, ); retryable_iter.next(); @@ -392,7 +391,7 @@ impl PrioGraphScheduler { return Ok(0); } - let (ids, transactions, max_age_slots, total_cus) = batches.take_batch(thread_index); + let (ids, transactions, max_ages, total_cus) = batches.take_batch(thread_index); let batch_id = self .in_flight_tracker @@ -403,7 +402,7 @@ impl PrioGraphScheduler { batch_id, ids, transactions, - max_age_slots, + max_ages, }; self.consume_work_senders[thread_index] .send(work) @@ -477,7 +476,7 @@ pub(crate) struct SchedulingSummary { struct Batches { ids: Vec>, transactions: Vec>, - max_age_slots: Vec>, + max_ages: Vec>, total_cus: Vec, } @@ -486,7 +485,7 @@ impl Batches { Self { ids: vec![Vec::with_capacity(TARGET_NUM_TRANSACTIONS_PER_BATCH); num_threads], transactions: vec![Vec::with_capacity(TARGET_NUM_TRANSACTIONS_PER_BATCH); num_threads], - max_age_slots: vec![Vec::with_capacity(TARGET_NUM_TRANSACTIONS_PER_BATCH); num_threads], + max_ages: vec![Vec::with_capacity(TARGET_NUM_TRANSACTIONS_PER_BATCH); num_threads], total_cus: vec![0; num_threads], } } @@ -497,7 +496,7 @@ impl Batches { ) -> ( Vec, Vec, - Vec, + Vec, u64, ) { ( @@ -510,7 +509,7 @@ impl Batches { Vec::with_capacity(TARGET_NUM_TRANSACTIONS_PER_BATCH), ), core::mem::replace( - &mut self.max_age_slots[thread_id], + &mut self.max_ages[thread_id], Vec::with_capacity(TARGET_NUM_TRANSACTIONS_PER_BATCH), ), core::mem::replace(&mut self.total_cus[thread_id], 0), @@ -522,7 +521,7 @@ impl Batches { struct TransactionSchedulingInfo { thread_id: ThreadId, transaction: SanitizedTransaction, - max_age_slot: Slot, + max_age: MaxAge, cost: u64, } @@ -583,7 +582,7 @@ fn try_schedule_transaction( Ok(TransactionSchedulingInfo { thread_id, transaction: sanitized_transaction_ttl.transaction, - max_age_slot: sanitized_transaction_ttl.max_age_slot, + max_age: sanitized_transaction_ttl.max_age, cost, }) } @@ -599,8 +598,8 @@ mod tests { crossbeam_channel::{unbounded, Receiver}, itertools::Itertools, solana_sdk::{ - compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, packet::Packet, - pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction, + clock::Slot, compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, + packet::Packet, pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction, transaction::Transaction, }, std::{borrow::Borrow, sync::Arc}, @@ -686,7 +685,10 @@ mod tests { ); let transaction_ttl = SanitizedTransactionTTL { transaction, - max_age_slot: Slot::MAX, + max_age: MaxAge { + epoch_invalidation_slot: Slot::MAX, + alt_invalidation_slot: Slot::MAX, + }, }; const TEST_TRANSACTION_COST: u64 = 5000; container.insert_new_transaction( diff --git a/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs b/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs index 995b1a5782702b..ddec4ec90711c8 100644 --- a/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs +++ b/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs @@ -19,6 +19,7 @@ use { forwarder::Forwarder, immutable_deserialized_packet::ImmutableDeserializedPacket, packet_deserializer::PacketDeserializer, + scheduler_messages::MaxAge, ForwardOption, LikeClusterInfo, TOTAL_BUFFERED_PACKETS, }, arrayvec::ArrayVec, @@ -30,7 +31,8 @@ use { solana_runtime_transaction::instructions_processor::process_compute_budget_instructions, solana_sdk::{ self, - clock::{FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE}, + address_lookup_table::state::estimate_last_valid_slot, + clock::{Slot, FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE}, fee::FeeBudgetLimits, saturating_add_assign, transaction::SanitizedTransaction, @@ -500,16 +502,25 @@ impl SchedulerController { // Convert to Arcs let packets: Vec<_> = packets.into_iter().map(Arc::new).collect(); // Sanitize packets, generate IDs, and insert into the container. - let bank = self.bank_forks.read().unwrap().working_bank(); - let last_slot_in_epoch = bank.epoch_schedule().get_last_slot_in_epoch(bank.epoch()); - let transaction_account_lock_limit = bank.get_transaction_account_lock_limit(); - let vote_only = bank.vote_only_bank(); + let (root_bank, working_bank) = { + let bank_forks = self.bank_forks.read().unwrap(); + let root_bank = bank_forks.root_bank(); + let working_bank = bank_forks.working_bank(); + (root_bank, working_bank) + }; + let alt_resolved_slot = root_bank.slot(); + let last_slot_in_epoch = working_bank + .epoch_schedule() + .get_last_slot_in_epoch(working_bank.epoch()); + let transaction_account_lock_limit = working_bank.get_transaction_account_lock_limit(); + let vote_only = working_bank.vote_only_bank(); const CHUNK_SIZE: usize = 128; let lock_results: [_; CHUNK_SIZE] = core::array::from_fn(|_| Ok(())); let mut arc_packets = ArrayVec::<_, CHUNK_SIZE>::new(); let mut transactions = ArrayVec::<_, CHUNK_SIZE>::new(); + let mut max_ages = ArrayVec::<_, CHUNK_SIZE>::new(); let mut fee_budget_limits_vec = ArrayVec::<_, CHUNK_SIZE>::new(); let mut error_counts = TransactionErrorMetrics::default(); @@ -521,31 +532,43 @@ impl SchedulerController { packet .build_sanitized_transaction( vote_only, - bank.as_ref(), - bank.get_reserved_account_keys(), + root_bank.as_ref(), + working_bank.get_reserved_account_keys(), ) - .map(|tx| (packet.clone(), tx)) + .map(|(tx, deactivation_slot)| (packet.clone(), tx, deactivation_slot)) }) .inspect(|_| saturating_add_assign!(post_sanitization_count, 1)) - .filter(|(_packet, tx)| { + .filter(|(_packet, tx, _deactivation_slot)| { validate_account_locks( tx.message().account_keys(), transaction_account_lock_limit, ) .is_ok() }) - .filter_map(|(packet, tx)| { + .filter_map(|(packet, tx, deactivation_slot)| { process_compute_budget_instructions(SVMMessage::program_instructions_iter(&tx)) - .map(|compute_budget| (packet, tx, compute_budget.into())) + .map(|compute_budget| { + (packet, tx, deactivation_slot, compute_budget.into()) + }) .ok() }) - .for_each(|(packet, tx, fee_budget_limits)| { + .for_each(|(packet, tx, deactivation_slot, fee_budget_limits)| { arc_packets.push(packet); transactions.push(tx); + max_ages.push(calculate_max_age( + last_slot_in_epoch, + deactivation_slot, + alt_resolved_slot, + )); fee_budget_limits_vec.push(fee_budget_limits); }); - let check_results = bank.check_transactions( + let check_results: Vec< + Result< + solana_svm::account_loader::CheckedTransactionDetails, + solana_sdk::transaction::TransactionError, + >, + > = working_bank.check_transactions( &transactions, &lock_results[..transactions.len()], MAX_PROCESSING_AGE, @@ -556,21 +579,26 @@ impl SchedulerController { let mut post_transaction_check_count: usize = 0; let mut num_dropped_on_capacity: usize = 0; let mut num_buffered: usize = 0; - for (((packet, transaction), fee_budget_limits), _check_result) in arc_packets - .drain(..) - .zip(transactions.drain(..)) - .zip(fee_budget_limits_vec.drain(..)) - .zip(check_results) - .filter(|(_, check_result)| check_result.is_ok()) + for ((((packet, transaction), max_age), fee_budget_limits), _check_result) in + arc_packets + .drain(..) + .zip(transactions.drain(..)) + .zip(max_ages.drain(..)) + .zip(fee_budget_limits_vec.drain(..)) + .zip(check_results) + .filter(|(_, check_result)| check_result.is_ok()) { saturating_add_assign!(post_transaction_check_count, 1); let transaction_id = self.transaction_id_generator.next(); - let (priority, cost) = - Self::calculate_priority_and_cost(&transaction, &fee_budget_limits, &bank); + let (priority, cost) = Self::calculate_priority_and_cost( + &transaction, + &fee_budget_limits, + &working_bank, + ); let transaction_ttl = SanitizedTransactionTTL { transaction, - max_age_slot: last_slot_in_epoch, + max_age, }; if self.container.insert_new_transaction( @@ -655,6 +683,34 @@ impl SchedulerController { } } +/// Given the last slot in the epoch, the minimum deactivation slot, +/// and the current slot, return the `MaxAge` that should be used for +/// the transaction. This is used to determine the maximum slot that a +/// transaction will be considered valid for, without re-resolving addresses +/// or resanitizing. +/// +/// This function considers the deactivation period of Address Table +/// accounts. If the deactivation period runs past the end of the epoch, +/// then the transaction is considered valid until the end of the epoch. +/// Otherwise, the transaction is considered valid until the deactivation +/// period. +/// +/// Since the deactivation period technically uses blocks rather than +/// slots, the value used here is the lower-bound on the deactivation +/// period, i.e. the transaction's address lookups are valid until +/// AT LEAST this slot. +fn calculate_max_age( + last_slot_in_epoch: Slot, + deactivation_slot: Slot, + current_slot: Slot, +) -> MaxAge { + let alt_min_expire_slot = estimate_last_valid_slot(deactivation_slot.min(current_slot)); + MaxAge { + epoch_invalidation_slot: last_slot_in_epoch, + alt_invalidation_slot: alt_min_expire_slot, + } +} + #[cfg(test)] mod tests { use { @@ -827,7 +883,7 @@ mod tests { batch_id: TransactionBatchId::new(0), ids: vec![], transactions: vec![], - max_age_slots: vec![], + max_ages: vec![], }, retryable_indexes: vec![], }) @@ -1158,4 +1214,29 @@ mod tests { .collect_vec(); assert_eq!(message_hashes, vec![&tx1_hash]); } + + #[test] + fn test_calculate_max_age() { + let current_slot = 100; + let last_slot_in_epoch = 1000; + + // ALT deactivation slot is delayed + assert_eq!( + calculate_max_age(last_slot_in_epoch, current_slot - 1, current_slot), + MaxAge { + epoch_invalidation_slot: last_slot_in_epoch, + alt_invalidation_slot: current_slot - 1 + + solana_sdk::slot_hashes::get_entries() as u64, + } + ); + + // no deactivation slot + assert_eq!( + calculate_max_age(last_slot_in_epoch, u64::MAX, current_slot), + MaxAge { + epoch_invalidation_slot: last_slot_in_epoch, + alt_invalidation_slot: current_slot + solana_sdk::slot_hashes::get_entries() as u64, + } + ); + } } diff --git a/core/src/banking_stage/transaction_scheduler/transaction_state.rs b/core/src/banking_stage/transaction_scheduler/transaction_state.rs index 85af8217309e93..efb59be1b8b5b5 100644 --- a/core/src/banking_stage/transaction_scheduler/transaction_state.rs +++ b/core/src/banking_stage/transaction_scheduler/transaction_state.rs @@ -1,13 +1,15 @@ use { - crate::banking_stage::immutable_deserialized_packet::ImmutableDeserializedPacket, - solana_sdk::{clock::Slot, transaction::SanitizedTransaction}, + crate::banking_stage::{ + immutable_deserialized_packet::ImmutableDeserializedPacket, scheduler_messages::MaxAge, + }, + solana_sdk::transaction::SanitizedTransaction, std::sync::Arc, }; /// Simple wrapper type to tie a sanitized transaction to max age slot. pub(crate) struct SanitizedTransactionTTL { pub(crate) transaction: SanitizedTransaction, - pub(crate) max_age_slot: Slot, + pub(crate) max_age: MaxAge, } /// TransactionState is used to track the state of a transaction in the transaction scheduler @@ -207,8 +209,9 @@ mod tests { use { super::*, solana_sdk::{ - compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, packet::Packet, - signature::Keypair, signer::Signer, system_instruction, transaction::Transaction, + clock::Slot, compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message, + packet::Packet, signature::Keypair, signer::Signer, system_instruction, + transaction::Transaction, }, }; @@ -230,7 +233,10 @@ mod tests { ); let transaction_ttl = SanitizedTransactionTTL { transaction: SanitizedTransaction::from_transaction_for_tests(tx), - max_age_slot: Slot::MAX, + max_age: MaxAge { + epoch_invalidation_slot: Slot::MAX, + alt_invalidation_slot: Slot::MAX, + }, }; const TEST_TRANSACTION_COST: u64 = 5000; TransactionState::new( @@ -271,11 +277,11 @@ mod tests { // Manually clone `SanitizedTransactionTTL` let SanitizedTransactionTTL { transaction, - max_age_slot, + max_age, } = transaction_state.transaction_ttl(); let transaction_ttl = SanitizedTransactionTTL { transaction: transaction.clone(), - max_age_slot: *max_age_slot, + max_age: *max_age, }; transaction_state.transition_to_unprocessed(transaction_ttl); // invalid transition } @@ -321,7 +327,13 @@ mod tests { transaction_state, TransactionState::Unprocessed { .. } )); - assert_eq!(transaction_ttl.max_age_slot, Slot::MAX); + assert_eq!( + transaction_ttl.max_age, + MaxAge { + epoch_invalidation_slot: Slot::MAX, + alt_invalidation_slot: Slot::MAX, + } + ); let _ = transaction_state.transition_to_pending(); assert!(matches!( @@ -339,7 +351,13 @@ mod tests { transaction_state, TransactionState::Unprocessed { .. } )); - assert_eq!(transaction_ttl.max_age_slot, Slot::MAX); + assert_eq!( + transaction_ttl.max_age, + MaxAge { + epoch_invalidation_slot: Slot::MAX, + alt_invalidation_slot: Slot::MAX, + } + ); // ensure transaction_ttl is not lost through state transitions let transaction_ttl = transaction_state.transition_to_pending(); @@ -354,6 +372,12 @@ mod tests { transaction_state, TransactionState::Unprocessed { .. } )); - assert_eq!(transaction_ttl.max_age_slot, Slot::MAX); + assert_eq!( + transaction_ttl.max_age, + MaxAge { + epoch_invalidation_slot: Slot::MAX, + alt_invalidation_slot: Slot::MAX, + } + ); } } diff --git a/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs b/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs index ed78b41983fa2a..7d40c66ec1b673 100644 --- a/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs +++ b/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs @@ -153,6 +153,7 @@ impl TransactionStateContainer { mod tests { use { super::*, + crate::banking_stage::scheduler_messages::MaxAge, solana_sdk::{ compute_budget::ComputeBudgetInstruction, hash::Hash, @@ -198,7 +199,10 @@ mod tests { ); let transaction_ttl = SanitizedTransactionTTL { transaction: tx, - max_age_slot: Slot::MAX, + max_age: MaxAge { + epoch_invalidation_slot: Slot::MAX, + alt_invalidation_slot: Slot::MAX, + }, }; const TEST_TRANSACTION_COST: u64 = 5000; (transaction_ttl, packet, priority, TEST_TRANSACTION_COST) diff --git a/core/src/banking_stage/unprocessed_packet_batches.rs b/core/src/banking_stage/unprocessed_packet_batches.rs index f92eeb09c57b54..3c4e0f66664dd2 100644 --- a/core/src/banking_stage/unprocessed_packet_batches.rs +++ b/core/src/banking_stage/unprocessed_packet_batches.rs @@ -307,13 +307,14 @@ mod tests { use { super::*, solana_perf::packet::PacketFlags, + solana_runtime::bank::Bank, solana_sdk::{ compute_budget::ComputeBudgetInstruction, message::Message, reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signer}, system_instruction, system_transaction, - transaction::{SimpleAddressLoader, Transaction}, + transaction::Transaction, }, solana_vote_program::{vote_state::TowerSync, vote_transaction}, }; @@ -475,6 +476,7 @@ mod tests { &keypair, None, ); + let bank = Bank::default_for_tests(); // packets with no votes { @@ -486,7 +488,7 @@ mod tests { let txs = packet_vector.iter().filter_map(|tx| { tx.immutable_section().build_sanitized_transaction( votes_only, - SimpleAddressLoader::Disabled, + &bank, &ReservedAccountKeys::empty_key_set(), ) }); @@ -496,7 +498,7 @@ mod tests { let txs = packet_vector.iter().filter_map(|tx| { tx.immutable_section().build_sanitized_transaction( votes_only, - SimpleAddressLoader::Disabled, + &bank, &ReservedAccountKeys::empty_key_set(), ) }); @@ -515,7 +517,7 @@ mod tests { let txs = packet_vector.iter().filter_map(|tx| { tx.immutable_section().build_sanitized_transaction( votes_only, - SimpleAddressLoader::Disabled, + &bank, &ReservedAccountKeys::empty_key_set(), ) }); @@ -525,7 +527,7 @@ mod tests { let txs = packet_vector.iter().filter_map(|tx| { tx.immutable_section().build_sanitized_transaction( votes_only, - SimpleAddressLoader::Disabled, + &bank, &ReservedAccountKeys::empty_key_set(), ) }); @@ -544,7 +546,7 @@ mod tests { let txs = packet_vector.iter().filter_map(|tx| { tx.immutable_section().build_sanitized_transaction( votes_only, - SimpleAddressLoader::Disabled, + &bank, &ReservedAccountKeys::empty_key_set(), ) }); @@ -554,7 +556,7 @@ mod tests { let txs = packet_vector.iter().filter_map(|tx| { tx.immutable_section().build_sanitized_transaction( votes_only, - SimpleAddressLoader::Disabled, + &bank, &ReservedAccountKeys::empty_key_set(), ) }); diff --git a/core/src/banking_stage/unprocessed_transaction_storage.rs b/core/src/banking_stage/unprocessed_transaction_storage.rs index f612f5eaf08b11..56e814acea9219 100644 --- a/core/src/banking_stage/unprocessed_transaction_storage.rs +++ b/core/src/banking_stage/unprocessed_transaction_storage.rs @@ -154,13 +154,15 @@ fn consume_scan_should_process_packet( return ProcessingDecision::Now; } - // Try to sanitize the packet + // Try to sanitize the packet. Ignore deactivation slot since we are + // immediately attempting to process the transaction. let (maybe_sanitized_transaction, sanitization_time_us) = measure_us!(packet .build_sanitized_transaction( bank.vote_only_bank(), bank, bank.get_reserved_account_keys(), - )); + ) + .map(|(tx, _deactivation_slot)| tx)); payload .slot_metrics_tracker @@ -799,7 +801,7 @@ impl ThreadLocalUnprocessedPackets { bank, bank.get_reserved_account_keys(), ) - .map(|transaction| (transaction, packet_index)) + .map(|(transaction, _deactivation_slot)| (transaction, packet_index)) }) .unzip(); diff --git a/inline-spl/Cargo.toml b/inline-spl/Cargo.toml index 82aa5907ce0aa2..132e10f07ab533 100644 --- a/inline-spl/Cargo.toml +++ b/inline-spl/Cargo.toml @@ -11,7 +11,9 @@ edition = { workspace = true } [dependencies] bytemuck = { workspace = true } -solana-program = { workspace = true, default-features = false } +solana-pubkey = { workspace = true, default-features = false, features = [ + "bytemuck", +] } [lib] crate-type = ["lib"] diff --git a/inline-spl/src/associated_token_account.rs b/inline-spl/src/associated_token_account.rs index 2048c5b743d222..289dc0f8555e47 100644 --- a/inline-spl/src/associated_token_account.rs +++ b/inline-spl/src/associated_token_account.rs @@ -1,6 +1,6 @@ // Partial SPL Associated Token Account declarations inlined to avoid an external dependency on the spl-associated-token-account crate -solana_program::declare_id!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); +solana_pubkey::declare_id!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"); pub mod program_v1_1_0 { - solana_program::declare_id!("NatA1Zyo48dJ7yuwR7cGURwhskKA8ywUyxb9GvG7mTC"); + solana_pubkey::declare_id!("NatA1Zyo48dJ7yuwR7cGURwhskKA8ywUyxb9GvG7mTC"); } diff --git a/inline-spl/src/token.rs b/inline-spl/src/token.rs index 1a495d8ca3a241..af456c3b6242a7 100644 --- a/inline-spl/src/token.rs +++ b/inline-spl/src/token.rs @@ -1,10 +1,10 @@ /// Partial SPL Token declarations inlined to avoid an external dependency on the spl-token crate -use solana_program::pubkey::{Pubkey, PUBKEY_BYTES}; +use solana_pubkey::{Pubkey, PUBKEY_BYTES}; -solana_program::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); +solana_pubkey::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); pub mod program_v3_4_0 { - solana_program::declare_id!("NToK4t5AQzxPNpUA84DkxgfXaVDbDQQjpHKCqsbY46B"); + solana_pubkey::declare_id!("NToK4t5AQzxPNpUA84DkxgfXaVDbDQQjpHKCqsbY46B"); } /* @@ -72,7 +72,7 @@ impl GenericTokenAccount for Account { } pub mod native_mint { - solana_program::declare_id!("So11111111111111111111111111111111111111112"); + solana_pubkey::declare_id!("So11111111111111111111111111111111111111112"); /* Mint { diff --git a/inline-spl/src/token_2022.rs b/inline-spl/src/token_2022.rs index 4b0e0d1b3c05db..fafa2b4cfce68a 100644 --- a/inline-spl/src/token_2022.rs +++ b/inline-spl/src/token_2022.rs @@ -1,7 +1,7 @@ /// Partial SPL Token declarations inlined to avoid an external dependency on the spl-token-2022 crate use crate::token::{self, GenericTokenAccount}; -solana_program::declare_id!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); +solana_pubkey::declare_id!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); // `spl_token_program_2022::extension::AccountType::Account` ordinal value pub const ACCOUNTTYPE_ACCOUNT: u8 = 2; diff --git a/keygen/Cargo.toml b/keygen/Cargo.toml index 4dd74305996883..93c5e4f2e4f064 100644 --- a/keygen/Cargo.toml +++ b/keygen/Cargo.toml @@ -14,6 +14,7 @@ bs58 = { workspace = true } clap = { version = "3.1.5", features = ["cargo"] } dirs-next = { workspace = true } num_cpus = { workspace = true } +serde_json = { workspace = true } solana-clap-v3-utils = { workspace = true } solana-cli-config = { workspace = true } solana-derivation-path = { workspace = true } diff --git a/keygen/src/keygen.rs b/keygen/src/keygen.rs index cbccb33e9a9095..6f0b9ff93adc18 100644 --- a/keygen/src/keygen.rs +++ b/keygen/src/keygen.rs @@ -30,7 +30,7 @@ use { solana_sdk::{ instruction::{AccountMeta, Instruction}, message::Message, - pubkey::{write_pubkey_file, Pubkey}, + pubkey::Pubkey, signature::{ keypair_from_seed, keypair_from_seed_and_derivation_path, write_keypair, write_keypair_file, Keypair, Signer, @@ -424,6 +424,21 @@ fn app<'a>(num_threads: &'a str, crate_version: &'a str) -> Command<'a> { ) } +fn write_pubkey_file(outfile: &str, pubkey: Pubkey) -> Result<(), Box> { + use std::io::Write; + + let printable = format!("{pubkey}"); + let serialized = serde_json::to_string(&printable)?; + + if let Some(outdir) = std::path::Path::new(&outfile).parent() { + std::fs::create_dir_all(outdir)?; + } + let mut f = std::fs::File::create(outfile)?; + f.write_all(&serialized.into_bytes())?; + + Ok(()) +} + fn main() -> Result<(), Box> { let default_num_threads = num_cpus::get().to_string(); let matches = app(&default_num_threads, solana_version::version!()) @@ -768,6 +783,14 @@ mod tests { tempfile::{tempdir, TempDir}, }; + fn read_pubkey_file(infile: &str) -> Result> { + let f = std::fs::File::open(infile)?; + let printable: String = serde_json::from_reader(f)?; + + use std::str::FromStr; + Ok(Pubkey::from_str(&printable)?) + } + fn process_test_command(args: &[&str]) -> Result<(), Box> { let default_num_threads = num_cpus::get().to_string(); let solana_version = solana_version::version!(); @@ -919,7 +942,7 @@ mod tests { ]) .unwrap(); - let result_pubkey = solana_sdk::pubkey::read_pubkey_file(&outfile_path).unwrap(); + let result_pubkey = read_pubkey_file(&outfile_path).unwrap(); assert_eq!(result_pubkey, expected_pubkey); } @@ -938,7 +961,7 @@ mod tests { ]) .unwrap(); - let result_pubkey = solana_sdk::pubkey::read_pubkey_file(&outfile_path).unwrap(); + let result_pubkey = read_pubkey_file(&outfile_path).unwrap(); assert_eq!(result_pubkey, expected_pubkey); } @@ -962,7 +985,7 @@ mod tests { ]) .unwrap(); - let result_pubkey = solana_sdk::pubkey::read_pubkey_file(&outfile_path).unwrap(); + let result_pubkey = read_pubkey_file(&outfile_path).unwrap(); assert_eq!(result_pubkey, expected_pubkey); } @@ -1129,4 +1152,15 @@ mod tests { ]) .unwrap(); } + + #[test] + fn test_read_write_pubkey() -> Result<(), std::boxed::Box> { + let filename = "test_pubkey.json"; + let pubkey = solana_sdk::pubkey::new_rand(); + write_pubkey_file(filename, pubkey)?; + let read = read_pubkey_file(filename)?; + assert_eq!(read, pubkey); + std::fs::remove_file(filename)?; + Ok(()) + } } diff --git a/ledger-tool/src/args.rs b/ledger-tool/src/args.rs index e9149f7b9cab4b..61d3208fe848aa 100644 --- a/ledger-tool/src/args.rs +++ b/ledger-tool/src/args.rs @@ -345,6 +345,8 @@ pub fn get_accounts_db_config( create_ancient_storage, storage_access, scan_filter_for_shrinking, + enable_experimental_accumulator_hash: arg_matches + .is_present("accounts_db_experimental_accumulator_hash"), ..AccountsDbConfig::default() } } diff --git a/log-analyzer/Cargo.toml b/log-analyzer/Cargo.toml index 21df3661ddd0ea..fff8c9c2d3c745 100644 --- a/log-analyzer/Cargo.toml +++ b/log-analyzer/Cargo.toml @@ -13,6 +13,7 @@ edition = { workspace = true } byte-unit = { workspace = true } clap = { version = "3.1.5", features = ["cargo"] } serde = { workspace = true } +serde_derive = { workspace = true } serde_json = { workspace = true } solana-logger = { workspace = true } solana-version = { workspace = true } diff --git a/log-analyzer/src/main.rs b/log-analyzer/src/main.rs index fcedd7c0dc46cf..32ce3fbb5a27fc 100644 --- a/log-analyzer/src/main.rs +++ b/log-analyzer/src/main.rs @@ -4,7 +4,7 @@ extern crate byte_unit; use { byte_unit::Byte, clap::{crate_description, crate_name, Arg, ArgMatches, Command}, - serde::{Deserialize, Serialize}, + serde_derive::{Deserialize, Serialize}, std::{collections::HashMap, fs, ops::Sub, path::PathBuf}, }; diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 2bef9a5f9b5e60..34169e7df006a9 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -5278,7 +5278,11 @@ name = "solana-feature-set" version = "2.1.0" dependencies = [ "lazy_static", - "solana-program", + "solana-clock", + "solana-epoch-schedule", + "solana-hash", + "solana-pubkey", + "solana-sha256-hasher", ] [[package]] @@ -5395,7 +5399,7 @@ name = "solana-inline-spl" version = "2.1.0" dependencies = [ "bytemuck", - "solana-program", + "solana-pubkey", ] [[package]] @@ -5559,6 +5563,10 @@ dependencies = [ "solana-define-syscall", ] +[[package]] +name = "solana-native-token" +version = "2.1.0" + [[package]] name = "solana-net-utils" version = "2.1.0" @@ -5676,6 +5684,7 @@ dependencies = [ "solana-hash", "solana-instruction", "solana-msg", + "solana-native-token", "solana-program-error", "solana-program-memory", "solana-program-option", @@ -5803,6 +5812,7 @@ dependencies = [ "getrandom 0.2.10", "js-sys", "num-traits", + "rand 0.8.5", "serde", "serde_derive", "solana-atomic-u64", @@ -6633,6 +6643,7 @@ dependencies = [ "solana-decode-error", "solana-derivation-path", "solana-feature-set", + "solana-native-token", "solana-program", "solana-program-memory", "solana-pubkey", diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 6770010b5d1b84..0975a6dbccde23 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -1048,7 +1048,7 @@ impl Bank { }; bank.transaction_processor = - TransactionBatchProcessor::new(bank.slot, bank.epoch, HashSet::default()); + TransactionBatchProcessor::new_uninitialized(bank.slot, bank.epoch, HashSet::default()); let accounts_data_size_initial = bank.get_total_accounts_stats().unwrap().data_len as u64; bank.accounts_data_size_initial = accounts_data_size_initial; @@ -1702,7 +1702,7 @@ impl Bank { }; bank.transaction_processor = - TransactionBatchProcessor::new(bank.slot, bank.epoch, HashSet::default()); + TransactionBatchProcessor::new_uninitialized(bank.slot, bank.epoch, HashSet::default()); let thread_pool = ThreadPoolBuilder::new() .thread_name(|i| format!("solBnkNewFlds{i:02}")) diff --git a/runtime/src/bank/address_lookup_table.rs b/runtime/src/bank/address_lookup_table.rs index 4fa4e2bc0f570a..cb195202c9ddac 100644 --- a/runtime/src/bank/address_lookup_table.rs +++ b/runtime/src/bank/address_lookup_table.rs @@ -2,6 +2,7 @@ use { super::Bank, solana_sdk::{ address_lookup_table::error::AddressLookupError, + clock::Slot, message::{ v0::{LoadedAddresses, MessageAddressTableLookup}, AddressLoaderError, @@ -32,22 +33,25 @@ impl AddressLoader for &Bank { .iter() .map(SVMMessageAddressTableLookup::from), ) + .map(|(loaded_addresses, _deactivation_slot)| loaded_addresses) } } impl Bank { - /// Load addresses from an iterator of `SVMMessageAddressTableLookup`. + /// Load addresses from an iterator of `SVMMessageAddressTableLookup`, + /// additionally returning the minimum deactivation slot across all referenced ALTs pub fn load_addresses_from_ref<'a>( &self, address_table_lookups: impl Iterator>, - ) -> Result { + ) -> Result<(LoadedAddresses, Slot), AddressLoaderError> { let slot_hashes = self .transaction_processor .sysvar_cache() .get_slot_hashes() .map_err(|_| AddressLoaderError::SlotHashesSysvarNotFound)?; - address_table_lookups + let mut deactivation_slot = u64::MAX; + let loaded_addresses = address_table_lookups .map(|address_table_lookup| { self.rc .accounts @@ -56,8 +60,14 @@ impl Bank { address_table_lookup, &slot_hashes, ) + .map(|(loaded_addresses, table_deactivation_slot)| { + deactivation_slot = deactivation_slot.min(table_deactivation_slot); + loaded_addresses + }) .map_err(into_address_loader_error) }) - .collect::>() + .collect::>()?; + + Ok((loaded_addresses, deactivation_slot)) } } diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 9a671d5b845f5b..0ac7c22c4fddf8 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -33,6 +33,7 @@ full = [ "libsecp256k1", "sha3", "digest", + "solana-pubkey/rand", ] borsh = ["dep:borsh", "solana-program/borsh", "solana-secp256k1-recover/borsh"] dev-context-only-utils = ["qualifier_attr", "solana-account/dev-context-only-utils"] @@ -95,9 +96,10 @@ solana-frozen-abi = { workspace = true, optional = true, features = [ solana-frozen-abi-macro = { workspace = true, optional = true, features = [ "frozen-abi", ] } +solana-native-token = { workspace = true } solana-program = { workspace = true } solana-program-memory = { workspace = true } -solana-pubkey = { workspace = true } +solana-pubkey = { workspace = true, default-features = false, features = ["std"] } solana-sanitize = { workspace = true } solana-sdk-macro = { workspace = true } solana-secp256k1-recover = { workspace = true } diff --git a/sdk/feature-set/Cargo.toml b/sdk/feature-set/Cargo.toml index d6f2824b08982e..7352ff37a9680f 100644 --- a/sdk/feature-set/Cargo.toml +++ b/sdk/feature-set/Cargo.toml @@ -11,13 +11,17 @@ edition = { workspace = true } [dependencies] lazy_static = { workspace = true } +solana-clock = { workspace = true } +solana-epoch-schedule = { workspace = true } solana-frozen-abi = { workspace = true, optional = true, features = [ "frozen-abi", ] } solana-frozen-abi-macro = { workspace = true, optional = true, features = [ "frozen-abi", ] } -solana-program = { workspace = true } +solana-hash = { workspace = true } +solana-pubkey = { workspace = true } +solana-sha256-hasher = { workspace = true } [features] frozen-abi = [ diff --git a/sdk/feature-set/src/lib.rs b/sdk/feature-set/src/lib.rs index 53137f8bbfbc59..5bb8a5730fd339 100644 --- a/sdk/feature-set/src/lib.rs +++ b/sdk/feature-set/src/lib.rs @@ -12,7 +12,7 @@ //! through these steps, the PR process will facilitate a keypair holder being picked. That //! person will generate the keypair, provide pubkey for PR, and ultimately enable the feature. //! 2. Add a public module for the feature, specifying keypair pubkey as the id with -//! `solana_program::declare_id!()` within the module. +//! `solana_pubkey::declare_id!()` within the module. //! Additionally, add an entry to `FEATURE_NAMES` map. //! 3. Add desired logic to check for and switch on feature availability. //! @@ -21,854 +21,852 @@ use { lazy_static::lazy_static, - solana_program::{ - clock::Slot, - epoch_schedule::EpochSchedule, - hash::{Hash, Hasher}, - pubkey::Pubkey, - stake_history::Epoch, - }, + solana_clock::{Epoch, Slot}, + solana_epoch_schedule::EpochSchedule, + solana_hash::Hash, + solana_pubkey::Pubkey, + solana_sha256_hasher::Hasher, std::collections::{HashMap, HashSet}, }; pub mod deprecate_rewards_sysvar { - solana_program::declare_id!("GaBtBJvmS4Arjj5W1NmFcyvPjsHN38UGYDq2MDwbs9Qu"); + solana_pubkey::declare_id!("GaBtBJvmS4Arjj5W1NmFcyvPjsHN38UGYDq2MDwbs9Qu"); } pub mod pico_inflation { - solana_program::declare_id!("4RWNif6C2WCNiKVW7otP4G7dkmkHGyKQWRpuZ1pxKU5m"); + solana_pubkey::declare_id!("4RWNif6C2WCNiKVW7otP4G7dkmkHGyKQWRpuZ1pxKU5m"); } pub mod full_inflation { pub mod devnet_and_testnet { - solana_program::declare_id!("DT4n6ABDqs6w4bnfwrXT9rsprcPf6cdDga1egctaPkLC"); + solana_pubkey::declare_id!("DT4n6ABDqs6w4bnfwrXT9rsprcPf6cdDga1egctaPkLC"); } pub mod mainnet { pub mod certusone { pub mod vote { - solana_program::declare_id!("BzBBveUDymEYoYzcMWNQCx3cd4jQs7puaVFHLtsbB6fm"); + solana_pubkey::declare_id!("BzBBveUDymEYoYzcMWNQCx3cd4jQs7puaVFHLtsbB6fm"); } pub mod enable { - solana_program::declare_id!("7XRJcS5Ud5vxGB54JbK9N2vBZVwnwdBNeJW1ibRgD9gx"); + solana_pubkey::declare_id!("7XRJcS5Ud5vxGB54JbK9N2vBZVwnwdBNeJW1ibRgD9gx"); } } } } pub mod secp256k1_program_enabled { - solana_program::declare_id!("E3PHP7w8kB7np3CTQ1qQ2tW3KCtjRSXBQgW9vM2mWv2Y"); + solana_pubkey::declare_id!("E3PHP7w8kB7np3CTQ1qQ2tW3KCtjRSXBQgW9vM2mWv2Y"); } pub mod spl_token_v2_multisig_fix { - solana_program::declare_id!("E5JiFDQCwyC6QfT9REFyMpfK2mHcmv1GUDySU1Ue7TYv"); + solana_pubkey::declare_id!("E5JiFDQCwyC6QfT9REFyMpfK2mHcmv1GUDySU1Ue7TYv"); } pub mod no_overflow_rent_distribution { - solana_program::declare_id!("4kpdyrcj5jS47CZb2oJGfVxjYbsMm2Kx97gFyZrxxwXz"); + solana_pubkey::declare_id!("4kpdyrcj5jS47CZb2oJGfVxjYbsMm2Kx97gFyZrxxwXz"); } pub mod filter_stake_delegation_accounts { - solana_program::declare_id!("GE7fRxmW46K6EmCD9AMZSbnaJ2e3LfqCZzdHi9hmYAgi"); + solana_pubkey::declare_id!("GE7fRxmW46K6EmCD9AMZSbnaJ2e3LfqCZzdHi9hmYAgi"); } pub mod require_custodian_for_locked_stake_authorize { - solana_program::declare_id!("D4jsDcXaqdW8tDAWn8H4R25Cdns2YwLneujSL1zvjW6R"); + solana_pubkey::declare_id!("D4jsDcXaqdW8tDAWn8H4R25Cdns2YwLneujSL1zvjW6R"); } pub mod spl_token_v2_self_transfer_fix { - solana_program::declare_id!("BL99GYhdjjcv6ys22C9wPgn2aTVERDbPHHo4NbS3hgp7"); + solana_pubkey::declare_id!("BL99GYhdjjcv6ys22C9wPgn2aTVERDbPHHo4NbS3hgp7"); } pub mod warp_timestamp_again { - solana_program::declare_id!("GvDsGDkH5gyzwpDhxNixx8vtx1kwYHH13RiNAPw27zXb"); + solana_pubkey::declare_id!("GvDsGDkH5gyzwpDhxNixx8vtx1kwYHH13RiNAPw27zXb"); } pub mod check_init_vote_data { - solana_program::declare_id!("3ccR6QpxGYsAbWyfevEtBNGfWV4xBffxRj2tD6A9i39F"); + solana_pubkey::declare_id!("3ccR6QpxGYsAbWyfevEtBNGfWV4xBffxRj2tD6A9i39F"); } pub mod secp256k1_recover_syscall_enabled { - solana_program::declare_id!("6RvdSWHh8oh72Dp7wMTS2DBkf3fRPtChfNrAo3cZZoXJ"); + solana_pubkey::declare_id!("6RvdSWHh8oh72Dp7wMTS2DBkf3fRPtChfNrAo3cZZoXJ"); } pub mod system_transfer_zero_check { - solana_program::declare_id!("BrTR9hzw4WBGFP65AJMbpAo64DcA3U6jdPSga9fMV5cS"); + solana_pubkey::declare_id!("BrTR9hzw4WBGFP65AJMbpAo64DcA3U6jdPSga9fMV5cS"); } pub mod blake3_syscall_enabled { - solana_program::declare_id!("HTW2pSyErTj4BV6KBM9NZ9VBUJVxt7sacNWcf76wtzb3"); + solana_pubkey::declare_id!("HTW2pSyErTj4BV6KBM9NZ9VBUJVxt7sacNWcf76wtzb3"); } pub mod dedupe_config_program_signers { - solana_program::declare_id!("8kEuAshXLsgkUEdcFVLqrjCGGHVWFW99ZZpxvAzzMtBp"); + solana_pubkey::declare_id!("8kEuAshXLsgkUEdcFVLqrjCGGHVWFW99ZZpxvAzzMtBp"); } pub mod verify_tx_signatures_len { - solana_program::declare_id!("EVW9B5xD9FFK7vw1SBARwMA4s5eRo5eKJdKpsBikzKBz"); + solana_pubkey::declare_id!("EVW9B5xD9FFK7vw1SBARwMA4s5eRo5eKJdKpsBikzKBz"); } pub mod vote_stake_checked_instructions { - solana_program::declare_id!("BcWknVcgvonN8sL4HE4XFuEVgfcee5MwxWPAgP6ZV89X"); + solana_pubkey::declare_id!("BcWknVcgvonN8sL4HE4XFuEVgfcee5MwxWPAgP6ZV89X"); } pub mod rent_for_sysvars { - solana_program::declare_id!("BKCPBQQBZqggVnFso5nQ8rQ4RwwogYwjuUt9biBjxwNF"); + solana_pubkey::declare_id!("BKCPBQQBZqggVnFso5nQ8rQ4RwwogYwjuUt9biBjxwNF"); } pub mod libsecp256k1_0_5_upgrade_enabled { - solana_program::declare_id!("DhsYfRjxfnh2g7HKJYSzT79r74Afa1wbHkAgHndrA1oy"); + solana_pubkey::declare_id!("DhsYfRjxfnh2g7HKJYSzT79r74Afa1wbHkAgHndrA1oy"); } pub mod tx_wide_compute_cap { - solana_program::declare_id!("5ekBxc8itEnPv4NzGJtr8BVVQLNMQuLMNQQj7pHoLNZ9"); + solana_pubkey::declare_id!("5ekBxc8itEnPv4NzGJtr8BVVQLNMQuLMNQQj7pHoLNZ9"); } pub mod spl_token_v2_set_authority_fix { - solana_program::declare_id!("FToKNBYyiF4ky9s8WsmLBXHCht17Ek7RXaLZGHzzQhJ1"); + solana_pubkey::declare_id!("FToKNBYyiF4ky9s8WsmLBXHCht17Ek7RXaLZGHzzQhJ1"); } pub mod merge_nonce_error_into_system_error { - solana_program::declare_id!("21AWDosvp3pBamFW91KB35pNoaoZVTM7ess8nr2nt53B"); + solana_pubkey::declare_id!("21AWDosvp3pBamFW91KB35pNoaoZVTM7ess8nr2nt53B"); } pub mod disable_fees_sysvar { - solana_program::declare_id!("JAN1trEUEtZjgXYzNBYHU9DYd7GnThhXfFP7SzPXkPsG"); + solana_pubkey::declare_id!("JAN1trEUEtZjgXYzNBYHU9DYd7GnThhXfFP7SzPXkPsG"); } pub mod stake_merge_with_unmatched_credits_observed { - solana_program::declare_id!("meRgp4ArRPhD3KtCY9c5yAf2med7mBLsjKTPeVUHqBL"); + solana_pubkey::declare_id!("meRgp4ArRPhD3KtCY9c5yAf2med7mBLsjKTPeVUHqBL"); } pub mod zk_token_sdk_enabled { - solana_program::declare_id!("zk1snxsc6Fh3wsGNbbHAJNHiJoYgF29mMnTSusGx5EJ"); + solana_pubkey::declare_id!("zk1snxsc6Fh3wsGNbbHAJNHiJoYgF29mMnTSusGx5EJ"); } pub mod curve25519_syscall_enabled { - solana_program::declare_id!("7rcw5UtqgDTBBv2EcynNfYckgdAaH1MAsCjKgXMkN7Ri"); + solana_pubkey::declare_id!("7rcw5UtqgDTBBv2EcynNfYckgdAaH1MAsCjKgXMkN7Ri"); } pub mod curve25519_restrict_msm_length { - solana_program::declare_id!("eca6zf6JJRjQsYYPkBHF3N32MTzur4n2WL4QiiacPCL"); + solana_pubkey::declare_id!("eca6zf6JJRjQsYYPkBHF3N32MTzur4n2WL4QiiacPCL"); } pub mod versioned_tx_message_enabled { - solana_program::declare_id!("3KZZ6Ks1885aGBQ45fwRcPXVBCtzUvxhUTkwKMR41Tca"); + solana_pubkey::declare_id!("3KZZ6Ks1885aGBQ45fwRcPXVBCtzUvxhUTkwKMR41Tca"); } pub mod libsecp256k1_fail_on_bad_count { - solana_program::declare_id!("8aXvSuopd1PUj7UhehfXJRg6619RHp8ZvwTyyJHdUYsj"); + solana_pubkey::declare_id!("8aXvSuopd1PUj7UhehfXJRg6619RHp8ZvwTyyJHdUYsj"); } pub mod libsecp256k1_fail_on_bad_count2 { - solana_program::declare_id!("54KAoNiUERNoWWUhTWWwXgym94gzoXFVnHyQwPA18V9A"); + solana_pubkey::declare_id!("54KAoNiUERNoWWUhTWWwXgym94gzoXFVnHyQwPA18V9A"); } pub mod instructions_sysvar_owned_by_sysvar { - solana_program::declare_id!("H3kBSaKdeiUsyHmeHqjJYNc27jesXZ6zWj3zWkowQbkV"); + solana_pubkey::declare_id!("H3kBSaKdeiUsyHmeHqjJYNc27jesXZ6zWj3zWkowQbkV"); } pub mod stake_program_advance_activating_credits_observed { - solana_program::declare_id!("SAdVFw3RZvzbo6DvySbSdBnHN4gkzSTH9dSxesyKKPj"); + solana_pubkey::declare_id!("SAdVFw3RZvzbo6DvySbSdBnHN4gkzSTH9dSxesyKKPj"); } pub mod credits_auto_rewind { - solana_program::declare_id!("BUS12ciZ5gCoFafUHWW8qaFMMtwFQGVxjsDheWLdqBE2"); + solana_pubkey::declare_id!("BUS12ciZ5gCoFafUHWW8qaFMMtwFQGVxjsDheWLdqBE2"); } pub mod demote_program_write_locks { - solana_program::declare_id!("3E3jV7v9VcdJL8iYZUMax9DiDno8j7EWUVbhm9RtShj2"); + solana_pubkey::declare_id!("3E3jV7v9VcdJL8iYZUMax9DiDno8j7EWUVbhm9RtShj2"); } pub mod ed25519_program_enabled { - solana_program::declare_id!("6ppMXNYLhVd7GcsZ5uV11wQEW7spppiMVfqQv5SXhDpX"); + solana_pubkey::declare_id!("6ppMXNYLhVd7GcsZ5uV11wQEW7spppiMVfqQv5SXhDpX"); } pub mod return_data_syscall_enabled { - solana_program::declare_id!("DwScAzPUjuv65TMbDnFY7AgwmotzWy3xpEJMXM3hZFaB"); + solana_pubkey::declare_id!("DwScAzPUjuv65TMbDnFY7AgwmotzWy3xpEJMXM3hZFaB"); } pub mod reduce_required_deploy_balance { - solana_program::declare_id!("EBeznQDjcPG8491sFsKZYBi5S5jTVXMpAKNDJMQPS2kq"); + solana_pubkey::declare_id!("EBeznQDjcPG8491sFsKZYBi5S5jTVXMpAKNDJMQPS2kq"); } pub mod sol_log_data_syscall_enabled { - solana_program::declare_id!("6uaHcKPGUy4J7emLBgUTeufhJdiwhngW6a1R9B7c2ob9"); + solana_pubkey::declare_id!("6uaHcKPGUy4J7emLBgUTeufhJdiwhngW6a1R9B7c2ob9"); } pub mod stakes_remove_delegation_if_inactive { - solana_program::declare_id!("HFpdDDNQjvcXnXKec697HDDsyk6tFoWS2o8fkxuhQZpL"); + solana_pubkey::declare_id!("HFpdDDNQjvcXnXKec697HDDsyk6tFoWS2o8fkxuhQZpL"); } pub mod do_support_realloc { - solana_program::declare_id!("75m6ysz33AfLA5DDEzWM1obBrnPQRSsdVQ2nRmc8Vuu1"); + solana_pubkey::declare_id!("75m6ysz33AfLA5DDEzWM1obBrnPQRSsdVQ2nRmc8Vuu1"); } pub mod prevent_calling_precompiles_as_programs { - solana_program::declare_id!("4ApgRX3ud6p7LNMJmsuaAcZY5HWctGPr5obAsjB3A54d"); + solana_pubkey::declare_id!("4ApgRX3ud6p7LNMJmsuaAcZY5HWctGPr5obAsjB3A54d"); } pub mod optimize_epoch_boundary_updates { - solana_program::declare_id!("265hPS8k8xJ37ot82KEgjRunsUp5w4n4Q4VwwiN9i9ps"); + solana_pubkey::declare_id!("265hPS8k8xJ37ot82KEgjRunsUp5w4n4Q4VwwiN9i9ps"); } pub mod remove_native_loader { - solana_program::declare_id!("HTTgmruMYRZEntyL3EdCDdnS6e4D5wRq1FA7kQsb66qq"); + solana_pubkey::declare_id!("HTTgmruMYRZEntyL3EdCDdnS6e4D5wRq1FA7kQsb66qq"); } pub mod send_to_tpu_vote_port { - solana_program::declare_id!("C5fh68nJ7uyKAuYZg2x9sEQ5YrVf3dkW6oojNBSc3Jvo"); + solana_pubkey::declare_id!("C5fh68nJ7uyKAuYZg2x9sEQ5YrVf3dkW6oojNBSc3Jvo"); } pub mod requestable_heap_size { - solana_program::declare_id!("CCu4boMmfLuqcmfTLPHQiUo22ZdUsXjgzPAURYaWt1Bw"); + solana_pubkey::declare_id!("CCu4boMmfLuqcmfTLPHQiUo22ZdUsXjgzPAURYaWt1Bw"); } pub mod disable_fee_calculator { - solana_program::declare_id!("2jXx2yDmGysmBKfKYNgLj2DQyAQv6mMk2BPh4eSbyB4H"); + solana_pubkey::declare_id!("2jXx2yDmGysmBKfKYNgLj2DQyAQv6mMk2BPh4eSbyB4H"); } pub mod add_compute_budget_program { - solana_program::declare_id!("4d5AKtxoh93Dwm1vHXUU3iRATuMndx1c431KgT2td52r"); + solana_pubkey::declare_id!("4d5AKtxoh93Dwm1vHXUU3iRATuMndx1c431KgT2td52r"); } pub mod nonce_must_be_writable { - solana_program::declare_id!("BiCU7M5w8ZCMykVSyhZ7Q3m2SWoR2qrEQ86ERcDX77ME"); + solana_pubkey::declare_id!("BiCU7M5w8ZCMykVSyhZ7Q3m2SWoR2qrEQ86ERcDX77ME"); } pub mod spl_token_v3_3_0_release { - solana_program::declare_id!("Ftok2jhqAqxUWEiCVRrfRs9DPppWP8cgTB7NQNKL88mS"); + solana_pubkey::declare_id!("Ftok2jhqAqxUWEiCVRrfRs9DPppWP8cgTB7NQNKL88mS"); } pub mod leave_nonce_on_success { - solana_program::declare_id!("E8MkiWZNNPGU6n55jkGzyj8ghUmjCHRmDFdYYFYHxWhQ"); + solana_pubkey::declare_id!("E8MkiWZNNPGU6n55jkGzyj8ghUmjCHRmDFdYYFYHxWhQ"); } pub mod reject_empty_instruction_without_program { - solana_program::declare_id!("9kdtFSrXHQg3hKkbXkQ6trJ3Ja1xpJ22CTFSNAciEwmL"); + solana_pubkey::declare_id!("9kdtFSrXHQg3hKkbXkQ6trJ3Ja1xpJ22CTFSNAciEwmL"); } pub mod fixed_memcpy_nonoverlapping_check { - solana_program::declare_id!("36PRUK2Dz6HWYdG9SpjeAsF5F3KxnFCakA2BZMbtMhSb"); + solana_pubkey::declare_id!("36PRUK2Dz6HWYdG9SpjeAsF5F3KxnFCakA2BZMbtMhSb"); } pub mod reject_non_rent_exempt_vote_withdraws { - solana_program::declare_id!("7txXZZD6Um59YoLMF7XUNimbMjsqsWhc7g2EniiTrmp1"); + solana_pubkey::declare_id!("7txXZZD6Um59YoLMF7XUNimbMjsqsWhc7g2EniiTrmp1"); } pub mod evict_invalid_stakes_cache_entries { - solana_program::declare_id!("EMX9Q7TVFAmQ9V1CggAkhMzhXSg8ECp7fHrWQX2G1chf"); + solana_pubkey::declare_id!("EMX9Q7TVFAmQ9V1CggAkhMzhXSg8ECp7fHrWQX2G1chf"); } pub mod allow_votes_to_directly_update_vote_state { - solana_program::declare_id!("Ff8b1fBeB86q8cjq47ZhsQLgv5EkHu3G1C99zjUfAzrq"); + solana_pubkey::declare_id!("Ff8b1fBeB86q8cjq47ZhsQLgv5EkHu3G1C99zjUfAzrq"); } pub mod max_tx_account_locks { - solana_program::declare_id!("CBkDroRDqm8HwHe6ak9cguPjUomrASEkfmxEaZ5CNNxz"); + solana_pubkey::declare_id!("CBkDroRDqm8HwHe6ak9cguPjUomrASEkfmxEaZ5CNNxz"); } pub mod require_rent_exempt_accounts { - solana_program::declare_id!("BkFDxiJQWZXGTZaJQxH7wVEHkAmwCgSEVkrvswFfRJPD"); + solana_pubkey::declare_id!("BkFDxiJQWZXGTZaJQxH7wVEHkAmwCgSEVkrvswFfRJPD"); } pub mod filter_votes_outside_slot_hashes { - solana_program::declare_id!("3gtZPqvPpsbXZVCx6hceMfWxtsmrjMzmg8C7PLKSxS2d"); + solana_pubkey::declare_id!("3gtZPqvPpsbXZVCx6hceMfWxtsmrjMzmg8C7PLKSxS2d"); } pub mod update_syscall_base_costs { - solana_program::declare_id!("2h63t332mGCCsWK2nqqqHhN4U9ayyqhLVFvczznHDoTZ"); + solana_pubkey::declare_id!("2h63t332mGCCsWK2nqqqHhN4U9ayyqhLVFvczznHDoTZ"); } pub mod stake_deactivate_delinquent_instruction { - solana_program::declare_id!("437r62HoAdUb63amq3D7ENnBLDhHT2xY8eFkLJYVKK4x"); + solana_pubkey::declare_id!("437r62HoAdUb63amq3D7ENnBLDhHT2xY8eFkLJYVKK4x"); } pub mod vote_withdraw_authority_may_change_authorized_voter { - solana_program::declare_id!("AVZS3ZsN4gi6Rkx2QUibYuSJG3S6QHib7xCYhG6vGJxU"); + solana_pubkey::declare_id!("AVZS3ZsN4gi6Rkx2QUibYuSJG3S6QHib7xCYhG6vGJxU"); } pub mod spl_associated_token_account_v1_0_4 { - solana_program::declare_id!("FaTa4SpiaSNH44PGC4z8bnGVTkSRYaWvrBs3KTu8XQQq"); + solana_pubkey::declare_id!("FaTa4SpiaSNH44PGC4z8bnGVTkSRYaWvrBs3KTu8XQQq"); } pub mod reject_vote_account_close_unless_zero_credit_epoch { - solana_program::declare_id!("ALBk3EWdeAg2WAGf6GPDUf1nynyNqCdEVmgouG7rpuCj"); + solana_pubkey::declare_id!("ALBk3EWdeAg2WAGf6GPDUf1nynyNqCdEVmgouG7rpuCj"); } pub mod add_get_processed_sibling_instruction_syscall { - solana_program::declare_id!("CFK1hRCNy8JJuAAY8Pb2GjLFNdCThS2qwZNe3izzBMgn"); + solana_pubkey::declare_id!("CFK1hRCNy8JJuAAY8Pb2GjLFNdCThS2qwZNe3izzBMgn"); } pub mod bank_transaction_count_fix { - solana_program::declare_id!("Vo5siZ442SaZBKPXNocthiXysNviW4UYPwRFggmbgAp"); + solana_pubkey::declare_id!("Vo5siZ442SaZBKPXNocthiXysNviW4UYPwRFggmbgAp"); } pub mod disable_bpf_deprecated_load_instructions { - solana_program::declare_id!("3XgNukcZWf9o3HdA3fpJbm94XFc4qpvTXc8h1wxYwiPi"); + solana_pubkey::declare_id!("3XgNukcZWf9o3HdA3fpJbm94XFc4qpvTXc8h1wxYwiPi"); } pub mod disable_bpf_unresolved_symbols_at_runtime { - solana_program::declare_id!("4yuaYAj2jGMGTh1sSmi4G2eFscsDq8qjugJXZoBN6YEa"); + solana_pubkey::declare_id!("4yuaYAj2jGMGTh1sSmi4G2eFscsDq8qjugJXZoBN6YEa"); } pub mod record_instruction_in_transaction_context_push { - solana_program::declare_id!("3aJdcZqxoLpSBxgeYGjPwaYS1zzcByxUDqJkbzWAH1Zb"); + solana_pubkey::declare_id!("3aJdcZqxoLpSBxgeYGjPwaYS1zzcByxUDqJkbzWAH1Zb"); } pub mod syscall_saturated_math { - solana_program::declare_id!("HyrbKftCdJ5CrUfEti6x26Cj7rZLNe32weugk7tLcWb8"); + solana_pubkey::declare_id!("HyrbKftCdJ5CrUfEti6x26Cj7rZLNe32weugk7tLcWb8"); } pub mod check_physical_overlapping { - solana_program::declare_id!("nWBqjr3gpETbiaVj3CBJ3HFC5TMdnJDGt21hnvSTvVZ"); + solana_pubkey::declare_id!("nWBqjr3gpETbiaVj3CBJ3HFC5TMdnJDGt21hnvSTvVZ"); } pub mod limit_secp256k1_recovery_id { - solana_program::declare_id!("7g9EUwj4j7CS21Yx1wvgWLjSZeh5aPq8x9kpoPwXM8n8"); + solana_pubkey::declare_id!("7g9EUwj4j7CS21Yx1wvgWLjSZeh5aPq8x9kpoPwXM8n8"); } pub mod disable_deprecated_loader { - solana_program::declare_id!("GTUMCZ8LTNxVfxdrw7ZsDFTxXb7TutYkzJnFwinpE6dg"); + solana_pubkey::declare_id!("GTUMCZ8LTNxVfxdrw7ZsDFTxXb7TutYkzJnFwinpE6dg"); } pub mod check_slice_translation_size { - solana_program::declare_id!("GmC19j9qLn2RFk5NduX6QXaDhVpGncVVBzyM8e9WMz2F"); + solana_pubkey::declare_id!("GmC19j9qLn2RFk5NduX6QXaDhVpGncVVBzyM8e9WMz2F"); } pub mod stake_split_uses_rent_sysvar { - solana_program::declare_id!("FQnc7U4koHqWgRvFaBJjZnV8VPg6L6wWK33yJeDp4yvV"); + solana_pubkey::declare_id!("FQnc7U4koHqWgRvFaBJjZnV8VPg6L6wWK33yJeDp4yvV"); } pub mod add_get_minimum_delegation_instruction_to_stake_program { - solana_program::declare_id!("St8k9dVXP97xT6faW24YmRSYConLbhsMJA4TJTBLmMT"); + solana_pubkey::declare_id!("St8k9dVXP97xT6faW24YmRSYConLbhsMJA4TJTBLmMT"); } pub mod error_on_syscall_bpf_function_hash_collisions { - solana_program::declare_id!("8199Q2gMD2kwgfopK5qqVWuDbegLgpuFUFHCcUJQDN8b"); + solana_pubkey::declare_id!("8199Q2gMD2kwgfopK5qqVWuDbegLgpuFUFHCcUJQDN8b"); } pub mod reject_callx_r10 { - solana_program::declare_id!("3NKRSwpySNwD3TvP5pHnRmkAQRsdkXWRr1WaQh8p4PWX"); + solana_pubkey::declare_id!("3NKRSwpySNwD3TvP5pHnRmkAQRsdkXWRr1WaQh8p4PWX"); } pub mod drop_redundant_turbine_path { - solana_program::declare_id!("4Di3y24QFLt5QEUPZtbnjyfQKfm6ZMTfa6Dw1psfoMKU"); + solana_pubkey::declare_id!("4Di3y24QFLt5QEUPZtbnjyfQKfm6ZMTfa6Dw1psfoMKU"); } pub mod executables_incur_cpi_data_cost { - solana_program::declare_id!("7GUcYgq4tVtaqNCKT3dho9r4665Qp5TxCZ27Qgjx3829"); + solana_pubkey::declare_id!("7GUcYgq4tVtaqNCKT3dho9r4665Qp5TxCZ27Qgjx3829"); } pub mod fix_recent_blockhashes { - solana_program::declare_id!("6iyggb5MTcsvdcugX7bEKbHV8c6jdLbpHwkncrgLMhfo"); + solana_pubkey::declare_id!("6iyggb5MTcsvdcugX7bEKbHV8c6jdLbpHwkncrgLMhfo"); } pub mod update_rewards_from_cached_accounts { - solana_program::declare_id!("28s7i3htzhahXQKqmS2ExzbEoUypg9krwvtK2M9UWXh9"); + solana_pubkey::declare_id!("28s7i3htzhahXQKqmS2ExzbEoUypg9krwvtK2M9UWXh9"); } pub mod enable_partitioned_epoch_reward { - solana_program::declare_id!("9bn2vTJUsUcnpiZWbu2woSKtTGW3ErZC9ERv88SDqQjK"); + solana_pubkey::declare_id!("9bn2vTJUsUcnpiZWbu2woSKtTGW3ErZC9ERv88SDqQjK"); } pub mod partitioned_epoch_rewards_superfeature { - solana_program::declare_id!("PERzQrt5gBD1XEe2c9XdFWqwgHY3mr7cYWbm5V772V8"); + solana_pubkey::declare_id!("PERzQrt5gBD1XEe2c9XdFWqwgHY3mr7cYWbm5V772V8"); } pub mod spl_token_v3_4_0 { - solana_program::declare_id!("Ftok4njE8b7tDffYkC5bAbCaQv5sL6jispYrprzatUwN"); + solana_pubkey::declare_id!("Ftok4njE8b7tDffYkC5bAbCaQv5sL6jispYrprzatUwN"); } pub mod spl_associated_token_account_v1_1_0 { - solana_program::declare_id!("FaTa17gVKoqbh38HcfiQonPsAaQViyDCCSg71AubYZw8"); + solana_pubkey::declare_id!("FaTa17gVKoqbh38HcfiQonPsAaQViyDCCSg71AubYZw8"); } pub mod default_units_per_instruction { - solana_program::declare_id!("J2QdYx8crLbTVK8nur1jeLsmc3krDbfjoxoea2V1Uy5Q"); + solana_pubkey::declare_id!("J2QdYx8crLbTVK8nur1jeLsmc3krDbfjoxoea2V1Uy5Q"); } pub mod stake_allow_zero_undelegated_amount { - solana_program::declare_id!("sTKz343FM8mqtyGvYWvbLpTThw3ixRM4Xk8QvZ985mw"); + solana_pubkey::declare_id!("sTKz343FM8mqtyGvYWvbLpTThw3ixRM4Xk8QvZ985mw"); } pub mod require_static_program_ids_in_transaction { - solana_program::declare_id!("8FdwgyHFEjhAdjWfV2vfqk7wA1g9X3fQpKH7SBpEv3kC"); + solana_pubkey::declare_id!("8FdwgyHFEjhAdjWfV2vfqk7wA1g9X3fQpKH7SBpEv3kC"); } pub mod stake_raise_minimum_delegation_to_1_sol { // This is a feature-proposal *feature id*. The feature keypair address is `GQXzC7YiSNkje6FFUk6sc2p53XRvKoaZ9VMktYzUMnpL`. - solana_program::declare_id!("9onWzzvCzNC2jfhxxeqRgs5q7nFAAKpCUvkj6T6GJK9i"); + solana_pubkey::declare_id!("9onWzzvCzNC2jfhxxeqRgs5q7nFAAKpCUvkj6T6GJK9i"); } pub mod stake_minimum_delegation_for_rewards { - solana_program::declare_id!("G6ANXD6ptCSyNd9znZm7j4dEczAJCfx7Cy43oBx3rKHJ"); + solana_pubkey::declare_id!("G6ANXD6ptCSyNd9znZm7j4dEczAJCfx7Cy43oBx3rKHJ"); } pub mod add_set_compute_unit_price_ix { - solana_program::declare_id!("98std1NSHqXi9WYvFShfVepRdCoq1qvsp8fsR2XZtG8g"); + solana_pubkey::declare_id!("98std1NSHqXi9WYvFShfVepRdCoq1qvsp8fsR2XZtG8g"); } pub mod disable_deploy_of_alloc_free_syscall { - solana_program::declare_id!("79HWsX9rpnnJBPcdNURVqygpMAfxdrAirzAGAVmf92im"); + solana_pubkey::declare_id!("79HWsX9rpnnJBPcdNURVqygpMAfxdrAirzAGAVmf92im"); } pub mod include_account_index_in_rent_error { - solana_program::declare_id!("2R72wpcQ7qV7aTJWUumdn8u5wmmTyXbK7qzEy7YSAgyY"); + solana_pubkey::declare_id!("2R72wpcQ7qV7aTJWUumdn8u5wmmTyXbK7qzEy7YSAgyY"); } pub mod add_shred_type_to_shred_seed { - solana_program::declare_id!("Ds87KVeqhbv7Jw8W6avsS1mqz3Mw5J3pRTpPoDQ2QdiJ"); + solana_pubkey::declare_id!("Ds87KVeqhbv7Jw8W6avsS1mqz3Mw5J3pRTpPoDQ2QdiJ"); } pub mod warp_timestamp_with_a_vengeance { - solana_program::declare_id!("3BX6SBeEBibHaVQXywdkcgyUk6evfYZkHdztXiDtEpFS"); + solana_pubkey::declare_id!("3BX6SBeEBibHaVQXywdkcgyUk6evfYZkHdztXiDtEpFS"); } pub mod separate_nonce_from_blockhash { - solana_program::declare_id!("Gea3ZkK2N4pHuVZVxWcnAtS6UEDdyumdYt4pFcKjA3ar"); + solana_pubkey::declare_id!("Gea3ZkK2N4pHuVZVxWcnAtS6UEDdyumdYt4pFcKjA3ar"); } pub mod enable_durable_nonce { - solana_program::declare_id!("4EJQtF2pkRyawwcTVfQutzq4Sa5hRhibF6QAK1QXhtEX"); + solana_pubkey::declare_id!("4EJQtF2pkRyawwcTVfQutzq4Sa5hRhibF6QAK1QXhtEX"); } pub mod vote_state_update_credit_per_dequeue { - solana_program::declare_id!("CveezY6FDLVBToHDcvJRmtMouqzsmj4UXYh5ths5G5Uv"); + solana_pubkey::declare_id!("CveezY6FDLVBToHDcvJRmtMouqzsmj4UXYh5ths5G5Uv"); } pub mod quick_bail_on_panic { - solana_program::declare_id!("DpJREPyuMZ5nDfU6H3WTqSqUFSXAfw8u7xqmWtEwJDcP"); + solana_pubkey::declare_id!("DpJREPyuMZ5nDfU6H3WTqSqUFSXAfw8u7xqmWtEwJDcP"); } pub mod nonce_must_be_authorized { - solana_program::declare_id!("HxrEu1gXuH7iD3Puua1ohd5n4iUKJyFNtNxk9DVJkvgr"); + solana_pubkey::declare_id!("HxrEu1gXuH7iD3Puua1ohd5n4iUKJyFNtNxk9DVJkvgr"); } pub mod nonce_must_be_advanceable { - solana_program::declare_id!("3u3Er5Vc2jVcwz4xr2GJeSAXT3fAj6ADHZ4BJMZiScFd"); + solana_pubkey::declare_id!("3u3Er5Vc2jVcwz4xr2GJeSAXT3fAj6ADHZ4BJMZiScFd"); } pub mod vote_authorize_with_seed { - solana_program::declare_id!("6tRxEYKuy2L5nnv5bgn7iT28MxUbYxp5h7F3Ncf1exrT"); + solana_pubkey::declare_id!("6tRxEYKuy2L5nnv5bgn7iT28MxUbYxp5h7F3Ncf1exrT"); } pub mod preserve_rent_epoch_for_rent_exempt_accounts { - solana_program::declare_id!("HH3MUYReL2BvqqA3oEcAa7txju5GY6G4nxJ51zvsEjEZ"); + solana_pubkey::declare_id!("HH3MUYReL2BvqqA3oEcAa7txju5GY6G4nxJ51zvsEjEZ"); } pub mod enable_bpf_loader_extend_program_ix { - solana_program::declare_id!("8Zs9W7D9MpSEtUWSQdGniZk2cNmV22y6FLJwCx53asme"); + solana_pubkey::declare_id!("8Zs9W7D9MpSEtUWSQdGniZk2cNmV22y6FLJwCx53asme"); } pub mod enable_early_verification_of_account_modifications { - solana_program::declare_id!("7Vced912WrRnfjaiKRiNBcbuFw7RrnLv3E3z95Y4GTNc"); + solana_pubkey::declare_id!("7Vced912WrRnfjaiKRiNBcbuFw7RrnLv3E3z95Y4GTNc"); } pub mod skip_rent_rewrites { - solana_program::declare_id!("CGB2jM8pwZkeeiXQ66kBMyBR6Np61mggL7XUsmLjVcrw"); + solana_pubkey::declare_id!("CGB2jM8pwZkeeiXQ66kBMyBR6Np61mggL7XUsmLjVcrw"); } pub mod prevent_crediting_accounts_that_end_rent_paying { - solana_program::declare_id!("812kqX67odAp5NFwM8D2N24cku7WTm9CHUTFUXaDkWPn"); + solana_pubkey::declare_id!("812kqX67odAp5NFwM8D2N24cku7WTm9CHUTFUXaDkWPn"); } pub mod cap_bpf_program_instruction_accounts { - solana_program::declare_id!("9k5ijzTbYPtjzu8wj2ErH9v45xecHzQ1x4PMYMMxFgdM"); + solana_pubkey::declare_id!("9k5ijzTbYPtjzu8wj2ErH9v45xecHzQ1x4PMYMMxFgdM"); } pub mod loosen_cpi_size_restriction { - solana_program::declare_id!("GDH5TVdbTPUpRnXaRyQqiKUa7uZAbZ28Q2N9bhbKoMLm"); + solana_pubkey::declare_id!("GDH5TVdbTPUpRnXaRyQqiKUa7uZAbZ28Q2N9bhbKoMLm"); } pub mod use_default_units_in_fee_calculation { - solana_program::declare_id!("8sKQrMQoUHtQSUP83SPG4ta2JDjSAiWs7t5aJ9uEd6To"); + solana_pubkey::declare_id!("8sKQrMQoUHtQSUP83SPG4ta2JDjSAiWs7t5aJ9uEd6To"); } pub mod compact_vote_state_updates { - solana_program::declare_id!("86HpNqzutEZwLcPxS6EHDcMNYWk6ikhteg9un7Y2PBKE"); + solana_pubkey::declare_id!("86HpNqzutEZwLcPxS6EHDcMNYWk6ikhteg9un7Y2PBKE"); } pub mod incremental_snapshot_only_incremental_hash_calculation { - solana_program::declare_id!("25vqsfjk7Nv1prsQJmA4Xu1bN61s8LXCBGUPp8Rfy1UF"); + solana_pubkey::declare_id!("25vqsfjk7Nv1prsQJmA4Xu1bN61s8LXCBGUPp8Rfy1UF"); } pub mod disable_cpi_setting_executable_and_rent_epoch { - solana_program::declare_id!("B9cdB55u4jQsDNsdTK525yE9dmSc5Ga7YBaBrDFvEhM9"); + solana_pubkey::declare_id!("B9cdB55u4jQsDNsdTK525yE9dmSc5Ga7YBaBrDFvEhM9"); } pub mod on_load_preserve_rent_epoch_for_rent_exempt_accounts { - solana_program::declare_id!("CpkdQmspsaZZ8FVAouQTtTWZkc8eeQ7V3uj7dWz543rZ"); + solana_pubkey::declare_id!("CpkdQmspsaZZ8FVAouQTtTWZkc8eeQ7V3uj7dWz543rZ"); } pub mod account_hash_ignore_slot { - solana_program::declare_id!("SVn36yVApPLYsa8koK3qUcy14zXDnqkNYWyUh1f4oK1"); + solana_pubkey::declare_id!("SVn36yVApPLYsa8koK3qUcy14zXDnqkNYWyUh1f4oK1"); } pub mod set_exempt_rent_epoch_max { - solana_program::declare_id!("5wAGiy15X1Jb2hkHnPDCM8oB9V42VNA9ftNVFK84dEgv"); + solana_pubkey::declare_id!("5wAGiy15X1Jb2hkHnPDCM8oB9V42VNA9ftNVFK84dEgv"); } pub mod relax_authority_signer_check_for_lookup_table_creation { - solana_program::declare_id!("FKAcEvNgSY79RpqsPNUV5gDyumopH4cEHqUxyfm8b8Ap"); + solana_pubkey::declare_id!("FKAcEvNgSY79RpqsPNUV5gDyumopH4cEHqUxyfm8b8Ap"); } pub mod stop_sibling_instruction_search_at_parent { - solana_program::declare_id!("EYVpEP7uzH1CoXzbD6PubGhYmnxRXPeq3PPsm1ba3gpo"); + solana_pubkey::declare_id!("EYVpEP7uzH1CoXzbD6PubGhYmnxRXPeq3PPsm1ba3gpo"); } pub mod vote_state_update_root_fix { - solana_program::declare_id!("G74BkWBzmsByZ1kxHy44H3wjwp5hp7JbrGRuDpco22tY"); + solana_pubkey::declare_id!("G74BkWBzmsByZ1kxHy44H3wjwp5hp7JbrGRuDpco22tY"); } pub mod cap_accounts_data_allocations_per_transaction { - solana_program::declare_id!("9gxu85LYRAcZL38We8MYJ4A9AwgBBPtVBAqebMcT1241"); + solana_pubkey::declare_id!("9gxu85LYRAcZL38We8MYJ4A9AwgBBPtVBAqebMcT1241"); } pub mod epoch_accounts_hash { - solana_program::declare_id!("5GpmAKxaGsWWbPp4bNXFLJxZVvG92ctxf7jQnzTQjF3n"); + solana_pubkey::declare_id!("5GpmAKxaGsWWbPp4bNXFLJxZVvG92ctxf7jQnzTQjF3n"); } pub mod remove_deprecated_request_unit_ix { - solana_program::declare_id!("EfhYd3SafzGT472tYQDUc4dPd2xdEfKs5fwkowUgVt4W"); + solana_pubkey::declare_id!("EfhYd3SafzGT472tYQDUc4dPd2xdEfKs5fwkowUgVt4W"); } pub mod disable_rehash_for_rent_epoch { - solana_program::declare_id!("DTVTkmw3JSofd8CJVJte8PXEbxNQ2yZijvVr3pe2APPj"); + solana_pubkey::declare_id!("DTVTkmw3JSofd8CJVJte8PXEbxNQ2yZijvVr3pe2APPj"); } pub mod increase_tx_account_lock_limit { - solana_program::declare_id!("9LZdXeKGeBV6hRLdxS1rHbHoEUsKqesCC2ZAPTPKJAbK"); + solana_pubkey::declare_id!("9LZdXeKGeBV6hRLdxS1rHbHoEUsKqesCC2ZAPTPKJAbK"); } pub mod limit_max_instruction_trace_length { - solana_program::declare_id!("GQALDaC48fEhZGWRj9iL5Q889emJKcj3aCvHF7VCbbF4"); + solana_pubkey::declare_id!("GQALDaC48fEhZGWRj9iL5Q889emJKcj3aCvHF7VCbbF4"); } pub mod check_syscall_outputs_do_not_overlap { - solana_program::declare_id!("3uRVPBpyEJRo1emLCrq38eLRFGcu6uKSpUXqGvU8T7SZ"); + solana_pubkey::declare_id!("3uRVPBpyEJRo1emLCrq38eLRFGcu6uKSpUXqGvU8T7SZ"); } pub mod enable_bpf_loader_set_authority_checked_ix { - solana_program::declare_id!("5x3825XS7M2A3Ekbn5VGGkvFoAg5qrRWkTrY4bARP1GL"); + solana_pubkey::declare_id!("5x3825XS7M2A3Ekbn5VGGkvFoAg5qrRWkTrY4bARP1GL"); } pub mod enable_alt_bn128_syscall { - solana_program::declare_id!("A16q37opZdQMCbe5qJ6xpBB9usykfv8jZaMkxvZQi4GJ"); + solana_pubkey::declare_id!("A16q37opZdQMCbe5qJ6xpBB9usykfv8jZaMkxvZQi4GJ"); } pub mod simplify_alt_bn128_syscall_error_codes { - solana_program::declare_id!("JDn5q3GBeqzvUa7z67BbmVHVdE3EbUAjvFep3weR3jxX"); + solana_pubkey::declare_id!("JDn5q3GBeqzvUa7z67BbmVHVdE3EbUAjvFep3weR3jxX"); } pub mod enable_alt_bn128_compression_syscall { - solana_program::declare_id!("EJJewYSddEEtSZHiqugnvhQHiWyZKjkFDQASd7oKSagn"); + solana_pubkey::declare_id!("EJJewYSddEEtSZHiqugnvhQHiWyZKjkFDQASd7oKSagn"); } pub mod enable_program_redeployment_cooldown { - solana_program::declare_id!("J4HFT8usBxpcF63y46t1upYobJgChmKyZPm5uTBRg25Z"); + solana_pubkey::declare_id!("J4HFT8usBxpcF63y46t1upYobJgChmKyZPm5uTBRg25Z"); } pub mod commission_updates_only_allowed_in_first_half_of_epoch { - solana_program::declare_id!("noRuG2kzACwgaY7TVmLRnUNPLKNVQE1fb7X55YWBehp"); + solana_pubkey::declare_id!("noRuG2kzACwgaY7TVmLRnUNPLKNVQE1fb7X55YWBehp"); } pub mod enable_turbine_fanout_experiments { - solana_program::declare_id!("D31EFnLgdiysi84Woo3of4JMu7VmasUS3Z7j9HYXCeLY"); + solana_pubkey::declare_id!("D31EFnLgdiysi84Woo3of4JMu7VmasUS3Z7j9HYXCeLY"); } pub mod disable_turbine_fanout_experiments { - solana_program::declare_id!("Gz1aLrbeQ4Q6PTSafCZcGWZXz91yVRi7ASFzFEr1U4sa"); + solana_pubkey::declare_id!("Gz1aLrbeQ4Q6PTSafCZcGWZXz91yVRi7ASFzFEr1U4sa"); } pub mod move_serialized_len_ptr_in_cpi { - solana_program::declare_id!("74CoWuBmt3rUVUrCb2JiSTvh6nXyBWUsK4SaMj3CtE3T"); + solana_pubkey::declare_id!("74CoWuBmt3rUVUrCb2JiSTvh6nXyBWUsK4SaMj3CtE3T"); } pub mod update_hashes_per_tick { - solana_program::declare_id!("3uFHb9oKdGfgZGJK9EHaAXN4USvnQtAFC13Fh5gGFS5B"); + solana_pubkey::declare_id!("3uFHb9oKdGfgZGJK9EHaAXN4USvnQtAFC13Fh5gGFS5B"); } pub mod enable_big_mod_exp_syscall { - solana_program::declare_id!("EBq48m8irRKuE7ZnMTLvLg2UuGSqhe8s8oMqnmja1fJw"); + solana_pubkey::declare_id!("EBq48m8irRKuE7ZnMTLvLg2UuGSqhe8s8oMqnmja1fJw"); } pub mod disable_builtin_loader_ownership_chains { - solana_program::declare_id!("4UDcAfQ6EcA6bdcadkeHpkarkhZGJ7Bpq7wTAiRMjkoi"); + solana_pubkey::declare_id!("4UDcAfQ6EcA6bdcadkeHpkarkhZGJ7Bpq7wTAiRMjkoi"); } pub mod cap_transaction_accounts_data_size { - solana_program::declare_id!("DdLwVYuvDz26JohmgSbA7mjpJFgX5zP2dkp8qsF2C33V"); + solana_pubkey::declare_id!("DdLwVYuvDz26JohmgSbA7mjpJFgX5zP2dkp8qsF2C33V"); } pub mod remove_congestion_multiplier_from_fee_calculation { - solana_program::declare_id!("A8xyMHZovGXFkorFqEmVH2PKGLiBip5JD7jt4zsUWo4H"); + solana_pubkey::declare_id!("A8xyMHZovGXFkorFqEmVH2PKGLiBip5JD7jt4zsUWo4H"); } pub mod enable_request_heap_frame_ix { - solana_program::declare_id!("Hr1nUA9b7NJ6eChS26o7Vi8gYYDDwWD3YeBfzJkTbU86"); + solana_pubkey::declare_id!("Hr1nUA9b7NJ6eChS26o7Vi8gYYDDwWD3YeBfzJkTbU86"); } pub mod prevent_rent_paying_rent_recipients { - solana_program::declare_id!("Fab5oP3DmsLYCiQZXdjyqT3ukFFPrsmqhXU4WU1AWVVF"); + solana_pubkey::declare_id!("Fab5oP3DmsLYCiQZXdjyqT3ukFFPrsmqhXU4WU1AWVVF"); } pub mod delay_visibility_of_program_deployment { - solana_program::declare_id!("GmuBvtFb2aHfSfMXpuFeWZGHyDeCLPS79s48fmCWCfM5"); + solana_pubkey::declare_id!("GmuBvtFb2aHfSfMXpuFeWZGHyDeCLPS79s48fmCWCfM5"); } pub mod apply_cost_tracker_during_replay { - solana_program::declare_id!("2ry7ygxiYURULZCrypHhveanvP5tzZ4toRwVp89oCNSj"); + solana_pubkey::declare_id!("2ry7ygxiYURULZCrypHhveanvP5tzZ4toRwVp89oCNSj"); } pub mod bpf_account_data_direct_mapping { - solana_program::declare_id!("EenyoWx9UMXYKpR8mW5Jmfmy2fRjzUtM7NduYMY8bx33"); + solana_pubkey::declare_id!("EenyoWx9UMXYKpR8mW5Jmfmy2fRjzUtM7NduYMY8bx33"); } pub mod add_set_tx_loaded_accounts_data_size_instruction { - solana_program::declare_id!("G6vbf1UBok8MWb8m25ex86aoQHeKTzDKzuZADHkShqm6"); + solana_pubkey::declare_id!("G6vbf1UBok8MWb8m25ex86aoQHeKTzDKzuZADHkShqm6"); } pub mod switch_to_new_elf_parser { - solana_program::declare_id!("Cdkc8PPTeTNUPoZEfCY5AyetUrEdkZtNPMgz58nqyaHD"); + solana_pubkey::declare_id!("Cdkc8PPTeTNUPoZEfCY5AyetUrEdkZtNPMgz58nqyaHD"); } pub mod round_up_heap_size { - solana_program::declare_id!("CE2et8pqgyQMP2mQRg3CgvX8nJBKUArMu3wfiQiQKY1y"); + solana_pubkey::declare_id!("CE2et8pqgyQMP2mQRg3CgvX8nJBKUArMu3wfiQiQKY1y"); } pub mod remove_bpf_loader_incorrect_program_id { - solana_program::declare_id!("2HmTkCj9tXuPE4ueHzdD7jPeMf9JGCoZh5AsyoATiWEe"); + solana_pubkey::declare_id!("2HmTkCj9tXuPE4ueHzdD7jPeMf9JGCoZh5AsyoATiWEe"); } pub mod include_loaded_accounts_data_size_in_fee_calculation { - solana_program::declare_id!("EaQpmC6GtRssaZ3PCUM5YksGqUdMLeZ46BQXYtHYakDS"); + solana_pubkey::declare_id!("EaQpmC6GtRssaZ3PCUM5YksGqUdMLeZ46BQXYtHYakDS"); } pub mod native_programs_consume_cu { - solana_program::declare_id!("8pgXCMNXC8qyEFypuwpXyRxLXZdpM4Qo72gJ6k87A6wL"); + solana_pubkey::declare_id!("8pgXCMNXC8qyEFypuwpXyRxLXZdpM4Qo72gJ6k87A6wL"); } pub mod simplify_writable_program_account_check { - solana_program::declare_id!("5ZCcFAzJ1zsFKe1KSZa9K92jhx7gkcKj97ci2DBo1vwj"); + solana_pubkey::declare_id!("5ZCcFAzJ1zsFKe1KSZa9K92jhx7gkcKj97ci2DBo1vwj"); } pub mod stop_truncating_strings_in_syscalls { - solana_program::declare_id!("16FMCmgLzCNNz6eTwGanbyN2ZxvTBSLuQ6DZhgeMshg"); + solana_pubkey::declare_id!("16FMCmgLzCNNz6eTwGanbyN2ZxvTBSLuQ6DZhgeMshg"); } pub mod clean_up_delegation_errors { - solana_program::declare_id!("Bj2jmUsM2iRhfdLLDSTkhM5UQRQvQHm57HSmPibPtEyu"); + solana_pubkey::declare_id!("Bj2jmUsM2iRhfdLLDSTkhM5UQRQvQHm57HSmPibPtEyu"); } pub mod vote_state_add_vote_latency { - solana_program::declare_id!("7axKe5BTYBDD87ftzWbk5DfzWMGyRvqmWTduuo22Yaqy"); + solana_pubkey::declare_id!("7axKe5BTYBDD87ftzWbk5DfzWMGyRvqmWTduuo22Yaqy"); } pub mod checked_arithmetic_in_fee_validation { - solana_program::declare_id!("5Pecy6ie6XGm22pc9d4P9W5c31BugcFBuy6hsP2zkETv"); + solana_pubkey::declare_id!("5Pecy6ie6XGm22pc9d4P9W5c31BugcFBuy6hsP2zkETv"); } pub mod last_restart_slot_sysvar { - solana_program::declare_id!("HooKD5NC9QNxk25QuzCssB8ecrEzGt6eXEPBUxWp1LaR"); + solana_pubkey::declare_id!("HooKD5NC9QNxk25QuzCssB8ecrEzGt6eXEPBUxWp1LaR"); } pub mod reduce_stake_warmup_cooldown { - solana_program::declare_id!("GwtDQBghCTBgmX2cpEGNPxTEBUTQRaDMGTr5qychdGMj"); + solana_pubkey::declare_id!("GwtDQBghCTBgmX2cpEGNPxTEBUTQRaDMGTr5qychdGMj"); } mod revise_turbine_epoch_stakes { - solana_program::declare_id!("BTWmtJC8U5ZLMbBUUA1k6As62sYjPEjAiNAT55xYGdJU"); + solana_pubkey::declare_id!("BTWmtJC8U5ZLMbBUUA1k6As62sYjPEjAiNAT55xYGdJU"); } pub mod enable_poseidon_syscall { - solana_program::declare_id!("FL9RsQA6TVUoh5xJQ9d936RHSebA1NLQqe3Zv9sXZRpr"); + solana_pubkey::declare_id!("FL9RsQA6TVUoh5xJQ9d936RHSebA1NLQqe3Zv9sXZRpr"); } pub mod timely_vote_credits { - solana_program::declare_id!("tvcF6b1TRz353zKuhBjinZkKzjmihXmBAHJdjNYw1sQ"); + solana_pubkey::declare_id!("tvcF6b1TRz353zKuhBjinZkKzjmihXmBAHJdjNYw1sQ"); } pub mod remaining_compute_units_syscall_enabled { - solana_program::declare_id!("5TuppMutoyzhUSfuYdhgzD47F92GL1g89KpCZQKqedxP"); + solana_pubkey::declare_id!("5TuppMutoyzhUSfuYdhgzD47F92GL1g89KpCZQKqedxP"); } pub mod enable_program_runtime_v2_and_loader_v4 { - solana_program::declare_id!("8oBxsYqnCvUTGzgEpxPcnVf7MLbWWPYddE33PftFeBBd"); + solana_pubkey::declare_id!("8oBxsYqnCvUTGzgEpxPcnVf7MLbWWPYddE33PftFeBBd"); } pub mod require_rent_exempt_split_destination { - solana_program::declare_id!("D2aip4BBr8NPWtU9vLrwrBvbuaQ8w1zV38zFLxx4pfBV"); + solana_pubkey::declare_id!("D2aip4BBr8NPWtU9vLrwrBvbuaQ8w1zV38zFLxx4pfBV"); } pub mod better_error_codes_for_tx_lamport_check { - solana_program::declare_id!("Ffswd3egL3tccB6Rv3XY6oqfdzn913vUcjCSnpvCKpfx"); + solana_pubkey::declare_id!("Ffswd3egL3tccB6Rv3XY6oqfdzn913vUcjCSnpvCKpfx"); } pub mod update_hashes_per_tick2 { - solana_program::declare_id!("EWme9uFqfy1ikK1jhJs8fM5hxWnK336QJpbscNtizkTU"); + solana_pubkey::declare_id!("EWme9uFqfy1ikK1jhJs8fM5hxWnK336QJpbscNtizkTU"); } pub mod update_hashes_per_tick3 { - solana_program::declare_id!("8C8MCtsab5SsfammbzvYz65HHauuUYdbY2DZ4sznH6h5"); + solana_pubkey::declare_id!("8C8MCtsab5SsfammbzvYz65HHauuUYdbY2DZ4sznH6h5"); } pub mod update_hashes_per_tick4 { - solana_program::declare_id!("8We4E7DPwF2WfAN8tRTtWQNhi98B99Qpuj7JoZ3Aikgg"); + solana_pubkey::declare_id!("8We4E7DPwF2WfAN8tRTtWQNhi98B99Qpuj7JoZ3Aikgg"); } pub mod update_hashes_per_tick5 { - solana_program::declare_id!("BsKLKAn1WM4HVhPRDsjosmqSg2J8Tq5xP2s2daDS6Ni4"); + solana_pubkey::declare_id!("BsKLKAn1WM4HVhPRDsjosmqSg2J8Tq5xP2s2daDS6Ni4"); } pub mod update_hashes_per_tick6 { - solana_program::declare_id!("FKu1qYwLQSiehz644H6Si65U5ZQ2cp9GxsyFUfYcuADv"); + solana_pubkey::declare_id!("FKu1qYwLQSiehz644H6Si65U5ZQ2cp9GxsyFUfYcuADv"); } pub mod validate_fee_collector_account { - solana_program::declare_id!("prpFrMtgNmzaNzkPJg9o753fVvbHKqNrNTm76foJ2wm"); + solana_pubkey::declare_id!("prpFrMtgNmzaNzkPJg9o753fVvbHKqNrNTm76foJ2wm"); } pub mod disable_rent_fees_collection { - solana_program::declare_id!("CJzY83ggJHqPGDq8VisV3U91jDJLuEaALZooBrXtnnLU"); + solana_pubkey::declare_id!("CJzY83ggJHqPGDq8VisV3U91jDJLuEaALZooBrXtnnLU"); } pub mod enable_zk_transfer_with_fee { - solana_program::declare_id!("zkNLP7EQALfC1TYeB3biDU7akDckj8iPkvh9y2Mt2K3"); + solana_pubkey::declare_id!("zkNLP7EQALfC1TYeB3biDU7akDckj8iPkvh9y2Mt2K3"); } pub mod drop_legacy_shreds { - solana_program::declare_id!("GV49KKQdBNaiv2pgqhS2Dy3GWYJGXMTVYbYkdk91orRy"); + solana_pubkey::declare_id!("GV49KKQdBNaiv2pgqhS2Dy3GWYJGXMTVYbYkdk91orRy"); } pub mod allow_commission_decrease_at_any_time { - solana_program::declare_id!("decoMktMcnmiq6t3u7g5BfgcQu91nKZr6RvMYf9z1Jb"); + solana_pubkey::declare_id!("decoMktMcnmiq6t3u7g5BfgcQu91nKZr6RvMYf9z1Jb"); } pub mod add_new_reserved_account_keys { - solana_program::declare_id!("8U4skmMVnF6k2kMvrWbQuRUT3qQSiTYpSjqmhmgfthZu"); + solana_pubkey::declare_id!("8U4skmMVnF6k2kMvrWbQuRUT3qQSiTYpSjqmhmgfthZu"); } pub mod consume_blockstore_duplicate_proofs { - solana_program::declare_id!("6YsBCejwK96GZCkJ6mkZ4b68oP63z2PLoQmWjC7ggTqZ"); + solana_pubkey::declare_id!("6YsBCejwK96GZCkJ6mkZ4b68oP63z2PLoQmWjC7ggTqZ"); } pub mod index_erasure_conflict_duplicate_proofs { - solana_program::declare_id!("dupPajaLy2SSn8ko42aZz4mHANDNrLe8Nw8VQgFecLa"); + solana_pubkey::declare_id!("dupPajaLy2SSn8ko42aZz4mHANDNrLe8Nw8VQgFecLa"); } pub mod merkle_conflict_duplicate_proofs { - solana_program::declare_id!("mrkPjRg79B2oK2ZLgd7S3AfEJaX9B6gAF3H9aEykRUS"); + solana_pubkey::declare_id!("mrkPjRg79B2oK2ZLgd7S3AfEJaX9B6gAF3H9aEykRUS"); } pub mod disable_bpf_loader_instructions { - solana_program::declare_id!("7WeS1vfPRgeeoXArLh7879YcB9mgE9ktjPDtajXeWfXn"); + solana_pubkey::declare_id!("7WeS1vfPRgeeoXArLh7879YcB9mgE9ktjPDtajXeWfXn"); } pub mod enable_zk_proof_from_account { - solana_program::declare_id!("zkiTNuzBKxrCLMKehzuQeKZyLtX2yvFcEKMML8nExU8"); + solana_pubkey::declare_id!("zkiTNuzBKxrCLMKehzuQeKZyLtX2yvFcEKMML8nExU8"); } pub mod cost_model_requested_write_lock_cost { - solana_program::declare_id!("wLckV1a64ngtcKPRGU4S4grVTestXjmNjxBjaKZrAcn"); + solana_pubkey::declare_id!("wLckV1a64ngtcKPRGU4S4grVTestXjmNjxBjaKZrAcn"); } pub mod enable_gossip_duplicate_proof_ingestion { - solana_program::declare_id!("FNKCMBzYUdjhHyPdsKG2LSmdzH8TCHXn3ytj8RNBS4nG"); + solana_pubkey::declare_id!("FNKCMBzYUdjhHyPdsKG2LSmdzH8TCHXn3ytj8RNBS4nG"); } pub mod chained_merkle_conflict_duplicate_proofs { - solana_program::declare_id!("chaie9S2zVfuxJKNRGkyTDokLwWxx6kD2ZLsqQHaDD8"); + solana_pubkey::declare_id!("chaie9S2zVfuxJKNRGkyTDokLwWxx6kD2ZLsqQHaDD8"); } pub mod enable_chained_merkle_shreds { - solana_program::declare_id!("7uZBkJXJ1HkuP6R3MJfZs7mLwymBcDbKdqbF51ZWLier"); + solana_pubkey::declare_id!("7uZBkJXJ1HkuP6R3MJfZs7mLwymBcDbKdqbF51ZWLier"); } pub mod remove_rounding_in_fee_calculation { - solana_program::declare_id!("BtVN7YjDzNE6Dk7kTT7YTDgMNUZTNgiSJgsdzAeTg2jF"); + solana_pubkey::declare_id!("BtVN7YjDzNE6Dk7kTT7YTDgMNUZTNgiSJgsdzAeTg2jF"); } pub mod enable_tower_sync_ix { - solana_program::declare_id!("tSynMCspg4xFiCj1v3TDb4c7crMR5tSBhLz4sF7rrNA"); + solana_pubkey::declare_id!("tSynMCspg4xFiCj1v3TDb4c7crMR5tSBhLz4sF7rrNA"); } pub mod deprecate_unused_legacy_vote_plumbing { - solana_program::declare_id!("6Uf8S75PVh91MYgPQSHnjRAPQq6an5BDv9vomrCwDqLe"); + solana_pubkey::declare_id!("6Uf8S75PVh91MYgPQSHnjRAPQq6an5BDv9vomrCwDqLe"); } pub mod reward_full_priority_fee { - solana_program::declare_id!("3opE3EzAKnUftUDURkzMgwpNgimBAypW1mNDYH4x4Zg7"); + solana_pubkey::declare_id!("3opE3EzAKnUftUDURkzMgwpNgimBAypW1mNDYH4x4Zg7"); } pub mod get_sysvar_syscall_enabled { - solana_program::declare_id!("CLCoTADvV64PSrnR6QXty6Fwrt9Xc6EdxSJE4wLRePjq"); + solana_pubkey::declare_id!("CLCoTADvV64PSrnR6QXty6Fwrt9Xc6EdxSJE4wLRePjq"); } pub mod abort_on_invalid_curve { - solana_program::declare_id!("FuS3FPfJDKSNot99ECLXtp3rueq36hMNStJkPJwWodLh"); + solana_pubkey::declare_id!("FuS3FPfJDKSNot99ECLXtp3rueq36hMNStJkPJwWodLh"); } pub mod migrate_feature_gate_program_to_core_bpf { - solana_program::declare_id!("4eohviozzEeivk1y9UbrnekbAFMDQyJz5JjA9Y6gyvky"); + solana_pubkey::declare_id!("4eohviozzEeivk1y9UbrnekbAFMDQyJz5JjA9Y6gyvky"); } pub mod vote_only_full_fec_sets { - solana_program::declare_id!("ffecLRhhakKSGhMuc6Fz2Lnfq4uT9q3iu9ZsNaPLxPc"); + solana_pubkey::declare_id!("ffecLRhhakKSGhMuc6Fz2Lnfq4uT9q3iu9ZsNaPLxPc"); } pub mod migrate_config_program_to_core_bpf { - solana_program::declare_id!("2Fr57nzzkLYXW695UdDxDeR5fhnZWSttZeZYemrnpGFV"); + solana_pubkey::declare_id!("2Fr57nzzkLYXW695UdDxDeR5fhnZWSttZeZYemrnpGFV"); } pub mod enable_get_epoch_stake_syscall { - solana_program::declare_id!("7mScTYkJXsbdrcwTQRs7oeCSXoJm4WjzBsRyf8bCU3Np"); + solana_pubkey::declare_id!("7mScTYkJXsbdrcwTQRs7oeCSXoJm4WjzBsRyf8bCU3Np"); } pub mod migrate_address_lookup_table_program_to_core_bpf { - solana_program::declare_id!("C97eKZygrkU4JxJsZdjgbUY7iQR7rKTr4NyDWo2E5pRm"); + solana_pubkey::declare_id!("C97eKZygrkU4JxJsZdjgbUY7iQR7rKTr4NyDWo2E5pRm"); } pub mod zk_elgamal_proof_program_enabled { - solana_program::declare_id!("zkhiy5oLowR7HY4zogXjCjeMXyruLqBwSWH21qcFtnv"); + solana_pubkey::declare_id!("zkhiy5oLowR7HY4zogXjCjeMXyruLqBwSWH21qcFtnv"); } pub mod verify_retransmitter_signature { - solana_program::declare_id!("BZ5g4hRbu5hLQQBdPyo2z9icGyJ8Khiyj3QS6dhWijTb"); + solana_pubkey::declare_id!("BZ5g4hRbu5hLQQBdPyo2z9icGyJ8Khiyj3QS6dhWijTb"); } pub mod move_stake_and_move_lamports_ixs { - solana_program::declare_id!("7bTK6Jis8Xpfrs8ZoUfiMDPazTcdPcTWheZFJTA5Z6X4"); + solana_pubkey::declare_id!("7bTK6Jis8Xpfrs8ZoUfiMDPazTcdPcTWheZFJTA5Z6X4"); } pub mod ed25519_precompile_verify_strict { - solana_program::declare_id!("ed9tNscbWLYBooxWA7FE2B5KHWs8A6sxfY8EzezEcoo"); + solana_pubkey::declare_id!("ed9tNscbWLYBooxWA7FE2B5KHWs8A6sxfY8EzezEcoo"); } pub mod vote_only_retransmitter_signed_fec_sets { - solana_program::declare_id!("RfEcA95xnhuwooVAhUUksEJLZBF7xKCLuqrJoqk4Zph"); + solana_pubkey::declare_id!("RfEcA95xnhuwooVAhUUksEJLZBF7xKCLuqrJoqk4Zph"); } pub mod move_precompile_verification_to_svm { - solana_program::declare_id!("9ypxGLzkMxi89eDerRKXWDXe44UY2z4hBig4mDhNq5Dp"); + solana_pubkey::declare_id!("9ypxGLzkMxi89eDerRKXWDXe44UY2z4hBig4mDhNq5Dp"); } pub mod enable_transaction_loading_failure_fees { - solana_program::declare_id!("PaymEPK2oqwT9TXAVfadjztH2H6KfLEB9Hhd5Q5frvP"); + solana_pubkey::declare_id!("PaymEPK2oqwT9TXAVfadjztH2H6KfLEB9Hhd5Q5frvP"); } pub mod enable_turbine_extended_fanout_experiments { - solana_program::declare_id!("BZn14Liea52wtBwrXUxTv6vojuTTmfc7XGEDTXrvMD7b"); + solana_pubkey::declare_id!("BZn14Liea52wtBwrXUxTv6vojuTTmfc7XGEDTXrvMD7b"); } pub mod deprecate_legacy_vote_ixs { - solana_program::declare_id!("depVvnQ2UysGrhwdiwU42tCadZL8GcBb1i2GYhMopQv"); + solana_pubkey::declare_id!("depVvnQ2UysGrhwdiwU42tCadZL8GcBb1i2GYhMopQv"); } pub mod disable_sbpf_v1_execution { - solana_program::declare_id!("TestFeature11111111111111111111111111111111"); + solana_pubkey::declare_id!("TestFeature11111111111111111111111111111111"); } pub mod reenable_sbpf_v1_execution { - solana_program::declare_id!("TestFeature21111111111111111111111111111111"); + solana_pubkey::declare_id!("TestFeature21111111111111111111111111111111"); } pub mod enable_secp256r1_precompile { @@ -1178,7 +1176,7 @@ impl FeatureSet { } /// Activate a feature - pub fn activate(&mut self, feature_id: &Pubkey, slot: u64) { + pub fn activate(&mut self, feature_id: &Pubkey, slot: Slot) { self.inactive.remove(feature_id); self.active.insert(*feature_id, slot); } diff --git a/sdk/native-token/Cargo.toml b/sdk/native-token/Cargo.toml new file mode 100644 index 00000000000000..cac63f3e88597f --- /dev/null +++ b/sdk/native-token/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "solana-native-token" +description = "Definitions for the native SOL token and its fractional lamports." +documentation = "https://docs.rs/solana-native-token" +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/sdk/program/src/native_token.rs b/sdk/native-token/src/lib.rs similarity index 100% rename from sdk/program/src/native_token.rs rename to sdk/native-token/src/lib.rs diff --git a/sdk/program/Cargo.toml b/sdk/program/Cargo.toml index 391e5e148f11ec..c3d373fb3f7835 100644 --- a/sdk/program/Cargo.toml +++ b/sdk/program/Cargo.toml @@ -51,6 +51,7 @@ solana-instruction = { workspace = true, default-features = false, features = [ "std", ] } solana-msg = { workspace = true } +solana-native-token = { workspace = true } solana-program-error = { workspace = true, features = ["serde"] } solana-program-memory = { workspace = true } solana-program-option = { workspace = true } diff --git a/sdk/program/src/address_lookup_table/state.rs b/sdk/program/src/address_lookup_table/state.rs index 13a66637faa919..3136dd063f85da 100644 --- a/sdk/program/src/address_lookup_table/state.rs +++ b/sdk/program/src/address_lookup_table/state.rs @@ -1,6 +1,7 @@ #[cfg(feature = "frozen-abi")] use solana_frozen_abi_macro::{AbiEnumVisitor, AbiExample}; use { + crate::slot_hashes::get_entries, serde_derive::{Deserialize, Serialize}, solana_clock::Slot, solana_program::{ @@ -12,6 +13,19 @@ use { std::borrow::Cow, }; +/// The lookup table may be in a deactivating state until +/// the `deactivation_slot`` is no longer "recent". +/// This function returns a conservative estimate for the +/// last block that the table may be used for lookups. +/// This estimate may be incorrect due to skipped blocks, +/// however, if the current slot is lower than the returned +/// value, the table is guaranteed to still be in the +/// deactivating state. +#[inline] +pub fn estimate_last_valid_slot(deactivation_slot: Slot) -> Slot { + deactivation_slot.saturating_add(get_entries() as Slot) +} + /// The maximum number of addresses that a lookup table can hold pub const LOOKUP_TABLE_MAX_ADDRESSES: usize = 256; diff --git a/sdk/program/src/lib.rs b/sdk/program/src/lib.rs index f75d6adcb8a9c2..474e5a2934a93e 100644 --- a/sdk/program/src/lib.rs +++ b/sdk/program/src/lib.rs @@ -502,7 +502,6 @@ pub mod loader_v4; pub mod loader_v4_instruction; pub mod log; pub mod message; -pub mod native_token; pub mod nonce; pub mod program; pub mod program_error; @@ -542,7 +541,8 @@ pub use { solana_account_info::{self as account_info, debug_account_data}, solana_clock as clock, solana_msg::msg, - solana_program_option as program_option, solana_pubkey as pubkey, solana_rent as rent, + solana_native_token as native_token, solana_program_option as program_option, + solana_pubkey as pubkey, solana_rent as rent, }; /// The [config native program][np]. diff --git a/sdk/pubkey/Cargo.toml b/sdk/pubkey/Cargo.toml index 50d7a5ed6bdef7..cdafef8a939f15 100644 --- a/sdk/pubkey/Cargo.toml +++ b/sdk/pubkey/Cargo.toml @@ -18,6 +18,7 @@ bytemuck = { workspace = true, optional = true } bytemuck_derive = { workspace = true, optional = true } five8_const = { workspace = true } num-traits = { workspace = true } +rand = { workspace = true, optional = true } serde = { workspace = true, optional = true } serde_derive = { workspace = true, optional = true } solana-atomic-u64 = { workspace = true } @@ -47,7 +48,6 @@ wasm-bindgen = { workspace = true } anyhow = { workspace = true } arbitrary = { workspace = true, features = ["derive"] } bs58 = { workspace = true, features = ["alloc"] } -rand = { workspace = true } # circular dev deps need to be path deps for `cargo publish` to be happy, # and for now the doc tests need solana-program solana-program = { path = "../program" } @@ -65,11 +65,12 @@ borsh = ["dep:borsh", "dep:borsh0-10", "std"] bytemuck = ["dep:bytemuck", "dep:bytemuck_derive"] curve25519 = ["dep:curve25519-dalek", "sha2"] default = ["std"] -dev-context-only-utils = ["dep:arbitrary", "std"] +dev-context-only-utils = ["dep:arbitrary", "rand"] frozen-abi = [ "dep:solana-frozen-abi", "dep:solana-frozen-abi-macro" ] +rand = ["dep:rand", "std"] serde = ["dep:serde", "dep:serde_derive"] sha2 = ["dep:solana-sha256-hasher", "solana-sha256-hasher/sha2"] std = [] diff --git a/sdk/pubkey/src/lib.rs b/sdk/pubkey/src/lib.rs index e378c44caf3f06..d603d6a97b3b9b 100644 --- a/sdk/pubkey/src/lib.rs +++ b/sdk/pubkey/src/lib.rs @@ -1114,6 +1114,12 @@ macro_rules! pubkey { }; } +/// New random Pubkey for tests and benchmarks. +#[cfg(all(feature = "rand", not(target_os = "solana")))] +pub fn new_rand() -> Pubkey { + Pubkey::from(rand::random::<[u8; PUBKEY_BYTES]>()) +} + #[cfg(test)] mod tests { use {super::*, strum::IntoEnumIterator}; diff --git a/sanitize/Cargo.toml b/sdk/sanitize/Cargo.toml similarity index 100% rename from sanitize/Cargo.toml rename to sdk/sanitize/Cargo.toml diff --git a/sanitize/src/lib.rs b/sdk/sanitize/src/lib.rs similarity index 100% rename from sanitize/src/lib.rs rename to sdk/sanitize/src/lib.rs diff --git a/sdk/src/fee.rs b/sdk/src/fee.rs index 22d04812fa0d76..08a825cd1ba2a2 100644 --- a/sdk/src/fee.rs +++ b/sdk/src/fee.rs @@ -2,7 +2,7 @@ #[cfg(not(target_os = "solana"))] use solana_program::message::SanitizedMessage; -use {crate::native_token::sol_to_lamports, std::num::NonZeroU32}; +use {solana_native_token::sol_to_lamports, std::num::NonZeroU32}; /// A fee and its associated compute unit limit #[derive(Debug, Default, Clone, Eq, PartialEq)] diff --git a/sdk/src/genesis_config.rs b/sdk/src/genesis_config.rs index 6b48f8fd1e7645..ba82ee531e5ccc 100644 --- a/sdk/src/genesis_config.rs +++ b/sdk/src/genesis_config.rs @@ -9,7 +9,6 @@ use { fee_calculator::FeeRateGovernor, hash::{hash, Hash}, inflation::Inflation, - native_token::lamports_to_sol, poh_config::PohConfig, pubkey::Pubkey, rent::Rent, @@ -22,6 +21,7 @@ use { chrono::{TimeZone, Utc}, memmap2::Mmap, solana_account::{Account, AccountSharedData}, + solana_native_token::lamports_to_sol, std::{ collections::BTreeMap, fmt, diff --git a/sdk/src/pubkey.rs b/sdk/src/pubkey.rs index 92d1365d03c5bf..344f0698444cb2 100644 --- a/sdk/src/pubkey.rs +++ b/sdk/src/pubkey.rs @@ -1,13 +1,13 @@ -//! Solana account addresses. - -pub use solana_program::pubkey::*; - -/// New random Pubkey for tests and benchmarks. #[cfg(feature = "full")] -pub fn new_rand() -> Pubkey { - Pubkey::from(rand::random::<[u8; PUBKEY_BYTES]>()) -} - +pub use solana_pubkey::new_rand; +#[cfg(target_os = "solana")] +pub use solana_pubkey::syscalls; +pub use solana_pubkey::{ + bytes_are_curve_point, ParsePubkeyError, Pubkey, PubkeyError, MAX_SEEDS, MAX_SEED_LEN, + PUBKEY_BYTES, +}; + +#[deprecated(since = "2.1.0")] #[cfg(feature = "full")] pub fn write_pubkey_file(outfile: &str, pubkey: Pubkey) -> Result<(), Box> { use std::io::Write; @@ -24,6 +24,7 @@ pub fn write_pubkey_file(outfile: &str, pubkey: Pubkey) -> Result<(), Box Result> { let f = std::fs::File::open(infile)?; @@ -32,19 +33,3 @@ pub fn read_pubkey_file(infile: &str) -> Result Result<(), Box> { - let filename = "test_pubkey.json"; - let pubkey = solana_sdk::pubkey::new_rand(); - write_pubkey_file(filename, pubkey)?; - let read = read_pubkey_file(filename)?; - assert_eq!(read, pubkey); - remove_file(filename)?; - Ok(()) - } -} diff --git a/svm/examples/json-rpc/server/src/rpc_process.rs b/svm/examples/json-rpc/server/src/rpc_process.rs index ed239323b462b4..f0721783c9d38d 100644 --- a/svm/examples/json-rpc/server/src/rpc_process.rs +++ b/svm/examples/json-rpc/server/src/rpc_process.rs @@ -208,7 +208,7 @@ impl JsonRpcRequestProcessor { (pubkey, acc_data) }) .collect(); - let batch_processor = TransactionBatchProcessor::::new( + let batch_processor = TransactionBatchProcessor::::new_uninitialized( EXECUTION_SLOT, EXECUTION_EPOCH, HashSet::new(), diff --git a/svm/examples/paytube/src/processor.rs b/svm/examples/paytube/src/processor.rs index 71eaccc956826b..663c1b5044665e 100644 --- a/svm/examples/paytube/src/processor.rs +++ b/svm/examples/paytube/src/processor.rs @@ -3,17 +3,18 @@ use { solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1, solana_compute_budget::compute_budget::ComputeBudget, - solana_program_runtime::loaded_programs::{ - BlockRelation, ForkGraph, LoadProgramMetrics, ProgramCacheEntry, - }, - solana_sdk::{account::ReadableAccount, clock::Slot, feature_set::FeatureSet, transaction}, + solana_program_runtime::loaded_programs::{BlockRelation, ForkGraph, ProgramCacheEntry}, + solana_sdk::{clock::Slot, feature_set::FeatureSet, transaction}, solana_svm::{ account_loader::CheckedTransactionDetails, transaction_processing_callback::TransactionProcessingCallback, transaction_processor::TransactionBatchProcessor, }, solana_system_program::system_processor, - std::sync::{Arc, RwLock}, + std::{ + collections::HashSet, + sync::{Arc, RwLock}, + }, }; /// In order to use the `TransactionBatchProcessor`, another trait - Solana @@ -40,13 +41,25 @@ pub(crate) fn create_transaction_batch_processor>, ) -> TransactionBatchProcessor { - let processor = TransactionBatchProcessor::::default(); + // Create a new transaction batch processor. + // + // We're going to use slot 1 specifically because any programs we add will + // be deployed in slot 0, and they are delayed visibility until the next + // slot (1). + // This includes programs owned by BPF Loader v2, which are automatically + // marked as "depoyed" in slot 0. + // See `solana_svm::program_loader::load_program_with_pubkey` for more + // details. + let processor = TransactionBatchProcessor::::new_uninitialized( + /* slot */ 1, + /* epoch */ 1, + /* builtin_program_ids */ HashSet::new(), + ); { let mut cache = processor.program_cache.write().unwrap(); // Initialize the mocked fork graph. - // let fork_graph = Arc::new(RwLock::new(PayTubeForkGraph {})); cache.fork_graph = Some(Arc::downgrade(&fork_graph)); // Initialize a proper cache environment. @@ -55,27 +68,6 @@ pub(crate) fn create_transaction_batch_processor Default for TransactionBatchProcessor { } impl TransactionBatchProcessor { - pub fn new(slot: Slot, epoch: Epoch, builtin_program_ids: HashSet) -> Self { + /// Create a new, uninitialized `TransactionBatchProcessor`. + /// + /// In this context, uninitialized means that the `TransactionBatchProcessor` + /// has been initialized with an empty program cache. The cache contains no + /// programs (including builtins) and has not been configured with a valid + /// fork graph. + /// + /// When using this method, it's advisable to call `set_fork_graph_in_program_cache` + /// as well as `add_builtin` to configure the cache before using the processor. + pub fn new_uninitialized( + slot: Slot, + epoch: Epoch, + builtin_program_ids: HashSet, + ) -> Self { Self { slot, epoch, @@ -199,6 +212,12 @@ impl TransactionBatchProcessor { } } + /// Create a new `TransactionBatchProcessor` from the current instance, but + /// with the provided slot and epoch. + /// + /// * Inherits the program cache and builtin program ids from the current + /// instance. + /// * Resets the sysvar cache. pub fn new_from(&self, slot: Slot, epoch: Epoch) -> Self { Self { slot, diff --git a/svm/tests/concurrent_tests.rs b/svm/tests/concurrent_tests.rs index 2e84fbba243663..4c547675784577 100644 --- a/svm/tests/concurrent_tests.rs +++ b/svm/tests/concurrent_tests.rs @@ -40,7 +40,8 @@ mod transaction_builder; fn program_cache_execution(threads: usize) { let mut mock_bank = MockBankCallback::default(); - let batch_processor = TransactionBatchProcessor::::new(5, 5, HashSet::new()); + let batch_processor = + TransactionBatchProcessor::::new_uninitialized(5, 5, HashSet::new()); let fork_graph = Arc::new(RwLock::new(MockForkGraph {})); batch_processor.program_cache.write().unwrap().fork_graph = Some(Arc::downgrade(&fork_graph)); @@ -126,11 +127,9 @@ fn test_program_cache_with_exhaustive_scheduler() { // correctly. fn svm_concurrent() { let mock_bank = Arc::new(MockBankCallback::default()); - let batch_processor = Arc::new(TransactionBatchProcessor::::new( - 5, - 2, - HashSet::new(), - )); + let batch_processor = Arc::new( + TransactionBatchProcessor::::new_uninitialized(5, 2, HashSet::new()), + ); let fork_graph = Arc::new(RwLock::new(MockForkGraph {})); create_executable_environment( diff --git a/svm/tests/conformance.rs b/svm/tests/conformance.rs index dc521bc36eee15..7bc9ee5184b2c6 100644 --- a/svm/tests/conformance.rs +++ b/svm/tests/conformance.rs @@ -244,7 +244,8 @@ fn run_fixture(fixture: InstrFixture, filename: OsString, execute_as_instr: bool create_program_runtime_environment_v1(&feature_set, &compute_budget, false, false).unwrap(); mock_bank.override_feature_set(feature_set); - let batch_processor = TransactionBatchProcessor::::new(42, 2, HashSet::new()); + let batch_processor = + TransactionBatchProcessor::::new_uninitialized(42, 2, HashSet::new()); let fork_graph = Arc::new(RwLock::new(MockForkGraph {})); { diff --git a/svm/tests/integration_test.rs b/svm/tests/integration_test.rs index 6b1325a643d2f0..9f781607aa3112 100644 --- a/svm/tests/integration_test.rs +++ b/svm/tests/integration_test.rs @@ -872,7 +872,7 @@ fn execute_test_entry(test_entry: SvmTestEntry) { .insert(*pubkey, account.clone()); } - let batch_processor = TransactionBatchProcessor::::new( + let batch_processor = TransactionBatchProcessor::::new_uninitialized( EXECUTION_SLOT, EXECUTION_EPOCH, HashSet::new(), @@ -1059,7 +1059,7 @@ fn svm_inspect_account() { // Load and execute the transaction - let batch_processor = TransactionBatchProcessor::::new( + let batch_processor = TransactionBatchProcessor::::new_uninitialized( EXECUTION_SLOT, EXECUTION_EPOCH, HashSet::new(), diff --git a/svm/tests/transaction_builder.rs b/svm/tests/transaction_builder.rs index 803487773a63ec..664ea6237120cb 100644 --- a/svm/tests/transaction_builder.rs +++ b/svm/tests/transaction_builder.rs @@ -26,7 +26,7 @@ pub struct SanitizedTransactionBuilder { signed_readonly_accounts: Vec<(Pubkey, Signature)>, signed_mutable_accounts: Vec<(Pubkey, Signature)>, unsigned_readonly_accounts: Vec, - unsigned_mutable_account: Vec, + unsigned_mutable_accounts: Vec, } #[derive(PartialEq, Eq, Hash, Clone)] @@ -91,7 +91,7 @@ impl SanitizedTransactionBuilder { AccountType::SignerReadonly } (false, true) => { - self.unsigned_mutable_account.push(item.pubkey); + self.unsigned_mutable_accounts.push(item.pubkey); AccountType::Writable } (false, false) => { @@ -117,7 +117,7 @@ impl SanitizedTransactionBuilder { self.signed_mutable_accounts .len() .saturating_add(self.signed_readonly_accounts.len()) - .saturating_add(self.unsigned_mutable_account.len()) + .saturating_add(self.unsigned_mutable_accounts.len()) .saturating_add(self.unsigned_readonly_accounts.len()) .saturating_add(1), ); @@ -159,7 +159,7 @@ impl SanitizedTransactionBuilder { positions_lambda(key, AccountType::SignerReadonly); signatures.push(*signature); }); - self.unsigned_mutable_account + self.unsigned_mutable_accounts .iter() .for_each(|key| positions_lambda(key, AccountType::Writable)); self.unsigned_readonly_accounts @@ -232,8 +232,8 @@ impl SanitizedTransactionBuilder { self.num_readonly_unsigned_accounts = 0; self.signed_mutable_accounts.clear(); self.signed_readonly_accounts.clear(); - self.unsigned_mutable_account.clear(); - self.unsigned_mutable_account.clear(); + self.unsigned_mutable_accounts.clear(); + self.unsigned_readonly_accounts.clear(); instructions }