1#[allow(deprecated)]
37use solana_sdk::recent_blockhashes_account;
38pub use solana_sdk::reward_type::RewardType;
39use {
40 crate::{
41 account_overrides::AccountOverrides,
42 accounts::{
43 AccountAddressFilter, Accounts, LoadedTransaction, PubkeyAccountSlot,
44 TransactionLoadResult,
45 },
46 accounts_db::{
47 AccountShrinkThreshold, AccountsDbConfig, SnapshotStorages,
48 ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
49 },
50 accounts_index::{AccountSecondaryIndexes, IndexKey, ScanConfig, ScanResult, ZeroLamport},
51 accounts_update_notifier_interface::AccountsUpdateNotifier,
52 ancestors::{Ancestors, AncestorsForSerialization},
53 blockhash_queue::BlockhashQueue,
54 builtins::{self, BuiltinAction, BuiltinFeatureTransition, Builtins},
55 cost_tracker::CostTracker,
56 epoch_stakes::{EpochStakes, NodeVoteAccounts},
57 inline_safe_associated_token_account, inline_safe_token,
58 message_processor::MessageProcessor,
59 rent_collector::{CollectedInfo, RentCollector},
60 stake_account::{self, StakeAccount},
61 stake_weighted_timestamp::{
62 calculate_stake_weighted_timestamp, MaxAllowableDrift,
63 MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST, MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
64 },
65 stakes::{InvalidCacheEntryReason, Stakes, StakesCache, StakesEnum},
66 status_cache::{SlotDelta, StatusCache},
67 storable_accounts::StorableAccounts,
68 system_instruction_processor::{get_system_account_kind, SystemAccountKind},
69 transaction_batch::TransactionBatch,
70 transaction_error_metrics::TransactionErrorMetrics,
71 vote_account::{VoteAccount, VoteAccountsHashMap},
72 vote_parser,
73 },
74 byteorder::{ByteOrder, LittleEndian},
75 dashmap::{DashMap, DashSet},
76 itertools::Itertools,
77 log::*,
78 rayon::{
79 iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator},
80 ThreadPool, ThreadPoolBuilder,
81 },
82 safecoin_measure::{measure, measure::Measure},
83 solana_metrics::{inc_new_counter_debug, inc_new_counter_info},
84 solana_program_runtime::{
85 accounts_data_meter::MAX_ACCOUNTS_DATA_LEN,
86 compute_budget::{self, ComputeBudget},
87 executor_cache::{CachedExecutors, Executors, TransactionExecutor, MAX_CACHED_EXECUTORS},
88 invoke_context::{BuiltinProgram, ProcessInstructionWithContext},
89 log_collector::LogCollector,
90 sysvar_cache::SysvarCache,
91 timings::{ExecuteTimingType, ExecuteTimings},
92 },
93 solana_sdk::{
94 account::{
95 create_account_shared_data_with_fields as create_account, from_account, Account,
96 AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
97 },
98 account_utils::StateMut,
99 clock::{
100 BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND,
101 INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY,
102 SECONDS_PER_DAY,
103 },
104 ed25519_program,
105 epoch_info::EpochInfo,
106 epoch_schedule::EpochSchedule,
107 feature,
108 feature_set::{
109 self, add_set_compute_unit_price_ix, default_units_per_instruction,
110 disable_fee_calculator, enable_early_verification_of_account_modifications,
111 enable_request_heap_frame_ix, use_default_units_in_fee_calculation, FeatureSet,
112 },
113 fee::FeeStructure,
114 fee_calculator::{FeeCalculator, FeeRateGovernor},
115 genesis_config::{ClusterType, GenesisConfig},
116 hard_forks::HardForks,
117 hash::{extend_and_hash, hashv, Hash},
118 incinerator,
119 inflation::Inflation,
120 instruction::CompiledInstruction,
121 lamports::LamportsError,
122 message::{AccountKeys, SanitizedMessage},
123 native_loader,
124 native_token::{sol_to_lamports, LAMPORTS_PER_SAFE},
125 nonce::{self, state::DurableNonce, NONCED_TX_MARKER_IX_INDEX},
126 nonce_account,
127 packet::PACKET_DATA_SIZE,
128 precompiles::get_precompiles,
129 pubkey::Pubkey,
130 saturating_add_assign, secp256k1_program,
131 signature::{Keypair, Signature},
132 slot_hashes::SlotHashes,
133 slot_history::{Check, SlotHistory},
134 stake::state::Delegation,
135 system_transaction,
136 sysvar::{self, Sysvar, SysvarId},
137 timing::years_as_slots,
138 transaction::{
139 MessageHash, Result, SanitizedTransaction, Transaction, TransactionError,
140 TransactionVerificationMode, VersionedTransaction, MAX_TX_ACCOUNT_LOCKS,
141 },
142 transaction_context::{
143 ExecutionRecord, InstructionTrace, TransactionAccount, TransactionContext,
144 TransactionReturnData,
145 },
146 },
147 solana_stake_program::stake_state::{
148 self, InflationPointCalculationEvent, PointValue, StakeState,
149 },
150 solana_vote_program::vote_state::{VoteState, VoteStateVersions},
151 std::{
152 borrow::Cow,
153 cell::RefCell,
154 collections::{HashMap, HashSet},
155 convert::{TryFrom, TryInto},
156 fmt, mem,
157 ops::{Deref, RangeInclusive},
158 path::PathBuf,
159 rc::Rc,
160 sync::{
161 atomic::{
162 AtomicBool, AtomicI64, AtomicU64, AtomicUsize,
163 Ordering::{AcqRel, Acquire, Relaxed},
164 },
165 Arc, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard,
166 },
167 thread::Builder,
168 time::{Duration, Instant},
169 },
170};
171
172pub struct VerifyBankHash {
174 pub test_hash_calculation: bool,
175 pub can_cached_slot_be_unflushed: bool,
176 pub ignore_mismatch: bool,
177 pub require_rooted_bank: bool,
178 pub run_in_background: bool,
179 pub store_hash_raw_data_for_debug: bool,
180}
181
182#[derive(Debug, Default)]
183struct RewardsMetrics {
184 load_vote_and_stake_accounts_us: AtomicU64,
185 calculate_points_us: AtomicU64,
186 redeem_rewards_us: u64,
187 store_stake_accounts_us: AtomicU64,
188 store_vote_accounts_us: AtomicU64,
189 invalid_cached_vote_accounts: usize,
190 invalid_cached_stake_accounts: usize,
191 invalid_cached_stake_accounts_rent_epoch: usize,
192 vote_accounts_cache_miss_count: usize,
193}
194
195mod address_lookup_table;
196mod builtin_programs;
197mod sysvar_cache;
198mod transaction_account_state_info;
199
200pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0;
201
202pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5;
203
204pub type Rewrites = RwLock<HashMap<Pubkey, Hash>>;
205
206#[derive(Default)]
207struct RentMetrics {
208 hold_range_us: AtomicU64,
209 load_us: AtomicU64,
210 collect_us: AtomicU64,
211 hash_us: AtomicU64,
212 store_us: AtomicU64,
213 count: AtomicUsize,
214}
215
216#[derive(Clone, Debug, PartialEq, Eq)]
217pub struct RentDebit {
218 rent_collected: u64,
219 post_balance: u64,
220}
221
222impl RentDebit {
223 fn try_into_reward_info(self) -> Option<RewardInfo> {
224 let rent_debit = i64::try_from(self.rent_collected)
225 .ok()
226 .and_then(|r| r.checked_neg());
227 rent_debit.map(|rent_debit| RewardInfo {
228 reward_type: RewardType::Rent,
229 lamports: rent_debit,
230 post_balance: self.post_balance,
231 commission: None, })
233 }
234}
235
236#[derive(Serialize, Deserialize, AbiExample, Clone, Debug, Default, PartialEq, Eq)]
242pub struct BankIncrementalSnapshotPersistence {
243 pub full_slot: Slot,
245 pub full_hash: Hash,
247 pub full_capitalization: u64,
249 pub incremental_hash: Hash,
251 pub incremental_capitalization: u64,
253}
254
255#[derive(Clone, Debug, Default, PartialEq, Eq)]
256pub struct RentDebits(HashMap<Pubkey, RentDebit>);
257impl RentDebits {
258 fn get_account_rent_debit(&self, address: &Pubkey) -> u64 {
259 self.0
260 .get(address)
261 .map(|r| r.rent_collected)
262 .unwrap_or_default()
263 }
264
265 pub fn insert(&mut self, address: &Pubkey, rent_collected: u64, post_balance: u64) {
266 if rent_collected != 0 {
267 self.0.insert(
268 *address,
269 RentDebit {
270 rent_collected,
271 post_balance,
272 },
273 );
274 }
275 }
276
277 pub fn into_unordered_rewards_iter(self) -> impl Iterator<Item = (Pubkey, RewardInfo)> {
278 self.0
279 .into_iter()
280 .filter_map(|(address, rent_debit)| Some((address, rent_debit.try_into_reward_info()?)))
281 }
282}
283
284pub type BankStatusCache = StatusCache<Result<()>>;
285#[frozen_abi(digest = "HEJXoycXvGT2pwMuKcUKzzbeemnqbfrUC4jHZx1ncaWv")]
286pub type BankSlotDelta = SlotDelta<Result<()>>;
287
288pub(crate) type PartitionIndex = u64;
292pub type PartitionsPerCycle = u64;
293type Partition = (PartitionIndex, PartitionIndex, PartitionsPerCycle);
294type RentCollectionCycleParams = (
295 Epoch,
296 SlotCount,
297 bool,
298 Epoch,
299 EpochCount,
300 PartitionsPerCycle,
301);
302
303pub struct SquashTiming {
304 pub squash_accounts_ms: u64,
305 pub squash_accounts_cache_ms: u64,
306 pub squash_accounts_index_ms: u64,
307 pub squash_accounts_store_ms: u64,
308
309 pub squash_cache_ms: u64,
310}
311
312type EpochCount = u64;
313
314#[derive(Debug)]
315pub struct BankRc {
316 pub accounts: Arc<Accounts>,
318
319 pub(crate) parent: RwLock<Option<Arc<Bank>>>,
321
322 pub(crate) slot: Slot,
324
325 pub(crate) bank_id_generator: Arc<AtomicU64>,
326}
327
328#[cfg(RUSTC_WITH_SPECIALIZATION)]
329use safecoin_frozen_abi::abi_example::AbiExample;
330
331#[cfg(RUSTC_WITH_SPECIALIZATION)]
332impl AbiExample for BankRc {
333 fn example() -> Self {
334 BankRc {
335 parent: RwLock::new(None),
337 accounts: AbiExample::example(),
339 slot: AbiExample::example(),
340 bank_id_generator: Arc::new(AtomicU64::new(0)),
341 }
342 }
343}
344
345impl BankRc {
346 pub(crate) fn new(accounts: Accounts, slot: Slot) -> Self {
347 Self {
348 accounts: Arc::new(accounts),
349 parent: RwLock::new(None),
350 slot,
351 bank_id_generator: Arc::new(AtomicU64::new(0)),
352 }
353 }
354}
355
356pub type TransactionCheckResult = (Result<()>, Option<NoncePartial>);
357
358pub struct TransactionResults {
359 pub fee_collection_results: Vec<Result<()>>,
360 pub execution_results: Vec<TransactionExecutionResult>,
361 pub rent_debits: Vec<RentDebits>,
362}
363
364#[derive(Debug, Clone)]
365pub struct TransactionExecutionDetails {
366 pub status: Result<()>,
367 pub log_messages: Option<Vec<String>>,
368 pub inner_instructions: Option<InnerInstructionsList>,
369 pub durable_nonce_fee: Option<DurableNonceFee>,
370 pub return_data: Option<TransactionReturnData>,
371 pub executed_units: u64,
372 pub accounts_data_len_delta: i64,
375}
376
377#[derive(Debug, Clone)]
388pub enum TransactionExecutionResult {
389 Executed {
390 details: TransactionExecutionDetails,
391 executors: Rc<RefCell<Executors>>,
392 },
393 NotExecuted(TransactionError),
394}
395
396impl TransactionExecutionResult {
397 pub fn was_executed_successfully(&self) -> bool {
398 match self {
399 Self::Executed { details, .. } => details.status.is_ok(),
400 Self::NotExecuted { .. } => false,
401 }
402 }
403
404 pub fn was_executed(&self) -> bool {
405 match self {
406 Self::Executed { .. } => true,
407 Self::NotExecuted(_) => false,
408 }
409 }
410
411 pub fn details(&self) -> Option<&TransactionExecutionDetails> {
412 match self {
413 Self::Executed { details, .. } => Some(details),
414 Self::NotExecuted(_) => None,
415 }
416 }
417
418 pub fn flattened_result(&self) -> Result<()> {
419 match self {
420 Self::Executed { details, .. } => details.status.clone(),
421 Self::NotExecuted(err) => Err(err.clone()),
422 }
423 }
424}
425
426pub struct LoadAndExecuteTransactionsOutput {
427 pub loaded_transactions: Vec<TransactionLoadResult>,
428 pub execution_results: Vec<TransactionExecutionResult>,
431 pub retryable_transaction_indexes: Vec<usize>,
432 pub executed_transactions_count: usize,
434 pub executed_with_successful_result_count: usize,
437 pub signature_count: u64,
438 pub error_counters: TransactionErrorMetrics,
439}
440
441#[derive(Debug, Clone)]
442pub enum DurableNonceFee {
443 Valid(u64),
444 Invalid,
445}
446
447impl From<&NonceFull> for DurableNonceFee {
448 fn from(nonce: &NonceFull) -> Self {
449 match nonce.lamports_per_signature() {
450 Some(lamports_per_signature) => Self::Valid(lamports_per_signature),
451 None => Self::Invalid,
452 }
453 }
454}
455
456impl DurableNonceFee {
457 pub fn lamports_per_signature(&self) -> Option<u64> {
458 match self {
459 Self::Valid(lamports_per_signature) => Some(*lamports_per_signature),
460 Self::Invalid => None,
461 }
462 }
463}
464
465pub struct TransactionSimulationResult {
466 pub result: Result<()>,
467 pub logs: TransactionLogMessages,
468 pub post_simulation_accounts: Vec<TransactionAccount>,
469 pub units_consumed: u64,
470 pub return_data: Option<TransactionReturnData>,
471}
472pub struct TransactionBalancesSet {
473 pub pre_balances: TransactionBalances,
474 pub post_balances: TransactionBalances,
475}
476
477impl TransactionBalancesSet {
478 pub fn new(pre_balances: TransactionBalances, post_balances: TransactionBalances) -> Self {
479 assert_eq!(pre_balances.len(), post_balances.len());
480 Self {
481 pre_balances,
482 post_balances,
483 }
484 }
485}
486pub type TransactionBalances = Vec<Vec<u64>>;
487
488pub type InnerInstructions = Vec<CompiledInstruction>;
491
492pub type InnerInstructionsList = Vec<InnerInstructions>;
495
496pub fn inner_instructions_list_from_instruction_trace(
498 instruction_trace: &InstructionTrace,
499) -> InnerInstructionsList {
500 instruction_trace
501 .iter()
502 .map(|inner_instructions_trace| {
503 inner_instructions_trace
504 .iter()
505 .skip(1)
506 .map(|instruction_context| {
507 CompiledInstruction::new_from_raw_parts(
508 instruction_context
509 .get_index_of_program_account_in_transaction(
510 instruction_context
511 .get_number_of_program_accounts()
512 .saturating_sub(1),
513 )
514 .unwrap_or_default() as u8,
515 instruction_context.get_instruction_data().to_vec(),
516 (0..instruction_context.get_number_of_instruction_accounts())
517 .map(|instruction_account_index| {
518 instruction_context
519 .get_index_of_instruction_account_in_transaction(
520 instruction_account_index,
521 )
522 .unwrap_or_default() as u8
523 })
524 .collect(),
525 )
526 })
527 .collect()
528 })
529 .collect()
530}
531
532pub type TransactionLogMessages = Vec<String>;
534
535#[derive(Serialize, Deserialize, AbiExample, AbiEnumVisitor, Debug, PartialEq, Eq)]
536pub enum TransactionLogCollectorFilter {
537 All,
538 AllWithVotes,
539 None,
540 OnlyMentionedAddresses,
541}
542
543impl Default for TransactionLogCollectorFilter {
544 fn default() -> Self {
545 Self::None
546 }
547}
548
549#[derive(AbiExample, Debug, Default)]
550pub struct TransactionLogCollectorConfig {
551 pub mentioned_addresses: HashSet<Pubkey>,
552 pub filter: TransactionLogCollectorFilter,
553}
554
555#[derive(AbiExample, Clone, Debug, PartialEq, Eq)]
556pub struct TransactionLogInfo {
557 pub signature: Signature,
558 pub result: Result<()>,
559 pub is_vote: bool,
560 pub log_messages: TransactionLogMessages,
561}
562
563#[derive(AbiExample, Default, Debug)]
564pub struct TransactionLogCollector {
565 pub logs: Vec<TransactionLogInfo>,
568
569 pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
572}
573
574impl TransactionLogCollector {
575 pub fn get_logs_for_address(
576 &self,
577 address: Option<&Pubkey>,
578 ) -> Option<Vec<TransactionLogInfo>> {
579 match address {
580 None => Some(self.logs.clone()),
581 Some(address) => self.mentioned_address_map.get(address).map(|log_indices| {
582 log_indices
583 .iter()
584 .filter_map(|i| self.logs.get(*i).cloned())
585 .collect()
586 }),
587 }
588 }
589}
590
591pub trait NonceInfo {
592 fn address(&self) -> &Pubkey;
593 fn account(&self) -> &AccountSharedData;
594 fn lamports_per_signature(&self) -> Option<u64>;
595 fn fee_payer_account(&self) -> Option<&AccountSharedData>;
596}
597
598#[derive(Clone, Debug, Default, PartialEq, Eq)]
600pub struct NoncePartial {
601 address: Pubkey,
602 account: AccountSharedData,
603}
604impl NoncePartial {
605 pub fn new(address: Pubkey, account: AccountSharedData) -> Self {
606 Self { address, account }
607 }
608}
609impl NonceInfo for NoncePartial {
610 fn address(&self) -> &Pubkey {
611 &self.address
612 }
613 fn account(&self) -> &AccountSharedData {
614 &self.account
615 }
616 fn lamports_per_signature(&self) -> Option<u64> {
617 nonce_account::lamports_per_signature_of(&self.account)
618 }
619 fn fee_payer_account(&self) -> Option<&AccountSharedData> {
620 None
621 }
622}
623
624#[derive(Clone, Debug, Default, PartialEq, Eq)]
626pub struct NonceFull {
627 address: Pubkey,
628 account: AccountSharedData,
629 fee_payer_account: Option<AccountSharedData>,
630}
631impl NonceFull {
632 pub fn new(
633 address: Pubkey,
634 account: AccountSharedData,
635 fee_payer_account: Option<AccountSharedData>,
636 ) -> Self {
637 Self {
638 address,
639 account,
640 fee_payer_account,
641 }
642 }
643 pub fn from_partial(
644 partial: NoncePartial,
645 message: &SanitizedMessage,
646 accounts: &[TransactionAccount],
647 rent_debits: &RentDebits,
648 ) -> Result<Self> {
649 let fee_payer = (0..message.account_keys().len()).find_map(|i| {
650 if let Some((k, a)) = &accounts.get(i) {
651 if message.is_non_loader_key(i) {
652 return Some((k, a));
653 }
654 }
655 None
656 });
657
658 if let Some((fee_payer_address, fee_payer_account)) = fee_payer {
659 let mut fee_payer_account = fee_payer_account.clone();
660 let rent_debit = rent_debits.get_account_rent_debit(fee_payer_address);
661 fee_payer_account.set_lamports(fee_payer_account.lamports().saturating_add(rent_debit));
662
663 let nonce_address = *partial.address();
664 if *fee_payer_address == nonce_address {
665 Ok(Self::new(nonce_address, fee_payer_account, None))
666 } else {
667 Ok(Self::new(
668 nonce_address,
669 partial.account().clone(),
670 Some(fee_payer_account),
671 ))
672 }
673 } else {
674 Err(TransactionError::AccountNotFound)
675 }
676 }
677}
678impl NonceInfo for NonceFull {
679 fn address(&self) -> &Pubkey {
680 &self.address
681 }
682 fn account(&self) -> &AccountSharedData {
683 &self.account
684 }
685 fn lamports_per_signature(&self) -> Option<u64> {
686 nonce_account::lamports_per_signature_of(&self.account)
687 }
688 fn fee_payer_account(&self) -> Option<&AccountSharedData> {
689 self.fee_payer_account.as_ref()
690 }
691}
692
693#[derive(Clone, Debug, Default, PartialEq)]
697pub struct BankFieldsToDeserialize {
698 pub(crate) blockhash_queue: BlockhashQueue,
699 pub(crate) ancestors: AncestorsForSerialization,
700 pub(crate) hash: Hash,
701 pub(crate) parent_hash: Hash,
702 pub(crate) parent_slot: Slot,
703 pub(crate) hard_forks: HardForks,
704 pub(crate) transaction_count: u64,
705 pub(crate) tick_height: u64,
706 pub(crate) signature_count: u64,
707 pub(crate) capitalization: u64,
708 pub(crate) max_tick_height: u64,
709 pub(crate) hashes_per_tick: Option<u64>,
710 pub(crate) ticks_per_slot: u64,
711 pub(crate) ns_per_slot: u128,
712 pub(crate) genesis_creation_time: UnixTimestamp,
713 pub(crate) slots_per_year: f64,
714 pub(crate) slot: Slot,
715 pub(crate) epoch: Epoch,
716 pub(crate) block_height: u64,
717 pub(crate) collector_id: Pubkey,
718 pub(crate) collector_fees: u64,
719 pub(crate) fee_calculator: FeeCalculator,
720 pub(crate) fee_rate_governor: FeeRateGovernor,
721 pub(crate) collected_rent: u64,
722 pub(crate) rent_collector: RentCollector,
723 pub(crate) epoch_schedule: EpochSchedule,
724 pub(crate) inflation: Inflation,
725 pub(crate) stakes: Stakes<Delegation>,
726 pub(crate) epoch_stakes: HashMap<Epoch, EpochStakes>,
727 pub(crate) is_delta: bool,
728 pub(crate) accounts_data_len: u64,
729 pub(crate) incremental_snapshot_persistence: Option<BankIncrementalSnapshotPersistence>,
730 pub(crate) epoch_accounts_hash: Option<Hash>,
731}
732
733#[derive(Debug)]
738pub(crate) struct BankFieldsToSerialize<'a> {
739 pub(crate) blockhash_queue: &'a RwLock<BlockhashQueue>,
740 pub(crate) ancestors: &'a AncestorsForSerialization,
741 pub(crate) hash: Hash,
742 pub(crate) parent_hash: Hash,
743 pub(crate) parent_slot: Slot,
744 pub(crate) hard_forks: &'a RwLock<HardForks>,
745 pub(crate) transaction_count: u64,
746 pub(crate) tick_height: u64,
747 pub(crate) signature_count: u64,
748 pub(crate) capitalization: u64,
749 pub(crate) max_tick_height: u64,
750 pub(crate) hashes_per_tick: Option<u64>,
751 pub(crate) ticks_per_slot: u64,
752 pub(crate) ns_per_slot: u128,
753 pub(crate) genesis_creation_time: UnixTimestamp,
754 pub(crate) slots_per_year: f64,
755 pub(crate) slot: Slot,
756 pub(crate) epoch: Epoch,
757 pub(crate) block_height: u64,
758 pub(crate) collector_id: Pubkey,
759 pub(crate) collector_fees: u64,
760 pub(crate) fee_calculator: FeeCalculator,
761 pub(crate) fee_rate_governor: FeeRateGovernor,
762 pub(crate) collected_rent: u64,
763 pub(crate) rent_collector: RentCollector,
764 pub(crate) epoch_schedule: EpochSchedule,
765 pub(crate) inflation: Inflation,
766 pub(crate) stakes: &'a StakesCache,
767 pub(crate) epoch_stakes: &'a HashMap<Epoch, EpochStakes>,
768 pub(crate) is_delta: bool,
769 pub(crate) accounts_data_len: u64,
770}
771
772impl PartialEq for Bank {
774 fn eq(&self, other: &Self) -> bool {
775 if std::ptr::eq(self, other) {
776 return true;
777 }
778 let Self {
779 rc: _,
780 status_cache: _,
781 blockhash_queue,
782 ancestors,
783 hash,
784 parent_hash,
785 parent_slot,
786 hard_forks,
787 transaction_count,
788 transaction_error_count: _,
789 transaction_entries_count: _,
790 transactions_per_entry_max: _,
791 tick_height,
792 signature_count,
793 capitalization,
794 max_tick_height,
795 hashes_per_tick,
796 ticks_per_slot,
797 ns_per_slot,
798 genesis_creation_time,
799 slots_per_year,
800 slot,
801 bank_id: _,
802 epoch,
803 block_height,
804 collector_id,
805 collector_fees,
806 fee_calculator,
807 fee_rate_governor,
808 collected_rent,
809 rent_collector,
810 epoch_schedule,
811 inflation,
812 stakes_cache,
813 epoch_stakes,
814 is_delta,
815 builtin_programs: _,
817 compute_budget: _,
818 builtin_feature_transitions: _,
819 rewards: _,
820 cluster_type: _,
821 lazy_rent_collection: _,
822 rewards_pool_pubkeys: _,
823 cached_executors: _,
824 transaction_debug_keys: _,
825 transaction_log_collector_config: _,
826 transaction_log_collector: _,
827 feature_set: _,
828 drop_callback: _,
829 freeze_started: _,
830 vote_only_bank: _,
831 cost_tracker: _,
832 rewrites_skipped_this_slot: _,
833 sysvar_cache: _,
834 accounts_data_size_initial: _,
835 accounts_data_size_delta_on_chain: _,
836 accounts_data_size_delta_off_chain: _,
837 fee_structure: _,
838 incremental_snapshot_persistence: _,
839 } = self;
843 *blockhash_queue.read().unwrap() == *other.blockhash_queue.read().unwrap()
844 && ancestors == &other.ancestors
845 && *hash.read().unwrap() == *other.hash.read().unwrap()
846 && parent_hash == &other.parent_hash
847 && parent_slot == &other.parent_slot
848 && *hard_forks.read().unwrap() == *other.hard_forks.read().unwrap()
849 && transaction_count.load(Relaxed) == other.transaction_count.load(Relaxed)
850 && tick_height.load(Relaxed) == other.tick_height.load(Relaxed)
851 && signature_count.load(Relaxed) == other.signature_count.load(Relaxed)
852 && capitalization.load(Relaxed) == other.capitalization.load(Relaxed)
853 && max_tick_height == &other.max_tick_height
854 && hashes_per_tick == &other.hashes_per_tick
855 && ticks_per_slot == &other.ticks_per_slot
856 && ns_per_slot == &other.ns_per_slot
857 && genesis_creation_time == &other.genesis_creation_time
858 && slots_per_year == &other.slots_per_year
859 && slot == &other.slot
860 && epoch == &other.epoch
861 && block_height == &other.block_height
862 && collector_id == &other.collector_id
863 && collector_fees.load(Relaxed) == other.collector_fees.load(Relaxed)
864 && fee_calculator == &other.fee_calculator
865 && fee_rate_governor == &other.fee_rate_governor
866 && collected_rent.load(Relaxed) == other.collected_rent.load(Relaxed)
867 && rent_collector == &other.rent_collector
868 && epoch_schedule == &other.epoch_schedule
869 && *inflation.read().unwrap() == *other.inflation.read().unwrap()
870 && *stakes_cache.stakes() == *other.stakes_cache.stakes()
871 && epoch_stakes == &other.epoch_stakes
872 && is_delta.load(Relaxed) == other.is_delta.load(Relaxed)
873 }
874}
875
876#[derive(Debug)]
877pub enum RewardCalculationEvent<'a, 'b> {
878 Staking(&'a Pubkey, &'b InflationPointCalculationEvent),
879}
880
881fn null_tracer() -> Option<impl Fn(&RewardCalculationEvent) + Send + Sync> {
882 None::<fn(&RewardCalculationEvent)>
883}
884
885pub trait DropCallback: fmt::Debug {
886 fn callback(&self, b: &Bank);
887 fn clone_box(&self) -> Box<dyn DropCallback + Send + Sync>;
888}
889
890#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, AbiExample, Clone, Copy)]
891pub struct RewardInfo {
892 pub reward_type: RewardType,
893 pub lamports: i64, pub post_balance: u64, pub commission: Option<u8>, }
897
898#[derive(Debug, Default)]
899pub struct OptionalDropCallback(Option<Box<dyn DropCallback + Send + Sync>>);
900
901#[cfg(RUSTC_WITH_SPECIALIZATION)]
902impl AbiExample for OptionalDropCallback {
903 fn example() -> Self {
904 Self(None)
905 }
906}
907
908#[derive(Debug, Clone, Default)]
909pub struct BuiltinPrograms {
910 pub vec: Vec<BuiltinProgram>,
911}
912
913#[cfg(RUSTC_WITH_SPECIALIZATION)]
914impl AbiExample for BuiltinPrograms {
915 fn example() -> Self {
916 Self::default()
917 }
918}
919
920#[derive(AbiExample, Debug)]
924pub struct Bank {
925 pub rc: BankRc,
927
928 pub status_cache: Arc<RwLock<BankStatusCache>>,
930
931 blockhash_queue: RwLock<BlockhashQueue>,
933
934 pub ancestors: Ancestors,
936
937 hash: RwLock<Hash>,
939
940 parent_hash: Hash,
942
943 parent_slot: Slot,
945
946 hard_forks: Arc<RwLock<HardForks>>,
948
949 transaction_count: AtomicU64,
951
952 transaction_error_count: AtomicU64,
954
955 transaction_entries_count: AtomicU64,
957
958 transactions_per_entry_max: AtomicU64,
960
961 tick_height: AtomicU64,
963
964 signature_count: AtomicU64,
966
967 capitalization: AtomicU64,
969
970 max_tick_height: u64,
972
973 hashes_per_tick: Option<u64>,
975
976 ticks_per_slot: u64,
978
979 pub ns_per_slot: u128,
981
982 genesis_creation_time: UnixTimestamp,
984
985 slots_per_year: f64,
987
988 slot: Slot,
990
991 bank_id: BankId,
992
993 epoch: Epoch,
995
996 block_height: u64,
998
999 collector_id: Pubkey,
1001
1002 collector_fees: AtomicU64,
1004
1005 pub(crate) fee_calculator: FeeCalculator,
1008
1009 pub(crate) fee_rate_governor: FeeRateGovernor,
1011
1012 collected_rent: AtomicU64,
1014
1015 rent_collector: RentCollector,
1017
1018 epoch_schedule: EpochSchedule,
1020
1021 inflation: Arc<RwLock<Inflation>>,
1023
1024 stakes_cache: StakesCache,
1026
1027 epoch_stakes: HashMap<Epoch, EpochStakes>,
1030
1031 is_delta: AtomicBool,
1034
1035 builtin_programs: BuiltinPrograms,
1037
1038 compute_budget: Option<ComputeBudget>,
1039
1040 #[allow(clippy::rc_buffer)]
1042 builtin_feature_transitions: Arc<Vec<BuiltinFeatureTransition>>,
1043
1044 pub rewards: RwLock<Vec<(Pubkey, RewardInfo)>>,
1046
1047 pub cluster_type: Option<ClusterType>,
1048
1049 pub lazy_rent_collection: AtomicBool,
1050
1051 pub rewards_pool_pubkeys: Arc<HashSet<Pubkey>>,
1053
1054 cached_executors: RwLock<CachedExecutors>,
1056
1057 transaction_debug_keys: Option<Arc<HashSet<Pubkey>>>,
1058
1059 pub transaction_log_collector_config: Arc<RwLock<TransactionLogCollectorConfig>>,
1061
1062 pub transaction_log_collector: Arc<RwLock<TransactionLogCollector>>,
1065
1066 pub feature_set: Arc<FeatureSet>,
1067
1068 pub drop_callback: RwLock<OptionalDropCallback>,
1070
1071 pub freeze_started: AtomicBool,
1072
1073 vote_only_bank: bool,
1074
1075 cost_tracker: RwLock<CostTracker>,
1076
1077 sysvar_cache: RwLock<SysvarCache>,
1078
1079 pub rewrites_skipped_this_slot: Rewrites,
1081
1082 accounts_data_size_initial: u64,
1084 accounts_data_size_delta_on_chain: AtomicI64,
1086 accounts_data_size_delta_off_chain: AtomicI64,
1088
1089 pub fee_structure: FeeStructure,
1091
1092 pub incremental_snapshot_persistence: Option<BankIncrementalSnapshotPersistence>,
1093}
1094
1095struct VoteWithStakeDelegations {
1096 vote_state: Arc<VoteState>,
1097 vote_account: AccountSharedData,
1098 delegations: Vec<(Pubkey, StakeAccount<()>)>,
1100}
1101
1102struct LoadVoteAndStakeAccountsResult {
1103 vote_with_stake_delegations_map: DashMap<Pubkey, VoteWithStakeDelegations>,
1104 invalid_stake_keys: DashMap<Pubkey, InvalidCacheEntryReason>,
1105 invalid_vote_keys: DashMap<Pubkey, InvalidCacheEntryReason>,
1106 invalid_cached_vote_accounts: usize,
1107 invalid_cached_stake_accounts: usize,
1108 invalid_cached_stake_accounts_rent_epoch: usize,
1109 vote_accounts_cache_miss_count: usize,
1110}
1111
1112#[derive(Debug, Default)]
1113pub struct NewBankOptions {
1114 pub vote_only_bank: bool,
1115}
1116
1117#[derive(Debug)]
1118struct PrevEpochInflationRewards {
1119 validator_rewards: u64,
1120 prev_epoch_duration_in_years: f64,
1121 validator_rate: f64,
1122 foundation_rate: f64,
1123}
1124
1125pub struct CommitTransactionCounts {
1126 pub committed_transactions_count: u64,
1127 pub committed_with_failure_result_count: u64,
1128 pub signature_count: u64,
1129}
1130
1131struct StakeReward {
1132 stake_pubkey: Pubkey,
1133 stake_reward_info: RewardInfo,
1134 stake_account: AccountSharedData,
1135}
1136
1137impl StakeReward {
1138 pub fn get_stake_reward(&self) -> i64 {
1139 self.stake_reward_info.lamports
1140 }
1141}
1142
1143impl<'a> StorableAccounts<'a, AccountSharedData> for (Slot, &'a [StakeReward]) {
1145 fn pubkey(&self, index: usize) -> &Pubkey {
1146 &self.1[index].stake_pubkey
1147 }
1148 fn account(&self, index: usize) -> &AccountSharedData {
1149 &self.1[index].stake_account
1150 }
1151 fn slot(&self, _index: usize) -> Slot {
1152 self.target_slot()
1154 }
1155 fn target_slot(&self) -> Slot {
1156 self.0
1157 }
1158 fn len(&self) -> usize {
1159 self.1.len()
1160 }
1161 fn contains_multiple_slots(&self) -> bool {
1162 false
1163 }
1164}
1165
1166impl Bank {
1167 pub fn default_for_tests() -> Self {
1168 Self::default_with_accounts(Accounts::default_for_tests())
1169 }
1170
1171 pub fn new_for_benches(genesis_config: &GenesisConfig) -> Self {
1172 Self::new_with_paths_for_benches(
1173 genesis_config,
1174 Vec::new(),
1175 None,
1176 None,
1177 AccountSecondaryIndexes::default(),
1178 false,
1179 AccountShrinkThreshold::default(),
1180 false,
1181 )
1182 }
1183
1184 pub fn new_for_tests(genesis_config: &GenesisConfig) -> Self {
1185 Self::new_with_config_for_tests(
1186 genesis_config,
1187 AccountSecondaryIndexes::default(),
1188 false,
1189 AccountShrinkThreshold::default(),
1190 )
1191 }
1192
1193 pub fn new_no_wallclock_throttle_for_tests(genesis_config: &GenesisConfig) -> Self {
1194 let mut bank = Self::new_for_tests(genesis_config);
1195
1196 bank.ns_per_slot = std::u128::MAX;
1197 bank
1198 }
1199
1200 pub(crate) fn new_with_config_for_tests(
1201 genesis_config: &GenesisConfig,
1202 account_indexes: AccountSecondaryIndexes,
1203 accounts_db_caching_enabled: bool,
1204 shrink_ratio: AccountShrinkThreshold,
1205 ) -> Self {
1206 Self::new_with_paths_for_tests(
1207 genesis_config,
1208 Vec::new(),
1209 None,
1210 None,
1211 account_indexes,
1212 accounts_db_caching_enabled,
1213 shrink_ratio,
1214 false,
1215 None,
1216 )
1217 }
1218
1219 fn default_with_accounts(accounts: Accounts) -> Self {
1220 let mut bank = Self {
1221 incremental_snapshot_persistence: None,
1222 rewrites_skipped_this_slot: Rewrites::default(),
1223 rc: BankRc::new(accounts, Slot::default()),
1224 status_cache: Arc::<RwLock<BankStatusCache>>::default(),
1225 blockhash_queue: RwLock::<BlockhashQueue>::default(),
1226 ancestors: Ancestors::default(),
1227 hash: RwLock::<Hash>::default(),
1228 parent_hash: Hash::default(),
1229 parent_slot: Slot::default(),
1230 hard_forks: Arc::<RwLock<HardForks>>::default(),
1231 transaction_count: AtomicU64::default(),
1232 transaction_error_count: AtomicU64::default(),
1233 transaction_entries_count: AtomicU64::default(),
1234 transactions_per_entry_max: AtomicU64::default(),
1235 tick_height: AtomicU64::default(),
1236 signature_count: AtomicU64::default(),
1237 capitalization: AtomicU64::default(),
1238 max_tick_height: u64::default(),
1239 hashes_per_tick: Option::<u64>::default(),
1240 ticks_per_slot: u64::default(),
1241 ns_per_slot: u128::default(),
1242 genesis_creation_time: UnixTimestamp::default(),
1243 slots_per_year: f64::default(),
1244 slot: Slot::default(),
1245 bank_id: BankId::default(),
1246 epoch: Epoch::default(),
1247 block_height: u64::default(),
1248 collector_id: Pubkey::default(),
1249 collector_fees: AtomicU64::default(),
1250 fee_calculator: FeeCalculator::default(),
1251 fee_rate_governor: FeeRateGovernor::default(),
1252 collected_rent: AtomicU64::default(),
1253 rent_collector: RentCollector::default(),
1254 epoch_schedule: EpochSchedule::default(),
1255 inflation: Arc::<RwLock<Inflation>>::default(),
1256 stakes_cache: StakesCache::default(),
1257 epoch_stakes: HashMap::<Epoch, EpochStakes>::default(),
1258 is_delta: AtomicBool::default(),
1259 builtin_programs: BuiltinPrograms::default(),
1260 compute_budget: Option::<ComputeBudget>::default(),
1261 builtin_feature_transitions: Arc::<Vec<BuiltinFeatureTransition>>::default(),
1262 rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
1263 cluster_type: Option::<ClusterType>::default(),
1264 lazy_rent_collection: AtomicBool::default(),
1265 rewards_pool_pubkeys: Arc::<HashSet<Pubkey>>::default(),
1266 cached_executors: RwLock::<CachedExecutors>::default(),
1267 transaction_debug_keys: Option::<Arc<HashSet<Pubkey>>>::default(),
1268 transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
1269 ),
1270 transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
1271 feature_set: Arc::<FeatureSet>::default(),
1272 drop_callback: RwLock::new(OptionalDropCallback(None)),
1273 freeze_started: AtomicBool::default(),
1274 vote_only_bank: false,
1275 cost_tracker: RwLock::<CostTracker>::default(),
1276 sysvar_cache: RwLock::<SysvarCache>::default(),
1277 accounts_data_size_initial: 0,
1278 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1279 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1280 fee_structure: FeeStructure::default(),
1281 };
1282
1283 let accounts_data_size_initial = bank.get_total_accounts_stats().unwrap().data_len as u64;
1284 bank.accounts_data_size_initial = accounts_data_size_initial;
1285
1286 bank
1287 }
1288
1289 pub fn new_with_paths_for_tests(
1290 genesis_config: &GenesisConfig,
1291 paths: Vec<PathBuf>,
1292 debug_keys: Option<Arc<HashSet<Pubkey>>>,
1293 additional_builtins: Option<&Builtins>,
1294 account_indexes: AccountSecondaryIndexes,
1295 accounts_db_caching_enabled: bool,
1296 shrink_ratio: AccountShrinkThreshold,
1297 debug_do_not_add_builtins: bool,
1298 accounts_db_config: Option<AccountsDbConfig>,
1299 ) -> Self {
1300 Self::new_with_paths(
1301 genesis_config,
1302 paths,
1303 debug_keys,
1304 additional_builtins,
1305 account_indexes,
1306 accounts_db_caching_enabled,
1307 shrink_ratio,
1308 debug_do_not_add_builtins,
1309 accounts_db_config.or(Some(ACCOUNTS_DB_CONFIG_FOR_TESTING)),
1310 None,
1311 )
1312 }
1313
1314 pub fn new_with_paths_for_benches(
1315 genesis_config: &GenesisConfig,
1316 paths: Vec<PathBuf>,
1317 debug_keys: Option<Arc<HashSet<Pubkey>>>,
1318 additional_builtins: Option<&Builtins>,
1319 account_indexes: AccountSecondaryIndexes,
1320 accounts_db_caching_enabled: bool,
1321 shrink_ratio: AccountShrinkThreshold,
1322 debug_do_not_add_builtins: bool,
1323 ) -> Self {
1324 Self::new_with_paths(
1325 genesis_config,
1326 paths,
1327 debug_keys,
1328 additional_builtins,
1329 account_indexes,
1330 accounts_db_caching_enabled,
1331 shrink_ratio,
1332 debug_do_not_add_builtins,
1333 Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
1334 None,
1335 )
1336 }
1337
1338 #[allow(clippy::too_many_arguments)]
1339 pub fn new_with_paths(
1340 genesis_config: &GenesisConfig,
1341 paths: Vec<PathBuf>,
1342 debug_keys: Option<Arc<HashSet<Pubkey>>>,
1343 additional_builtins: Option<&Builtins>,
1344 account_indexes: AccountSecondaryIndexes,
1345 accounts_db_caching_enabled: bool,
1346 shrink_ratio: AccountShrinkThreshold,
1347 debug_do_not_add_builtins: bool,
1348 accounts_db_config: Option<AccountsDbConfig>,
1349 accounts_update_notifier: Option<AccountsUpdateNotifier>,
1350 ) -> Self {
1351 let accounts = Accounts::new_with_config(
1352 paths,
1353 &genesis_config.cluster_type,
1354 account_indexes,
1355 accounts_db_caching_enabled,
1356 shrink_ratio,
1357 accounts_db_config,
1358 accounts_update_notifier,
1359 );
1360 let mut bank = Self::default_with_accounts(accounts);
1361 bank.ancestors = Ancestors::from(vec![bank.slot()]);
1362 bank.transaction_debug_keys = debug_keys;
1363 bank.cluster_type = Some(genesis_config.cluster_type);
1364
1365 bank.process_genesis_config(genesis_config);
1366 bank.finish_init(
1367 genesis_config,
1368 additional_builtins,
1369 debug_do_not_add_builtins,
1370 );
1371
1372 {
1375 let stakes = bank.stakes_cache.stakes().clone();
1376 let stakes = Arc::new(StakesEnum::from(stakes));
1377 for epoch in 0..=bank.get_leader_schedule_epoch(bank.slot) {
1378 bank.epoch_stakes
1379 .insert(epoch, EpochStakes::new(stakes.clone(), epoch));
1380 }
1381 bank.update_stake_history(None);
1382 }
1383 bank.update_clock(None);
1384 bank.update_rent();
1385 bank.update_epoch_schedule();
1386 bank.update_recent_blockhashes();
1387 bank.fill_missing_sysvar_cache_entries();
1388 bank
1389 }
1390
1391 pub fn new_from_parent(parent: &Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self {
1393 Self::_new_from_parent(
1394 parent,
1395 collector_id,
1396 slot,
1397 null_tracer(),
1398 NewBankOptions::default(),
1399 )
1400 }
1401
1402 pub fn new_from_parent_with_options(
1403 parent: &Arc<Bank>,
1404 collector_id: &Pubkey,
1405 slot: Slot,
1406 new_bank_options: NewBankOptions,
1407 ) -> Self {
1408 Self::_new_from_parent(parent, collector_id, slot, null_tracer(), new_bank_options)
1409 }
1410
1411 pub fn new_from_parent_with_tracer(
1412 parent: &Arc<Bank>,
1413 collector_id: &Pubkey,
1414 slot: Slot,
1415 reward_calc_tracer: impl Fn(&RewardCalculationEvent) + Send + Sync,
1416 ) -> Self {
1417 Self::_new_from_parent(
1418 parent,
1419 collector_id,
1420 slot,
1421 Some(reward_calc_tracer),
1422 NewBankOptions::default(),
1423 )
1424 }
1425
1426 fn get_rent_collector_from(rent_collector: &RentCollector, epoch: Epoch) -> RentCollector {
1427 rent_collector.clone_with_epoch(epoch)
1428 }
1429
1430 fn _new_from_parent(
1431 parent: &Arc<Bank>,
1432 collector_id: &Pubkey,
1433 slot: Slot,
1434 reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
1435 new_bank_options: NewBankOptions,
1436 ) -> Self {
1437 let mut time = Measure::start("bank::new_from_parent");
1438 let NewBankOptions { vote_only_bank } = new_bank_options;
1439
1440 parent.freeze();
1441 assert_ne!(slot, parent.slot());
1442
1443 let epoch_schedule = parent.epoch_schedule;
1444 let epoch = epoch_schedule.get_epoch(slot);
1445
1446 let (rc, bank_rc_time) = measure!(
1447 BankRc {
1448 accounts: Arc::new(Accounts::new_from_parent(
1449 &parent.rc.accounts,
1450 slot,
1451 parent.slot(),
1452 )),
1453 parent: RwLock::new(Some(parent.clone())),
1454 slot,
1455 bank_id_generator: parent.rc.bank_id_generator.clone(),
1456 },
1457 "bank_rc_creation",
1458 );
1459
1460 let (status_cache, status_cache_time) =
1461 measure!(Arc::clone(&parent.status_cache), "status_cache_creation",);
1462
1463 let ((fee_rate_governor, fee_calculator), fee_components_time) = measure!(
1464 {
1465 let fee_rate_governor = FeeRateGovernor::new_derived(
1466 &parent.fee_rate_governor,
1467 parent.signature_count(),
1468 );
1469
1470 let fee_calculator = if parent.feature_set.is_active(&disable_fee_calculator::id())
1471 {
1472 FeeCalculator::default()
1473 } else {
1474 fee_rate_governor.create_fee_calculator()
1475 };
1476 (fee_rate_governor, fee_calculator)
1477 },
1478 "fee_components_creation",
1479 );
1480
1481 let bank_id = rc.bank_id_generator.fetch_add(1, Relaxed) + 1;
1482 let (blockhash_queue, blockhash_queue_time) = measure!(
1483 RwLock::new(parent.blockhash_queue.read().unwrap().clone()),
1484 "blockhash_queue_creation",
1485 );
1486
1487 let (stakes_cache, stakes_cache_time) = measure!(
1488 StakesCache::new(parent.stakes_cache.stakes().clone()),
1489 "stakes_cache_creation",
1490 );
1491
1492 let (epoch_stakes, epoch_stakes_time) =
1493 measure!(parent.epoch_stakes.clone(), "epoch_stakes_creation");
1494
1495 let (builtin_programs, builtin_programs_time) =
1496 measure!(parent.builtin_programs.clone(), "builtin_programs_creation");
1497
1498 let (rewards_pool_pubkeys, rewards_pool_pubkeys_time) = measure!(
1499 parent.rewards_pool_pubkeys.clone(),
1500 "rewards_pool_pubkeys_creation",
1501 );
1502
1503 let (cached_executors, cached_executors_time) = measure!(
1504 {
1505 let parent_bank_executors = parent.cached_executors.read().unwrap();
1506 RwLock::new(CachedExecutors::new_from_parent_bank_executors(
1507 &parent_bank_executors,
1508 epoch,
1509 ))
1510 },
1511 "cached_executors_creation",
1512 );
1513
1514 let (transaction_debug_keys, transaction_debug_keys_time) = measure!(
1515 parent.transaction_debug_keys.clone(),
1516 "transation_debug_keys_creation",
1517 );
1518
1519 let (transaction_log_collector_config, transaction_log_collector_config_time) = measure!(
1520 parent.transaction_log_collector_config.clone(),
1521 "transaction_log_collector_config_creation",
1522 );
1523
1524 let (feature_set, feature_set_time) =
1525 measure!(parent.feature_set.clone(), "feature_set_creation");
1526
1527 let accounts_data_size_initial = parent.load_accounts_data_size();
1528 let mut new = Bank {
1529 incremental_snapshot_persistence: None,
1530 rewrites_skipped_this_slot: Rewrites::default(),
1531 rc,
1532 status_cache,
1533 slot,
1534 bank_id,
1535 epoch,
1536 blockhash_queue,
1537
1538 hashes_per_tick: parent.hashes_per_tick,
1540 ticks_per_slot: parent.ticks_per_slot,
1541 ns_per_slot: parent.ns_per_slot,
1542 genesis_creation_time: parent.genesis_creation_time,
1543 slots_per_year: parent.slots_per_year,
1544 epoch_schedule,
1545 collected_rent: AtomicU64::new(0),
1546 rent_collector: Self::get_rent_collector_from(&parent.rent_collector, epoch),
1547 max_tick_height: (slot + 1) * parent.ticks_per_slot,
1548 block_height: parent.block_height + 1,
1549 fee_calculator,
1550 fee_rate_governor,
1551 capitalization: AtomicU64::new(parent.capitalization()),
1552 vote_only_bank,
1553 inflation: parent.inflation.clone(),
1554 transaction_count: AtomicU64::new(parent.transaction_count()),
1555 transaction_error_count: AtomicU64::new(0),
1556 transaction_entries_count: AtomicU64::new(0),
1557 transactions_per_entry_max: AtomicU64::new(0),
1558 stakes_cache,
1560 epoch_stakes,
1561 parent_hash: parent.hash(),
1562 parent_slot: parent.slot(),
1563 collector_id: *collector_id,
1564 collector_fees: AtomicU64::new(0),
1565 ancestors: Ancestors::default(),
1566 hash: RwLock::new(Hash::default()),
1567 is_delta: AtomicBool::new(false),
1568 tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)),
1569 signature_count: AtomicU64::new(0),
1570 builtin_programs,
1571 compute_budget: parent.compute_budget,
1572 builtin_feature_transitions: parent.builtin_feature_transitions.clone(),
1573 hard_forks: parent.hard_forks.clone(),
1574 rewards: RwLock::new(vec![]),
1575 cluster_type: parent.cluster_type,
1576 lazy_rent_collection: AtomicBool::new(parent.lazy_rent_collection.load(Relaxed)),
1577 rewards_pool_pubkeys,
1578 cached_executors,
1579 transaction_debug_keys,
1580 transaction_log_collector_config,
1581 transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
1582 feature_set: Arc::clone(&feature_set),
1583 drop_callback: RwLock::new(OptionalDropCallback(
1584 parent
1585 .drop_callback
1586 .read()
1587 .unwrap()
1588 .0
1589 .as_ref()
1590 .map(|drop_callback| drop_callback.clone_box()),
1591 )),
1592 freeze_started: AtomicBool::new(false),
1593 cost_tracker: RwLock::new(CostTracker::new_with_account_data_size_limit(
1594 feature_set
1595 .is_active(&feature_set::cap_accounts_data_len::id())
1596 .then(|| {
1597 parent
1598 .accounts_data_size_limit()
1599 .saturating_sub(accounts_data_size_initial)
1600 }),
1601 )),
1602 sysvar_cache: RwLock::new(SysvarCache::default()),
1603 accounts_data_size_initial,
1604 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1605 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1606 fee_structure: parent.fee_structure.clone(),
1607 };
1608
1609 let (_, ancestors_time) = measure!(
1610 {
1611 let mut ancestors = Vec::with_capacity(1 + new.parents().len());
1612 ancestors.push(new.slot());
1613 new.parents().iter().for_each(|p| {
1614 ancestors.push(p.slot());
1615 });
1616 new.ancestors = Ancestors::from(ancestors);
1617 },
1618 "ancestors_creation",
1619 );
1620
1621 let parent_epoch = parent.epoch();
1623 let (_, update_epoch_time) = measure!(
1624 {
1625 if parent_epoch < new.epoch() {
1626 let (thread_pool, thread_pool_time) = measure!(
1627 ThreadPoolBuilder::new().build().unwrap(),
1628 "thread_pool_creation",
1629 );
1630
1631 let (_, apply_feature_activations_time) = measure!(
1632 new.apply_feature_activations(
1633 ApplyFeatureActivationsCaller::NewFromParent,
1634 false
1635 ),
1636 "apply_feature_activation",
1637 );
1638
1639 let (_, activate_epoch_time) = measure!(
1643 new.stakes_cache.activate_epoch(epoch, &thread_pool),
1644 "activate_epoch",
1645 );
1646
1647 let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot);
1649 let (_, update_epoch_stakes_time) = measure!(
1650 new.update_epoch_stakes(leader_schedule_epoch),
1651 "update_epoch_stakes",
1652 );
1653
1654 let mut metrics = RewardsMetrics::default();
1655 let (_, update_rewards_with_thread_pool_time) = measure!(
1657 {
1658 new.update_rewards_with_thread_pool(
1659 parent_epoch,
1660 reward_calc_tracer,
1661 &thread_pool,
1662 &mut metrics,
1663 )
1664 },
1665 "update_rewards_with_thread_pool",
1666 );
1667
1668 datapoint_info!(
1669 "bank-new_from_parent-new_epoch_timings",
1670 ("epoch", new.epoch(), i64),
1671 ("slot", slot, i64),
1672 ("parent_slot", parent.slot(), i64),
1673 ("thread_pool_creation_us", thread_pool_time.as_us(), i64),
1674 (
1675 "apply_feature_activations",
1676 apply_feature_activations_time.as_us(),
1677 i64
1678 ),
1679 ("activate_epoch_us", activate_epoch_time.as_us(), i64),
1680 (
1681 "update_epoch_stakes_us",
1682 update_epoch_stakes_time.as_us(),
1683 i64
1684 ),
1685 (
1686 "update_rewards_with_thread_pool_us",
1687 update_rewards_with_thread_pool_time.as_us(),
1688 i64
1689 ),
1690 (
1691 "load_vote_and_stake_accounts_us",
1692 metrics.load_vote_and_stake_accounts_us.load(Relaxed),
1693 i64
1694 ),
1695 (
1696 "calculate_points_us",
1697 metrics.calculate_points_us.load(Relaxed),
1698 i64
1699 ),
1700 ("redeem_rewards_us", metrics.redeem_rewards_us, i64),
1701 (
1702 "store_stake_accounts_us",
1703 metrics.store_stake_accounts_us.load(Relaxed),
1704 i64
1705 ),
1706 (
1707 "store_vote_accounts_us",
1708 metrics.store_vote_accounts_us.load(Relaxed),
1709 i64
1710 ),
1711 (
1712 "invalid_cached_vote_accounts",
1713 metrics.invalid_cached_vote_accounts,
1714 i64
1715 ),
1716 (
1717 "invalid_cached_stake_accounts",
1718 metrics.invalid_cached_stake_accounts,
1719 i64
1720 ),
1721 (
1722 "invalid_cached_stake_accounts_rent_epoch",
1723 metrics.invalid_cached_stake_accounts_rent_epoch,
1724 i64
1725 ),
1726 (
1727 "vote_accounts_cache_miss_count",
1728 metrics.vote_accounts_cache_miss_count,
1729 i64
1730 ),
1731 );
1732 } else {
1733 let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot);
1735 new.update_epoch_stakes(leader_schedule_epoch);
1736 }
1737 },
1738 "update_epoch",
1739 );
1740
1741 let (_, update_sysvars_time) = measure!(
1743 {
1744 new.update_slot_hashes();
1745 new.update_stake_history(Some(parent_epoch));
1746 new.update_clock(Some(parent_epoch));
1747 new.update_fees();
1748 },
1749 "update_sysvars",
1750 );
1751
1752 let (_, fill_sysvar_cache_time) =
1753 measure!(new.fill_missing_sysvar_cache_entries(), "fill_sysvar_cache");
1754
1755 time.stop();
1756
1757 datapoint_info!(
1758 "bank-new_from_parent-heights",
1759 ("slot", slot, i64),
1760 ("block_height", new.block_height, i64),
1761 ("parent_slot", parent.slot(), i64),
1762 ("bank_rc_creation_us", bank_rc_time.as_us(), i64),
1763 ("total_elapsed_us", time.as_us(), i64),
1764 ("status_cache_us", status_cache_time.as_us(), i64),
1765 ("fee_components_us", fee_components_time.as_us(), i64),
1766 ("blockhash_queue_us", blockhash_queue_time.as_us(), i64),
1767 ("stakes_cache_us", stakes_cache_time.as_us(), i64),
1768 ("epoch_stakes_time_us", epoch_stakes_time.as_us(), i64),
1769 ("builtin_programs_us", builtin_programs_time.as_us(), i64),
1770 (
1771 "rewards_pool_pubkeys_us",
1772 rewards_pool_pubkeys_time.as_us(),
1773 i64
1774 ),
1775 ("cached_executors_us", cached_executors_time.as_us(), i64),
1776 (
1777 "transaction_debug_keys_us",
1778 transaction_debug_keys_time.as_us(),
1779 i64
1780 ),
1781 (
1782 "transaction_log_collector_config_us",
1783 transaction_log_collector_config_time.as_us(),
1784 i64
1785 ),
1786 ("feature_set_us", feature_set_time.as_us(), i64),
1787 ("ancestors_us", ancestors_time.as_us(), i64),
1788 ("update_epoch_us", update_epoch_time.as_us(), i64),
1789 ("update_sysvars_us", update_sysvars_time.as_us(), i64),
1790 ("fill_sysvar_cache_us", fill_sysvar_cache_time.as_us(), i64),
1791 );
1792
1793 parent
1794 .cached_executors
1795 .read()
1796 .unwrap()
1797 .stats
1798 .submit(parent.slot());
1799
1800 new
1801 }
1802
1803 pub fn byte_limit_for_scans(&self) -> Option<usize> {
1804 self.rc
1805 .accounts
1806 .accounts_db
1807 .accounts_index
1808 .scan_results_limit_bytes
1809 }
1810
1811 pub fn proper_ancestors_set(&self) -> HashSet<Slot> {
1812 HashSet::from_iter(self.proper_ancestors())
1813 }
1814
1815 pub(crate) fn proper_ancestors(&self) -> impl Iterator<Item = Slot> + '_ {
1817 self.ancestors
1818 .keys()
1819 .into_iter()
1820 .filter(move |slot| *slot != self.slot)
1821 }
1822
1823 pub fn set_callback(&self, callback: Option<Box<dyn DropCallback + Send + Sync>>) {
1824 *self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
1825 }
1826
1827 pub fn vote_only_bank(&self) -> bool {
1828 self.vote_only_bank
1829 }
1830
1831 pub fn warp_from_parent(parent: &Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self {
1837 let parent_timestamp = parent.clock().unix_timestamp;
1838 let mut new = Bank::new_from_parent(parent, collector_id, slot);
1839 new.apply_feature_activations(ApplyFeatureActivationsCaller::WarpFromParent, false);
1840 new.update_epoch_stakes(new.epoch_schedule().get_epoch(slot));
1841 new.tick_height.store(new.max_tick_height(), Relaxed);
1842
1843 let mut clock = new.clock();
1844 clock.epoch_start_timestamp = parent_timestamp;
1845 clock.unix_timestamp = parent_timestamp;
1846 new.update_sysvar_account(&sysvar::clock::id(), |account| {
1847 create_account(
1848 &clock,
1849 new.inherit_specially_retained_account_fields(account),
1850 )
1851 });
1852 new.fill_missing_sysvar_cache_entries();
1853 new.freeze();
1854 new
1855 }
1856
1857 #[allow(clippy::float_cmp)]
1859 pub(crate) fn new_from_fields(
1860 bank_rc: BankRc,
1861 genesis_config: &GenesisConfig,
1862 fields: BankFieldsToDeserialize,
1863 debug_keys: Option<Arc<HashSet<Pubkey>>>,
1864 additional_builtins: Option<&Builtins>,
1865 debug_do_not_add_builtins: bool,
1866 accounts_data_size_initial: u64,
1867 ) -> Self {
1868 let now = Instant::now();
1869 let ancestors = Ancestors::from(&fields.ancestors);
1870 let stakes = Stakes::new(&fields.stakes, |pubkey| {
1877 let (account, _slot) = bank_rc.accounts.load_with_fixed_root(&ancestors, pubkey)?;
1878 Some(account)
1879 })
1880 .expect(
1881 "Stakes cache is inconsistent with accounts-db. This can indicate \
1882 a corrupted snapshot or bugs in cached accounts or accounts-db.",
1883 );
1884 let stakes_accounts_load_duration = now.elapsed();
1885 fn new<T: Default>() -> T {
1886 T::default()
1887 }
1888 let feature_set = new();
1889 let mut bank = Self {
1890 incremental_snapshot_persistence: fields.incremental_snapshot_persistence,
1891 rewrites_skipped_this_slot: Rewrites::default(),
1892 rc: bank_rc,
1893 status_cache: new(),
1894 blockhash_queue: RwLock::new(fields.blockhash_queue),
1895 ancestors,
1896 hash: RwLock::new(fields.hash),
1897 parent_hash: fields.parent_hash,
1898 parent_slot: fields.parent_slot,
1899 hard_forks: Arc::new(RwLock::new(fields.hard_forks)),
1900 transaction_count: AtomicU64::new(fields.transaction_count),
1901 transaction_error_count: new(),
1902 transaction_entries_count: new(),
1903 transactions_per_entry_max: new(),
1904 tick_height: AtomicU64::new(fields.tick_height),
1905 signature_count: AtomicU64::new(fields.signature_count),
1906 capitalization: AtomicU64::new(fields.capitalization),
1907 max_tick_height: fields.max_tick_height,
1908 hashes_per_tick: fields.hashes_per_tick,
1909 ticks_per_slot: fields.ticks_per_slot,
1910 ns_per_slot: fields.ns_per_slot,
1911 genesis_creation_time: fields.genesis_creation_time,
1912 slots_per_year: fields.slots_per_year,
1913 slot: fields.slot,
1914 bank_id: 0,
1915 epoch: fields.epoch,
1916 block_height: fields.block_height,
1917 collector_id: fields.collector_id,
1918 collector_fees: AtomicU64::new(fields.collector_fees),
1919 fee_calculator: fields.fee_calculator,
1920 fee_rate_governor: fields.fee_rate_governor,
1921 collected_rent: AtomicU64::new(fields.collected_rent),
1922 rent_collector: Self::get_rent_collector_from(&fields.rent_collector, fields.epoch),
1924 epoch_schedule: fields.epoch_schedule,
1925 inflation: Arc::new(RwLock::new(fields.inflation)),
1926 stakes_cache: StakesCache::new(stakes),
1927 epoch_stakes: fields.epoch_stakes,
1928 is_delta: AtomicBool::new(fields.is_delta),
1929 builtin_programs: new(),
1930 compute_budget: None,
1931 builtin_feature_transitions: new(),
1932 rewards: new(),
1933 cluster_type: Some(genesis_config.cluster_type),
1934 lazy_rent_collection: new(),
1935 rewards_pool_pubkeys: new(),
1936 cached_executors: RwLock::new(CachedExecutors::new(MAX_CACHED_EXECUTORS, fields.epoch)),
1937 transaction_debug_keys: debug_keys,
1938 transaction_log_collector_config: new(),
1939 transaction_log_collector: new(),
1940 feature_set: Arc::clone(&feature_set),
1941 drop_callback: RwLock::new(OptionalDropCallback(None)),
1942 freeze_started: AtomicBool::new(fields.hash != Hash::default()),
1943 vote_only_bank: false,
1944 cost_tracker: RwLock::new(CostTracker::default()),
1945 sysvar_cache: RwLock::new(SysvarCache::default()),
1946 accounts_data_size_initial,
1947 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1948 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1949 fee_structure: FeeStructure::default(),
1950 };
1951 bank.finish_init(
1952 genesis_config,
1953 additional_builtins,
1954 debug_do_not_add_builtins,
1955 );
1956
1957 assert_eq!(
1962 bank.genesis_creation_time, genesis_config.creation_time,
1963 "Bank snapshot genesis creation time does not match genesis.bin creation time.\
1964 The snapshot and genesis.bin might pertain to different clusters"
1965 );
1966 assert_eq!(
1967 bank.hashes_per_tick,
1968 genesis_config.poh_config.hashes_per_tick
1969 );
1970 assert_eq!(bank.ticks_per_slot, genesis_config.ticks_per_slot);
1971 assert_eq!(
1972 bank.ns_per_slot,
1973 genesis_config.poh_config.target_tick_duration.as_nanos()
1974 * genesis_config.ticks_per_slot as u128
1975 );
1976 assert_eq!(bank.max_tick_height, (bank.slot + 1) * bank.ticks_per_slot);
1977 assert_eq!(
1978 bank.slots_per_year,
1979 years_as_slots(
1980 1.0,
1981 &genesis_config.poh_config.target_tick_duration,
1982 bank.ticks_per_slot,
1983 )
1984 );
1985 assert_eq!(bank.epoch_schedule, genesis_config.epoch_schedule);
1986 assert_eq!(bank.epoch, bank.epoch_schedule.get_epoch(bank.slot));
1987 if !bank.feature_set.is_active(&disable_fee_calculator::id()) {
1988 bank.fee_rate_governor.lamports_per_signature =
1989 bank.fee_calculator.lamports_per_signature;
1990 assert_eq!(
1991 bank.fee_rate_governor.create_fee_calculator(),
1992 bank.fee_calculator
1993 );
1994 }
1995
1996 datapoint_info!(
1997 "bank-new-from-fields",
1998 (
1999 "accounts_data_len-from-snapshot",
2000 fields.accounts_data_len as i64,
2001 i64
2002 ),
2003 (
2004 "accounts_data_len-from-generate_index",
2005 accounts_data_size_initial as i64,
2006 i64
2007 ),
2008 (
2009 "stakes_accounts_load_duration_us",
2010 stakes_accounts_load_duration.as_micros(),
2011 i64
2012 ),
2013 );
2014 bank
2015 }
2016
2017 pub(crate) fn get_fields_to_serialize<'a>(
2019 &'a self,
2020 ancestors: &'a HashMap<Slot, usize>,
2021 ) -> BankFieldsToSerialize<'a> {
2022 BankFieldsToSerialize {
2023 blockhash_queue: &self.blockhash_queue,
2024 ancestors,
2025 hash: *self.hash.read().unwrap(),
2026 parent_hash: self.parent_hash,
2027 parent_slot: self.parent_slot,
2028 hard_forks: &*self.hard_forks,
2029 transaction_count: self.transaction_count.load(Relaxed),
2030 tick_height: self.tick_height.load(Relaxed),
2031 signature_count: self.signature_count.load(Relaxed),
2032 capitalization: self.capitalization.load(Relaxed),
2033 max_tick_height: self.max_tick_height,
2034 hashes_per_tick: self.hashes_per_tick,
2035 ticks_per_slot: self.ticks_per_slot,
2036 ns_per_slot: self.ns_per_slot,
2037 genesis_creation_time: self.genesis_creation_time,
2038 slots_per_year: self.slots_per_year,
2039 slot: self.slot,
2040 epoch: self.epoch,
2041 block_height: self.block_height,
2042 collector_id: self.collector_id,
2043 collector_fees: self.collector_fees.load(Relaxed),
2044 fee_calculator: self.fee_calculator,
2045 fee_rate_governor: self.fee_rate_governor.clone(),
2046 collected_rent: self.collected_rent.load(Relaxed),
2047 rent_collector: self.rent_collector.clone(),
2048 epoch_schedule: self.epoch_schedule,
2049 inflation: *self.inflation.read().unwrap(),
2050 stakes: &self.stakes_cache,
2051 epoch_stakes: &self.epoch_stakes,
2052 is_delta: self.is_delta.load(Relaxed),
2053 accounts_data_len: self.load_accounts_data_size(),
2054 }
2055 }
2056
2057 pub fn collector_id(&self) -> &Pubkey {
2058 &self.collector_id
2059 }
2060
2061 pub fn genesis_creation_time(&self) -> UnixTimestamp {
2062 self.genesis_creation_time
2063 }
2064
2065 pub fn slot(&self) -> Slot {
2066 self.slot
2067 }
2068
2069 pub fn bank_id(&self) -> BankId {
2070 self.bank_id
2071 }
2072
2073 pub fn epoch(&self) -> Epoch {
2074 self.epoch
2075 }
2076
2077 pub fn first_normal_epoch(&self) -> Epoch {
2078 self.epoch_schedule().first_normal_epoch
2079 }
2080
2081 pub fn freeze_lock(&self) -> RwLockReadGuard<Hash> {
2082 self.hash.read().unwrap()
2083 }
2084
2085 pub fn hash(&self) -> Hash {
2086 *self.hash.read().unwrap()
2087 }
2088
2089 pub fn is_frozen(&self) -> bool {
2090 *self.hash.read().unwrap() != Hash::default()
2091 }
2092
2093 pub fn freeze_started(&self) -> bool {
2094 self.freeze_started.load(Relaxed)
2095 }
2096
2097 pub fn status_cache_ancestors(&self) -> Vec<u64> {
2098 let mut roots = self.status_cache.read().unwrap().roots().clone();
2099 let min = roots.iter().min().cloned().unwrap_or(0);
2100 for ancestor in self.ancestors.keys() {
2101 if ancestor >= min {
2102 roots.insert(ancestor);
2103 }
2104 }
2105
2106 let mut ancestors: Vec<_> = roots.into_iter().collect();
2107 #[allow(clippy::stable_sort_primitive)]
2108 ancestors.sort();
2109 ancestors
2110 }
2111
2112 pub fn unix_timestamp_from_genesis(&self) -> i64 {
2114 self.genesis_creation_time + ((self.slot as u128 * self.ns_per_slot) / 1_000_000_000) as i64
2115 }
2116
2117 fn update_sysvar_account<F>(&self, pubkey: &Pubkey, updater: F)
2118 where
2119 F: Fn(&Option<AccountSharedData>) -> AccountSharedData,
2120 {
2121 let old_account = self.get_account_with_fixed_root(pubkey);
2122 let mut new_account = updater(&old_account);
2123
2124 self.adjust_sysvar_balance_for_rent(&mut new_account);
2130 self.store_account_and_update_capitalization(pubkey, &new_account);
2131 }
2132
2133 fn inherit_specially_retained_account_fields(
2134 &self,
2135 old_account: &Option<AccountSharedData>,
2136 ) -> InheritableAccountFields {
2137 const RENT_UNADJUSTED_INITIAL_BALANCE: u64 = 1;
2138
2139 (
2140 old_account
2141 .as_ref()
2142 .map(|a| a.lamports())
2143 .unwrap_or(RENT_UNADJUSTED_INITIAL_BALANCE),
2144 old_account
2145 .as_ref()
2146 .map(|a| a.rent_epoch())
2147 .unwrap_or(INITIAL_RENT_EPOCH),
2148 )
2149 }
2150
2151 pub fn clock(&self) -> sysvar::clock::Clock {
2152 from_account(&self.get_account(&sysvar::clock::id()).unwrap_or_default())
2153 .unwrap_or_default()
2154 }
2155
2156 fn update_clock(&self, parent_epoch: Option<Epoch>) {
2157 let mut unix_timestamp = self.clock().unix_timestamp;
2158 let epoch_start_timestamp = {
2160 let epoch = if let Some(epoch) = parent_epoch {
2161 epoch
2162 } else {
2163 self.epoch()
2164 };
2165 let first_slot_in_epoch = self.epoch_schedule().get_first_slot_in_epoch(epoch);
2166 Some((first_slot_in_epoch, self.clock().epoch_start_timestamp))
2167 };
2168 let max_allowable_drift = MaxAllowableDrift {
2169 fast: MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST,
2170 slow: MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
2171 };
2172
2173 let ancestor_timestamp = self.clock().unix_timestamp;
2174 if let Some(timestamp_estimate) =
2175 self.get_timestamp_estimate(max_allowable_drift, epoch_start_timestamp)
2176 {
2177 unix_timestamp = timestamp_estimate;
2178 if timestamp_estimate < ancestor_timestamp {
2179 unix_timestamp = ancestor_timestamp;
2180 }
2181 }
2182 datapoint_info!(
2183 "bank-timestamp-correction",
2184 ("slot", self.slot(), i64),
2185 ("from_genesis", self.unix_timestamp_from_genesis(), i64),
2186 ("corrected", unix_timestamp, i64),
2187 ("ancestor_timestamp", ancestor_timestamp, i64),
2188 );
2189 let mut epoch_start_timestamp =
2190 if parent_epoch.is_some() && parent_epoch.unwrap() != self.epoch() {
2192 unix_timestamp
2193 } else {
2194 self.clock().epoch_start_timestamp
2195 };
2196 if self.slot == 0 {
2197 unix_timestamp = self.unix_timestamp_from_genesis();
2198 epoch_start_timestamp = self.unix_timestamp_from_genesis();
2199 }
2200 let clock = sysvar::clock::Clock {
2201 slot: self.slot,
2202 epoch_start_timestamp,
2203 epoch: self.epoch_schedule().get_epoch(self.slot),
2204 leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
2205 unix_timestamp,
2206 };
2207 self.update_sysvar_account(&sysvar::clock::id(), |account| {
2208 create_account(
2209 &clock,
2210 self.inherit_specially_retained_account_fields(account),
2211 )
2212 });
2213 }
2214
2215 pub fn set_sysvar_for_tests<T>(&self, sysvar: &T)
2216 where
2217 T: Sysvar + SysvarId,
2218 {
2219 self.update_sysvar_account(&T::id(), |account| {
2220 create_account(
2221 sysvar,
2222 self.inherit_specially_retained_account_fields(account),
2223 )
2224 });
2225 self.reset_sysvar_cache();
2228 self.fill_missing_sysvar_cache_entries();
2229 }
2230
2231 fn update_slot_history(&self) {
2232 self.update_sysvar_account(&sysvar::slot_history::id(), |account| {
2233 let mut slot_history = account
2234 .as_ref()
2235 .map(|account| from_account::<SlotHistory, _>(account).unwrap())
2236 .unwrap_or_default();
2237 slot_history.add(self.slot());
2238 create_account(
2239 &slot_history,
2240 self.inherit_specially_retained_account_fields(account),
2241 )
2242 });
2243 }
2244
2245 fn update_slot_hashes(&self) {
2246 self.update_sysvar_account(&sysvar::slot_hashes::id(), |account| {
2247 let mut slot_hashes = account
2248 .as_ref()
2249 .map(|account| from_account::<SlotHashes, _>(account).unwrap())
2250 .unwrap_or_default();
2251 slot_hashes.add(self.parent_slot, self.parent_hash);
2252 create_account(
2253 &slot_hashes,
2254 self.inherit_specially_retained_account_fields(account),
2255 )
2256 });
2257 }
2258
2259 pub fn get_slot_history(&self) -> SlotHistory {
2260 from_account(&self.get_account(&sysvar::slot_history::id()).unwrap()).unwrap()
2261 }
2262
2263 fn update_epoch_stakes(&mut self, leader_schedule_epoch: Epoch) {
2264 if self.epoch_stakes.get(&leader_schedule_epoch).is_none() {
2268 self.epoch_stakes.retain(|&epoch, _| {
2269 epoch >= leader_schedule_epoch.saturating_sub(MAX_LEADER_SCHEDULE_STAKES)
2270 });
2271 let stakes = self.stakes_cache.stakes().clone();
2272 let stakes = Arc::new(StakesEnum::from(stakes));
2273 let new_epoch_stakes = EpochStakes::new(stakes, leader_schedule_epoch);
2274 {
2275 let vote_stakes: HashMap<_, _> = self
2276 .stakes_cache
2277 .stakes()
2278 .vote_accounts()
2279 .delegated_stakes()
2280 .map(|(pubkey, stake)| (*pubkey, stake))
2281 .collect();
2282 info!(
2283 "new epoch stakes, epoch: {}, stakes: {:#?}, total_stake: {}",
2284 leader_schedule_epoch,
2285 vote_stakes,
2286 new_epoch_stakes.total_stake(),
2287 );
2288 }
2289 self.epoch_stakes
2290 .insert(leader_schedule_epoch, new_epoch_stakes);
2291 }
2292 }
2293
2294 #[allow(deprecated)]
2295 fn update_fees(&self) {
2296 if !self
2297 .feature_set
2298 .is_active(&feature_set::disable_fees_sysvar::id())
2299 {
2300 self.update_sysvar_account(&sysvar::fees::id(), |account| {
2301 create_account(
2302 &sysvar::fees::Fees::new(&self.fee_rate_governor.create_fee_calculator()),
2303 self.inherit_specially_retained_account_fields(account),
2304 )
2305 });
2306 }
2307 }
2308
2309 fn update_rent(&self) {
2310 self.update_sysvar_account(&sysvar::rent::id(), |account| {
2311 create_account(
2312 &self.rent_collector.rent,
2313 self.inherit_specially_retained_account_fields(account),
2314 )
2315 });
2316 }
2317
2318 fn update_epoch_schedule(&self) {
2319 self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
2320 create_account(
2321 self.epoch_schedule(),
2322 self.inherit_specially_retained_account_fields(account),
2323 )
2324 });
2325 }
2326
2327 fn update_stake_history(&self, epoch: Option<Epoch>) {
2328 if epoch == Some(self.epoch()) {
2329 return;
2330 }
2331 self.update_sysvar_account(&sysvar::stake_history::id(), |account| {
2333 create_account::<sysvar::stake_history::StakeHistory>(
2334 self.stakes_cache.stakes().history(),
2335 self.inherit_specially_retained_account_fields(account),
2336 )
2337 });
2338 }
2339
2340 pub fn epoch_duration_in_years(&self, prev_epoch: Epoch) -> f64 {
2341 self.epoch_schedule().get_slots_in_epoch(prev_epoch) as f64 / self.slots_per_year
2345 }
2346
2347 fn get_inflation_start_slot(&self) -> Slot {
2353 let mut slots = self
2354 .feature_set
2355 .full_inflation_features_enabled()
2356 .iter()
2357 .filter_map(|id| self.feature_set.activated_slot(id))
2358 .collect::<Vec<_>>();
2359 slots.sort_unstable();
2360 slots.first().cloned().unwrap_or_else(|| {
2361 self.feature_set
2362 .activated_slot(&feature_set::pico_inflation::id())
2363 .unwrap_or(0)
2364 })
2365 }
2366
2367 fn get_inflation_num_slots(&self) -> u64 {
2368 let inflation_activation_slot = self.get_inflation_start_slot();
2369 let inflation_start_slot = self.epoch_schedule().get_first_slot_in_epoch(
2371 self.epoch_schedule()
2372 .get_epoch(inflation_activation_slot)
2373 .saturating_sub(1),
2374 );
2375 self.epoch_schedule().get_first_slot_in_epoch(self.epoch()) - inflation_start_slot
2376 }
2377
2378 pub fn slot_in_year_for_inflation(&self) -> f64 {
2379 let num_slots = self.get_inflation_num_slots();
2380
2381 num_slots as f64 / self.slots_per_year
2383 }
2384
2385 fn calculate_previous_epoch_inflation_rewards(
2386 &self,
2387 prev_epoch_capitalization: u64,
2388 prev_epoch: Epoch,
2389 ) -> PrevEpochInflationRewards {
2390 let slot_in_year = self.slot_in_year_for_inflation();
2391 let (validator_rate, foundation_rate) = {
2392 let inflation = self.inflation.read().unwrap();
2393 (
2394 (*inflation).validator(slot_in_year),
2395 (*inflation).foundation(slot_in_year),
2396 )
2397 };
2398
2399 let prev_epoch_duration_in_years = self.epoch_duration_in_years(prev_epoch);
2400 let validator_rewards = (validator_rate
2401 * prev_epoch_capitalization as f64
2402 * prev_epoch_duration_in_years) as u64;
2403
2404 PrevEpochInflationRewards {
2405 validator_rewards,
2406 prev_epoch_duration_in_years,
2407 validator_rate,
2408 foundation_rate,
2409 }
2410 }
2411
2412 fn update_rewards_with_thread_pool(
2414 &mut self,
2415 prev_epoch: Epoch,
2416 reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
2417 thread_pool: &ThreadPool,
2418 metrics: &mut RewardsMetrics,
2419 ) {
2420 let capitalization = self.capitalization();
2421 let PrevEpochInflationRewards {
2422 validator_rewards,
2423 prev_epoch_duration_in_years,
2424 validator_rate,
2425 foundation_rate,
2426 } = self.calculate_previous_epoch_inflation_rewards(capitalization, prev_epoch);
2427
2428 let old_vote_balance_and_staked = self.stakes_cache.stakes().vote_balance_and_staked();
2429 let update_rewards_from_cached_accounts = self
2430 .feature_set
2431 .is_active(&feature_set::update_rewards_from_cached_accounts::id());
2432
2433 self.pay_validator_rewards_with_thread_pool(
2434 prev_epoch,
2435 validator_rewards,
2436 reward_calc_tracer,
2437 self.credits_auto_rewind(),
2438 thread_pool,
2439 metrics,
2440 update_rewards_from_cached_accounts,
2441 );
2442
2443 let new_vote_balance_and_staked = self.stakes_cache.stakes().vote_balance_and_staked();
2444 let validator_rewards_paid = new_vote_balance_and_staked - old_vote_balance_and_staked;
2445 assert_eq!(
2446 validator_rewards_paid,
2447 u64::try_from(
2448 self.rewards
2449 .read()
2450 .unwrap()
2451 .iter()
2452 .map(|(_address, reward_info)| {
2453 match reward_info.reward_type {
2454 RewardType::Voting | RewardType::Staking => reward_info.lamports,
2455 _ => 0,
2456 }
2457 })
2458 .sum::<i64>()
2459 )
2460 .unwrap()
2461 );
2462
2463 assert!(validator_rewards >= validator_rewards_paid);
2465
2466 info!(
2467 "distributed inflation: {} (rounded from: {})",
2468 validator_rewards_paid, validator_rewards
2469 );
2470 let (num_stake_accounts, num_vote_accounts) = {
2471 let stakes = self.stakes_cache.stakes();
2472 (
2473 stakes.stake_delegations().len(),
2474 stakes.vote_accounts().len(),
2475 )
2476 };
2477 self.capitalization
2478 .fetch_add(validator_rewards_paid, Relaxed);
2479
2480 let active_stake = if let Some(stake_history_entry) =
2481 self.stakes_cache.stakes().history().get(prev_epoch)
2482 {
2483 stake_history_entry.effective
2484 } else {
2485 0
2486 };
2487
2488 datapoint_warn!(
2489 "epoch_rewards",
2490 ("slot", self.slot, i64),
2491 ("epoch", prev_epoch, i64),
2492 ("validator_rate", validator_rate, f64),
2493 ("foundation_rate", foundation_rate, f64),
2494 ("epoch_duration_in_years", prev_epoch_duration_in_years, f64),
2495 ("validator_rewards", validator_rewards_paid, i64),
2496 ("active_stake", active_stake, i64),
2497 ("pre_capitalization", capitalization, i64),
2498 ("post_capitalization", self.capitalization(), i64),
2499 ("num_stake_accounts", num_stake_accounts as i64, i64),
2500 ("num_vote_accounts", num_vote_accounts as i64, i64),
2501 );
2502 }
2503
2504 fn load_vote_and_stake_accounts_with_thread_pool(
2510 &self,
2511 thread_pool: &ThreadPool,
2512 reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
2513 ) -> LoadVoteAndStakeAccountsResult {
2514 let stakes = self.stakes_cache.stakes();
2515 let cached_vote_accounts = stakes.vote_accounts();
2516 let vote_with_stake_delegations_map = DashMap::with_capacity(cached_vote_accounts.len());
2517 let invalid_stake_keys: DashMap<Pubkey, InvalidCacheEntryReason> = DashMap::new();
2518 let invalid_vote_keys: DashMap<Pubkey, InvalidCacheEntryReason> = DashMap::new();
2519 let invalid_cached_stake_accounts = AtomicUsize::default();
2520 let invalid_cached_vote_accounts = AtomicUsize::default();
2521 let invalid_cached_stake_accounts_rent_epoch = AtomicUsize::default();
2522
2523 let stake_delegations = self.filter_stake_delegations(&stakes);
2524 thread_pool.install(|| {
2525 stake_delegations
2526 .into_par_iter()
2527 .for_each(|(stake_pubkey, cached_stake_account)| {
2528 let delegation = cached_stake_account.delegation();
2529 let vote_pubkey = &delegation.voter_pubkey;
2530 if invalid_vote_keys.contains_key(vote_pubkey) {
2531 return;
2532 }
2533 let stake_account = match self.get_account_with_fixed_root(stake_pubkey) {
2534 Some(stake_account) => stake_account,
2535 None => {
2536 invalid_stake_keys
2537 .insert(*stake_pubkey, InvalidCacheEntryReason::Missing);
2538 invalid_cached_stake_accounts.fetch_add(1, Relaxed);
2539 return;
2540 }
2541 };
2542 if cached_stake_account.account() != &stake_account {
2543 invalid_cached_stake_accounts.fetch_add(1, Relaxed);
2544 let cached_stake_account = cached_stake_account.account();
2545 if cached_stake_account.lamports() == stake_account.lamports()
2546 && cached_stake_account.data() == stake_account.data()
2547 && cached_stake_account.owner() == stake_account.owner()
2548 && cached_stake_account.executable() == stake_account.executable()
2549 {
2550 invalid_cached_stake_accounts_rent_epoch.fetch_add(1, Relaxed);
2551 } else {
2552 debug!(
2553 "cached stake account mismatch: {}: {:?}, {:?}",
2554 stake_pubkey, stake_account, cached_stake_account
2555 );
2556 }
2557 }
2558 let stake_account = match StakeAccount::<()>::try_from(stake_account) {
2559 Ok(stake_account) => stake_account,
2560 Err(stake_account::Error::InvalidOwner { .. }) => {
2561 invalid_stake_keys
2562 .insert(*stake_pubkey, InvalidCacheEntryReason::WrongOwner);
2563 return;
2564 }
2565 Err(stake_account::Error::InstructionError(_)) => {
2566 invalid_stake_keys
2567 .insert(*stake_pubkey, InvalidCacheEntryReason::BadState);
2568 return;
2569 }
2570 Err(stake_account::Error::InvalidDelegation(_)) => {
2571 error!(
2573 "Unexpected code path! StakeAccount<()> \
2574 should not check if stake-state is a \
2575 Delegation."
2576 );
2577 return;
2578 }
2579 };
2580 let stake_delegation = (*stake_pubkey, stake_account);
2581 let mut vote_delegations = if let Some(vote_delegations) =
2582 vote_with_stake_delegations_map.get_mut(vote_pubkey)
2583 {
2584 vote_delegations
2585 } else {
2586 let cached_vote_account = cached_vote_accounts.get(vote_pubkey);
2587 let vote_account = match self.get_account_with_fixed_root(vote_pubkey) {
2588 Some(vote_account) => {
2589 if vote_account.owner() != &solana_vote_program::id() {
2590 invalid_vote_keys
2591 .insert(*vote_pubkey, InvalidCacheEntryReason::WrongOwner);
2592 if cached_vote_account.is_some() {
2593 invalid_cached_vote_accounts.fetch_add(1, Relaxed);
2594 }
2595 return;
2596 }
2597 vote_account
2598 }
2599 None => {
2600 if cached_vote_account.is_some() {
2601 invalid_cached_vote_accounts.fetch_add(1, Relaxed);
2602 }
2603 invalid_vote_keys
2604 .insert(*vote_pubkey, InvalidCacheEntryReason::Missing);
2605 return;
2606 }
2607 };
2608
2609 let vote_state = if let Ok(vote_state) =
2610 StateMut::<VoteStateVersions>::state(&vote_account)
2611 {
2612 vote_state.convert_to_current()
2613 } else {
2614 invalid_vote_keys
2615 .insert(*vote_pubkey, InvalidCacheEntryReason::BadState);
2616 if cached_vote_account.is_some() {
2617 invalid_cached_vote_accounts.fetch_add(1, Relaxed);
2618 }
2619 return;
2620 };
2621 match cached_vote_account {
2622 Some(cached_vote_account)
2623 if cached_vote_account.account() == &vote_account => {}
2624 _ => {
2625 invalid_cached_vote_accounts.fetch_add(1, Relaxed);
2626 }
2627 };
2628 vote_with_stake_delegations_map
2629 .entry(*vote_pubkey)
2630 .or_insert_with(|| VoteWithStakeDelegations {
2631 vote_state: Arc::new(vote_state),
2632 vote_account,
2633 delegations: vec![],
2634 })
2635 };
2636
2637 if let Some(reward_calc_tracer) = reward_calc_tracer.as_ref() {
2638 reward_calc_tracer(&RewardCalculationEvent::Staking(
2639 stake_pubkey,
2640 &InflationPointCalculationEvent::Delegation(
2641 delegation,
2642 solana_vote_program::id(),
2643 ),
2644 ));
2645 }
2646
2647 vote_delegations.delegations.push(stake_delegation);
2648 });
2649 });
2650 invalid_cached_stake_accounts.fetch_add(invalid_stake_keys.len(), Relaxed);
2651 LoadVoteAndStakeAccountsResult {
2652 vote_with_stake_delegations_map,
2653 invalid_vote_keys,
2654 invalid_stake_keys,
2655 invalid_cached_vote_accounts: invalid_cached_vote_accounts.into_inner(),
2656 invalid_cached_stake_accounts: invalid_cached_stake_accounts.into_inner(),
2657 invalid_cached_stake_accounts_rent_epoch: invalid_cached_stake_accounts_rent_epoch
2658 .into_inner(),
2659 vote_accounts_cache_miss_count: 0,
2660 }
2661 }
2662
2663 fn filter_stake_delegations<'a>(
2664 &self,
2665 stakes: &'a Stakes<StakeAccount<Delegation>>,
2666 ) -> Vec<(&'a Pubkey, &'a StakeAccount<Delegation>)> {
2667 if self
2668 .feature_set
2669 .is_active(&feature_set::stake_minimum_delegation_for_rewards::id())
2670 {
2671 let num_stake_delegations = stakes.stake_delegations().len();
2672 let min_stake_delegation =
2673 solana_stake_program::get_minimum_delegation(&self.feature_set)
2674 .max(LAMPORTS_PER_SAFE);
2675
2676 let (stake_delegations, filter_timer) = measure!(stakes
2677 .stake_delegations()
2678 .iter()
2679 .filter(|(_stake_pubkey, cached_stake_account)| {
2680 cached_stake_account.delegation().stake >= min_stake_delegation
2681 })
2682 .collect::<Vec<_>>());
2683
2684 datapoint_info!(
2685 "stake_account_filter_time",
2686 ("filter_time_us", filter_timer.as_us(), i64),
2687 ("num_stake_delegations_before", num_stake_delegations, i64),
2688 ("num_stake_delegations_after", stake_delegations.len(), i64)
2689 );
2690 stake_delegations
2691 } else {
2692 stakes.stake_delegations().iter().collect()
2693 }
2694 }
2695
2696 fn load_vote_and_stake_accounts<F>(
2697 &self,
2698 thread_pool: &ThreadPool,
2699 reward_calc_tracer: Option<F>,
2700 ) -> LoadVoteAndStakeAccountsResult
2701 where
2702 F: Fn(&RewardCalculationEvent) + Send + Sync,
2703 {
2704 let stakes = self.stakes_cache.stakes();
2705 let stake_delegations = self.filter_stake_delegations(&stakes);
2706
2707 fn merge(mut acc: HashSet<Pubkey>, other: HashSet<Pubkey>) -> HashSet<Pubkey> {
2709 if acc.len() < other.len() {
2710 return merge(other, acc);
2711 }
2712 acc.extend(other);
2713 acc
2714 }
2715 let voter_pubkeys = thread_pool.install(|| {
2716 stake_delegations
2717 .par_iter()
2718 .fold(
2719 HashSet::default,
2720 |mut voter_pubkeys, (_stake_pubkey, stake_account)| {
2721 let delegation = stake_account.delegation();
2722 voter_pubkeys.insert(delegation.voter_pubkey);
2723 voter_pubkeys
2724 },
2725 )
2726 .reduce(HashSet::default, merge)
2727 });
2728 let cached_vote_accounts = stakes.vote_accounts();
2730 let solana_vote_program: Pubkey = solana_vote_program::id();
2731 let vote_accounts_cache_miss_count = AtomicUsize::default();
2732 let get_vote_account = |vote_pubkey: &Pubkey| -> Option<VoteAccount> {
2733 if let Some(vote_account) = cached_vote_accounts.get(vote_pubkey) {
2734 return Some(vote_account.clone());
2735 }
2736 let account = self.get_account_with_fixed_root(vote_pubkey)?;
2741 if account.owner() == &solana_vote_program
2742 && VoteState::deserialize(account.data()).is_ok()
2743 {
2744 vote_accounts_cache_miss_count.fetch_add(1, Relaxed);
2745 }
2746 VoteAccount::try_from(account).ok()
2747 };
2748 let invalid_vote_keys = DashMap::<Pubkey, InvalidCacheEntryReason>::new();
2749 let make_vote_delegations_entry = |vote_pubkey| {
2750 let vote_account = match get_vote_account(&vote_pubkey) {
2751 Some(vote_account) => vote_account,
2752 None => {
2753 invalid_vote_keys.insert(vote_pubkey, InvalidCacheEntryReason::Missing);
2754 return None;
2755 }
2756 };
2757 if vote_account.owner() != &solana_vote_program {
2758 invalid_vote_keys.insert(vote_pubkey, InvalidCacheEntryReason::WrongOwner);
2759 return None;
2760 }
2761 let vote_state = match vote_account.vote_state().deref() {
2762 Ok(vote_state) => vote_state.clone(),
2763 Err(_) => {
2764 invalid_vote_keys.insert(vote_pubkey, InvalidCacheEntryReason::BadState);
2765 return None;
2766 }
2767 };
2768 let vote_with_stake_delegations = VoteWithStakeDelegations {
2769 vote_state: Arc::new(vote_state),
2770 vote_account: AccountSharedData::from(vote_account),
2771 delegations: Vec::default(),
2772 };
2773 Some((vote_pubkey, vote_with_stake_delegations))
2774 };
2775 let vote_with_stake_delegations_map: DashMap<Pubkey, VoteWithStakeDelegations> =
2776 thread_pool.install(|| {
2777 voter_pubkeys
2778 .into_par_iter()
2779 .filter_map(make_vote_delegations_entry)
2780 .collect()
2781 });
2782 let push_stake_delegation = |(stake_pubkey, stake_account): (&Pubkey, &StakeAccount<_>)| {
2784 let delegation = stake_account.delegation();
2785 let mut vote_delegations =
2786 match vote_with_stake_delegations_map.get_mut(&delegation.voter_pubkey) {
2787 Some(vote_delegations) => vote_delegations,
2788 None => return,
2789 };
2790 if let Some(reward_calc_tracer) = reward_calc_tracer.as_ref() {
2791 let delegation =
2792 InflationPointCalculationEvent::Delegation(delegation, solana_vote_program);
2793 let event = RewardCalculationEvent::Staking(stake_pubkey, &delegation);
2794 reward_calc_tracer(&event);
2795 }
2796 let stake_account = StakeAccount::from(stake_account.clone());
2797 let stake_delegation = (*stake_pubkey, stake_account);
2798 vote_delegations.delegations.push(stake_delegation);
2799 };
2800 thread_pool.install(|| {
2801 stake_delegations
2802 .into_par_iter()
2803 .for_each(push_stake_delegation);
2804 });
2805 LoadVoteAndStakeAccountsResult {
2806 vote_with_stake_delegations_map,
2807 invalid_vote_keys,
2808 invalid_stake_keys: DashMap::default(),
2809 invalid_cached_vote_accounts: 0,
2810 invalid_cached_stake_accounts: 0,
2811 invalid_cached_stake_accounts_rent_epoch: 0,
2812 vote_accounts_cache_miss_count: vote_accounts_cache_miss_count.into_inner(),
2813 }
2814 }
2815
2816 fn pay_validator_rewards_with_thread_pool(
2819 &mut self,
2820 rewarded_epoch: Epoch,
2821 rewards: u64,
2822 reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
2823 credits_auto_rewind: bool,
2824 thread_pool: &ThreadPool,
2825 metrics: &mut RewardsMetrics,
2826 update_rewards_from_cached_accounts: bool,
2827 ) -> f64 {
2828 let stake_history = self.stakes_cache.stakes().history().clone();
2829 let vote_with_stake_delegations_map = {
2830 let mut m = Measure::start("load_vote_and_stake_accounts_us");
2831 let LoadVoteAndStakeAccountsResult {
2832 vote_with_stake_delegations_map,
2833 invalid_stake_keys,
2834 invalid_vote_keys,
2835 invalid_cached_vote_accounts,
2836 invalid_cached_stake_accounts,
2837 invalid_cached_stake_accounts_rent_epoch,
2838 vote_accounts_cache_miss_count,
2839 } = if update_rewards_from_cached_accounts {
2840 self.load_vote_and_stake_accounts(thread_pool, reward_calc_tracer.as_ref())
2841 } else {
2842 self.load_vote_and_stake_accounts_with_thread_pool(
2843 thread_pool,
2844 reward_calc_tracer.as_ref(),
2845 )
2846 };
2847 m.stop();
2848 metrics
2849 .load_vote_and_stake_accounts_us
2850 .fetch_add(m.as_us(), Relaxed);
2851 metrics.invalid_cached_vote_accounts += invalid_cached_vote_accounts;
2852 metrics.invalid_cached_stake_accounts += invalid_cached_stake_accounts;
2853 metrics.invalid_cached_stake_accounts_rent_epoch +=
2854 invalid_cached_stake_accounts_rent_epoch;
2855 metrics.vote_accounts_cache_miss_count += vote_accounts_cache_miss_count;
2856 self.stakes_cache.handle_invalid_keys(
2857 invalid_stake_keys,
2858 invalid_vote_keys,
2859 self.slot(),
2860 );
2861 vote_with_stake_delegations_map
2862 };
2863
2864 let mut m = Measure::start("calculate_points");
2865 let points: u128 = thread_pool.install(|| {
2866 vote_with_stake_delegations_map
2867 .par_iter()
2868 .map(|entry| {
2869 let VoteWithStakeDelegations {
2870 vote_state,
2871 delegations,
2872 ..
2873 } = entry.value();
2874
2875 delegations
2876 .par_iter()
2877 .map(|(_stake_pubkey, stake_account)| {
2878 stake_state::calculate_points(
2879 stake_account.stake_state(),
2880 vote_state,
2881 Some(&stake_history),
2882 )
2883 .unwrap_or(0)
2884 })
2885 .sum::<u128>()
2886 })
2887 .sum()
2888 });
2889 m.stop();
2890 metrics.calculate_points_us.fetch_add(m.as_us(), Relaxed);
2891
2892 if points == 0 {
2893 return 0.0;
2894 }
2895
2896 let point_value = PointValue { rewards, points };
2898 let vote_account_rewards: DashMap<Pubkey, (AccountSharedData, u8, u64, bool)> =
2899 DashMap::with_capacity(vote_with_stake_delegations_map.len());
2900 let stake_delegation_iterator = vote_with_stake_delegations_map.into_par_iter().flat_map(
2901 |(
2902 vote_pubkey,
2903 VoteWithStakeDelegations {
2904 vote_state,
2905 vote_account,
2906 delegations,
2907 },
2908 )| {
2909 vote_account_rewards
2910 .insert(vote_pubkey, (vote_account, vote_state.commission, 0, false));
2911 delegations
2912 .into_par_iter()
2913 .map(move |delegation| (vote_pubkey, Arc::clone(&vote_state), delegation))
2914 },
2915 );
2916
2917 let mut m = Measure::start("redeem_rewards");
2918 let stake_rewards: Vec<StakeReward> = thread_pool.install(|| {
2919 stake_delegation_iterator
2920 .filter_map(|(vote_pubkey, vote_state, (stake_pubkey, stake_account))| {
2921 let reward_calc_tracer = reward_calc_tracer.as_ref().map(|outer| {
2923 move |inner_event: &_| {
2925 outer(&RewardCalculationEvent::Staking(&stake_pubkey, inner_event))
2926 }
2927 });
2928 let (mut stake_account, stake_state) =
2929 <(AccountSharedData, StakeState)>::from(stake_account);
2930 let redeemed = stake_state::redeem_rewards(
2931 rewarded_epoch,
2932 stake_state,
2933 &mut stake_account,
2934 &vote_state,
2935 &point_value,
2936 Some(&stake_history),
2937 reward_calc_tracer.as_ref(),
2938 credits_auto_rewind,
2939 );
2940 if let Ok((stakers_reward, voters_reward)) = redeemed {
2941 if let Some((
2943 _vote_account,
2944 _commission,
2945 vote_rewards_sum,
2946 vote_needs_store,
2947 )) = vote_account_rewards.get_mut(&vote_pubkey).as_deref_mut()
2948 {
2949 *vote_needs_store = true;
2950 *vote_rewards_sum = vote_rewards_sum.saturating_add(voters_reward);
2951 }
2952
2953 let post_balance = stake_account.lamports();
2954 return Some(StakeReward {
2955 stake_pubkey,
2956 stake_reward_info: RewardInfo {
2957 reward_type: RewardType::Staking,
2958 lamports: i64::try_from(stakers_reward).unwrap(),
2959 post_balance,
2960 commission: Some(vote_state.commission),
2961 },
2962 stake_account,
2963 });
2964 } else {
2965 debug!(
2966 "stake_state::redeem_rewards() failed for {}: {:?}",
2967 stake_pubkey, redeemed
2968 );
2969 }
2970 None
2971 })
2972 .collect()
2973 });
2974 m.stop();
2975 metrics.redeem_rewards_us += m.as_us();
2976
2977 let mut m = Measure::start("store_stake_account");
2980 self.store_accounts((self.slot(), &stake_rewards[..]));
2981 m.stop();
2982 metrics
2983 .store_stake_accounts_us
2984 .fetch_add(m.as_us(), Relaxed);
2985
2986 let mut m = Measure::start("store_vote_accounts");
2987 let mut vote_rewards = vote_account_rewards
2988 .into_iter()
2989 .filter_map(
2990 |(vote_pubkey, (mut vote_account, commission, vote_rewards, vote_needs_store))| {
2991 if let Err(err) = vote_account.checked_add_lamports(vote_rewards) {
2992 debug!("reward redemption failed for {}: {:?}", vote_pubkey, err);
2993 return None;
2994 }
2995
2996 if vote_needs_store {
2997 self.store_account(&vote_pubkey, &vote_account);
2998 }
2999
3000 Some((
3001 vote_pubkey,
3002 RewardInfo {
3003 reward_type: RewardType::Voting,
3004 lamports: vote_rewards as i64,
3005 post_balance: vote_account.lamports(),
3006 commission: Some(commission),
3007 },
3008 ))
3009 },
3010 )
3011 .collect::<Vec<_>>();
3012
3013 m.stop();
3014 metrics.store_vote_accounts_us.fetch_add(m.as_us(), Relaxed);
3015
3016 let additional_reserve = stake_rewards.len() + vote_rewards.len();
3017 {
3018 let mut rewards = self.rewards.write().unwrap();
3019 rewards.reserve(additional_reserve);
3020 rewards.append(&mut vote_rewards);
3021 stake_rewards
3022 .into_iter()
3023 .filter(|x| x.get_stake_reward() > 0)
3024 .for_each(|x| rewards.push((x.stake_pubkey, x.stake_reward_info)));
3025 }
3026
3027 point_value.rewards as f64 / point_value.points as f64
3028 }
3029
3030 fn update_recent_blockhashes_locked(&self, locked_blockhash_queue: &BlockhashQueue) {
3031 #[allow(deprecated)]
3032 self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
3033 let recent_blockhash_iter = locked_blockhash_queue.get_recent_blockhashes();
3034 recent_blockhashes_account::create_account_with_data_and_fields(
3035 recent_blockhash_iter,
3036 self.inherit_specially_retained_account_fields(account),
3037 )
3038 });
3039 }
3040
3041 pub fn update_recent_blockhashes(&self) {
3042 let blockhash_queue = self.blockhash_queue.read().unwrap();
3043 self.update_recent_blockhashes_locked(&blockhash_queue);
3044 }
3045
3046 fn get_timestamp_estimate(
3047 &self,
3048 max_allowable_drift: MaxAllowableDrift,
3049 epoch_start_timestamp: Option<(Slot, UnixTimestamp)>,
3050 ) -> Option<UnixTimestamp> {
3051 let mut get_timestamp_estimate_time = Measure::start("get_timestamp_estimate");
3052 let slots_per_epoch = self.epoch_schedule().slots_per_epoch;
3053 let vote_accounts = self.vote_accounts();
3054 let recent_timestamps = vote_accounts.iter().filter_map(|(pubkey, (_, account))| {
3055 let vote_state = account.vote_state();
3056 let vote_state = vote_state.as_ref().ok()?;
3057 let slot_delta = self.slot().checked_sub(vote_state.last_timestamp.slot)?;
3058 (slot_delta <= slots_per_epoch).then(|| {
3059 (
3060 *pubkey,
3061 (
3062 vote_state.last_timestamp.slot,
3063 vote_state.last_timestamp.timestamp,
3064 ),
3065 )
3066 })
3067 });
3068 let slot_duration = Duration::from_nanos(self.ns_per_slot as u64);
3069 let epoch = self.epoch_schedule().get_epoch(self.slot());
3070 let stakes = self.epoch_vote_accounts(epoch)?;
3071 let stake_weighted_timestamp = calculate_stake_weighted_timestamp(
3072 recent_timestamps,
3073 stakes,
3074 self.slot(),
3075 slot_duration,
3076 epoch_start_timestamp,
3077 max_allowable_drift,
3078 self.feature_set
3079 .is_active(&feature_set::warp_timestamp_again::id()),
3080 );
3081 get_timestamp_estimate_time.stop();
3082 datapoint_info!(
3083 "bank-timestamp",
3084 (
3085 "get_timestamp_estimate_us",
3086 get_timestamp_estimate_time.as_us(),
3087 i64
3088 ),
3089 );
3090 stake_weighted_timestamp
3091 }
3092
3093 fn collect_fees(&self) {
3108 let collector_fees = self.collector_fees.load(Relaxed) as u64;
3109
3110 if collector_fees != 0 {
3111 let (deposit, mut burn) = self.fee_rate_governor.burn(collector_fees);
3112 debug!(
3114 "distributed fee: {} (rounded from: {}, burned: {})",
3115 deposit, collector_fees, burn
3116 );
3117
3118 match self.deposit(&self.collector_id, deposit) {
3119 Ok(post_balance) => {
3120 if deposit != 0 {
3121 self.rewards.write().unwrap().push((
3122 self.collector_id,
3123 RewardInfo {
3124 reward_type: RewardType::Fee,
3125 lamports: deposit as i64,
3126 post_balance,
3127 commission: None,
3128 },
3129 ));
3130 }
3131 }
3132 Err(_) => {
3133 error!(
3134 "Burning {} fee instead of crediting {}",
3135 deposit, self.collector_id
3136 );
3137 inc_new_counter_error!("bank-burned_fee_lamports", deposit as usize);
3138 burn += deposit;
3139 }
3140 }
3141 self.capitalization.fetch_sub(burn, Relaxed);
3142 }
3143 }
3144
3145 pub fn rehash(&self) {
3146 let mut hash = self.hash.write().unwrap();
3147 let new = self.hash_internal_state();
3148 if new != *hash {
3149 warn!("Updating bank hash to {}", new);
3150 *hash = new;
3151 }
3152 }
3153
3154 pub fn freeze(&self) {
3155 let mut hash = self.hash.write().unwrap();
3167 if *hash == Hash::default() {
3168 self.collect_rent_eagerly(false);
3170 self.collect_fees();
3171 self.distribute_rent();
3172 self.update_slot_history();
3173 self.run_incinerator();
3174
3175 self.freeze_started.store(true, Relaxed);
3177 *hash = self.hash_internal_state();
3178 self.rc.accounts.accounts_db.mark_slot_frozen(self.slot());
3179 }
3180 }
3181
3182 pub fn unfreeze_for_ledger_tool(&self) {
3184 self.freeze_started.store(false, Relaxed);
3185 }
3186
3187 pub fn epoch_schedule(&self) -> &EpochSchedule {
3188 &self.epoch_schedule
3189 }
3190
3191 pub fn squash(&self) -> SquashTiming {
3194 self.freeze();
3195
3196 let mut roots = vec![self.slot()];
3198 roots.append(&mut self.parents().iter().map(|p| p.slot()).collect());
3199
3200 let mut total_index_us = 0;
3201 let mut total_cache_us = 0;
3202 let mut total_store_us = 0;
3203
3204 let mut squash_accounts_time = Measure::start("squash_accounts_time");
3205 for slot in roots.iter().rev() {
3206 let add_root_timing = self.rc.accounts.add_root(*slot);
3208 total_index_us += add_root_timing.index_us;
3209 total_cache_us += add_root_timing.cache_us;
3210 total_store_us += add_root_timing.store_us;
3211 }
3212 squash_accounts_time.stop();
3213
3214 *self.rc.parent.write().unwrap() = None;
3215
3216 let mut squash_cache_time = Measure::start("squash_cache_time");
3217 roots
3218 .iter()
3219 .for_each(|slot| self.status_cache.write().unwrap().add_root(*slot));
3220 squash_cache_time.stop();
3221
3222 SquashTiming {
3223 squash_accounts_ms: squash_accounts_time.as_ms(),
3224 squash_accounts_index_ms: total_index_us / 1000,
3225 squash_accounts_cache_ms: total_cache_us / 1000,
3226 squash_accounts_store_ms: total_store_us / 1000,
3227
3228 squash_cache_ms: squash_cache_time.as_ms(),
3229 }
3230 }
3231
3232 pub fn parent(&self) -> Option<Arc<Bank>> {
3234 self.rc.parent.read().unwrap().clone()
3235 }
3236
3237 pub fn parent_slot(&self) -> Slot {
3238 self.parent_slot
3239 }
3240
3241 pub fn parent_hash(&self) -> Hash {
3242 self.parent_hash
3243 }
3244
3245 fn process_genesis_config(&mut self, genesis_config: &GenesisConfig) {
3246 self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
3248 self.fee_calculator = self.fee_rate_governor.create_fee_calculator();
3249
3250 for (pubkey, account) in genesis_config.accounts.iter() {
3251 assert!(
3252 self.get_account(pubkey).is_none(),
3253 "{} repeated in genesis config",
3254 pubkey
3255 );
3256 self.store_account(pubkey, account);
3257 self.capitalization.fetch_add(account.lamports(), Relaxed);
3258 self.accounts_data_size_initial += account.data().len() as u64;
3259 }
3260 self.update_fees();
3263
3264 for (pubkey, account) in genesis_config.rewards_pools.iter() {
3265 assert!(
3266 self.get_account(pubkey).is_none(),
3267 "{} repeated in genesis config",
3268 pubkey
3269 );
3270 self.store_account(pubkey, account);
3271 self.accounts_data_size_initial += account.data().len() as u64;
3272 }
3273
3274 self.collector_id = self
3276 .stakes_cache
3277 .stakes()
3278 .highest_staked_node()
3279 .unwrap_or_default();
3280
3281 self.blockhash_queue.write().unwrap().genesis_hash(
3282 &genesis_config.hash(),
3283 self.fee_rate_governor.lamports_per_signature,
3284 );
3285
3286 self.hashes_per_tick = genesis_config.hashes_per_tick();
3287 self.ticks_per_slot = genesis_config.ticks_per_slot();
3288 self.ns_per_slot = genesis_config.ns_per_slot();
3289 self.genesis_creation_time = genesis_config.creation_time;
3290 self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
3291 self.slots_per_year = genesis_config.slots_per_year();
3292
3293 self.epoch_schedule = genesis_config.epoch_schedule;
3294
3295 self.inflation = Arc::new(RwLock::new(genesis_config.inflation));
3296
3297 self.rent_collector = RentCollector::new(
3298 self.epoch,
3299 *self.epoch_schedule(),
3300 self.slots_per_year,
3301 genesis_config.rent,
3302 );
3303
3304 for (name, program_id) in &genesis_config.native_instruction_processors {
3306 self.add_builtin_account(name, program_id, false);
3307 }
3308 }
3309
3310 fn burn_and_purge_account(&self, program_id: &Pubkey, mut account: AccountSharedData) {
3311 let old_data_size = account.data().len();
3312 self.capitalization.fetch_sub(account.lamports(), Relaxed);
3313 account.set_lamports(0);
3316 account.data_as_mut_slice().fill(0);
3317 self.store_account(program_id, &account);
3318 self.calculate_and_update_accounts_data_size_delta_off_chain(old_data_size, 0);
3319 }
3320
3321 pub fn add_builtin_account(&self, name: &str, program_id: &Pubkey, must_replace: bool) {
3324 let existing_genuine_program =
3325 self.get_account_with_fixed_root(program_id)
3326 .and_then(|account| {
3327 if native_loader::check_id(account.owner()) {
3331 Some(account)
3332 } else {
3333 self.burn_and_purge_account(program_id, account);
3335 None
3336 }
3337 });
3338
3339 if must_replace {
3340 match &existing_genuine_program {
3342 None => panic!(
3343 "There is no account to replace with builtin program ({}, {}).",
3344 name, program_id
3345 ),
3346 Some(account) => {
3347 if *name == String::from_utf8_lossy(account.data()) {
3348 return;
3350 }
3351 }
3352 }
3353 } else {
3354 if existing_genuine_program.is_some() {
3356 return;
3358 }
3359 }
3360
3361 assert!(
3362 !self.freeze_started(),
3363 "Can't change frozen bank by adding not-existing new builtin program ({}, {}). \
3364 Maybe, inconsistent program activation is detected on snapshot restore?",
3365 name,
3366 program_id
3367 );
3368
3369 let account = native_loader::create_loadable_account_with_fields(
3371 name,
3372 self.inherit_specially_retained_account_fields(&existing_genuine_program),
3373 );
3374 self.store_account_and_update_capitalization(program_id, &account);
3375 }
3376
3377 pub fn add_precompiled_account(&self, program_id: &Pubkey) {
3379 self.add_precompiled_account_with_owner(program_id, native_loader::id())
3380 }
3381
3382 fn add_precompiled_account_with_owner(&self, program_id: &Pubkey, owner: Pubkey) {
3384 if let Some(account) = self.get_account_with_fixed_root(program_id) {
3385 if account.executable() {
3386 return;
3388 } else {
3389 self.burn_and_purge_account(program_id, account);
3391 }
3392 };
3393
3394 assert!(
3395 !self.freeze_started(),
3396 "Can't change frozen bank by adding not-existing new precompiled program ({}). \
3397 Maybe, inconsistent program activation is detected on snapshot restore?",
3398 program_id
3399 );
3400
3401 let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None);
3403 let account = AccountSharedData::from(Account {
3404 lamports,
3405 owner,
3406 data: vec![],
3407 executable: true,
3408 rent_epoch,
3409 });
3410 self.store_account_and_update_capitalization(program_id, &account);
3411 }
3412
3413 pub fn set_rent_burn_percentage(&mut self, burn_percent: u8) {
3414 self.rent_collector.rent.burn_percent = burn_percent;
3415 }
3416
3417 pub fn set_hashes_per_tick(&mut self, hashes_per_tick: Option<u64>) {
3418 self.hashes_per_tick = hashes_per_tick;
3419 }
3420
3421 pub fn last_blockhash(&self) -> Hash {
3423 self.blockhash_queue.read().unwrap().last_hash()
3424 }
3425
3426 pub fn last_blockhash_and_lamports_per_signature(&self) -> (Hash, u64) {
3427 let blockhash_queue = self.blockhash_queue.read().unwrap();
3428 let last_hash = blockhash_queue.last_hash();
3429 let last_lamports_per_signature = blockhash_queue
3430 .get_lamports_per_signature(&last_hash)
3431 .unwrap(); (last_hash, last_lamports_per_signature)
3433 }
3434
3435 pub fn is_blockhash_valid(&self, hash: &Hash) -> bool {
3436 let blockhash_queue = self.blockhash_queue.read().unwrap();
3437 blockhash_queue.is_hash_valid(hash)
3438 }
3439
3440 pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
3441 self.rent_collector.rent.minimum_balance(data_len).max(1)
3442 }
3443
3444 pub fn get_lamports_per_signature(&self) -> u64 {
3445 self.fee_rate_governor.lamports_per_signature
3446 }
3447
3448 pub fn get_lamports_per_signature_for_blockhash(&self, hash: &Hash) -> Option<u64> {
3449 let blockhash_queue = self.blockhash_queue.read().unwrap();
3450 blockhash_queue.get_lamports_per_signature(hash)
3451 }
3452
3453 #[deprecated(since = "1.9.0", note = "Please use `get_fee_for_message` instead")]
3454 pub fn get_fee_rate_governor(&self) -> &FeeRateGovernor {
3455 &self.fee_rate_governor
3456 }
3457
3458 pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option<u64> {
3459 let lamports_per_signature = {
3460 let blockhash_queue = self.blockhash_queue.read().unwrap();
3461 blockhash_queue.get_lamports_per_signature(message.recent_blockhash())
3462 }
3463 .or_else(|| {
3464 self.check_message_for_nonce(message)
3465 .and_then(|(address, account)| {
3466 NoncePartial::new(address, account).lamports_per_signature()
3467 })
3468 })?;
3469 Some(Self::calculate_fee(
3470 message,
3471 lamports_per_signature,
3472 &self.fee_structure,
3473 self.feature_set
3474 .is_active(&add_set_compute_unit_price_ix::id()),
3475 self.feature_set
3476 .is_active(&use_default_units_in_fee_calculation::id()),
3477 self.enable_request_heap_frame_ix(),
3478 ))
3479 }
3480
3481 pub fn get_startup_verification_complete(&self) -> &Arc<AtomicBool> {
3482 &self
3483 .rc
3484 .accounts
3485 .accounts_db
3486 .verify_accounts_hash_in_bg
3487 .verified
3488 }
3489
3490 pub fn is_startup_verification_complete(&self) -> bool {
3491 self.rc
3492 .accounts
3493 .accounts_db
3494 .verify_accounts_hash_in_bg
3495 .check_complete()
3496 }
3497
3498 pub fn set_startup_verification_complete(&self) {
3501 self.rc
3502 .accounts
3503 .accounts_db
3504 .verify_accounts_hash_in_bg
3505 .verification_complete()
3506 }
3507
3508 pub fn get_fee_for_message_with_lamports_per_signature(
3509 &self,
3510 message: &SanitizedMessage,
3511 lamports_per_signature: u64,
3512 ) -> u64 {
3513 Self::calculate_fee(
3514 message,
3515 lamports_per_signature,
3516 &self.fee_structure,
3517 self.feature_set
3518 .is_active(&add_set_compute_unit_price_ix::id()),
3519 self.feature_set
3520 .is_active(&use_default_units_in_fee_calculation::id()),
3521 self.enable_request_heap_frame_ix(),
3522 )
3523 }
3524
3525 #[deprecated(
3526 since = "1.6.11",
3527 note = "Please use `get_blockhash_last_valid_block_height`"
3528 )]
3529 pub fn get_blockhash_last_valid_slot(&self, blockhash: &Hash) -> Option<Slot> {
3530 let blockhash_queue = self.blockhash_queue.read().unwrap();
3531 blockhash_queue
3534 .get_hash_age(blockhash)
3535 .map(|age| self.slot + blockhash_queue.get_max_age() as u64 - age)
3536 }
3537
3538 pub fn get_blockhash_last_valid_block_height(&self, blockhash: &Hash) -> Option<Slot> {
3539 let blockhash_queue = self.blockhash_queue.read().unwrap();
3540 blockhash_queue
3543 .get_hash_age(blockhash)
3544 .map(|age| self.block_height + blockhash_queue.get_max_age() as u64 - age)
3545 }
3546
3547 pub fn confirmed_last_blockhash(&self) -> Hash {
3548 const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
3549
3550 let parents = self.parents();
3551 if parents.is_empty() {
3552 self.last_blockhash()
3553 } else {
3554 let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
3555 parents[index].last_blockhash()
3556 }
3557 }
3558
3559 pub fn clear_signatures(&self) {
3561 self.status_cache.write().unwrap().clear();
3562 }
3563
3564 pub fn clear_slot_signatures(&self, slot: Slot) {
3565 self.status_cache.write().unwrap().clear_slot_entries(slot);
3566 }
3567
3568 fn update_transaction_statuses(
3569 &self,
3570 sanitized_txs: &[SanitizedTransaction],
3571 execution_results: &[TransactionExecutionResult],
3572 ) {
3573 let mut status_cache = self.status_cache.write().unwrap();
3574 assert_eq!(sanitized_txs.len(), execution_results.len());
3575 for (tx, execution_result) in sanitized_txs.iter().zip(execution_results) {
3576 if let Some(details) = execution_result.details() {
3577 status_cache.insert(
3580 tx.message().recent_blockhash(),
3581 tx.message_hash(),
3582 self.slot(),
3583 details.status.clone(),
3584 );
3585 status_cache.insert(
3589 tx.message().recent_blockhash(),
3590 tx.signature(),
3591 self.slot(),
3592 details.status.clone(),
3593 );
3594 }
3595 }
3596 }
3597
3598 pub fn register_recent_blockhash(&self, blockhash: &Hash) {
3602 let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3606 w_blockhash_queue.register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3607 self.update_recent_blockhashes_locked(&w_blockhash_queue);
3608 }
3609
3610 pub fn register_tick(&self, hash: &Hash) {
3617 assert!(
3618 !self.freeze_started(),
3619 "register_tick() working on a bank that is already frozen or is undergoing freezing!"
3620 );
3621
3622 inc_new_counter_debug!("bank-register_tick-registered", 1);
3623 if self.is_block_boundary(self.tick_height.load(Relaxed) + 1) {
3624 self.register_recent_blockhash(hash);
3625 }
3626
3627 self.tick_height.fetch_add(1, Relaxed);
3633 }
3634
3635 pub fn is_complete(&self) -> bool {
3636 self.tick_height() == self.max_tick_height()
3637 }
3638
3639 pub fn is_block_boundary(&self, tick_height: u64) -> bool {
3640 if self
3641 .feature_set
3642 .is_active(&feature_set::fix_recent_blockhashes::id())
3643 {
3644 tick_height == self.max_tick_height
3645 } else {
3646 tick_height % self.ticks_per_slot == 0
3647 }
3648 }
3649
3650 pub fn get_transaction_account_lock_limit(&self) -> usize {
3652 if self
3653 .feature_set
3654 .is_active(&feature_set::increase_tx_account_lock_limit::id())
3655 {
3656 MAX_TX_ACCOUNT_LOCKS
3657 } else {
3658 64
3659 }
3660 }
3661
3662 pub fn prepare_batch_for_tests(&self, txs: Vec<Transaction>) -> TransactionBatch {
3664 let sanitized_txs = txs
3665 .into_iter()
3666 .map(SanitizedTransaction::from_transaction_for_tests)
3667 .collect::<Vec<_>>();
3668 let lock_results = self.rc.accounts.lock_accounts(
3669 sanitized_txs.iter(),
3670 self.get_transaction_account_lock_limit(),
3671 );
3672 TransactionBatch::new(lock_results, self, Cow::Owned(sanitized_txs))
3673 }
3674
3675 pub fn prepare_entry_batch(&self, txs: Vec<VersionedTransaction>) -> Result<TransactionBatch> {
3678 let sanitized_txs = txs
3679 .into_iter()
3680 .map(|tx| {
3681 SanitizedTransaction::try_create(
3682 tx,
3683 MessageHash::Compute,
3684 None,
3685 self,
3686 self.feature_set
3687 .is_active(&feature_set::require_static_program_ids_in_transaction::ID),
3688 )
3689 })
3690 .collect::<Result<Vec<_>>>()?;
3691 let lock_results = self.rc.accounts.lock_accounts(
3692 sanitized_txs.iter(),
3693 self.get_transaction_account_lock_limit(),
3694 );
3695 Ok(TransactionBatch::new(
3696 lock_results,
3697 self,
3698 Cow::Owned(sanitized_txs),
3699 ))
3700 }
3701
3702 pub fn prepare_sanitized_batch<'a, 'b>(
3704 &'a self,
3705 txs: &'b [SanitizedTransaction],
3706 ) -> TransactionBatch<'a, 'b> {
3707 let lock_results = self
3708 .rc
3709 .accounts
3710 .lock_accounts(txs.iter(), self.get_transaction_account_lock_limit());
3711 TransactionBatch::new(lock_results, self, Cow::Borrowed(txs))
3712 }
3713
3714 pub fn prepare_sanitized_batch_with_results<'a, 'b>(
3717 &'a self,
3718 transactions: &'b [SanitizedTransaction],
3719 transaction_results: impl Iterator<Item = &'b Result<()>>,
3720 ) -> TransactionBatch<'a, 'b> {
3721 let lock_results = self.rc.accounts.lock_accounts_with_results(
3723 transactions.iter(),
3724 transaction_results,
3725 self.get_transaction_account_lock_limit(),
3726 );
3727 TransactionBatch::new(lock_results, self, Cow::Borrowed(transactions))
3728 }
3729
3730 pub(crate) fn prepare_simulation_batch<'a>(
3732 &'a self,
3733 transaction: SanitizedTransaction,
3734 ) -> TransactionBatch<'a, '_> {
3735 let lock_result = transaction
3736 .get_account_locks(self.get_transaction_account_lock_limit())
3737 .map(|_| ());
3738 let mut batch =
3739 TransactionBatch::new(vec![lock_result], self, Cow::Owned(vec![transaction]));
3740 batch.set_needs_unlock(false);
3741 batch
3742 }
3743
3744 pub fn simulate_transaction(
3746 &self,
3747 transaction: SanitizedTransaction,
3748 ) -> TransactionSimulationResult {
3749 assert!(self.is_frozen(), "simulation bank must be frozen");
3750
3751 self.simulate_transaction_unchecked(transaction)
3752 }
3753
3754 pub fn simulate_transaction_unchecked(
3757 &self,
3758 transaction: SanitizedTransaction,
3759 ) -> TransactionSimulationResult {
3760 let account_keys = transaction.message().account_keys();
3761 let number_of_accounts = account_keys.len();
3762 let account_overrides = self.get_account_overrides_for_simulation(&account_keys);
3763 let batch = self.prepare_simulation_batch(transaction);
3764 let mut timings = ExecuteTimings::default();
3765
3766 let LoadAndExecuteTransactionsOutput {
3767 loaded_transactions,
3768 mut execution_results,
3769 ..
3770 } = self.load_and_execute_transactions(
3771 &batch,
3772 MAX_PROCESSING_AGE - MAX_TRANSACTION_FORWARDING_DELAY,
3776 false,
3777 true,
3778 true,
3779 &mut timings,
3780 Some(&account_overrides),
3781 None,
3782 );
3783
3784 let post_simulation_accounts = loaded_transactions
3785 .into_iter()
3786 .next()
3787 .unwrap()
3788 .0
3789 .ok()
3790 .map(|loaded_transaction| {
3791 loaded_transaction
3792 .accounts
3793 .into_iter()
3794 .take(number_of_accounts)
3795 .collect::<Vec<_>>()
3796 })
3797 .unwrap_or_default();
3798
3799 let units_consumed = timings
3800 .details
3801 .per_program_timings
3802 .iter()
3803 .fold(0, |acc: u64, (_, program_timing)| {
3804 acc.saturating_add(program_timing.accumulated_units)
3805 });
3806
3807 debug!("simulate_transaction: {:?}", timings);
3808
3809 let execution_result = execution_results.pop().unwrap();
3810 let flattened_result = execution_result.flattened_result();
3811 let (logs, return_data) = match execution_result {
3812 TransactionExecutionResult::Executed { details, .. } => {
3813 (details.log_messages, details.return_data)
3814 }
3815 TransactionExecutionResult::NotExecuted(_) => (None, None),
3816 };
3817 let logs = logs.unwrap_or_default();
3818
3819 TransactionSimulationResult {
3820 result: flattened_result,
3821 logs,
3822 post_simulation_accounts,
3823 units_consumed,
3824 return_data,
3825 }
3826 }
3827
3828 fn get_account_overrides_for_simulation(&self, account_keys: &AccountKeys) -> AccountOverrides {
3829 let mut account_overrides = AccountOverrides::default();
3830 let slot_history_id = sysvar::slot_history::id();
3831 if account_keys.iter().any(|pubkey| *pubkey == slot_history_id) {
3832 let current_account = self.get_account_with_fixed_root(&slot_history_id);
3833 let slot_history = current_account
3834 .as_ref()
3835 .map(|account| from_account::<SlotHistory, _>(account).unwrap())
3836 .unwrap_or_default();
3837 if slot_history.check(self.slot()) == Check::Found {
3838 let ancestors = Ancestors::from(self.proper_ancestors().collect::<Vec<_>>());
3839 if let Some((account, _)) =
3840 self.load_slow_with_fixed_root(&ancestors, &slot_history_id)
3841 {
3842 account_overrides.set_slot_history(Some(account));
3843 }
3844 }
3845 }
3846 account_overrides
3847 }
3848
3849 pub fn unlock_accounts(&self, batch: &mut TransactionBatch) {
3850 if batch.needs_unlock() {
3851 batch.set_needs_unlock(false);
3852 self.rc
3853 .accounts
3854 .unlock_accounts(batch.sanitized_transactions().iter(), batch.lock_results())
3855 }
3856 }
3857
3858 pub fn remove_unrooted_slots(&self, slots: &[(Slot, BankId)]) {
3859 self.rc.accounts.accounts_db.remove_unrooted_slots(slots)
3860 }
3861
3862 pub fn set_shrink_paths(&self, paths: Vec<PathBuf>) {
3863 self.rc.accounts.accounts_db.set_shrink_paths(paths);
3864 }
3865
3866 fn check_age<'a>(
3867 &self,
3868 txs: impl Iterator<Item = &'a SanitizedTransaction>,
3869 lock_results: &[Result<()>],
3870 max_age: usize,
3871 error_counters: &mut TransactionErrorMetrics,
3872 ) -> Vec<TransactionCheckResult> {
3873 let hash_queue = self.blockhash_queue.read().unwrap();
3874 let last_blockhash = hash_queue.last_hash();
3875 let next_durable_nonce = DurableNonce::from_blockhash(&last_blockhash);
3876
3877 txs.zip(lock_results)
3878 .map(|(tx, lock_res)| match lock_res {
3879 Ok(()) => {
3880 let recent_blockhash = tx.message().recent_blockhash();
3881 if hash_queue.is_hash_valid_for_age(recent_blockhash, max_age) {
3882 (Ok(()), None)
3883 } else if let Some((address, account)) =
3884 self.check_transaction_for_nonce(tx, &next_durable_nonce)
3885 {
3886 (Ok(()), Some(NoncePartial::new(address, account)))
3887 } else {
3888 error_counters.blockhash_not_found += 1;
3889 (Err(TransactionError::BlockhashNotFound), None)
3890 }
3891 }
3892 Err(e) => (Err(e.clone()), None),
3893 })
3894 .collect()
3895 }
3896
3897 fn is_transaction_already_processed(
3898 &self,
3899 sanitized_tx: &SanitizedTransaction,
3900 status_cache: &BankStatusCache,
3901 ) -> bool {
3902 let key = sanitized_tx.message_hash();
3903 let transaction_blockhash = sanitized_tx.message().recent_blockhash();
3904 status_cache
3905 .get_status(key, transaction_blockhash, &self.ancestors)
3906 .is_some()
3907 }
3908
3909 fn check_status_cache(
3910 &self,
3911 sanitized_txs: &[SanitizedTransaction],
3912 lock_results: Vec<TransactionCheckResult>,
3913 error_counters: &mut TransactionErrorMetrics,
3914 ) -> Vec<TransactionCheckResult> {
3915 let rcache = self.status_cache.read().unwrap();
3916 sanitized_txs
3917 .iter()
3918 .zip(lock_results)
3919 .map(|(sanitized_tx, (lock_result, nonce))| {
3920 if lock_result.is_ok()
3921 && self.is_transaction_already_processed(sanitized_tx, &rcache)
3922 {
3923 error_counters.already_processed += 1;
3924 return (Err(TransactionError::AlreadyProcessed), None);
3925 }
3926
3927 (lock_result, nonce)
3928 })
3929 .collect()
3930 }
3931
3932 pub fn get_hash_age(&self, hash: &Hash) -> Option<u64> {
3933 self.blockhash_queue.read().unwrap().get_hash_age(hash)
3934 }
3935
3936 pub fn is_hash_valid_for_age(&self, hash: &Hash, max_age: usize) -> bool {
3937 self.blockhash_queue
3938 .read()
3939 .unwrap()
3940 .is_hash_valid_for_age(hash, max_age)
3941 }
3942
3943 fn check_message_for_nonce(&self, message: &SanitizedMessage) -> Option<TransactionAccount> {
3944 let nonce_address = message.get_durable_nonce()?;
3945 let nonce_account = self.get_account_with_fixed_root(nonce_address)?;
3946 let nonce_data =
3947 nonce_account::verify_nonce_account(&nonce_account, message.recent_blockhash())?;
3948
3949 let nonce_is_authorized = message
3950 .get_ix_signers(NONCED_TX_MARKER_IX_INDEX as usize)
3951 .any(|signer| signer == &nonce_data.authority);
3952 if !nonce_is_authorized {
3953 return None;
3954 }
3955
3956 Some((*nonce_address, nonce_account))
3957 }
3958
3959 fn check_transaction_for_nonce(
3960 &self,
3961 tx: &SanitizedTransaction,
3962 next_durable_nonce: &DurableNonce,
3963 ) -> Option<TransactionAccount> {
3964 let nonce_is_advanceable = tx.message().recent_blockhash() != next_durable_nonce.as_hash();
3965 if nonce_is_advanceable {
3966 self.check_message_for_nonce(tx.message())
3967 } else {
3968 None
3969 }
3970 }
3971
3972 pub fn check_transactions(
3973 &self,
3974 sanitized_txs: &[SanitizedTransaction],
3975 lock_results: &[Result<()>],
3976 max_age: usize,
3977 error_counters: &mut TransactionErrorMetrics,
3978 ) -> Vec<TransactionCheckResult> {
3979 let age_results =
3980 self.check_age(sanitized_txs.iter(), lock_results, max_age, error_counters);
3981 self.check_status_cache(sanitized_txs, age_results, error_counters)
3982 }
3983
3984 pub fn collect_balances(&self, batch: &TransactionBatch) -> TransactionBalances {
3985 let mut balances: TransactionBalances = vec![];
3986 for transaction in batch.sanitized_transactions() {
3987 let mut transaction_balances: Vec<u64> = vec![];
3988 for account_key in transaction.message().account_keys().iter() {
3989 transaction_balances.push(self.get_balance(account_key));
3990 }
3991 balances.push(transaction_balances);
3992 }
3993 balances
3994 }
3995
3996 fn get_executors(&self, accounts: &[TransactionAccount]) -> Rc<RefCell<Executors>> {
3998 let executable_keys: Vec<_> = accounts
3999 .iter()
4000 .filter_map(|(key, account)| {
4001 if account.executable() && !native_loader::check_id(account.owner()) {
4002 Some(key)
4003 } else {
4004 None
4005 }
4006 })
4007 .collect();
4008
4009 if executable_keys.is_empty() {
4010 return Rc::new(RefCell::new(Executors::default()));
4011 }
4012
4013 let executors = {
4014 let cache = self.cached_executors.read().unwrap();
4015 executable_keys
4016 .into_iter()
4017 .filter_map(|key| {
4018 cache
4019 .get(key)
4020 .map(|executor| (*key, TransactionExecutor::new_cached(executor)))
4021 })
4022 .collect()
4023 };
4024
4025 Rc::new(RefCell::new(executors))
4026 }
4027
4028 fn store_missing_executors(&self, executors: &RefCell<Executors>) {
4030 self.store_executors_internal(executors, |e| e.is_missing())
4031 }
4032
4033 fn store_updated_executors(&self, executors: &RefCell<Executors>) {
4035 self.store_executors_internal(executors, |e| e.is_updated())
4036 }
4037
4038 fn store_executors_internal(
4040 &self,
4041 executors: &RefCell<Executors>,
4042 selector: impl Fn(&TransactionExecutor) -> bool,
4043 ) {
4044 let executors = executors.borrow();
4045 let dirty_executors: Vec<_> = executors
4046 .iter()
4047 .filter_map(|(key, executor)| selector(executor).then(|| (key, executor.get())))
4048 .collect();
4049
4050 if !dirty_executors.is_empty() {
4051 self.cached_executors.write().unwrap().put(&dirty_executors);
4052 }
4053 }
4054
4055 fn remove_executor(&self, pubkey: &Pubkey) {
4057 let _ = self.cached_executors.write().unwrap().remove(pubkey);
4058 }
4059
4060 pub fn clear_executors(&self) {
4061 self.cached_executors.write().unwrap().clear();
4062 }
4063
4064 #[allow(clippy::too_many_arguments)]
4067 fn execute_loaded_transaction(
4068 &self,
4069 tx: &SanitizedTransaction,
4070 loaded_transaction: &mut LoadedTransaction,
4071 compute_budget: ComputeBudget,
4072 durable_nonce_fee: Option<DurableNonceFee>,
4073 enable_cpi_recording: bool,
4074 enable_log_recording: bool,
4075 enable_return_data_recording: bool,
4076 timings: &mut ExecuteTimings,
4077 error_counters: &mut TransactionErrorMetrics,
4078 log_messages_bytes_limit: Option<usize>,
4079 ) -> TransactionExecutionResult {
4080 let mut get_executors_time = Measure::start("get_executors_time");
4081 let executors = self.get_executors(&loaded_transaction.accounts);
4082 get_executors_time.stop();
4083 saturating_add_assign!(
4084 timings.execute_accessories.get_executors_us,
4085 get_executors_time.as_us()
4086 );
4087
4088 let prev_accounts_data_len = self.load_accounts_data_size();
4089 let transaction_accounts = std::mem::take(&mut loaded_transaction.accounts);
4090 let mut transaction_context = TransactionContext::new(
4091 transaction_accounts,
4092 if self
4093 .feature_set
4094 .is_active(&enable_early_verification_of_account_modifications::id())
4095 {
4096 Some(self.rent_collector.rent)
4097 } else {
4098 None
4099 },
4100 compute_budget.max_invoke_depth.saturating_add(1),
4101 tx.message().instructions().len(),
4102 );
4103
4104 let pre_account_state_info =
4105 self.get_transaction_account_state_info(&transaction_context, tx.message());
4106
4107 let log_collector = if enable_log_recording {
4108 match log_messages_bytes_limit {
4109 None => Some(LogCollector::new_ref()),
4110 Some(log_messages_bytes_limit) => Some(LogCollector::new_ref_with_limit(Some(
4111 log_messages_bytes_limit,
4112 ))),
4113 }
4114 } else {
4115 None
4116 };
4117
4118 let (blockhash, lamports_per_signature) = self.last_blockhash_and_lamports_per_signature();
4119
4120 let mut executed_units = 0u64;
4121
4122 let mut process_message_time = Measure::start("process_message_time");
4123 let process_result = MessageProcessor::process_message(
4124 &self.builtin_programs.vec,
4125 tx.message(),
4126 &loaded_transaction.program_indices,
4127 &mut transaction_context,
4128 self.rent_collector.rent,
4129 log_collector.clone(),
4130 executors.clone(),
4131 self.feature_set.clone(),
4132 compute_budget,
4133 timings,
4134 &*self.sysvar_cache.read().unwrap(),
4135 blockhash,
4136 lamports_per_signature,
4137 prev_accounts_data_len,
4138 &mut executed_units,
4139 );
4140 process_message_time.stop();
4141
4142 saturating_add_assign!(
4143 timings.execute_accessories.process_message_us,
4144 process_message_time.as_us()
4145 );
4146
4147 let mut store_missing_executors_time = Measure::start("store_missing_executors_time");
4148 self.store_missing_executors(&executors);
4149 store_missing_executors_time.stop();
4150 saturating_add_assign!(
4151 timings.execute_accessories.update_executors_us,
4152 store_missing_executors_time.as_us()
4153 );
4154
4155 let status = process_result
4156 .and_then(|info| {
4157 let post_account_state_info =
4158 self.get_transaction_account_state_info(&transaction_context, tx.message());
4159 self.verify_transaction_account_state_changes(
4160 &pre_account_state_info,
4161 &post_account_state_info,
4162 &transaction_context,
4163 )
4164 .map(|_| info)
4165 })
4166 .map_err(|err| {
4167 match err {
4168 TransactionError::InvalidRentPayingAccount
4169 | TransactionError::InsufficientFundsForRent { .. } => {
4170 error_counters.invalid_rent_paying_account += 1;
4171 }
4172 TransactionError::InvalidAccountIndex => {
4173 error_counters.invalid_account_index += 1;
4174 }
4175 _ => {
4176 error_counters.instruction_error += 1;
4177 }
4178 }
4179 err
4180 });
4181 let mut accounts_data_len_delta = status
4182 .as_ref()
4183 .map_or(0, |info| info.accounts_data_len_delta);
4184 let status = status.map(|_| ());
4185
4186 let log_messages: Option<TransactionLogMessages> =
4187 log_collector.and_then(|log_collector| {
4188 Rc::try_unwrap(log_collector)
4189 .map(|log_collector| log_collector.into_inner().into())
4190 .ok()
4191 });
4192
4193 let ExecutionRecord {
4194 accounts,
4195 instruction_trace,
4196 mut return_data,
4197 changed_account_count,
4198 total_size_of_all_accounts,
4199 total_size_of_touched_accounts,
4200 accounts_resize_delta,
4201 } = transaction_context.into();
4202 loaded_transaction.accounts = accounts;
4203 if self
4204 .feature_set
4205 .is_active(&enable_early_verification_of_account_modifications::id())
4206 {
4207 saturating_add_assign!(
4208 timings.details.total_account_count,
4209 loaded_transaction.accounts.len() as u64
4210 );
4211 saturating_add_assign!(timings.details.changed_account_count, changed_account_count);
4212 saturating_add_assign!(
4213 timings.details.total_data_size,
4214 total_size_of_all_accounts as usize
4215 );
4216 saturating_add_assign!(
4217 timings.details.data_size_changed,
4218 total_size_of_touched_accounts as usize
4219 );
4220 accounts_data_len_delta = status.as_ref().map_or(0, |_| accounts_resize_delta);
4221 }
4222
4223 let inner_instructions = if enable_cpi_recording {
4224 Some(inner_instructions_list_from_instruction_trace(
4225 &instruction_trace,
4226 ))
4227 } else {
4228 None
4229 };
4230
4231 let return_data = if enable_return_data_recording {
4232 if let Some(end_index) = return_data.data.iter().rposition(|&x| x != 0) {
4233 let end_index = end_index.saturating_add(1);
4234 return_data.data.truncate(end_index);
4235 Some(return_data)
4236 } else {
4237 None
4238 }
4239 } else {
4240 None
4241 };
4242
4243 TransactionExecutionResult::Executed {
4244 details: TransactionExecutionDetails {
4245 status,
4246 log_messages,
4247 inner_instructions,
4248 durable_nonce_fee,
4249 return_data,
4250 executed_units,
4251 accounts_data_len_delta,
4252 },
4253 executors,
4254 }
4255 }
4256
4257 fn enable_request_heap_frame_ix(&self) -> bool {
4261 self.feature_set
4262 .is_active(&enable_request_heap_frame_ix::id())
4263 || self.cluster_type() != ClusterType::MainnetBeta
4264 }
4265
4266 #[allow(clippy::type_complexity)]
4267 pub fn load_and_execute_transactions(
4268 &self,
4269 batch: &TransactionBatch,
4270 max_age: usize,
4271 enable_cpi_recording: bool,
4272 enable_log_recording: bool,
4273 enable_return_data_recording: bool,
4274 timings: &mut ExecuteTimings,
4275 account_overrides: Option<&AccountOverrides>,
4276 log_messages_bytes_limit: Option<usize>,
4277 ) -> LoadAndExecuteTransactionsOutput {
4278 let sanitized_txs = batch.sanitized_transactions();
4279 debug!("processing transactions: {}", sanitized_txs.len());
4280 inc_new_counter_info!("bank-process_transactions", sanitized_txs.len());
4281 let mut error_counters = TransactionErrorMetrics::default();
4282
4283 let retryable_transaction_indexes: Vec<_> = batch
4284 .lock_results()
4285 .iter()
4286 .enumerate()
4287 .filter_map(|(index, res)| match res {
4288 Err(TransactionError::AccountInUse) => {
4290 error_counters.account_in_use += 1;
4291 Some(index)
4292 }
4293 Err(TransactionError::WouldExceedMaxBlockCostLimit) => {
4294 error_counters.would_exceed_max_block_cost_limit += 1;
4295 Some(index)
4296 }
4297 Err(TransactionError::WouldExceedMaxVoteCostLimit) => {
4298 error_counters.would_exceed_max_vote_cost_limit += 1;
4299 Some(index)
4300 }
4301 Err(TransactionError::WouldExceedMaxAccountCostLimit) => {
4302 error_counters.would_exceed_max_account_cost_limit += 1;
4303 Some(index)
4304 }
4305 Err(TransactionError::WouldExceedAccountDataBlockLimit) => {
4306 error_counters.would_exceed_account_data_block_limit += 1;
4307 Some(index)
4308 }
4309 Err(TransactionError::TooManyAccountLocks) => {
4311 error_counters.too_many_account_locks += 1;
4312 None
4313 }
4314 Err(_) => None,
4315 Ok(_) => None,
4316 })
4317 .collect();
4318
4319 let mut check_time = Measure::start("check_transactions");
4320 let check_results = self.check_transactions(
4321 sanitized_txs,
4322 batch.lock_results(),
4323 max_age,
4324 &mut error_counters,
4325 );
4326 check_time.stop();
4327
4328 let mut load_time = Measure::start("accounts_load");
4329 let mut loaded_transactions = self.rc.accounts.load_accounts(
4330 &self.ancestors,
4331 sanitized_txs,
4332 check_results,
4333 &self.blockhash_queue.read().unwrap(),
4334 &mut error_counters,
4335 &self.rent_collector,
4336 &self.feature_set,
4337 &self.fee_structure,
4338 account_overrides,
4339 );
4340 load_time.stop();
4341
4342 let mut execution_time = Measure::start("execution_time");
4343 let mut signature_count: u64 = 0;
4344
4345 let execution_results: Vec<TransactionExecutionResult> = loaded_transactions
4346 .iter_mut()
4347 .zip(sanitized_txs.iter())
4348 .map(|(accs, tx)| match accs {
4349 (Err(e), _nonce) => TransactionExecutionResult::NotExecuted(e.clone()),
4350 (Ok(loaded_transaction), nonce) => {
4351 let mut feature_set_clone_time = Measure::start("feature_set_clone");
4352 let feature_set = self.feature_set.clone();
4353 feature_set_clone_time.stop();
4354 saturating_add_assign!(
4355 timings.execute_accessories.feature_set_clone_us,
4356 feature_set_clone_time.as_us()
4357 );
4358
4359 let compute_budget = if let Some(compute_budget) = self.compute_budget {
4360 compute_budget
4361 } else {
4362 let mut compute_budget =
4363 ComputeBudget::new(compute_budget::MAX_COMPUTE_UNIT_LIMIT as u64);
4364
4365 let mut compute_budget_process_transaction_time =
4366 Measure::start("compute_budget_process_transaction_time");
4367 let process_transaction_result = compute_budget.process_instructions(
4368 tx.message().program_instructions_iter(),
4369 feature_set.is_active(&default_units_per_instruction::id()),
4370 feature_set.is_active(&add_set_compute_unit_price_ix::id()),
4371 true, );
4373 compute_budget_process_transaction_time.stop();
4374 saturating_add_assign!(
4375 timings
4376 .execute_accessories
4377 .compute_budget_process_transaction_us,
4378 compute_budget_process_transaction_time.as_us()
4379 );
4380 if let Err(err) = process_transaction_result {
4381 return TransactionExecutionResult::NotExecuted(err);
4382 }
4383 compute_budget
4384 };
4385
4386 self.execute_loaded_transaction(
4387 tx,
4388 loaded_transaction,
4389 compute_budget,
4390 nonce.as_ref().map(DurableNonceFee::from),
4391 enable_cpi_recording,
4392 enable_log_recording,
4393 enable_return_data_recording,
4394 timings,
4395 &mut error_counters,
4396 log_messages_bytes_limit,
4397 )
4398 }
4399 })
4400 .collect();
4401
4402 execution_time.stop();
4403
4404 debug!(
4405 "check: {}us load: {}us execute: {}us txs_len={}",
4406 check_time.as_us(),
4407 load_time.as_us(),
4408 execution_time.as_us(),
4409 sanitized_txs.len(),
4410 );
4411
4412 timings.saturating_add_in_place(ExecuteTimingType::CheckUs, check_time.as_us());
4413 timings.saturating_add_in_place(ExecuteTimingType::LoadUs, load_time.as_us());
4414 timings.saturating_add_in_place(ExecuteTimingType::ExecuteUs, execution_time.as_us());
4415
4416 let mut executed_transactions_count: usize = 0;
4417 let mut executed_with_successful_result_count: usize = 0;
4418 let err_count = &mut error_counters.total;
4419 let transaction_log_collector_config =
4420 self.transaction_log_collector_config.read().unwrap();
4421
4422 let mut collect_logs_time = Measure::start("collect_logs_time");
4423 for (execution_result, tx) in execution_results.iter().zip(sanitized_txs) {
4424 if let Some(debug_keys) = &self.transaction_debug_keys {
4425 for key in tx.message().account_keys().iter() {
4426 if debug_keys.contains(key) {
4427 let result = execution_result.flattened_result();
4428 info!("slot: {} result: {:?} tx: {:?}", self.slot, result, tx);
4429 break;
4430 }
4431 }
4432 }
4433
4434 if execution_result.was_executed() && transaction_log_collector_config.filter != TransactionLogCollectorFilter::None
4436 {
4437 let mut filtered_mentioned_addresses = Vec::new();
4438 if !transaction_log_collector_config
4439 .mentioned_addresses
4440 .is_empty()
4441 {
4442 for key in tx.message().account_keys().iter() {
4443 if transaction_log_collector_config
4444 .mentioned_addresses
4445 .contains(key)
4446 {
4447 filtered_mentioned_addresses.push(*key);
4448 }
4449 }
4450 }
4451
4452 let is_vote = vote_parser::is_simple_vote_transaction(tx);
4453 let store = match transaction_log_collector_config.filter {
4454 TransactionLogCollectorFilter::All => {
4455 !is_vote || !filtered_mentioned_addresses.is_empty()
4456 }
4457 TransactionLogCollectorFilter::AllWithVotes => true,
4458 TransactionLogCollectorFilter::None => false,
4459 TransactionLogCollectorFilter::OnlyMentionedAddresses => {
4460 !filtered_mentioned_addresses.is_empty()
4461 }
4462 };
4463
4464 if store {
4465 if let Some(TransactionExecutionDetails {
4466 status,
4467 log_messages: Some(log_messages),
4468 ..
4469 }) = execution_result.details()
4470 {
4471 let mut transaction_log_collector =
4472 self.transaction_log_collector.write().unwrap();
4473 let transaction_log_index = transaction_log_collector.logs.len();
4474
4475 transaction_log_collector.logs.push(TransactionLogInfo {
4476 signature: *tx.signature(),
4477 result: status.clone(),
4478 is_vote,
4479 log_messages: log_messages.clone(),
4480 });
4481 for key in filtered_mentioned_addresses.into_iter() {
4482 transaction_log_collector
4483 .mentioned_address_map
4484 .entry(key)
4485 .or_default()
4486 .push(transaction_log_index);
4487 }
4488 }
4489 }
4490 }
4491
4492 if execution_result.was_executed() {
4493 signature_count += u64::from(tx.message().header().num_required_signatures);
4497 executed_transactions_count += 1;
4498 }
4499
4500 match execution_result.flattened_result() {
4501 Ok(()) => {
4502 executed_with_successful_result_count += 1;
4503 }
4504 Err(err) => {
4505 if *err_count == 0 {
4506 debug!("tx error: {:?} {:?}", err, tx);
4507 }
4508 *err_count += 1;
4509 }
4510 }
4511 }
4512 collect_logs_time.stop();
4513 timings
4514 .saturating_add_in_place(ExecuteTimingType::CollectLogsUs, collect_logs_time.as_us());
4515
4516 if *err_count > 0 {
4517 debug!(
4518 "{} errors of {} txs",
4519 *err_count,
4520 *err_count + executed_with_successful_result_count
4521 );
4522 }
4523 LoadAndExecuteTransactionsOutput {
4524 loaded_transactions,
4525 execution_results,
4526 retryable_transaction_indexes,
4527 executed_transactions_count,
4528 executed_with_successful_result_count,
4529 signature_count,
4530 error_counters,
4531 }
4532 }
4533
4534 pub fn accounts_data_size_limit(&self) -> u64 {
4536 MAX_ACCOUNTS_DATA_LEN
4537 }
4538
4539 pub fn load_accounts_data_size(&self) -> u64 {
4541 fn saturating_add_signed(lhs: u64, rhs: i64) -> u64 {
4544 let (res, overflow) = lhs.overflowing_add(rhs as u64);
4545 if overflow == (rhs < 0) {
4546 res
4547 } else if overflow {
4548 u64::MAX
4549 } else {
4550 u64::MIN
4551 }
4552 }
4553 saturating_add_signed(
4554 self.accounts_data_size_initial,
4555 self.load_accounts_data_size_delta(),
4556 )
4557 }
4558
4559 pub fn load_accounts_data_size_delta(&self) -> i64 {
4561 let delta_on_chain = self.load_accounts_data_size_delta_on_chain();
4562 let delta_off_chain = self.load_accounts_data_size_delta_off_chain();
4563 delta_on_chain.saturating_add(delta_off_chain)
4564 }
4565
4566 pub fn load_accounts_data_size_delta_on_chain(&self) -> i64 {
4569 self.accounts_data_size_delta_on_chain.load(Acquire)
4570 }
4571
4572 pub fn load_accounts_data_size_delta_off_chain(&self) -> i64 {
4575 self.accounts_data_size_delta_off_chain.load(Acquire)
4576 }
4577
4578 fn update_accounts_data_size_delta_on_chain(&self, amount: i64) {
4581 if amount == 0 {
4582 return;
4583 }
4584
4585 self.accounts_data_size_delta_on_chain
4586 .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_on_chain| {
4587 Some(accounts_data_size_delta_on_chain.saturating_add(amount))
4588 })
4589 .unwrap();
4591 }
4592
4593 fn update_accounts_data_size_delta_off_chain(&self, amount: i64) {
4596 if amount == 0 {
4597 return;
4598 }
4599
4600 self.accounts_data_size_delta_off_chain
4601 .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_off_chain| {
4602 Some(accounts_data_size_delta_off_chain.saturating_add(amount))
4603 })
4604 .unwrap();
4606 }
4607
4608 fn calculate_and_update_accounts_data_size_delta_off_chain(
4610 &self,
4611 old_data_size: usize,
4612 new_data_size: usize,
4613 ) {
4614 let data_size_delta = calculate_data_size_delta(old_data_size, new_data_size);
4615 self.update_accounts_data_size_delta_off_chain(data_size_delta);
4616 }
4617
4618 pub fn set_accounts_data_size_initial_for_tests(&mut self, amount: u64) {
4621 self.accounts_data_size_initial = amount;
4622 }
4623
4624 pub fn update_accounts_data_size_delta_off_chain_for_tests(&self, amount: i64) {
4627 self.update_accounts_data_size_delta_off_chain(amount)
4628 }
4629
4630 fn get_num_signatures_in_message(message: &SanitizedMessage) -> u64 {
4631 let mut num_signatures = u64::from(message.header().num_required_signatures);
4632 for (program_id, instruction) in message.program_instructions_iter() {
4635 if secp256k1_program::check_id(program_id) || ed25519_program::check_id(program_id) {
4636 if let Some(num_verifies) = instruction.data.first() {
4637 num_signatures = num_signatures.saturating_add(u64::from(*num_verifies));
4638 }
4639 }
4640 }
4641 num_signatures
4642 }
4643
4644 fn get_num_write_locks_in_message(message: &SanitizedMessage) -> u64 {
4645 message
4646 .account_keys()
4647 .len()
4648 .saturating_sub(message.num_readonly_accounts()) as u64
4649 }
4650
4651 pub fn calculate_fee(
4653 message: &SanitizedMessage,
4654 lamports_per_signature: u64,
4655 fee_structure: &FeeStructure,
4656 support_set_compute_unit_price_ix: bool,
4657 use_default_units_per_instruction: bool,
4658 enable_request_heap_frame_ix: bool,
4659 ) -> u64 {
4660 const BASE_CONGESTION: f64 = 5_000.0;
4662 let current_congestion = BASE_CONGESTION.max(lamports_per_signature as f64);
4663 let congestion_multiplier = if lamports_per_signature == 0 {
4664 0.0 } else {
4666 BASE_CONGESTION / current_congestion
4667 };
4668
4669 let mut compute_budget = ComputeBudget::default();
4670 let prioritization_fee_details = compute_budget
4671 .process_instructions(
4672 message.program_instructions_iter(),
4673 use_default_units_per_instruction,
4674 support_set_compute_unit_price_ix,
4675 enable_request_heap_frame_ix,
4676 )
4677 .unwrap_or_default();
4678 let prioritization_fee = prioritization_fee_details.get_fee();
4679 let signature_fee = Self::get_num_signatures_in_message(message)
4680 .saturating_mul(fee_structure.lamports_per_signature);
4681 let write_lock_fee = Self::get_num_write_locks_in_message(message)
4682 .saturating_mul(fee_structure.lamports_per_write_lock);
4683 let compute_fee = fee_structure
4684 .compute_fee_bins
4685 .iter()
4686 .find(|bin| compute_budget.compute_unit_limit <= bin.limit)
4687 .map(|bin| bin.fee)
4688 .unwrap_or_else(|| {
4689 fee_structure
4690 .compute_fee_bins
4691 .last()
4692 .map(|bin| bin.fee)
4693 .unwrap_or_default()
4694 });
4695
4696 ((prioritization_fee
4697 .saturating_add(signature_fee)
4698 .saturating_add(write_lock_fee)
4699 .saturating_add(compute_fee) as f64)
4700 * congestion_multiplier)
4701 .round() as u64
4702 }
4703
4704 fn filter_program_errors_and_collect_fee(
4705 &self,
4706 txs: &[SanitizedTransaction],
4707 execution_results: &[TransactionExecutionResult],
4708 ) -> Vec<Result<()>> {
4709 let hash_queue = self.blockhash_queue.read().unwrap();
4710 let mut fees = 0;
4711
4712 let results = txs
4713 .iter()
4714 .zip(execution_results)
4715 .map(|(tx, execution_result)| {
4716 let (execution_status, durable_nonce_fee) = match &execution_result {
4717 TransactionExecutionResult::Executed { details, .. } => {
4718 Ok((&details.status, details.durable_nonce_fee.as_ref()))
4719 }
4720 TransactionExecutionResult::NotExecuted(err) => Err(err.clone()),
4721 }?;
4722
4723 let (lamports_per_signature, is_nonce) = durable_nonce_fee
4724 .map(|durable_nonce_fee| durable_nonce_fee.lamports_per_signature())
4725 .map(|maybe_lamports_per_signature| (maybe_lamports_per_signature, true))
4726 .unwrap_or_else(|| {
4727 (
4728 hash_queue.get_lamports_per_signature(tx.message().recent_blockhash()),
4729 false,
4730 )
4731 });
4732
4733 let lamports_per_signature =
4734 lamports_per_signature.ok_or(TransactionError::BlockhashNotFound)?;
4735 let fee = Self::calculate_fee(
4736 tx.message(),
4737 lamports_per_signature,
4738 &self.fee_structure,
4739 self.feature_set
4740 .is_active(&add_set_compute_unit_price_ix::id()),
4741 self.feature_set
4742 .is_active(&use_default_units_in_fee_calculation::id()),
4743 self.enable_request_heap_frame_ix(),
4744 );
4745
4746 if execution_status.is_err() && !is_nonce {
4754 self.withdraw(tx.message().fee_payer(), fee)?;
4755 }
4756
4757 fees += fee;
4758 Ok(())
4759 })
4760 .collect();
4761
4762 self.collector_fees.fetch_add(fees, Relaxed);
4763 results
4764 }
4765
4766 pub fn commit_transactions(
4771 &self,
4772 sanitized_txs: &[SanitizedTransaction],
4773 loaded_txs: &mut [TransactionLoadResult],
4774 execution_results: Vec<TransactionExecutionResult>,
4775 last_blockhash: Hash,
4776 lamports_per_signature: u64,
4777 counts: CommitTransactionCounts,
4778 timings: &mut ExecuteTimings,
4779 ) -> TransactionResults {
4780 assert!(
4781 !self.freeze_started(),
4782 "commit_transactions() working on a bank that is already frozen or is undergoing freezing!"
4783 );
4784
4785 let CommitTransactionCounts {
4786 committed_transactions_count,
4787 committed_with_failure_result_count,
4788 signature_count,
4789 } = counts;
4790
4791 let tx_count = if self.bank_tranaction_count_fix_enabled() {
4792 committed_transactions_count
4793 } else {
4794 committed_transactions_count.saturating_sub(committed_with_failure_result_count)
4795 };
4796
4797 self.increment_transaction_count(tx_count);
4798 self.increment_signature_count(signature_count);
4799
4800 inc_new_counter_info!(
4801 "bank-process_transactions-txs",
4802 committed_transactions_count as usize
4803 );
4804 inc_new_counter_info!("bank-process_transactions-sigs", signature_count as usize);
4805
4806 if committed_with_failure_result_count > 0 {
4807 self.transaction_error_count
4808 .fetch_add(committed_with_failure_result_count, Relaxed);
4809 }
4810
4811 if execution_results.iter().any(|result| result.was_executed()) {
4813 self.is_delta.store(true, Relaxed);
4814 self.transaction_entries_count.fetch_add(1, Relaxed);
4815 self.transactions_per_entry_max
4816 .fetch_max(committed_transactions_count, Relaxed);
4817 }
4818
4819 let mut write_time = Measure::start("write_time");
4820 let durable_nonce = DurableNonce::from_blockhash(&last_blockhash);
4821 self.rc.accounts.store_cached(
4822 self.slot(),
4823 sanitized_txs,
4824 &execution_results,
4825 loaded_txs,
4826 &self.rent_collector,
4827 &durable_nonce,
4828 lamports_per_signature,
4829 self.preserve_rent_epoch_for_rent_exempt_accounts(),
4830 );
4831 let rent_debits = self.collect_rent(&execution_results, loaded_txs);
4832
4833 let mut update_stakes_cache_time = Measure::start("update_stakes_cache_time");
4836 self.update_stakes_cache(sanitized_txs, &execution_results, loaded_txs);
4837 update_stakes_cache_time.stop();
4838
4839 write_time.stop();
4841 debug!(
4842 "store: {}us txs_len={}",
4843 write_time.as_us(),
4844 sanitized_txs.len()
4845 );
4846
4847 let mut store_updated_executors_time = Measure::start("store_updated_executors_time");
4848 for execution_result in &execution_results {
4849 if let TransactionExecutionResult::Executed { details, executors } = execution_result {
4850 if details.status.is_ok() {
4851 self.store_updated_executors(executors);
4852 }
4853 }
4854 }
4855 store_updated_executors_time.stop();
4856 saturating_add_assign!(
4857 timings.execute_accessories.update_executors_us,
4858 store_updated_executors_time.as_us()
4859 );
4860
4861 let accounts_data_len_delta = execution_results
4862 .iter()
4863 .filter_map(|execution_result| {
4864 execution_result
4865 .details()
4866 .map(|details| details.accounts_data_len_delta)
4867 })
4868 .sum();
4869 self.update_accounts_data_size_delta_on_chain(accounts_data_len_delta);
4870
4871 timings.saturating_add_in_place(ExecuteTimingType::StoreUs, write_time.as_us());
4872 timings.saturating_add_in_place(
4873 ExecuteTimingType::UpdateStakesCacheUs,
4874 update_stakes_cache_time.as_us(),
4875 );
4876
4877 let mut update_transaction_statuses_time = Measure::start("update_transaction_statuses");
4878 self.update_transaction_statuses(sanitized_txs, &execution_results);
4879 let fee_collection_results =
4880 self.filter_program_errors_and_collect_fee(sanitized_txs, &execution_results);
4881 update_transaction_statuses_time.stop();
4882 timings.saturating_add_in_place(
4883 ExecuteTimingType::UpdateTransactionStatuses,
4884 update_transaction_statuses_time.as_us(),
4885 );
4886
4887 TransactionResults {
4888 fee_collection_results,
4889 execution_results,
4890 rent_debits,
4891 }
4892 }
4893
4894 #[allow(clippy::needless_collect)]
4915 fn distribute_rent_to_validators(
4916 &self,
4917 vote_accounts: &VoteAccountsHashMap,
4918 rent_to_be_distributed: u64,
4919 ) {
4920 let mut total_staked = 0;
4921
4922 let mut validator_stakes = vote_accounts
4926 .iter()
4927 .filter_map(|(_vote_pubkey, (staked, account))| {
4928 if *staked == 0 {
4929 None
4930 } else {
4931 total_staked += *staked;
4932 Some((account.node_pubkey()?, *staked))
4933 }
4934 })
4935 .collect::<Vec<(Pubkey, u64)>>();
4936
4937 #[cfg(test)]
4938 if validator_stakes.is_empty() {
4939 self.capitalization
4941 .fetch_sub(rent_to_be_distributed, Relaxed);
4942 return;
4943 }
4944 #[cfg(not(test))]
4945 assert!(!validator_stakes.is_empty());
4946
4947 validator_stakes.sort_by(|(pubkey1, staked1), (pubkey2, staked2)| {
4949 match staked2.cmp(staked1) {
4950 std::cmp::Ordering::Equal => pubkey2.cmp(pubkey1),
4951 other => other,
4952 }
4953 });
4954
4955 let enforce_fix = self.no_overflow_rent_distribution_enabled();
4956
4957 let mut rent_distributed_in_initial_round = 0;
4958 let validator_rent_shares = validator_stakes
4959 .into_iter()
4960 .map(|(pubkey, staked)| {
4961 let rent_share = if !enforce_fix {
4962 (((staked * rent_to_be_distributed) as f64) / (total_staked as f64)) as u64
4963 } else {
4964 (((staked as u128) * (rent_to_be_distributed as u128)) / (total_staked as u128))
4965 .try_into()
4966 .unwrap()
4967 };
4968 rent_distributed_in_initial_round += rent_share;
4969 (pubkey, rent_share)
4970 })
4971 .collect::<Vec<(Pubkey, u64)>>();
4972
4973 let mut leftover_lamports = rent_to_be_distributed - rent_distributed_in_initial_round;
4976
4977 let mut rewards = vec![];
4978 validator_rent_shares
4979 .into_iter()
4980 .for_each(|(pubkey, rent_share)| {
4981 let rent_to_be_paid = if leftover_lamports > 0 {
4982 leftover_lamports -= 1;
4983 rent_share + 1
4984 } else {
4985 rent_share
4986 };
4987 if !enforce_fix || rent_to_be_paid > 0 {
4988 let mut account = self
4989 .get_account_with_fixed_root(&pubkey)
4990 .unwrap_or_default();
4991 if account.checked_add_lamports(rent_to_be_paid).is_err() {
4992 self.capitalization.fetch_sub(rent_to_be_paid, Relaxed);
4994 error!(
4995 "Burned {} rent lamports instead of sending to {}",
4996 rent_to_be_paid, pubkey
4997 );
4998 inc_new_counter_error!(
4999 "bank-burned_rent_lamports",
5000 rent_to_be_paid as usize
5001 );
5002 } else {
5003 self.store_account(&pubkey, &account);
5004 rewards.push((
5005 pubkey,
5006 RewardInfo {
5007 reward_type: RewardType::Rent,
5008 lamports: rent_to_be_paid as i64,
5009 post_balance: account.lamports(),
5010 commission: None,
5011 },
5012 ));
5013 }
5014 }
5015 });
5016 self.rewards.write().unwrap().append(&mut rewards);
5017
5018 if enforce_fix {
5019 assert_eq!(leftover_lamports, 0);
5020 } else if leftover_lamports != 0 {
5021 warn!(
5022 "There was leftover from rent distribution: {}",
5023 leftover_lamports
5024 );
5025 self.capitalization.fetch_sub(leftover_lamports, Relaxed);
5026 }
5027 }
5028
5029 fn distribute_rent(&self) {
5030 let total_rent_collected = self.collected_rent.load(Relaxed);
5031
5032 let (burned_portion, rent_to_be_distributed) = self
5033 .rent_collector
5034 .rent
5035 .calculate_burn(total_rent_collected);
5036
5037 debug!(
5038 "distributed rent: {} (rounded from: {}, burned: {})",
5039 rent_to_be_distributed, total_rent_collected, burned_portion
5040 );
5041 self.capitalization.fetch_sub(burned_portion, Relaxed);
5042
5043 if rent_to_be_distributed == 0 {
5044 return;
5045 }
5046
5047 self.distribute_rent_to_validators(&self.vote_accounts(), rent_to_be_distributed);
5048 }
5049
5050 fn collect_rent(
5051 &self,
5052 execution_results: &[TransactionExecutionResult],
5053 loaded_txs: &mut [TransactionLoadResult],
5054 ) -> Vec<RentDebits> {
5055 let mut collected_rent: u64 = 0;
5056 let rent_debits: Vec<_> = loaded_txs
5057 .iter_mut()
5058 .zip(execution_results)
5059 .map(|((load_result, _nonce), execution_result)| {
5060 if let (Ok(loaded_transaction), true) =
5061 (load_result, execution_result.was_executed_successfully())
5062 {
5063 collected_rent += loaded_transaction.rent;
5064 mem::take(&mut loaded_transaction.rent_debits)
5065 } else {
5066 RentDebits::default()
5067 }
5068 })
5069 .collect();
5070 self.collected_rent.fetch_add(collected_rent, Relaxed);
5071 rent_debits
5072 }
5073
5074 fn run_incinerator(&self) {
5075 if let Some((account, _)) =
5076 self.get_account_modified_since_parent_with_fixed_root(&incinerator::id())
5077 {
5078 self.capitalization.fetch_sub(account.lamports(), Relaxed);
5079 self.store_account(&incinerator::id(), &AccountSharedData::default());
5080 }
5081 }
5082
5083 pub fn prepare_rewrites_for_hash(&self) {
5085 self.collect_rent_eagerly(true);
5086 }
5087
5088 pub(crate) fn get_stake_accounts(&self, minimized_account_set: &DashSet<Pubkey>) {
5090 self.stakes_cache
5091 .stakes()
5092 .stake_delegations()
5093 .iter()
5094 .for_each(|(pubkey, _)| {
5095 minimized_account_set.insert(*pubkey);
5096 });
5097
5098 self.stakes_cache
5099 .stakes()
5100 .staked_nodes()
5101 .par_iter()
5102 .for_each(|(pubkey, _)| {
5103 minimized_account_set.insert(*pubkey);
5104 });
5105 }
5106
5107 fn get_partition_end_indexes(partition: &Partition) -> Vec<PartitionIndex> {
5118 if partition.0 == partition.1 && partition.0 == 0 {
5119 vec![0]
5121 } else {
5122 (partition.0..partition.1).map(|index| index + 1).collect()
5126 }
5127 }
5128
5129 fn collect_rent_eagerly(&self, just_rewrites: bool) {
5130 if self.lazy_rent_collection.load(Relaxed) {
5131 return;
5132 }
5133
5134 let mut measure = Measure::start("collect_rent_eagerly-ms");
5135 let partitions = self.rent_collection_partitions();
5136 let count = partitions.len();
5137 let rent_metrics = RentMetrics::default();
5138 let mut parallel = count > 1;
5140 if parallel {
5141 let ranges = partitions
5142 .iter()
5143 .map(|partition| (*partition, Self::pubkey_range_from_partition(*partition)))
5144 .collect::<Vec<_>>();
5145 'outer: for i in 0..ranges.len() {
5150 for j in 0..ranges.len() {
5151 if i == j {
5152 continue;
5153 }
5154
5155 let i = &ranges[i].1;
5156 let j = &ranges[j].1;
5157 if i.contains(j.start()) || i.contains(j.end()) {
5159 parallel = false;
5160 break 'outer;
5161 }
5162 }
5163 }
5164
5165 if parallel {
5166 let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
5167 thread_pool.install(|| {
5168 ranges.into_par_iter().for_each(|range| {
5169 self.collect_rent_in_range(range.0, range.1, just_rewrites, &rent_metrics)
5170 });
5171 });
5172 }
5173 }
5174 if !parallel {
5175 partitions.into_iter().for_each(|partition| {
5177 self.collect_rent_in_partition(partition, just_rewrites, &rent_metrics)
5178 });
5179 }
5180 measure.stop();
5181 datapoint_info!(
5182 "collect_rent_eagerly",
5183 ("accounts", rent_metrics.count.load(Relaxed), i64),
5184 ("partitions", count, i64),
5185 (
5186 "skipped_rewrites",
5187 self.rewrites_skipped_this_slot.read().unwrap().len(),
5188 i64
5189 ),
5190 ("total_time_us", measure.as_us(), i64),
5191 (
5192 "hold_range_us",
5193 rent_metrics.hold_range_us.load(Relaxed),
5194 i64
5195 ),
5196 ("load_us", rent_metrics.load_us.load(Relaxed), i64),
5197 ("collect_us", rent_metrics.collect_us.load(Relaxed), i64),
5198 ("hash_us", rent_metrics.hash_us.load(Relaxed), i64),
5199 ("store_us", rent_metrics.store_us.load(Relaxed), i64),
5200 );
5201 }
5202
5203 #[cfg(test)]
5204 fn restore_old_behavior_for_fragile_tests(&self) {
5205 self.lazy_rent_collection.store(true, Relaxed);
5206 }
5207
5208 fn rent_collection_partitions(&self) -> Vec<Partition> {
5209 if !self.use_fixed_collection_cycle() {
5210 self.variable_cycle_partitions()
5217 } else {
5218 self.fixed_cycle_partitions()
5225 }
5226 }
5227
5228 fn collect_rent_from_accounts(
5238 &self,
5239 mut accounts: Vec<(Pubkey, AccountSharedData, Slot)>,
5240 just_rewrites: bool,
5241 rent_paying_pubkeys: Option<&HashSet<Pubkey>>,
5242 partition_index: PartitionIndex,
5243 ) -> CollectRentFromAccountsInfo {
5244 let mut rent_debits = RentDebits::default();
5245 let mut total_rent_collected_info = CollectedInfo::default();
5246 let bank_slot = self.slot();
5247 let mut rewrites_skipped = Vec::with_capacity(accounts.len());
5248 let mut accounts_to_store =
5249 Vec::<(&Pubkey, &AccountSharedData)>::with_capacity(accounts.len());
5250 let mut time_collecting_rent_us = 0;
5251 let mut time_hashing_skipped_rewrites_us = 0;
5252 let mut time_storing_accounts_us = 0;
5253 let can_skip_rewrites = self.rc.accounts.accounts_db.skip_rewrites || just_rewrites;
5254 let preserve_rent_epoch_for_rent_exempt_accounts =
5255 self.preserve_rent_epoch_for_rent_exempt_accounts();
5256 for (pubkey, account, loaded_slot) in accounts.iter_mut() {
5257 let old_rent_epoch = account.rent_epoch();
5258 let (rent_collected_info, measure) =
5259 measure!(self.rent_collector.collect_from_existing_account(
5260 pubkey,
5261 account,
5262 self.rc.accounts.accounts_db.filler_account_suffix.as_ref(),
5263 preserve_rent_epoch_for_rent_exempt_accounts,
5264 ));
5265 time_collecting_rent_us += measure.as_us();
5266
5267 if can_skip_rewrites
5273 && Self::skip_rewrite(
5274 bank_slot,
5275 rent_collected_info.rent_amount,
5276 *loaded_slot,
5277 old_rent_epoch,
5278 account,
5279 )
5280 {
5281 let (hash, measure) = measure!(crate::accounts_db::AccountsDb::hash_account(
5285 self.slot(),
5286 account,
5287 pubkey
5288 ));
5289 time_hashing_skipped_rewrites_us += measure.as_us();
5290 rewrites_skipped.push((*pubkey, hash));
5291 assert_eq!(rent_collected_info, CollectedInfo::default());
5292 } else if !just_rewrites {
5293 if rent_collected_info.rent_amount > 0 {
5294 if let Some(rent_paying_pubkeys) = rent_paying_pubkeys {
5295 if !rent_paying_pubkeys.contains(pubkey) {
5296 inc_new_counter_info!("unexpected-rent-paying-pubkey", 1);
5298 warn!(
5299 "Collecting rent from unexpected pubkey: {}, slot: {}, parent_slot: {:?}, partition_index: {}, partition_from_pubkey: {}",
5300 pubkey,
5301 self.slot(),
5302 self.parent().map(|bank| bank.slot()),
5303 partition_index,
5304 Bank::partition_from_pubkey(pubkey, self.epoch_schedule.slots_per_epoch),
5305 );
5306 }
5307 }
5308 }
5309 total_rent_collected_info += rent_collected_info;
5310 accounts_to_store.push((pubkey, account));
5311 }
5312 rent_debits.insert(pubkey, rent_collected_info.rent_amount, account.lamports());
5313 }
5314
5315 if !accounts_to_store.is_empty() {
5316 let (_, measure) = measure!(self.store_accounts((self.slot(), &accounts_to_store[..])));
5319 time_storing_accounts_us += measure.as_us();
5320 }
5321
5322 CollectRentFromAccountsInfo {
5323 rent_collected_info: total_rent_collected_info,
5324 rent_rewards: rent_debits.into_unordered_rewards_iter().collect(),
5325 rewrites_skipped,
5326 time_collecting_rent_us,
5327 time_hashing_skipped_rewrites_us,
5328 time_storing_accounts_us,
5329 num_accounts: accounts.len(),
5330 }
5331 }
5332
5333 fn collect_rent_in_partition(
5335 &self,
5336 partition: Partition,
5337 just_rewrites: bool,
5338 metrics: &RentMetrics,
5339 ) {
5340 let subrange_full = Self::pubkey_range_from_partition(partition);
5341 self.collect_rent_in_range(partition, subrange_full, just_rewrites, metrics)
5342 }
5343
5344 fn get_rent_paying_pubkeys(&self, partition: &Partition) -> Option<HashSet<Pubkey>> {
5346 self.rc
5347 .accounts
5348 .accounts_db
5349 .accounts_index
5350 .rent_paying_accounts_by_partition
5351 .get()
5352 .and_then(|rent_paying_accounts| {
5353 rent_paying_accounts.is_initialized().then(|| {
5354 Self::get_partition_end_indexes(partition)
5355 .into_iter()
5356 .flat_map(|end_index| {
5357 rent_paying_accounts.get_pubkeys_in_partition_index(end_index)
5358 })
5359 .cloned()
5360 .collect::<HashSet<_>>()
5361 })
5362 })
5363 }
5364
5365 fn collect_rent_in_range(
5372 &self,
5373 partition: Partition,
5374 subrange_full: RangeInclusive<Pubkey>,
5375 just_rewrites: bool,
5376 metrics: &RentMetrics,
5377 ) {
5378 let mut hold_range = Measure::start("hold_range");
5379 let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
5380 thread_pool.install(|| {
5381 self.rc
5382 .accounts
5383 .hold_range_in_memory(&subrange_full, true, thread_pool);
5384 hold_range.stop();
5385 metrics.hold_range_us.fetch_add(hold_range.as_us(), Relaxed);
5386
5387 let rent_paying_pubkeys_ = self.get_rent_paying_pubkeys(&partition);
5388 let rent_paying_pubkeys = rent_paying_pubkeys_.as_ref();
5389
5390 let num_threads = crate::accounts_db::quarter_thread_count() as u64;
5394 let sz = std::mem::size_of::<u64>();
5395 let start_prefix = Self::prefix_from_pubkey(subrange_full.start());
5396 let end_prefix_inclusive = Self::prefix_from_pubkey(subrange_full.end());
5397 let range = end_prefix_inclusive - start_prefix;
5398 let increment = range / num_threads;
5399 let mut results = (0..num_threads)
5400 .into_par_iter()
5401 .map(|chunk| {
5402 let offset = |chunk| start_prefix + chunk * increment;
5403 let start = offset(chunk);
5404 let last = chunk == num_threads - 1;
5405 let merge_prefix = |prefix: u64, mut bound: Pubkey| {
5406 bound.as_mut()[0..sz].copy_from_slice(&prefix.to_be_bytes());
5407 bound
5408 };
5409 let start = merge_prefix(start, *subrange_full.start());
5410 let (accounts, measure_load_accounts) = measure!(if last {
5411 let end = *subrange_full.end();
5412 let subrange = start..=end; self.rc
5414 .accounts
5415 .load_to_collect_rent_eagerly(&self.ancestors, subrange)
5416 } else {
5417 let end = merge_prefix(offset(chunk + 1), *subrange_full.start());
5418 let subrange = start..end; self.rc
5420 .accounts
5421 .load_to_collect_rent_eagerly(&self.ancestors, subrange)
5422 });
5423 CollectRentInPartitionInfo::new(
5424 self.collect_rent_from_accounts(
5425 accounts,
5426 just_rewrites,
5427 rent_paying_pubkeys,
5428 partition.1,
5429 ),
5430 Duration::from_nanos(measure_load_accounts.as_ns()),
5431 )
5432 })
5433 .reduce(
5434 CollectRentInPartitionInfo::default,
5435 CollectRentInPartitionInfo::reduce,
5436 );
5437
5438 self.rc
5442 .accounts
5443 .hold_range_in_memory(&subrange_full, false, thread_pool);
5444
5445 self.collected_rent
5446 .fetch_add(results.rent_collected, Relaxed);
5447 self.update_accounts_data_size_delta_off_chain(
5448 -(results.accounts_data_size_reclaimed as i64),
5449 );
5450 self.rewards
5451 .write()
5452 .unwrap()
5453 .append(&mut results.rent_rewards);
5454 self.remember_skipped_rewrites(results.rewrites_skipped);
5455
5456 metrics
5457 .load_us
5458 .fetch_add(results.time_loading_accounts_us, Relaxed);
5459 metrics
5460 .collect_us
5461 .fetch_add(results.time_collecting_rent_us, Relaxed);
5462 metrics
5463 .hash_us
5464 .fetch_add(results.time_hashing_skipped_rewrites_us, Relaxed);
5465 metrics
5466 .store_us
5467 .fetch_add(results.time_storing_accounts_us, Relaxed);
5468 metrics.count.fetch_add(results.num_accounts, Relaxed);
5469 });
5470 }
5471
5472 fn remember_skipped_rewrites(&self, rewrites_skipped: Vec<(Pubkey, Hash)>) {
5474 if !rewrites_skipped.is_empty() {
5475 let mut rewrites_skipped_this_slot = self.rewrites_skipped_this_slot.write().unwrap();
5476 rewrites_skipped.into_iter().for_each(|(pubkey, hash)| {
5477 rewrites_skipped_this_slot.insert(pubkey, hash);
5478 });
5479 }
5480 }
5481
5482 fn skip_rewrite(
5484 bank_slot: Slot,
5485 rent_amount: u64,
5486 loaded_slot: Slot,
5487 old_rent_epoch: Epoch,
5488 account: &AccountSharedData,
5489 ) -> bool {
5490 if rent_amount != 0 || account.rent_epoch() == 0 {
5491 return false;
5495 }
5496 if old_rent_epoch != account.rent_epoch() && loaded_slot == bank_slot {
5497 return false;
5504 }
5505
5506 true
5508 }
5509
5510 fn prefix_from_pubkey(pubkey: &Pubkey) -> u64 {
5511 const PREFIX_SIZE: usize = mem::size_of::<u64>();
5512 u64::from_be_bytes(pubkey.as_ref()[0..PREFIX_SIZE].try_into().unwrap())
5513 }
5514
5515 pub fn partition_from_pubkey(
5518 pubkey: &Pubkey,
5519 partition_count: PartitionsPerCycle,
5520 ) -> PartitionIndex {
5521 type Prefix = u64;
5522 const PREFIX_MAX: Prefix = Prefix::max_value();
5523
5524 if partition_count == 1 {
5525 return 0;
5526 }
5527
5528 let partition_width = (PREFIX_MAX - partition_count + 1) / partition_count + 1;
5530
5531 let prefix = Self::prefix_from_pubkey(pubkey);
5532 if prefix == 0 {
5533 return 0;
5534 }
5535
5536 if prefix == PREFIX_MAX {
5537 return partition_count - 1;
5538 }
5539
5540 let mut result = (prefix + 1) / partition_width;
5541 if (prefix + 1) % partition_width == 0 {
5542 result = result.saturating_sub(1);
5544 }
5545 result
5546 }
5547
5548 pub fn pubkey_range_from_partition(
5553 (start_index, end_index, partition_count): Partition,
5554 ) -> RangeInclusive<Pubkey> {
5555 assert!(start_index <= end_index);
5556 assert!(start_index < partition_count);
5557 assert!(end_index < partition_count);
5558 assert!(0 < partition_count);
5559
5560 type Prefix = u64;
5561 const PREFIX_SIZE: usize = mem::size_of::<Prefix>();
5562 const PREFIX_MAX: Prefix = Prefix::max_value();
5563
5564 let mut start_pubkey = [0x00u8; 32];
5565 let mut end_pubkey = [0xffu8; 32];
5566
5567 if partition_count == 1 {
5568 assert_eq!(start_index, 0);
5569 assert_eq!(end_index, 0);
5570 return Pubkey::new_from_array(start_pubkey)..=Pubkey::new_from_array(end_pubkey);
5571 }
5572
5573 let partition_width = (PREFIX_MAX - partition_count + 1) / partition_count + 1;
5575 let mut start_key_prefix = if start_index == 0 && end_index == 0 {
5576 0
5577 } else if start_index + 1 == partition_count {
5578 PREFIX_MAX
5579 } else {
5580 (start_index + 1) * partition_width
5581 };
5582
5583 let mut end_key_prefix = if end_index + 1 == partition_count {
5584 PREFIX_MAX
5585 } else {
5586 (end_index + 1) * partition_width - 1
5587 };
5588
5589 if start_index != 0 && start_index == end_index {
5590 if end_key_prefix == PREFIX_MAX {
5593 start_key_prefix = end_key_prefix;
5594 start_pubkey = end_pubkey;
5595 } else {
5596 end_key_prefix = start_key_prefix;
5597 end_pubkey = start_pubkey;
5598 }
5599 }
5600
5601 start_pubkey[0..PREFIX_SIZE].copy_from_slice(&start_key_prefix.to_be_bytes());
5602 end_pubkey[0..PREFIX_SIZE].copy_from_slice(&end_key_prefix.to_be_bytes());
5603 let start_pubkey_final = Pubkey::new_from_array(start_pubkey);
5604 let end_pubkey_final = Pubkey::new_from_array(end_pubkey);
5605 trace!(
5606 "pubkey_range_from_partition: ({}-{})/{} [{}]: {}-{}",
5607 start_index,
5608 end_index,
5609 partition_count,
5610 (end_key_prefix - start_key_prefix),
5611 start_pubkey.iter().map(|x| format!("{:02x}", x)).join(""),
5612 end_pubkey.iter().map(|x| format!("{:02x}", x)).join(""),
5613 );
5614 #[cfg(test)]
5615 if start_index != end_index {
5616 assert_eq!(
5617 if start_index == 0 && end_index == 0 {
5618 0
5619 } else {
5620 start_index + 1
5621 },
5622 Self::partition_from_pubkey(&start_pubkey_final, partition_count),
5623 "{}, {}, start_key_prefix: {}, {}, {}",
5624 start_index,
5625 end_index,
5626 start_key_prefix,
5627 start_pubkey_final,
5628 partition_count
5629 );
5630 assert_eq!(
5631 end_index,
5632 Self::partition_from_pubkey(&end_pubkey_final, partition_count),
5633 "{}, {}, {}, {}",
5634 start_index,
5635 end_index,
5636 end_pubkey_final,
5637 partition_count
5638 );
5639 if start_index != 0 {
5640 start_pubkey[0..PREFIX_SIZE]
5641 .copy_from_slice(&start_key_prefix.saturating_sub(1).to_be_bytes());
5642 let pubkey_test = Pubkey::new_from_array(start_pubkey);
5643 assert_eq!(
5644 start_index,
5645 Self::partition_from_pubkey(&pubkey_test, partition_count),
5646 "{}, {}, start_key_prefix-1: {}, {}, {}",
5647 start_index,
5648 end_index,
5649 start_key_prefix.saturating_sub(1),
5650 pubkey_test,
5651 partition_count
5652 );
5653 }
5654 if end_index != partition_count - 1 && end_index != 0 {
5655 end_pubkey[0..PREFIX_SIZE]
5656 .copy_from_slice(&end_key_prefix.saturating_add(1).to_be_bytes());
5657 let pubkey_test = Pubkey::new_from_array(end_pubkey);
5658 assert_eq!(
5659 end_index.saturating_add(1),
5660 Self::partition_from_pubkey(&pubkey_test, partition_count),
5661 "start: {}, end: {}, pubkey: {}, partition_count: {}, prefix_before_addition: {}, prefix after: {}",
5662 start_index,
5663 end_index,
5664 pubkey_test,
5665 partition_count,
5666 end_key_prefix,
5667 end_key_prefix.saturating_add(1),
5668 );
5669 }
5670 }
5671 start_pubkey_final..=end_pubkey_final
5674 }
5675
5676 pub fn get_partitions(
5677 slot: Slot,
5678 parent_slot: Slot,
5679 slot_count_in_two_day: SlotCount,
5680 ) -> Vec<Partition> {
5681 let parent_cycle = parent_slot / slot_count_in_two_day;
5682 let current_cycle = slot / slot_count_in_two_day;
5683 let mut parent_cycle_index = parent_slot % slot_count_in_two_day;
5684 let current_cycle_index = slot % slot_count_in_two_day;
5685 let mut partitions = vec![];
5686 if parent_cycle < current_cycle {
5687 if current_cycle_index > 0 {
5688 let parent_last_cycle_index = slot_count_in_two_day - 1;
5690
5691 partitions.push((
5693 parent_cycle_index,
5694 parent_last_cycle_index,
5695 slot_count_in_two_day,
5696 ));
5697
5698 partitions.push((0, 0, slot_count_in_two_day));
5700 }
5701 parent_cycle_index = 0;
5702 }
5703
5704 partitions.push((
5705 parent_cycle_index,
5706 current_cycle_index,
5707 slot_count_in_two_day,
5708 ));
5709
5710 partitions
5711 }
5712
5713 pub(crate) fn fixed_cycle_partitions_between_slots(
5714 &self,
5715 starting_slot: Slot,
5716 ending_slot: Slot,
5717 ) -> Vec<Partition> {
5718 let slot_count_in_two_day = self.slot_count_in_two_day();
5719 Self::get_partitions(ending_slot, starting_slot, slot_count_in_two_day)
5720 }
5721
5722 fn fixed_cycle_partitions(&self) -> Vec<Partition> {
5723 self.fixed_cycle_partitions_between_slots(self.parent_slot(), self.slot())
5724 }
5725
5726 pub fn variable_cycle_partition_from_previous_slot(
5729 epoch_schedule: &EpochSchedule,
5730 slot: Slot,
5731 ) -> Partition {
5732 let (current_epoch, current_slot_index) = epoch_schedule.get_epoch_and_slot_index(slot);
5734 let (parent_epoch, mut parent_slot_index) =
5735 epoch_schedule.get_epoch_and_slot_index(slot.saturating_sub(1));
5736 let cycle_params = Self::rent_single_epoch_collection_cycle_params(
5737 current_epoch,
5738 epoch_schedule.get_slots_in_epoch(current_epoch),
5739 );
5740
5741 if parent_epoch < current_epoch {
5742 parent_slot_index = 0;
5743 }
5744
5745 let generated_for_gapped_epochs = false;
5746 Self::get_partition_from_slot_indexes(
5747 cycle_params,
5748 parent_slot_index,
5749 current_slot_index,
5750 generated_for_gapped_epochs,
5751 )
5752 }
5753
5754 pub(crate) fn variable_cycle_partitions_between_slots(
5755 &self,
5756 starting_slot: Slot,
5757 ending_slot: Slot,
5758 ) -> Vec<Partition> {
5759 let (starting_epoch, mut starting_slot_index) =
5760 self.get_epoch_and_slot_index(starting_slot);
5761 let (ending_epoch, ending_slot_index) = self.get_epoch_and_slot_index(ending_slot);
5762
5763 let mut partitions = vec![];
5764 if starting_epoch < ending_epoch {
5765 let slot_skipped = (ending_slot - starting_slot) > 1;
5766 if slot_skipped {
5767 let parent_last_slot_index = self.get_slots_in_epoch(starting_epoch) - 1;
5771
5772 partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
5774 starting_slot_index,
5775 parent_last_slot_index,
5776 starting_epoch,
5777 ));
5778
5779 if ending_slot_index > 0 {
5780 partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
5782 0,
5783 0,
5784 ending_epoch,
5785 ));
5786 }
5787 }
5788 starting_slot_index = 0;
5789 }
5790
5791 partitions.push(self.partition_from_normal_slot_indexes(
5792 starting_slot_index,
5793 ending_slot_index,
5794 ending_epoch,
5795 ));
5796
5797 partitions
5798 }
5799
5800 fn variable_cycle_partitions(&self) -> Vec<Partition> {
5801 self.variable_cycle_partitions_between_slots(self.parent_slot(), self.slot())
5802 }
5803
5804 fn do_partition_from_slot_indexes(
5805 &self,
5806 start_slot_index: SlotIndex,
5807 end_slot_index: SlotIndex,
5808 epoch: Epoch,
5809 generated_for_gapped_epochs: bool,
5810 ) -> Partition {
5811 let cycle_params = self.determine_collection_cycle_params(epoch);
5812 Self::get_partition_from_slot_indexes(
5813 cycle_params,
5814 start_slot_index,
5815 end_slot_index,
5816 generated_for_gapped_epochs,
5817 )
5818 }
5819
5820 fn get_partition_from_slot_indexes(
5821 cycle_params: RentCollectionCycleParams,
5822 start_slot_index: SlotIndex,
5823 end_slot_index: SlotIndex,
5824 generated_for_gapped_epochs: bool,
5825 ) -> Partition {
5826 let (_, _, in_multi_epoch_cycle, _, _, partition_count) = cycle_params;
5827
5828 let mut start_partition_index =
5832 Self::partition_index_from_slot_index(start_slot_index, cycle_params);
5833 let mut end_partition_index =
5834 Self::partition_index_from_slot_index(end_slot_index, cycle_params);
5835
5836 let is_special_new_epoch = start_slot_index == 0 && end_slot_index != 1;
5838 let in_middle_of_cycle = start_partition_index > 0;
5839 if in_multi_epoch_cycle && is_special_new_epoch && in_middle_of_cycle {
5840 start_partition_index -= 1;
5868 if generated_for_gapped_epochs {
5869 assert_eq!(start_slot_index, end_slot_index);
5870 end_partition_index -= 1;
5871 }
5872 }
5873
5874 (start_partition_index, end_partition_index, partition_count)
5875 }
5876
5877 fn partition_from_normal_slot_indexes(
5878 &self,
5879 start_slot_index: SlotIndex,
5880 end_slot_index: SlotIndex,
5881 epoch: Epoch,
5882 ) -> Partition {
5883 self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, false)
5884 }
5885
5886 fn partition_from_slot_indexes_with_gapped_epochs(
5887 &self,
5888 start_slot_index: SlotIndex,
5889 end_slot_index: SlotIndex,
5890 epoch: Epoch,
5891 ) -> Partition {
5892 self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, true)
5893 }
5894
5895 fn rent_single_epoch_collection_cycle_params(
5896 epoch: Epoch,
5897 slot_count_per_epoch: SlotCount,
5898 ) -> RentCollectionCycleParams {
5899 (
5900 epoch,
5901 slot_count_per_epoch,
5902 false,
5903 0,
5904 1,
5905 slot_count_per_epoch,
5906 )
5907 }
5908
5909 fn determine_collection_cycle_params(&self, epoch: Epoch) -> RentCollectionCycleParams {
5910 let slot_count_per_epoch = self.get_slots_in_epoch(epoch);
5911
5912 if !self.use_multi_epoch_collection_cycle(epoch) {
5913 Self::rent_single_epoch_collection_cycle_params(epoch, slot_count_per_epoch)
5915 } else {
5916 let epoch_count_in_cycle = self.slot_count_in_two_day() / slot_count_per_epoch;
5917 let partition_count = slot_count_per_epoch * epoch_count_in_cycle;
5918
5919 (
5920 epoch,
5921 slot_count_per_epoch,
5922 true,
5923 self.first_normal_epoch(),
5924 epoch_count_in_cycle,
5925 partition_count,
5926 )
5927 }
5928 }
5929
5930 fn partition_index_from_slot_index(
5931 slot_index_in_epoch: SlotIndex,
5932 (
5933 epoch,
5934 slot_count_per_epoch,
5935 _,
5936 base_epoch,
5937 epoch_count_per_cycle,
5938 _,
5939 ): RentCollectionCycleParams,
5940 ) -> PartitionIndex {
5941 let epoch_offset = epoch - base_epoch;
5942 let epoch_index_in_cycle = epoch_offset % epoch_count_per_cycle;
5943 slot_index_in_epoch + epoch_index_in_cycle * slot_count_per_epoch
5944 }
5945
5946 fn use_multi_epoch_collection_cycle(&self, epoch: Epoch) -> bool {
5952 #[cfg(not(test))]
5954 if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
5955 {
5956 return false;
5957 }
5958
5959 epoch >= self.first_normal_epoch()
5960 && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
5961 }
5962
5963 pub(crate) fn use_fixed_collection_cycle(&self) -> bool {
5964 #[cfg(not(test))]
5966 if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
5967 {
5968 return false;
5969 }
5970
5971 self.cluster_type() != ClusterType::MainnetBeta
5972 && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
5973 }
5974
5975 fn slot_count_in_two_day(&self) -> SlotCount {
5976 Self::slot_count_in_two_day_helper(self.ticks_per_slot)
5977 }
5978
5979 pub fn slot_count_in_two_day_helper(ticks_per_slot: SlotCount) -> SlotCount {
5983 2 * DEFAULT_TICKS_PER_SECOND * SECONDS_PER_DAY / ticks_per_slot
5984 }
5985
5986 fn slot_count_per_normal_epoch(&self) -> SlotCount {
5987 self.get_slots_in_epoch(self.first_normal_epoch())
5988 }
5989
5990 pub fn cluster_type(&self) -> ClusterType {
5991 self.cluster_type.unwrap()
5994 }
5995
5996 #[must_use]
5998 pub fn load_execute_and_commit_transactions(
5999 &self,
6000 batch: &TransactionBatch,
6001 max_age: usize,
6002 collect_balances: bool,
6003 enable_cpi_recording: bool,
6004 enable_log_recording: bool,
6005 enable_return_data_recording: bool,
6006 timings: &mut ExecuteTimings,
6007 log_messages_bytes_limit: Option<usize>,
6008 ) -> (TransactionResults, TransactionBalancesSet) {
6009 let pre_balances = if collect_balances {
6010 self.collect_balances(batch)
6011 } else {
6012 vec![]
6013 };
6014
6015 let LoadAndExecuteTransactionsOutput {
6016 mut loaded_transactions,
6017 execution_results,
6018 executed_transactions_count,
6019 executed_with_successful_result_count,
6020 signature_count,
6021 ..
6022 } = self.load_and_execute_transactions(
6023 batch,
6024 max_age,
6025 enable_cpi_recording,
6026 enable_log_recording,
6027 enable_return_data_recording,
6028 timings,
6029 None,
6030 log_messages_bytes_limit,
6031 );
6032
6033 let (last_blockhash, lamports_per_signature) =
6034 self.last_blockhash_and_lamports_per_signature();
6035 let results = self.commit_transactions(
6036 batch.sanitized_transactions(),
6037 &mut loaded_transactions,
6038 execution_results,
6039 last_blockhash,
6040 lamports_per_signature,
6041 CommitTransactionCounts {
6042 committed_transactions_count: executed_transactions_count as u64,
6043 committed_with_failure_result_count: executed_transactions_count
6044 .saturating_sub(executed_with_successful_result_count)
6045 as u64,
6046 signature_count,
6047 },
6048 timings,
6049 );
6050 let post_balances = if collect_balances {
6051 self.collect_balances(batch)
6052 } else {
6053 vec![]
6054 };
6055 (
6056 results,
6057 TransactionBalancesSet::new(pre_balances, post_balances),
6058 )
6059 }
6060
6061 pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
6064 self.try_process_transactions(std::iter::once(tx))?[0].clone()?;
6065 tx.signatures
6066 .get(0)
6067 .map_or(Ok(()), |sig| self.get_signature_status(sig).unwrap())
6068 }
6069
6070 pub fn process_transaction_with_logs(&self, tx: &Transaction) -> Result<()> {
6073 let txs = vec![VersionedTransaction::from(tx.clone())];
6074 let batch = self.prepare_entry_batch(txs)?;
6075 let _results = self.load_execute_and_commit_transactions(
6076 &batch,
6077 MAX_PROCESSING_AGE,
6078 false,
6079 false,
6080 true,
6081 false,
6082 &mut ExecuteTimings::default(),
6083 None,
6084 );
6085 tx.signatures
6086 .get(0)
6087 .map_or(Ok(()), |sig| self.get_signature_status(sig).unwrap())
6088 }
6089
6090 #[must_use]
6096 pub fn process_transactions<'a>(
6097 &self,
6098 txs: impl Iterator<Item = &'a Transaction>,
6099 ) -> Vec<Result<()>> {
6100 self.try_process_transactions(txs).unwrap()
6101 }
6102
6103 pub fn try_process_transactions<'a>(
6106 &self,
6107 txs: impl Iterator<Item = &'a Transaction>,
6108 ) -> Result<Vec<Result<()>>> {
6109 let txs = txs
6110 .map(|tx| VersionedTransaction::from(tx.clone()))
6111 .collect();
6112 self.try_process_entry_transactions(txs)
6113 }
6114
6115 #[must_use]
6121 pub fn process_entry_transactions(&self, txs: Vec<VersionedTransaction>) -> Vec<Result<()>> {
6122 self.try_process_entry_transactions(txs).unwrap()
6123 }
6124
6125 pub fn try_process_entry_transactions(
6128 &self,
6129 txs: Vec<VersionedTransaction>,
6130 ) -> Result<Vec<Result<()>>> {
6131 let batch = self.prepare_entry_batch(txs)?;
6132 Ok(self.process_transaction_batch(&batch))
6133 }
6134
6135 #[must_use]
6136 fn process_transaction_batch(&self, batch: &TransactionBatch) -> Vec<Result<()>> {
6137 self.load_execute_and_commit_transactions(
6138 batch,
6139 MAX_PROCESSING_AGE,
6140 false,
6141 false,
6142 false,
6143 false,
6144 &mut ExecuteTimings::default(),
6145 None,
6146 )
6147 .0
6148 .fee_collection_results
6149 }
6150
6151 pub fn transfer(&self, n: u64, keypair: &Keypair, to: &Pubkey) -> Result<Signature> {
6154 let blockhash = self.last_blockhash();
6155 let tx = system_transaction::transfer(keypair, to, n, blockhash);
6156 let signature = tx.signatures[0];
6157 self.process_transaction(&tx).map(|_| signature)
6158 }
6159
6160 pub fn read_balance(account: &AccountSharedData) -> u64 {
6161 account.lamports()
6162 }
6163 pub fn get_balance(&self, pubkey: &Pubkey) -> u64 {
6166 self.get_account(pubkey)
6167 .map(|x| Self::read_balance(&x))
6168 .unwrap_or(0)
6169 }
6170
6171 pub fn parents(&self) -> Vec<Arc<Bank>> {
6173 let mut parents = vec![];
6174 let mut bank = self.parent();
6175 while let Some(parent) = bank {
6176 parents.push(parent.clone());
6177 bank = parent.parent();
6178 }
6179 parents
6180 }
6181
6182 pub fn parents_inclusive(self: Arc<Self>) -> Vec<Arc<Bank>> {
6184 let mut parents = self.parents();
6185 parents.insert(0, self);
6186 parents
6187 }
6188
6189 pub fn store_account<T: ReadableAccount + Sync + ZeroLamport>(
6190 &self,
6191 pubkey: &Pubkey,
6192 account: &T,
6193 ) {
6194 self.store_accounts((self.slot(), &[(pubkey, account)][..]))
6195 }
6196
6197 pub fn store_accounts<'a, T: ReadableAccount + Sync + ZeroLamport>(
6198 &self,
6199 accounts: impl StorableAccounts<'a, T>,
6200 ) {
6201 assert!(!self.freeze_started());
6202 let mut m = Measure::start("stakes_cache.check_and_store");
6203 (0..accounts.len()).into_iter().for_each(|i| {
6204 self.stakes_cache
6205 .check_and_store(accounts.pubkey(i), accounts.account(i))
6206 });
6207 self.rc.accounts.store_accounts_cached(accounts);
6208 m.stop();
6209 self.rc
6210 .accounts
6211 .accounts_db
6212 .stats
6213 .stakes_cache_check_and_store_us
6214 .fetch_add(m.as_us(), Relaxed);
6215 }
6216
6217 pub fn force_flush_accounts_cache(&self) {
6218 self.rc
6219 .accounts
6220 .accounts_db
6221 .flush_accounts_cache(true, Some(self.slot()))
6222 }
6223
6224 pub fn flush_accounts_cache_if_needed(&self) {
6225 self.rc
6226 .accounts
6227 .accounts_db
6228 .flush_accounts_cache(false, Some(self.slot()))
6229 }
6230
6231 #[cfg(test)]
6232 pub fn flush_accounts_cache_slot(&self) {
6233 self.rc
6234 .accounts
6235 .accounts_db
6236 .flush_accounts_cache_slot(self.slot())
6237 }
6238
6239 pub fn expire_old_recycle_stores(&self) {
6240 self.rc.accounts.accounts_db.expire_old_recycle_stores()
6241 }
6242
6243 fn store_account_and_update_capitalization(
6246 &self,
6247 pubkey: &Pubkey,
6248 new_account: &AccountSharedData,
6249 ) {
6250 let old_account_data_size =
6251 if let Some(old_account) = self.get_account_with_fixed_root(pubkey) {
6252 match new_account.lamports().cmp(&old_account.lamports()) {
6253 std::cmp::Ordering::Greater => {
6254 let increased = new_account.lamports() - old_account.lamports();
6255 trace!(
6256 "store_account_and_update_capitalization: increased: {} {}",
6257 pubkey,
6258 increased
6259 );
6260 self.capitalization.fetch_add(increased, Relaxed);
6261 }
6262 std::cmp::Ordering::Less => {
6263 let decreased = old_account.lamports() - new_account.lamports();
6264 trace!(
6265 "store_account_and_update_capitalization: decreased: {} {}",
6266 pubkey,
6267 decreased
6268 );
6269 self.capitalization.fetch_sub(decreased, Relaxed);
6270 }
6271 std::cmp::Ordering::Equal => {}
6272 }
6273 old_account.data().len()
6274 } else {
6275 trace!(
6276 "store_account_and_update_capitalization: created: {} {}",
6277 pubkey,
6278 new_account.lamports()
6279 );
6280 self.capitalization
6281 .fetch_add(new_account.lamports(), Relaxed);
6282 0
6283 };
6284
6285 self.store_account(pubkey, new_account);
6286 self.calculate_and_update_accounts_data_size_delta_off_chain(
6287 old_account_data_size,
6288 new_account.data().len(),
6289 );
6290 }
6291
6292 fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
6293 match self.get_account_with_fixed_root(pubkey) {
6294 Some(mut account) => {
6295 let min_balance = match get_system_account_kind(&account) {
6296 Some(SystemAccountKind::Nonce) => self
6297 .rent_collector
6298 .rent
6299 .minimum_balance(nonce::State::size()),
6300 _ => 0,
6301 };
6302
6303 lamports
6304 .checked_add(min_balance)
6305 .filter(|required_balance| *required_balance <= account.lamports())
6306 .ok_or(TransactionError::InsufficientFundsForFee)?;
6307 account
6308 .checked_sub_lamports(lamports)
6309 .map_err(|_| TransactionError::InsufficientFundsForFee)?;
6310 self.store_account(pubkey, &account);
6311
6312 Ok(())
6313 }
6314 None => Err(TransactionError::AccountNotFound),
6315 }
6316 }
6317
6318 pub fn deposit(
6319 &self,
6320 pubkey: &Pubkey,
6321 lamports: u64,
6322 ) -> std::result::Result<u64, LamportsError> {
6323 let mut account = self.get_account_with_fixed_root(pubkey).unwrap_or_default();
6326 account.checked_add_lamports(lamports)?;
6327 self.store_account(pubkey, &account);
6328 Ok(account.lamports())
6329 }
6330
6331 pub fn accounts(&self) -> Arc<Accounts> {
6332 self.rc.accounts.clone()
6333 }
6334
6335 fn finish_init(
6336 &mut self,
6337 genesis_config: &GenesisConfig,
6338 additional_builtins: Option<&Builtins>,
6339 debug_do_not_add_builtins: bool,
6340 ) {
6341 self.rewards_pool_pubkeys =
6342 Arc::new(genesis_config.rewards_pools.keys().cloned().collect());
6343
6344 let mut builtins = builtins::get();
6345 if let Some(additional_builtins) = additional_builtins {
6346 builtins
6347 .genesis_builtins
6348 .extend_from_slice(&additional_builtins.genesis_builtins);
6349 builtins
6350 .feature_transitions
6351 .extend_from_slice(&additional_builtins.feature_transitions);
6352 }
6353 if !debug_do_not_add_builtins {
6354 for builtin in builtins.genesis_builtins {
6355 self.add_builtin(
6356 &builtin.name,
6357 &builtin.id,
6358 builtin.process_instruction_with_context,
6359 );
6360 }
6361 for precompile in get_precompiles() {
6362 if precompile.feature.is_none() {
6363 self.add_precompile(&precompile.program_id);
6364 }
6365 }
6366 }
6367 self.builtin_feature_transitions = Arc::new(builtins.feature_transitions);
6368
6369 self.apply_feature_activations(
6370 ApplyFeatureActivationsCaller::FinishInit,
6371 debug_do_not_add_builtins,
6372 );
6373
6374 if self
6375 .feature_set
6376 .is_active(&feature_set::cap_accounts_data_len::id())
6377 {
6378 self.cost_tracker = RwLock::new(CostTracker::new_with_account_data_size_limit(Some(
6379 self.accounts_data_size_limit()
6380 .saturating_sub(self.accounts_data_size_initial),
6381 )));
6382 }
6383 }
6384
6385 pub fn set_inflation(&self, inflation: Inflation) {
6386 *self.inflation.write().unwrap() = inflation;
6387 }
6388
6389 pub fn set_compute_budget(&mut self, compute_budget: Option<ComputeBudget>) {
6390 self.compute_budget = compute_budget;
6391 }
6392
6393 pub fn hard_forks(&self) -> Arc<RwLock<HardForks>> {
6394 self.hard_forks.clone()
6395 }
6396
6397 pub fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6401 self.get_account_modified_slot(pubkey)
6402 .map(|(acc, _slot)| acc)
6403 }
6404
6405 pub fn get_account_with_fixed_root(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6412 self.load_slow_with_fixed_root(&self.ancestors, pubkey)
6413 .map(|(acc, _slot)| acc)
6414 }
6415
6416 pub fn get_account_modified_slot(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
6417 self.load_slow(&self.ancestors, pubkey)
6418 }
6419
6420 fn load_slow(
6421 &self,
6422 ancestors: &Ancestors,
6423 pubkey: &Pubkey,
6424 ) -> Option<(AccountSharedData, Slot)> {
6425 self.rc.accounts.load_without_fixed_root(ancestors, pubkey)
6429 }
6430
6431 fn load_slow_with_fixed_root(
6432 &self,
6433 ancestors: &Ancestors,
6434 pubkey: &Pubkey,
6435 ) -> Option<(AccountSharedData, Slot)> {
6436 self.rc.accounts.load_with_fixed_root(ancestors, pubkey)
6437 }
6438
6439 pub fn get_program_accounts(
6440 &self,
6441 program_id: &Pubkey,
6442 config: &ScanConfig,
6443 ) -> ScanResult<Vec<TransactionAccount>> {
6444 self.rc
6445 .accounts
6446 .load_by_program(&self.ancestors, self.bank_id, program_id, config)
6447 }
6448
6449 pub fn get_filtered_program_accounts<F: Fn(&AccountSharedData) -> bool>(
6450 &self,
6451 program_id: &Pubkey,
6452 filter: F,
6453 config: &ScanConfig,
6454 ) -> ScanResult<Vec<TransactionAccount>> {
6455 self.rc.accounts.load_by_program_with_filter(
6456 &self.ancestors,
6457 self.bank_id,
6458 program_id,
6459 filter,
6460 config,
6461 )
6462 }
6463
6464 pub fn get_filtered_indexed_accounts<F: Fn(&AccountSharedData) -> bool>(
6465 &self,
6466 index_key: &IndexKey,
6467 filter: F,
6468 config: &ScanConfig,
6469 byte_limit_for_scan: Option<usize>,
6470 ) -> ScanResult<Vec<TransactionAccount>> {
6471 self.rc.accounts.load_by_index_key_with_filter(
6472 &self.ancestors,
6473 self.bank_id,
6474 index_key,
6475 filter,
6476 config,
6477 byte_limit_for_scan,
6478 )
6479 }
6480
6481 pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
6482 self.rc.accounts.account_indexes_include_key(key)
6483 }
6484
6485 pub fn get_all_accounts_with_modified_slots(&self) -> ScanResult<Vec<PubkeyAccountSlot>> {
6486 self.rc.accounts.load_all(&self.ancestors, self.bank_id)
6487 }
6488
6489 pub fn get_program_accounts_modified_since_parent(
6490 &self,
6491 program_id: &Pubkey,
6492 ) -> Vec<TransactionAccount> {
6493 self.rc
6494 .accounts
6495 .load_by_program_slot(self.slot(), Some(program_id))
6496 }
6497
6498 pub fn get_transaction_logs(
6499 &self,
6500 address: Option<&Pubkey>,
6501 ) -> Option<Vec<TransactionLogInfo>> {
6502 self.transaction_log_collector
6503 .read()
6504 .unwrap()
6505 .get_logs_for_address(address)
6506 }
6507
6508 pub fn get_all_accounts_modified_since_parent(&self) -> Vec<TransactionAccount> {
6509 self.rc.accounts.load_by_program_slot(self.slot(), None)
6510 }
6511
6512 fn get_account_modified_since_parent_with_fixed_root(
6514 &self,
6515 pubkey: &Pubkey,
6516 ) -> Option<(AccountSharedData, Slot)> {
6517 let just_self: Ancestors = Ancestors::from(vec![self.slot()]);
6518 if let Some((account, slot)) = self.load_slow_with_fixed_root(&just_self, pubkey) {
6519 if slot == self.slot() {
6520 return Some((account, slot));
6521 }
6522 }
6523 None
6524 }
6525
6526 pub fn get_largest_accounts(
6527 &self,
6528 num: usize,
6529 filter_by_address: &HashSet<Pubkey>,
6530 filter: AccountAddressFilter,
6531 ) -> ScanResult<Vec<(Pubkey, u64)>> {
6532 self.rc.accounts.load_largest_accounts(
6533 &self.ancestors,
6534 self.bank_id,
6535 num,
6536 filter_by_address,
6537 filter,
6538 )
6539 }
6540
6541 pub fn transaction_count(&self) -> u64 {
6542 self.transaction_count.load(Relaxed)
6543 }
6544
6545 pub fn transaction_error_count(&self) -> u64 {
6546 self.transaction_error_count.load(Relaxed)
6547 }
6548
6549 pub fn transaction_entries_count(&self) -> u64 {
6550 self.transaction_entries_count.load(Relaxed)
6551 }
6552
6553 pub fn transactions_per_entry_max(&self) -> u64 {
6554 self.transactions_per_entry_max.load(Relaxed)
6555 }
6556
6557 fn increment_transaction_count(&self, tx_count: u64) {
6558 self.transaction_count.fetch_add(tx_count, Relaxed);
6559 }
6560
6561 pub fn signature_count(&self) -> u64 {
6562 self.signature_count.load(Relaxed)
6563 }
6564
6565 fn increment_signature_count(&self, signature_count: u64) {
6566 self.signature_count.fetch_add(signature_count, Relaxed);
6567 }
6568
6569 pub fn get_signature_status_processed_since_parent(
6570 &self,
6571 signature: &Signature,
6572 ) -> Option<Result<()>> {
6573 if let Some((slot, status)) = self.get_signature_status_slot(signature) {
6574 if slot <= self.slot() {
6575 return Some(status);
6576 }
6577 }
6578 None
6579 }
6580
6581 pub fn get_signature_status_with_blockhash(
6582 &self,
6583 signature: &Signature,
6584 blockhash: &Hash,
6585 ) -> Option<Result<()>> {
6586 let rcache = self.status_cache.read().unwrap();
6587 rcache
6588 .get_status(signature, blockhash, &self.ancestors)
6589 .map(|v| v.1)
6590 }
6591
6592 pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
6593 let rcache = self.status_cache.read().unwrap();
6594 rcache.get_status_any_blockhash(signature, &self.ancestors)
6595 }
6596
6597 pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
6598 self.get_signature_status_slot(signature).map(|v| v.1)
6599 }
6600
6601 pub fn has_signature(&self, signature: &Signature) -> bool {
6602 self.get_signature_status_slot(signature).is_some()
6603 }
6604
6605 fn hash_internal_state(&self) -> Hash {
6608 let accounts_delta_hash = self
6610 .rc
6611 .accounts
6612 .bank_hash_info_at(self.slot(), &self.rewrites_skipped_this_slot);
6613 let mut signature_count_buf = [0u8; 8];
6614 LittleEndian::write_u64(&mut signature_count_buf[..], self.signature_count() as u64);
6615
6616 let mut hash = hashv(&[
6617 self.parent_hash.as_ref(),
6618 accounts_delta_hash.hash.as_ref(),
6619 &signature_count_buf,
6620 self.last_blockhash().as_ref(),
6621 ]);
6622
6623 let buf = self
6624 .hard_forks
6625 .read()
6626 .unwrap()
6627 .get_hash_data(self.slot(), self.parent_slot());
6628 if let Some(buf) = buf {
6629 let hard_forked_hash = extend_and_hash(&hash, &buf);
6630 warn!(
6631 "hard fork at slot {} by hashing {:?}: {} => {}",
6632 self.slot(),
6633 buf,
6634 hash,
6635 hard_forked_hash
6636 );
6637 hash = hard_forked_hash;
6638 }
6639
6640 info!(
6641 "bank frozen: {} hash: {} accounts_delta: {} signature_count: {} last_blockhash: {} capitalization: {}",
6642 self.slot(),
6643 hash,
6644 accounts_delta_hash.hash,
6645 self.signature_count(),
6646 self.last_blockhash(),
6647 self.capitalization(),
6648 );
6649
6650 info!(
6651 "accounts hash slot: {} stats: {:?}",
6652 self.slot(),
6653 accounts_delta_hash.stats,
6654 );
6655 hash
6656 }
6657
6658 #[must_use]
6663 pub fn verify_bank_hash(&self, config: VerifyBankHash) -> bool {
6664 let accounts = &self.rc.accounts;
6665 accounts
6668 .accounts_db
6669 .verify_accounts_hash_in_bg
6670 .wait_for_complete();
6671
6672 if config.require_rooted_bank
6673 && !accounts
6674 .accounts_db
6675 .accounts_index
6676 .is_alive_root(self.slot())
6677 {
6678 if let Some(parent) = self.parent() {
6679 info!("{} is not a root, so attempting to verify bank hash on parent bank at slot: {}", self.slot(), parent.slot());
6680 return parent.verify_bank_hash(config);
6681 } else {
6682 panic!("cannot verify bank hash when bank is not a root");
6685 }
6686 }
6687 let slot = self.slot();
6688 let ancestors = &self.ancestors;
6689 let cap = self.capitalization();
6690 let epoch_schedule = self.epoch_schedule();
6691 let rent_collector = self.rent_collector();
6692 if config.run_in_background {
6693 let ancestors = ancestors.clone();
6694 let accounts = Arc::clone(accounts);
6695 let epoch_schedule = *epoch_schedule;
6696 let rent_collector = rent_collector.clone();
6697 let accounts_ = Arc::clone(&accounts);
6698 accounts.accounts_db.verify_accounts_hash_in_bg.start(|| {
6699 Builder::new()
6700 .name("solBgHashVerify".into())
6701 .spawn(move || {
6702 info!(
6703 "running initial verification accounts hash calculation in background"
6704 );
6705 let result = accounts_.verify_bank_hash_and_lamports(
6706 slot,
6707 &ancestors,
6708 cap,
6709 config.test_hash_calculation,
6710 &epoch_schedule,
6711 &rent_collector,
6712 config.can_cached_slot_be_unflushed,
6713 config.ignore_mismatch,
6714 config.store_hash_raw_data_for_debug,
6715 true,
6717 );
6718 accounts_
6719 .accounts_db
6720 .verify_accounts_hash_in_bg
6721 .background_finished();
6722 result
6723 })
6724 .unwrap()
6725 });
6726 true } else {
6728 let result = accounts.verify_bank_hash_and_lamports(
6729 slot,
6730 &self.ancestors,
6731 cap,
6732 config.test_hash_calculation,
6733 epoch_schedule,
6734 rent_collector,
6735 config.can_cached_slot_be_unflushed,
6736 config.ignore_mismatch,
6737 config.store_hash_raw_data_for_debug,
6738 false,
6740 );
6741 self.set_initial_accounts_hash_verification_completed();
6742 result
6743 }
6744 }
6745
6746 pub fn set_initial_accounts_hash_verification_completed(&self) {
6750 self.rc
6751 .accounts
6752 .accounts_db
6753 .verify_accounts_hash_in_bg
6754 .verification_complete();
6755 }
6756
6757 pub fn has_initial_accounts_hash_verification_completed(&self) -> bool {
6761 self.rc
6762 .accounts
6763 .accounts_db
6764 .verify_accounts_hash_in_bg
6765 .check_complete()
6766 }
6767
6768 pub fn get_snapshot_storages(&self, base_slot: Option<Slot>) -> SnapshotStorages {
6769 self.rc
6770 .accounts
6771 .accounts_db
6772 .get_snapshot_storages(self.slot(), base_slot, None)
6773 .0
6774 }
6775
6776 #[must_use]
6777 fn verify_hash(&self) -> bool {
6778 assert!(self.is_frozen());
6779 let calculated_hash = self.hash_internal_state();
6780 let expected_hash = self.hash();
6781
6782 if calculated_hash == expected_hash {
6783 true
6784 } else {
6785 warn!(
6786 "verify failed: slot: {}, {} (calculated) != {} (expected)",
6787 self.slot(),
6788 calculated_hash,
6789 expected_hash
6790 );
6791 false
6792 }
6793 }
6794
6795 pub fn verify_transaction(
6796 &self,
6797 tx: VersionedTransaction,
6798 verification_mode: TransactionVerificationMode,
6799 ) -> Result<SanitizedTransaction> {
6800 let sanitized_tx = {
6801 let size =
6802 bincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?;
6803 if size > PACKET_DATA_SIZE as u64 {
6804 return Err(TransactionError::SanitizeFailure);
6805 }
6806 let message_hash = if verification_mode == TransactionVerificationMode::FullVerification
6807 {
6808 tx.verify_and_hash_message()?
6809 } else {
6810 tx.message.hash()
6811 };
6812
6813 SanitizedTransaction::try_create(
6814 tx,
6815 message_hash,
6816 None,
6817 self,
6818 self.feature_set
6819 .is_active(&feature_set::require_static_program_ids_in_transaction::ID),
6820 )
6821 }?;
6822
6823 if verification_mode == TransactionVerificationMode::HashAndVerifyPrecompiles
6824 || verification_mode == TransactionVerificationMode::FullVerification
6825 {
6826 sanitized_tx.verify_precompiles(&self.feature_set)?;
6827 }
6828
6829 Ok(sanitized_tx)
6830 }
6831
6832 fn calculate_capitalization(&self, debug_verify: bool) -> u64 {
6834 let can_cached_slot_be_unflushed = true; self.rc.accounts.calculate_capitalization(
6836 &self.ancestors,
6837 self.slot(),
6838 can_cached_slot_be_unflushed,
6839 debug_verify,
6840 self.epoch_schedule(),
6841 &self.rent_collector,
6842 )
6843 }
6844
6845 pub fn calculate_and_verify_capitalization(&self, debug_verify: bool) -> bool {
6847 let calculated = self.calculate_capitalization(debug_verify);
6848 *self.inflation.write().unwrap() = Inflation::full();
6849 let expected = self.capitalization();
6850 if calculated == expected {
6851 true
6852 } else {
6853 warn!(
6854 "Capitalization mismatch: calculated: {} != expected: {}",
6855 calculated, expected
6856 );
6857 false
6858 }
6859 }
6860
6861 pub fn set_capitalization(&self) -> u64 {
6864 let old = self.capitalization();
6865 let debug_verify = true;
6866 self.capitalization
6867 .store(self.calculate_capitalization(debug_verify), Relaxed);
6868 old
6869 }
6870
6871 pub fn get_accounts_hash(&self) -> Hash {
6872 self.rc.accounts.accounts_db.get_accounts_hash(self.slot)
6873 }
6874
6875 pub fn get_thread_pool(&self) -> &ThreadPool {
6876 &self.rc.accounts.accounts_db.thread_pool_clean
6877 }
6878
6879 pub fn load_account_into_read_cache(&self, key: &Pubkey) {
6880 self.rc
6881 .accounts
6882 .accounts_db
6883 .load_account_into_read_cache(&self.ancestors, key);
6884 }
6885
6886 pub fn update_accounts_hash_with_index_option(
6887 &self,
6888 use_index: bool,
6889 mut debug_verify: bool,
6890 is_startup: bool,
6891 ) -> Hash {
6892 let (hash, total_lamports) = self
6893 .rc
6894 .accounts
6895 .accounts_db
6896 .update_accounts_hash_with_index_option(
6897 use_index,
6898 debug_verify,
6899 self.slot(),
6900 &self.ancestors,
6901 Some(self.capitalization()),
6902 false,
6903 self.epoch_schedule(),
6904 &self.rent_collector,
6905 is_startup,
6906 );
6907 if total_lamports != self.capitalization() {
6908 datapoint_info!(
6909 "capitalization_mismatch",
6910 ("slot", self.slot(), i64),
6911 ("calculated_lamports", total_lamports, i64),
6912 ("capitalization", self.capitalization(), i64),
6913 );
6914
6915 if !debug_verify {
6916 debug_verify = true;
6919 self.rc
6920 .accounts
6921 .accounts_db
6922 .update_accounts_hash_with_index_option(
6923 use_index,
6924 debug_verify,
6925 self.slot(),
6926 &self.ancestors,
6927 Some(self.capitalization()),
6928 false,
6929 self.epoch_schedule(),
6930 &self.rent_collector,
6931 is_startup,
6932 );
6933 }
6934
6935 panic!(
6936 "capitalization_mismatch. slot: {}, calculated_lamports: {}, capitalization: {}",
6937 self.slot(),
6938 total_lamports,
6939 self.capitalization()
6940 );
6941 }
6942 hash
6943 }
6944
6945 pub fn update_accounts_hash(&self) -> Hash {
6946 self.update_accounts_hash_with_index_option(true, false, false)
6947 }
6948
6949 pub fn verify_snapshot_bank(
6952 &self,
6953 test_hash_calculation: bool,
6954 accounts_db_skip_shrink: bool,
6955 last_full_snapshot_slot: Option<Slot>,
6956 ) -> bool {
6957 let mut clean_time = Measure::start("clean");
6958 if !accounts_db_skip_shrink && self.slot() > 0 {
6959 info!("cleaning..");
6960 self.clean_accounts(true, true, last_full_snapshot_slot);
6961 }
6962 clean_time.stop();
6963
6964 let mut shrink_all_slots_time = Measure::start("shrink_all_slots");
6965 if !accounts_db_skip_shrink && self.slot() > 0 {
6966 info!("shrinking..");
6967 self.shrink_all_slots(true, last_full_snapshot_slot);
6968 }
6969 shrink_all_slots_time.stop();
6970
6971 let (mut verify, verify_time_us) = if !self.rc.accounts.accounts_db.skip_initial_hash_calc {
6972 info!("verify_bank_hash..");
6973 let mut verify_time = Measure::start("verify_bank_hash");
6974 let verify = self.verify_bank_hash(VerifyBankHash {
6975 test_hash_calculation,
6976 can_cached_slot_be_unflushed: false,
6977 ignore_mismatch: false,
6978 require_rooted_bank: false,
6979 run_in_background: true,
6980 store_hash_raw_data_for_debug: false,
6981 });
6982 verify_time.stop();
6983 (verify, verify_time.as_us())
6984 } else {
6985 self.rc
6986 .accounts
6987 .accounts_db
6988 .verify_accounts_hash_in_bg
6989 .verification_complete();
6990 (true, 0)
6991 };
6992
6993 info!("verify_hash..");
6994 let mut verify2_time = Measure::start("verify_hash");
6995 verify = verify && self.verify_hash();
6997 verify2_time.stop();
6998
6999 datapoint_info!(
7000 "verify_snapshot_bank",
7001 ("clean_us", clean_time.as_us(), i64),
7002 ("shrink_all_slots_us", shrink_all_slots_time.as_us(), i64),
7003 ("verify_bank_hash_us", verify_time_us, i64),
7004 ("verify_hash_us", verify2_time.as_us(), i64),
7005 );
7006
7007 verify
7008 }
7009
7010 pub fn hashes_per_tick(&self) -> &Option<u64> {
7012 &self.hashes_per_tick
7013 }
7014
7015 pub fn ticks_per_slot(&self) -> u64 {
7017 self.ticks_per_slot
7018 }
7019
7020 pub fn slots_per_year(&self) -> f64 {
7022 self.slots_per_year
7023 }
7024
7025 pub fn tick_height(&self) -> u64 {
7027 self.tick_height.load(Relaxed)
7028 }
7029
7030 pub fn inflation(&self) -> Inflation {
7032 *self.inflation.read().unwrap()
7033 }
7034
7035 pub fn rent_collector(&self) -> &RentCollector {
7036 &self.rent_collector
7037 }
7038
7039 pub fn capitalization(&self) -> u64 {
7041 self.capitalization.load(Relaxed)
7042 }
7043
7044 pub fn max_tick_height(&self) -> u64 {
7046 self.max_tick_height
7047 }
7048
7049 pub fn block_height(&self) -> u64 {
7051 self.block_height
7052 }
7053
7054 pub fn get_slots_in_epoch(&self, epoch: Epoch) -> u64 {
7056 self.epoch_schedule().get_slots_in_epoch(epoch)
7057 }
7058
7059 pub fn get_leader_schedule_epoch(&self, slot: Slot) -> Epoch {
7062 self.epoch_schedule().get_leader_schedule_epoch(slot)
7063 }
7064
7065 fn update_stakes_cache(
7067 &self,
7068 txs: &[SanitizedTransaction],
7069 execution_results: &[TransactionExecutionResult],
7070 loaded_txs: &[TransactionLoadResult],
7071 ) {
7072 for (i, ((load_result, _load_nonce), tx)) in loaded_txs.iter().zip(txs).enumerate() {
7073 if let (Ok(loaded_transaction), true) = (
7074 load_result,
7075 execution_results[i].was_executed_successfully(),
7076 ) {
7077 let message = tx.message();
7080 for (_i, (pubkey, account)) in
7081 (0..message.account_keys().len()).zip(loaded_transaction.accounts.iter())
7082 {
7083 self.stakes_cache.check_and_store(pubkey, account);
7084 }
7085 }
7086 }
7087 }
7088
7089 pub fn staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
7090 self.stakes_cache.stakes().staked_nodes()
7091 }
7092
7093 pub fn vote_accounts(&self) -> Arc<VoteAccountsHashMap> {
7096 let stakes = self.stakes_cache.stakes();
7097 Arc::from(stakes.vote_accounts())
7098 }
7099
7100 pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<VoteAccount> {
7102 let stakes = self.stakes_cache.stakes();
7103 let vote_account = stakes.vote_accounts().get(vote_account)?;
7104 Some(vote_account.clone())
7105 }
7106
7107 pub fn epoch_stakes(&self, epoch: Epoch) -> Option<&EpochStakes> {
7109 self.epoch_stakes.get(&epoch)
7110 }
7111
7112 pub fn epoch_stakes_map(&self) -> &HashMap<Epoch, EpochStakes> {
7113 &self.epoch_stakes
7114 }
7115
7116 pub fn epoch_staked_nodes(&self, epoch: Epoch) -> Option<Arc<HashMap<Pubkey, u64>>> {
7117 Some(self.epoch_stakes.get(&epoch)?.stakes().staked_nodes())
7118 }
7119
7120 pub fn epoch_vote_accounts(&self, epoch: Epoch) -> Option<&VoteAccountsHashMap> {
7123 let epoch_stakes = self.epoch_stakes.get(&epoch)?.stakes();
7124 Some(epoch_stakes.vote_accounts().as_ref())
7125 }
7126
7127 pub fn epoch_authorized_voter(&self, vote_account: &Pubkey) -> Option<&Pubkey> {
7130 self.epoch_stakes
7131 .get(&self.epoch)
7132 .expect("Epoch stakes for bank's own epoch must exist")
7133 .epoch_authorized_voters()
7134 .get(vote_account)
7135 }
7136
7137 pub fn epoch_vote_accounts_for_node_id(&self, node_id: &Pubkey) -> Option<&NodeVoteAccounts> {
7140 self.epoch_stakes
7141 .get(&self.epoch)
7142 .expect("Epoch stakes for bank's own epoch must exist")
7143 .node_id_to_vote_accounts()
7144 .get(node_id)
7145 }
7146
7147 pub fn total_epoch_stake(&self) -> u64 {
7149 self.epoch_stakes
7150 .get(&self.epoch)
7151 .expect("Epoch stakes for bank's own epoch must exist")
7152 .total_stake()
7153 }
7154
7155 pub fn epoch_vote_account_stake(&self, vote_account: &Pubkey) -> u64 {
7157 *self
7158 .epoch_vote_accounts(self.epoch())
7159 .expect("Bank epoch vote accounts must contain entry for the bank's own epoch")
7160 .get(vote_account)
7161 .map(|(stake, _)| stake)
7162 .unwrap_or(&0)
7163 }
7164
7165 pub fn get_epoch_and_slot_index(&self, slot: Slot) -> (Epoch, SlotIndex) {
7171 self.epoch_schedule().get_epoch_and_slot_index(slot)
7172 }
7173
7174 pub fn get_epoch_info(&self) -> EpochInfo {
7175 let absolute_slot = self.slot();
7176 let block_height = self.block_height();
7177 let (epoch, slot_index) = self.get_epoch_and_slot_index(absolute_slot);
7178 let slots_in_epoch = self.get_slots_in_epoch(epoch);
7179 let transaction_count = Some(self.transaction_count());
7180 EpochInfo {
7181 epoch,
7182 slot_index,
7183 slots_in_epoch,
7184 absolute_slot,
7185 block_height,
7186 transaction_count,
7187 }
7188 }
7189
7190 pub fn is_empty(&self) -> bool {
7191 !self.is_delta.load(Relaxed)
7192 }
7193
7194 pub fn add_builtin(
7196 &mut self,
7197 name: &str,
7198 program_id: &Pubkey,
7199 process_instruction: ProcessInstructionWithContext,
7200 ) {
7201 debug!("Adding program {} under {:?}", name, program_id);
7202 self.add_builtin_account(name, program_id, false);
7203 if let Some(entry) = self
7204 .builtin_programs
7205 .vec
7206 .iter_mut()
7207 .find(|entry| entry.program_id == *program_id)
7208 {
7209 entry.process_instruction = process_instruction;
7210 } else {
7211 self.builtin_programs.vec.push(BuiltinProgram {
7212 program_id: *program_id,
7213 process_instruction,
7214 });
7215 }
7216 debug!("Added program {} under {:?}", name, program_id);
7217 }
7218
7219 pub fn remove_builtin(&mut self, program_id: &Pubkey) {
7221 debug!("Removing program {}", program_id);
7222 if let Some(position) = self
7225 .builtin_programs
7226 .vec
7227 .iter()
7228 .position(|entry| entry.program_id == *program_id)
7229 {
7230 self.builtin_programs.vec.remove(position);
7231 }
7232 debug!("Removed program {}", program_id);
7233 }
7234
7235 pub fn add_precompile(&mut self, program_id: &Pubkey) {
7236 debug!("Adding precompiled program {}", program_id);
7237 self.add_precompiled_account(program_id);
7238 debug!("Added precompiled program {:?}", program_id);
7239 }
7240
7241 pub fn clean_accounts(
7242 &self,
7243 skip_last: bool,
7244 is_startup: bool,
7245 last_full_snapshot_slot: Option<Slot>,
7246 ) {
7247 let highest_slot_to_clean = skip_last.then(|| self.slot().saturating_sub(1));
7255
7256 self.rc.accounts.accounts_db.clean_accounts(
7257 highest_slot_to_clean,
7258 is_startup,
7259 last_full_snapshot_slot,
7260 );
7261 }
7262
7263 pub fn shrink_all_slots(&self, is_startup: bool, last_full_snapshot_slot: Option<Slot>) {
7264 self.rc
7265 .accounts
7266 .accounts_db
7267 .shrink_all_slots(is_startup, last_full_snapshot_slot);
7268 }
7269
7270 pub fn print_accounts_stats(&self) {
7271 self.rc.accounts.accounts_db.print_accounts_stats("");
7272 }
7273
7274 pub fn process_stale_slot_with_budget(
7275 &self,
7276 mut consumed_budget: usize,
7277 budget_recovery_delta: usize,
7278 ) -> usize {
7279 if consumed_budget == 0 {
7280 let shrunken_account_count = self.rc.accounts.accounts_db.process_stale_slot_v1();
7281 if shrunken_account_count > 0 {
7282 datapoint_info!(
7283 "stale_slot_shrink",
7284 ("accounts", shrunken_account_count, i64)
7285 );
7286 consumed_budget += shrunken_account_count;
7287 }
7288 }
7289 consumed_budget.saturating_sub(budget_recovery_delta)
7290 }
7291
7292 pub fn bank_tranaction_count_fix_enabled(&self) -> bool {
7293 self.feature_set
7294 .is_active(&feature_set::bank_tranaction_count_fix::id())
7295 }
7296
7297 pub fn shrink_candidate_slots(&self) -> usize {
7298 self.rc.accounts.accounts_db.shrink_candidate_slots()
7299 }
7300
7301 pub fn no_overflow_rent_distribution_enabled(&self) -> bool {
7302 self.feature_set
7303 .is_active(&feature_set::no_overflow_rent_distribution::id())
7304 }
7305
7306 pub fn versioned_tx_message_enabled(&self) -> bool {
7307 self.feature_set
7308 .is_active(&feature_set::versioned_tx_message_enabled::id())
7309 }
7310
7311 pub fn credits_auto_rewind(&self) -> bool {
7312 self.feature_set
7313 .is_active(&feature_set::credits_auto_rewind::id())
7314 }
7315
7316 pub fn send_to_tpu_vote_port_enabled(&self) -> bool {
7317 self.feature_set
7318 .is_active(&feature_set::send_to_tpu_vote_port::id())
7319 }
7320
7321 fn preserve_rent_epoch_for_rent_exempt_accounts(&self) -> bool {
7322 self.feature_set
7323 .is_active(&feature_set::preserve_rent_epoch_for_rent_exempt_accounts::id())
7324 }
7325
7326 pub fn concurrent_replay_of_forks(&self) -> bool {
7327 self.feature_set
7328 .is_active(&feature_set::concurrent_replay_of_forks::id())
7329 }
7330
7331 pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<CostTracker>> {
7332 self.cost_tracker.read()
7333 }
7334
7335 pub fn write_cost_tracker(&self) -> LockResult<RwLockWriteGuard<CostTracker>> {
7336 self.cost_tracker.write()
7337 }
7338
7339 pub fn should_bank_still_be_processing_txs(
7342 bank_creation_time: &Instant,
7343 max_tx_ingestion_nanos: u128,
7344 ) -> bool {
7345 bank_creation_time.elapsed().as_nanos() <= max_tx_ingestion_nanos
7347 }
7348
7349 pub fn deactivate_feature(&mut self, id: &Pubkey) {
7350 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
7351 feature_set.active.remove(id);
7352 feature_set.inactive.insert(*id);
7353 self.feature_set = Arc::new(feature_set);
7354 }
7355
7356 pub fn activate_feature(&mut self, id: &Pubkey) {
7357 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
7358 feature_set.inactive.remove(id);
7359 feature_set.active.insert(*id, 0);
7360 self.feature_set = Arc::new(feature_set);
7361 }
7362
7363 pub fn fill_bank_with_ticks_for_tests(&self) {
7364 if self.tick_height.load(Relaxed) < self.max_tick_height {
7365 let last_blockhash = self.last_blockhash();
7366 while self.last_blockhash() == last_blockhash {
7367 self.register_tick(&Hash::new_unique())
7368 }
7369 } else {
7370 warn!("Bank already reached max tick height, cannot fill it with more ticks");
7371 }
7372 }
7373
7374 fn apply_feature_activations(
7377 &mut self,
7378 caller: ApplyFeatureActivationsCaller,
7379 debug_do_not_add_builtins: bool,
7380 ) {
7381 use ApplyFeatureActivationsCaller::*;
7382 let allow_new_activations = match caller {
7383 FinishInit => false,
7384 NewFromParent => true,
7385 WarpFromParent => false,
7386 };
7387 let new_feature_activations = self.compute_active_feature_set(allow_new_activations);
7388
7389 if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
7390 *self.inflation.write().unwrap() = Inflation::full();
7391 self.fee_rate_governor.burn_percent = 50; self.rent_collector.rent.burn_percent = 50; }
7394
7395 if !new_feature_activations.is_disjoint(&self.feature_set.full_inflation_features_enabled())
7396 {
7397 *self.inflation.write().unwrap() = Inflation::full();
7398 self.fee_rate_governor.burn_percent = 50; self.rent_collector.rent.burn_percent = 50; }
7401
7402 if new_feature_activations.contains(&feature_set::safe_token_v3_4_0::id()) {
7403 self.replace_program_account(
7404 &inline_safe_token::id(),
7405 &inline_safe_token::program_v3_4_0::id(),
7406 "bank-apply_safe_token_v3_4_0",
7407 );
7408 }
7409
7410 if new_feature_activations.contains(&feature_set::safe_associated_token_account_v1_1_0::id())
7411 {
7412 self.replace_program_account(
7413 &inline_safe_associated_token_account::id(),
7414 &inline_safe_associated_token_account::program_v1_1_0::id(),
7415 "bank-apply_safe_associated_token_account_v1_1_0",
7416 );
7417 }
7418
7419 if !debug_do_not_add_builtins {
7420 self.apply_builtin_program_feature_transitions(
7421 allow_new_activations,
7422 &new_feature_activations,
7423 );
7424 self.reconfigure_token2_native_mint();
7425 }
7426 self.ensure_no_storage_rewards_pool();
7427
7428 if new_feature_activations.contains(&feature_set::cap_accounts_data_len::id()) {
7429 const ACCOUNTS_DATA_LEN: u64 = 50_000_000_000;
7430 self.accounts_data_size_initial = ACCOUNTS_DATA_LEN;
7431 }
7432 }
7433
7434 fn adjust_sysvar_balance_for_rent(&self, account: &mut AccountSharedData) {
7435 account.set_lamports(
7436 self.get_minimum_balance_for_rent_exemption(account.data().len())
7437 .max(account.lamports()),
7438 );
7439 }
7440
7441 fn compute_active_feature_set(&mut self, allow_new_activations: bool) -> HashSet<Pubkey> {
7443 let mut active = self.feature_set.active.clone();
7444 let mut inactive = HashSet::new();
7445 let mut newly_activated = HashSet::new();
7446 let slot = self.slot();
7447
7448 for feature_id in &self.feature_set.inactive {
7449 let mut activated = None;
7450 if let Some(mut account) = self.get_account_with_fixed_root(feature_id) {
7451 if let Some(mut feature) = feature::from_account(&account) {
7452 match feature.activated_at {
7453 None => {
7454 if allow_new_activations {
7455 feature.activated_at = Some(slot);
7457 if feature::to_account(&feature, &mut account).is_some() {
7458 self.store_account(feature_id, &account);
7459 }
7460 newly_activated.insert(*feature_id);
7461 activated = Some(slot);
7462 info!("Feature {} activated at slot {}", feature_id, slot);
7463 }
7464 }
7465 Some(activation_slot) => {
7466 if slot >= activation_slot {
7467 activated = Some(activation_slot);
7469 }
7470 }
7471 }
7472 }
7473 }
7474 if let Some(slot) = activated {
7475 active.insert(*feature_id, slot);
7476 } else {
7477 inactive.insert(*feature_id);
7478 }
7479 }
7480
7481 self.feature_set = Arc::new(FeatureSet { active, inactive });
7482 newly_activated
7483 }
7484
7485 fn apply_builtin_program_feature_transitions(
7486 &mut self,
7487 only_apply_transitions_for_new_features: bool,
7488 new_feature_activations: &HashSet<Pubkey>,
7489 ) {
7490 let feature_set = self.feature_set.clone();
7491 let should_apply_action_for_feature_transition = |feature_id: &Pubkey| -> bool {
7492 if only_apply_transitions_for_new_features {
7493 new_feature_activations.contains(feature_id)
7494 } else {
7495 feature_set.is_active(feature_id)
7496 }
7497 };
7498
7499 let builtin_feature_transitions = self.builtin_feature_transitions.clone();
7500 for transition in builtin_feature_transitions.iter() {
7501 if let Some(builtin_action) =
7502 transition.to_action(&should_apply_action_for_feature_transition)
7503 {
7504 match builtin_action {
7505 BuiltinAction::Add(builtin) => self.add_builtin(
7506 &builtin.name,
7507 &builtin.id,
7508 builtin.process_instruction_with_context,
7509 ),
7510 BuiltinAction::Remove(program_id) => self.remove_builtin(&program_id),
7511 }
7512 }
7513 }
7514
7515 for precompile in get_precompiles() {
7516 #[allow(clippy::blocks_in_if_conditions)]
7517 if precompile.feature.map_or(false, |ref feature_id| {
7518 self.feature_set.is_active(feature_id)
7519 }) {
7520 self.add_precompile(&precompile.program_id);
7521 }
7522 }
7523 }
7524
7525 fn replace_program_account(
7526 &mut self,
7527 old_address: &Pubkey,
7528 new_address: &Pubkey,
7529 datapoint_name: &'static str,
7530 ) {
7531 if let Some(old_account) = self.get_account_with_fixed_root(old_address) {
7532 if let Some(new_account) = self.get_account_with_fixed_root(new_address) {
7533 datapoint_info!(datapoint_name, ("slot", self.slot, i64));
7534
7535 self.capitalization
7537 .fetch_sub(old_account.lamports(), Relaxed);
7538
7539 self.store_account(old_address, &new_account);
7541
7542 self.store_account(new_address, &AccountSharedData::default());
7544
7545 self.remove_executor(old_address);
7546
7547 self.calculate_and_update_accounts_data_size_delta_off_chain(
7548 old_account.data().len(),
7549 new_account.data().len(),
7550 );
7551 }
7552 }
7553 }
7554
7555 fn reconfigure_token2_native_mint(&mut self) {
7556 let reconfigure_token2_native_mint = match self.cluster_type() {
7557 ClusterType::Development => true,
7558 ClusterType::Devnet => true,
7559 ClusterType::Testnet => self.epoch() == 93,
7560 ClusterType::MainnetBeta => self.epoch() == 9999999,
7561 };
7562
7563 if reconfigure_token2_native_mint {
7564 let mut native_mint_account = solana_sdk::account::AccountSharedData::from(Account {
7565 owner: inline_safe_token::id(),
7566 data: inline_safe_token::native_mint::ACCOUNT_DATA.to_vec(),
7567 lamports: sol_to_lamports(1.),
7568 executable: false,
7569 rent_epoch: self.epoch() + 1,
7570 });
7571
7572 let old_account_data_size;
7576 let store = if let Some(existing_native_mint_account) =
7577 self.get_account_with_fixed_root(&inline_safe_token::native_mint::id())
7578 {
7579 old_account_data_size = existing_native_mint_account.data().len();
7580 if existing_native_mint_account.owner() == &solana_sdk::system_program::id() {
7581 native_mint_account.set_lamports(existing_native_mint_account.lamports());
7582 true
7583 } else {
7584 false
7585 }
7586 } else {
7587 old_account_data_size = 0;
7588 self.capitalization
7589 .fetch_add(native_mint_account.lamports(), Relaxed);
7590 true
7591 };
7592
7593 if store {
7594 self.store_account(&inline_safe_token::native_mint::id(), &native_mint_account);
7595 self.calculate_and_update_accounts_data_size_delta_off_chain(
7596 old_account_data_size,
7597 native_mint_account.data().len(),
7598 );
7599 }
7600 }
7601 }
7602
7603 fn ensure_no_storage_rewards_pool(&mut self) {
7604 let purge_window_epoch = match self.cluster_type() {
7605 ClusterType::Development => false,
7606 ClusterType::Devnet => false,
7608 ClusterType::Testnet => self.epoch() == 93,
7610 ClusterType::MainnetBeta => false,
7612 };
7613
7614 if purge_window_epoch {
7615 for reward_pubkey in self.rewards_pool_pubkeys.iter() {
7616 if let Some(mut reward_account) = self.get_account_with_fixed_root(reward_pubkey) {
7617 if reward_account.lamports() == u64::MAX {
7618 reward_account.set_lamports(0);
7619 self.store_account(reward_pubkey, &reward_account);
7620 self.capitalization.fetch_add(1, Relaxed);
7622 info!(
7623 "purged rewards pool account: {}, new capitalization: {}",
7624 reward_pubkey,
7625 self.capitalization()
7626 );
7627 }
7628 };
7629 }
7630 }
7631 }
7632
7633 pub fn get_total_accounts_stats(&self) -> ScanResult<TotalAccountsStats> {
7635 let accounts = self.get_all_accounts_with_modified_slots()?;
7636 Ok(self.calculate_total_accounts_stats(
7637 accounts
7638 .iter()
7639 .map(|(pubkey, account, _slot)| (pubkey, account)),
7640 ))
7641 }
7642
7643 pub fn calculate_total_accounts_stats<'a>(
7645 &self,
7646 accounts: impl Iterator<Item = (&'a Pubkey, &'a AccountSharedData)>,
7647 ) -> TotalAccountsStats {
7648 let rent_collector = self.rent_collector();
7649 let mut total_accounts_stats = TotalAccountsStats::default();
7650 accounts.for_each(|(pubkey, account)| {
7651 let data_len = account.data().len();
7652 total_accounts_stats.num_accounts += 1;
7653 total_accounts_stats.data_len += data_len;
7654
7655 if account.executable() {
7656 total_accounts_stats.num_executable_accounts += 1;
7657 total_accounts_stats.executable_data_len += data_len;
7658 }
7659
7660 if !rent_collector.should_collect_rent(pubkey, account)
7661 || rent_collector.get_rent_due(account).is_exempt()
7662 {
7663 total_accounts_stats.num_rent_exempt_accounts += 1;
7664 } else {
7665 total_accounts_stats.num_rent_paying_accounts += 1;
7666 total_accounts_stats.lamports_in_rent_paying_accounts += account.lamports();
7667 if data_len == 0 {
7668 total_accounts_stats.num_rent_paying_accounts_without_data += 1;
7669 }
7670 }
7671 });
7672
7673 total_accounts_stats
7674 }
7675}
7676
7677fn calculate_data_size_delta(old_data_size: usize, new_data_size: usize) -> i64 {
7680 assert!(old_data_size <= i64::MAX as usize);
7681 assert!(new_data_size <= i64::MAX as usize);
7682 let old_data_size = old_data_size as i64;
7683 let new_data_size = new_data_size as i64;
7684
7685 new_data_size.saturating_sub(old_data_size)
7686}
7687
7688#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7691enum ApplyFeatureActivationsCaller {
7692 FinishInit,
7693 NewFromParent,
7694 WarpFromParent,
7695}
7696
7697#[derive(Debug, Default)]
7703struct CollectRentFromAccountsInfo {
7704 rent_collected_info: CollectedInfo,
7705 rent_rewards: Vec<(Pubkey, RewardInfo)>,
7706 rewrites_skipped: Vec<(Pubkey, Hash)>,
7707 time_collecting_rent_us: u64,
7708 time_hashing_skipped_rewrites_us: u64,
7709 time_storing_accounts_us: u64,
7710 num_accounts: usize,
7711}
7712
7713#[derive(Debug, Default)]
7716struct CollectRentInPartitionInfo {
7717 rent_collected: u64,
7718 accounts_data_size_reclaimed: u64,
7719 rent_rewards: Vec<(Pubkey, RewardInfo)>,
7720 rewrites_skipped: Vec<(Pubkey, Hash)>,
7721 time_loading_accounts_us: u64,
7722 time_collecting_rent_us: u64,
7723 time_hashing_skipped_rewrites_us: u64,
7724 time_storing_accounts_us: u64,
7725 num_accounts: usize,
7726}
7727
7728impl CollectRentInPartitionInfo {
7729 #[must_use]
7732 fn new(info: CollectRentFromAccountsInfo, time_loading_accounts: Duration) -> Self {
7733 Self {
7734 rent_collected: info.rent_collected_info.rent_amount,
7735 accounts_data_size_reclaimed: info.rent_collected_info.account_data_len_reclaimed,
7736 rent_rewards: info.rent_rewards,
7737 rewrites_skipped: info.rewrites_skipped,
7738 time_loading_accounts_us: time_loading_accounts.as_micros() as u64,
7739 time_collecting_rent_us: info.time_collecting_rent_us,
7740 time_hashing_skipped_rewrites_us: info.time_hashing_skipped_rewrites_us,
7741 time_storing_accounts_us: info.time_storing_accounts_us,
7742 num_accounts: info.num_accounts,
7743 }
7744 }
7745
7746 #[must_use]
7751 fn reduce(lhs: Self, rhs: Self) -> Self {
7752 Self {
7753 rent_collected: lhs.rent_collected.saturating_add(rhs.rent_collected),
7754 accounts_data_size_reclaimed: lhs
7755 .accounts_data_size_reclaimed
7756 .saturating_add(rhs.accounts_data_size_reclaimed),
7757 rent_rewards: [lhs.rent_rewards, rhs.rent_rewards].concat(),
7758 rewrites_skipped: [lhs.rewrites_skipped, rhs.rewrites_skipped].concat(),
7759 time_loading_accounts_us: lhs
7760 .time_loading_accounts_us
7761 .saturating_add(rhs.time_loading_accounts_us),
7762 time_collecting_rent_us: lhs
7763 .time_collecting_rent_us
7764 .saturating_add(rhs.time_collecting_rent_us),
7765 time_hashing_skipped_rewrites_us: lhs
7766 .time_hashing_skipped_rewrites_us
7767 .saturating_add(rhs.time_hashing_skipped_rewrites_us),
7768 time_storing_accounts_us: lhs
7769 .time_storing_accounts_us
7770 .saturating_add(rhs.time_storing_accounts_us),
7771 num_accounts: lhs.num_accounts.saturating_add(rhs.num_accounts),
7772 }
7773 }
7774}
7775
7776#[derive(Debug, Default, Copy, Clone)]
7778pub struct TotalAccountsStats {
7779 pub num_accounts: usize,
7781 pub data_len: usize,
7783
7784 pub num_executable_accounts: usize,
7786 pub executable_data_len: usize,
7788
7789 pub num_rent_exempt_accounts: usize,
7791 pub num_rent_paying_accounts: usize,
7793 pub num_rent_paying_accounts_without_data: usize,
7795 pub lamports_in_rent_paying_accounts: u64,
7797}
7798
7799impl Drop for Bank {
7800 fn drop(&mut self) {
7801 if let Some(drop_callback) = self.drop_callback.read().unwrap().0.as_ref() {
7802 drop_callback.callback(self);
7803 } else {
7804 self.rc
7806 .accounts
7807 .accounts_db
7808 .purge_slot(self.slot(), self.bank_id(), false);
7809 }
7810 }
7811}
7812
7813pub mod test_utils {
7815 use {super::Bank, solana_sdk::hash::hashv};
7816 pub fn goto_end_of_slot(bank: &mut Bank) {
7817 let mut tick_hash = bank.last_blockhash();
7818 loop {
7819 tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
7820 bank.register_tick(&tick_hash);
7821 if tick_hash == bank.last_blockhash() {
7822 bank.freeze();
7823 return;
7824 }
7825 }
7826 }
7827}
7828
7829#[cfg(test)]
7830pub(crate) mod tests {
7831 #[allow(deprecated)]
7832 use solana_sdk::sysvar::fees::Fees;
7833 use {
7834 super::*,
7835 crate::{
7836 accounts_background_service::{AbsRequestHandler, SendDroppedBankCallback},
7837 accounts_db::DEFAULT_ACCOUNTS_SHRINK_RATIO,
7838 accounts_index::{AccountIndex, AccountSecondaryIndexes, ScanError, ITER_BATCH_SIZE},
7839 ancestors::Ancestors,
7840 genesis_utils::{
7841 self, activate_all_features, bootstrap_validator_stake_lamports,
7842 create_genesis_config_with_leader, create_genesis_config_with_vote_accounts,
7843 genesis_sysvar_and_builtin_program_lamports, GenesisConfigInfo,
7844 ValidatorVoteKeypairs,
7845 },
7846 rent_paying_accounts_by_partition::RentPayingAccountsByPartition,
7847 status_cache::MAX_CACHE_ENTRIES,
7848 },
7849 crossbeam_channel::{bounded, unbounded},
7850 rand::Rng,
7851 solana_program_runtime::{
7852 compute_budget::MAX_COMPUTE_UNIT_LIMIT,
7853 executor_cache::Executor,
7854 invoke_context::InvokeContext,
7855 prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType},
7856 },
7857 solana_sdk::{
7858 account::Account,
7859 bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
7860 clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT, MAX_RECENT_BLOCKHASHES},
7861 compute_budget::ComputeBudgetInstruction,
7862 entrypoint::MAX_PERMITTED_DATA_INCREASE,
7863 epoch_schedule::MINIMUM_SLOTS_PER_EPOCH,
7864 feature::Feature,
7865 genesis_config::create_genesis_config,
7866 hash,
7867 instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
7868 message::{Message, MessageHeader},
7869 nonce,
7870 poh_config::PohConfig,
7871 program::MAX_RETURN_DATA,
7872 rent::Rent,
7873 signature::{keypair_from_seed, Keypair, Signer},
7874 stake::{
7875 instruction as stake_instruction,
7876 state::{Authorized, Delegation, Lockup, Stake},
7877 },
7878 system_instruction::{self, SystemError, MAX_PERMITTED_DATA_LENGTH},
7879 system_program,
7880 timing::duration_as_s,
7881 transaction_context::InstructionContext,
7882 },
7883 solana_vote_program::{
7884 vote_instruction,
7885 vote_state::{
7886 self, BlockTimestamp, Vote, VoteInit, VoteState, VoteStateVersions,
7887 MAX_LOCKOUT_HISTORY,
7888 },
7889 },
7890 std::{
7891 result, str::FromStr, sync::atomic::Ordering::Release, thread::Builder, time::Duration,
7892 },
7893 test_utils::goto_end_of_slot,
7894 };
7895
7896 fn new_sanitized_message(
7897 instructions: &[Instruction],
7898 payer: Option<&Pubkey>,
7899 ) -> SanitizedMessage {
7900 Message::new(instructions, payer).try_into().unwrap()
7901 }
7902
7903 fn new_execution_result(
7904 status: Result<()>,
7905 nonce: Option<&NonceFull>,
7906 ) -> TransactionExecutionResult {
7907 TransactionExecutionResult::Executed {
7908 details: TransactionExecutionDetails {
7909 status,
7910 log_messages: None,
7911 inner_instructions: None,
7912 durable_nonce_fee: nonce.map(DurableNonceFee::from),
7913 return_data: None,
7914 executed_units: 0,
7915 accounts_data_len_delta: 0,
7916 },
7917 executors: Rc::new(RefCell::new(Executors::default())),
7918 }
7919 }
7920
7921 #[test]
7922 fn test_nonce_info() {
7923 let lamports_per_signature = 42;
7924
7925 let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
7926 let nonce_address = nonce_authority.pubkey();
7927 let from = keypair_from_seed(&[1; 32]).unwrap();
7928 let from_address = from.pubkey();
7929 let to_address = Pubkey::new_unique();
7930
7931 let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique());
7932 let nonce_account = AccountSharedData::new_data(
7933 43,
7934 &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::new(
7935 Pubkey::default(),
7936 durable_nonce,
7937 lamports_per_signature,
7938 ))),
7939 &system_program::id(),
7940 )
7941 .unwrap();
7942 let from_account = AccountSharedData::new(44, 0, &Pubkey::default());
7943 let to_account = AccountSharedData::new(45, 0, &Pubkey::default());
7944 let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
7945
7946 const TEST_RENT_DEBIT: u64 = 1;
7947 let rent_collected_nonce_account = {
7948 let mut account = nonce_account.clone();
7949 account.set_lamports(nonce_account.lamports() - TEST_RENT_DEBIT);
7950 account
7951 };
7952 let rent_collected_from_account = {
7953 let mut account = from_account.clone();
7954 account.set_lamports(from_account.lamports() - TEST_RENT_DEBIT);
7955 account
7956 };
7957
7958 let instructions = vec![
7959 system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
7960 system_instruction::transfer(&from_address, &to_address, 42),
7961 ];
7962
7963 let partial = NoncePartial::new(nonce_address, rent_collected_nonce_account.clone());
7965 assert_eq!(*partial.address(), nonce_address);
7966 assert_eq!(*partial.account(), rent_collected_nonce_account);
7967 assert_eq!(
7968 partial.lamports_per_signature(),
7969 Some(lamports_per_signature)
7970 );
7971 assert_eq!(partial.fee_payer_account(), None);
7972
7973 let mut rent_debits = RentDebits::default();
7975 rent_debits.insert(
7976 &from_address,
7977 TEST_RENT_DEBIT,
7978 rent_collected_from_account.lamports(),
7979 );
7980 rent_debits.insert(
7981 &nonce_address,
7982 TEST_RENT_DEBIT,
7983 rent_collected_nonce_account.lamports(),
7984 );
7985
7986 {
7988 let message = new_sanitized_message(&instructions, Some(&from_address));
7989 let accounts = [
7990 (
7991 *message.account_keys().get(0).unwrap(),
7992 rent_collected_from_account.clone(),
7993 ),
7994 (
7995 *message.account_keys().get(1).unwrap(),
7996 rent_collected_nonce_account.clone(),
7997 ),
7998 (*message.account_keys().get(2).unwrap(), to_account.clone()),
7999 (
8000 *message.account_keys().get(3).unwrap(),
8001 recent_blockhashes_sysvar_account.clone(),
8002 ),
8003 ];
8004
8005 let full = NonceFull::from_partial(partial.clone(), &message, &accounts, &rent_debits)
8006 .unwrap();
8007 assert_eq!(*full.address(), nonce_address);
8008 assert_eq!(*full.account(), rent_collected_nonce_account);
8009 assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature));
8010 assert_eq!(
8011 full.fee_payer_account(),
8012 Some(&from_account),
8013 "rent debit should be refunded in captured fee account"
8014 );
8015 }
8016
8017 {
8019 let message = new_sanitized_message(&instructions, Some(&nonce_address));
8020 let accounts = [
8021 (
8022 *message.account_keys().get(0).unwrap(),
8023 rent_collected_nonce_account,
8024 ),
8025 (
8026 *message.account_keys().get(1).unwrap(),
8027 rent_collected_from_account,
8028 ),
8029 (*message.account_keys().get(2).unwrap(), to_account),
8030 (
8031 *message.account_keys().get(3).unwrap(),
8032 recent_blockhashes_sysvar_account,
8033 ),
8034 ];
8035
8036 let full = NonceFull::from_partial(partial.clone(), &message, &accounts, &rent_debits)
8037 .unwrap();
8038 assert_eq!(*full.address(), nonce_address);
8039 assert_eq!(*full.account(), nonce_account);
8040 assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature));
8041 assert_eq!(full.fee_payer_account(), None);
8042 }
8043
8044 {
8046 let message = new_sanitized_message(&instructions, Some(&nonce_address));
8047 assert_eq!(
8048 NonceFull::from_partial(partial, &message, &[], &RentDebits::default())
8049 .unwrap_err(),
8050 TransactionError::AccountNotFound,
8051 );
8052 }
8053 }
8054
8055 #[test]
8056 fn test_bank_unix_timestamp_from_genesis() {
8057 let (genesis_config, _mint_keypair) = create_genesis_config(1);
8058 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
8059
8060 assert_eq!(
8061 genesis_config.creation_time,
8062 bank.unix_timestamp_from_genesis()
8063 );
8064 let slots_per_sec = 1.0
8065 / (duration_as_s(&genesis_config.poh_config.target_tick_duration)
8066 * genesis_config.ticks_per_slot as f32);
8067
8068 for _i in 0..slots_per_sec as usize + 1 {
8069 bank = Arc::new(new_from_parent(&bank));
8070 }
8071
8072 assert!(bank.unix_timestamp_from_genesis() - genesis_config.creation_time >= 1);
8073 }
8074
8075 #[test]
8076 #[allow(clippy::float_cmp)]
8077 fn test_bank_new() {
8078 let dummy_leader_pubkey = solana_sdk::pubkey::new_rand();
8079 let dummy_leader_stake_lamports = bootstrap_validator_stake_lamports();
8080 let mint_lamports = 10_000;
8081 let GenesisConfigInfo {
8082 mut genesis_config,
8083 mint_keypair,
8084 voting_keypair,
8085 ..
8086 } = create_genesis_config_with_leader(
8087 mint_lamports,
8088 &dummy_leader_pubkey,
8089 dummy_leader_stake_lamports,
8090 );
8091
8092 genesis_config.rent = Rent {
8093 lamports_per_byte_year: 5,
8094 exemption_threshold: 1.2,
8095 burn_percent: 5,
8096 };
8097
8098 let bank = Bank::new_for_tests(&genesis_config);
8099 assert_eq!(bank.get_balance(&mint_keypair.pubkey()), mint_lamports);
8100 assert_eq!(
8101 bank.get_balance(&voting_keypair.pubkey()),
8102 dummy_leader_stake_lamports );
8104
8105 let rent_account = bank.get_account(&sysvar::rent::id()).unwrap();
8106 let rent = from_account::<sysvar::rent::Rent, _>(&rent_account).unwrap();
8107
8108 assert_eq!(rent.burn_percent, 5);
8109 assert_eq!(rent.exemption_threshold, 1.2);
8110 assert_eq!(rent.lamports_per_byte_year, 5);
8111 }
8112
8113 fn create_simple_test_bank(lamports: u64) -> Bank {
8114 let (genesis_config, _mint_keypair) = create_genesis_config(lamports);
8115 Bank::new_for_tests(&genesis_config)
8116 }
8117
8118 fn create_simple_test_arc_bank(lamports: u64) -> Arc<Bank> {
8119 Arc::new(create_simple_test_bank(lamports))
8120 }
8121
8122 #[test]
8123 fn test_bank_block_height() {
8124 let bank0 = create_simple_test_arc_bank(1);
8125 assert_eq!(bank0.block_height(), 0);
8126 let bank1 = Arc::new(new_from_parent(&bank0));
8127 assert_eq!(bank1.block_height(), 1);
8128 }
8129
8130 #[test]
8131 fn test_bank_update_epoch_stakes() {
8132 impl Bank {
8133 fn epoch_stake_keys(&self) -> Vec<Epoch> {
8134 let mut keys: Vec<Epoch> = self.epoch_stakes.keys().copied().collect();
8135 keys.sort_unstable();
8136 keys
8137 }
8138
8139 fn epoch_stake_key_info(&self) -> (Epoch, Epoch, usize) {
8140 let mut keys: Vec<Epoch> = self.epoch_stakes.keys().copied().collect();
8141 keys.sort_unstable();
8142 (*keys.first().unwrap(), *keys.last().unwrap(), keys.len())
8143 }
8144 }
8145
8146 let mut bank = create_simple_test_bank(100_000);
8147
8148 let initial_epochs = bank.epoch_stake_keys();
8149 assert_eq!(initial_epochs, vec![0, 1]);
8150
8151 for existing_epoch in &initial_epochs {
8152 bank.update_epoch_stakes(*existing_epoch);
8153 assert_eq!(bank.epoch_stake_keys(), initial_epochs);
8154 }
8155
8156 for epoch in (initial_epochs.len() as Epoch)..MAX_LEADER_SCHEDULE_STAKES {
8157 bank.update_epoch_stakes(epoch);
8158 assert_eq!(bank.epoch_stakes.len() as Epoch, epoch + 1);
8159 }
8160
8161 assert_eq!(
8162 bank.epoch_stake_key_info(),
8163 (
8164 0,
8165 MAX_LEADER_SCHEDULE_STAKES - 1,
8166 MAX_LEADER_SCHEDULE_STAKES as usize
8167 )
8168 );
8169
8170 bank.update_epoch_stakes(MAX_LEADER_SCHEDULE_STAKES);
8171 assert_eq!(
8172 bank.epoch_stake_key_info(),
8173 (
8174 0,
8175 MAX_LEADER_SCHEDULE_STAKES,
8176 MAX_LEADER_SCHEDULE_STAKES as usize + 1
8177 )
8178 );
8179
8180 bank.update_epoch_stakes(MAX_LEADER_SCHEDULE_STAKES + 1);
8181 assert_eq!(
8182 bank.epoch_stake_key_info(),
8183 (
8184 1,
8185 MAX_LEADER_SCHEDULE_STAKES + 1,
8186 MAX_LEADER_SCHEDULE_STAKES as usize + 1
8187 )
8188 );
8189 }
8190
8191 fn bank0_sysvar_delta() -> u64 {
8192 const SLOT_HISTORY_SYSVAR_MIN_BALANCE: u64 = 913_326_000;
8193 SLOT_HISTORY_SYSVAR_MIN_BALANCE
8194 }
8195
8196 fn bank1_sysvar_delta() -> u64 {
8197 const SLOT_HASHES_SYSVAR_MIN_BALANCE: u64 = 143_487_360;
8198 SLOT_HASHES_SYSVAR_MIN_BALANCE
8199 }
8200
8201 #[test]
8202 fn test_bank_capitalization() {
8203 let bank0 = Arc::new(Bank::new_for_tests(&GenesisConfig {
8204 accounts: (0..42)
8205 .map(|_| {
8206 (
8207 solana_sdk::pubkey::new_rand(),
8208 Account::new(42, 0, &Pubkey::default()),
8209 )
8210 })
8211 .collect(),
8212 cluster_type: ClusterType::MainnetBeta,
8213 ..GenesisConfig::default()
8214 }));
8215
8216 assert_eq!(
8217 bank0.capitalization(),
8218 42 * 42 + genesis_sysvar_and_builtin_program_lamports(),
8219 );
8220
8221 bank0.freeze();
8222
8223 assert_eq!(
8224 bank0.capitalization(),
8225 42 * 42 + genesis_sysvar_and_builtin_program_lamports() + bank0_sysvar_delta(),
8226 );
8227
8228 let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
8229 assert_eq!(
8230 bank1.capitalization(),
8231 42 * 42
8232 + genesis_sysvar_and_builtin_program_lamports()
8233 + bank0_sysvar_delta()
8234 + bank1_sysvar_delta(),
8235 );
8236 }
8237
8238 fn rent_with_exemption_threshold(exemption_threshold: f64) -> Rent {
8239 Rent {
8240 lamports_per_byte_year: 1,
8241 exemption_threshold,
8242 burn_percent: 10,
8243 }
8244 }
8245
8246 #[test]
8247 fn test_credit_debit_rent_no_side_effect_on_hash() {
8250 solana_logger::setup();
8251
8252 let (mut genesis_config, _mint_keypair) = create_genesis_config(10);
8253
8254 genesis_config.rent = rent_with_exemption_threshold(21.0);
8255
8256 let slot = years_as_slots(
8257 2.0,
8258 &genesis_config.poh_config.target_tick_duration,
8259 genesis_config.ticks_per_slot,
8260 ) as u64;
8261 let root_bank = Arc::new(Bank::new_for_tests(&genesis_config));
8262 let bank = Bank::new_from_parent(&root_bank, &Pubkey::default(), slot);
8263
8264 let root_bank_2 = Arc::new(Bank::new_for_tests(&genesis_config));
8265 let bank_with_success_txs = Bank::new_from_parent(&root_bank_2, &Pubkey::default(), slot);
8266
8267 assert_eq!(bank.last_blockhash(), genesis_config.hash());
8268
8269 let plenty_of_lamports = 264;
8270 let too_few_lamports = 10;
8271 let accounts = [
8273 AccountSharedData::new(plenty_of_lamports, 0, &Pubkey::default()),
8274 AccountSharedData::new(plenty_of_lamports, 1, &Pubkey::default()),
8275 AccountSharedData::new(plenty_of_lamports, 0, &Pubkey::default()),
8276 AccountSharedData::new(plenty_of_lamports, 1, &Pubkey::default()),
8277 AccountSharedData::new(too_few_lamports, 0, &Pubkey::default()),
8279 AccountSharedData::new(too_few_lamports, 1, &Pubkey::default()),
8280 ];
8281
8282 let keypairs = accounts.iter().map(|_| Keypair::new()).collect::<Vec<_>>();
8283 {
8284 let mut account_copy = accounts[4].clone();
8286 let expected_rent = bank.rent_collector().collect_from_existing_account(
8287 &keypairs[4].pubkey(),
8288 &mut account_copy,
8289 None,
8290 true, );
8292 assert_eq!(expected_rent.rent_amount, too_few_lamports);
8293 assert_eq!(account_copy.lamports(), 0);
8294 }
8295
8296 for i in 0..accounts.len() {
8297 let account = &accounts[i];
8298 bank.store_account(&keypairs[i].pubkey(), account);
8299 bank_with_success_txs.store_account(&keypairs[i].pubkey(), account);
8300 }
8301
8302 let system_program_id = system_program::id();
8304 let mut system_program_account = bank.get_account(&system_program_id).unwrap();
8305 system_program_account.set_lamports(
8306 bank.get_minimum_balance_for_rent_exemption(system_program_account.data().len()),
8307 );
8308 bank.store_account(&system_program_id, &system_program_account);
8309 bank_with_success_txs.store_account(&system_program_id, &system_program_account);
8310
8311 let t1 = system_transaction::transfer(
8312 &keypairs[0],
8313 &keypairs[1].pubkey(),
8314 1,
8315 genesis_config.hash(),
8316 );
8317 let t2 = system_transaction::transfer(
8318 &keypairs[2],
8319 &keypairs[3].pubkey(),
8320 1,
8321 genesis_config.hash(),
8322 );
8323 let t3 = system_transaction::transfer(
8325 &keypairs[4],
8326 &keypairs[5].pubkey(),
8327 1,
8328 genesis_config.hash(),
8329 );
8330
8331 let txs = vec![t1.clone(), t2.clone(), t3];
8332 let res = bank.process_transactions(txs.iter());
8333
8334 assert_eq!(res.len(), 3);
8335 assert_eq!(res[0], Ok(()));
8336 assert_eq!(res[1], Ok(()));
8337 assert_eq!(res[2], Err(TransactionError::AccountNotFound));
8338
8339 bank.freeze();
8340
8341 let rwlockguard_bank_hash = bank.hash.read().unwrap();
8342 let bank_hash = rwlockguard_bank_hash.as_ref();
8343
8344 let txs = vec![t2, t1];
8345 let res = bank_with_success_txs.process_transactions(txs.iter());
8346
8347 assert_eq!(res.len(), 2);
8348 assert_eq!(res[0], Ok(()));
8349 assert_eq!(res[1], Ok(()));
8350
8351 bank_with_success_txs.freeze();
8352
8353 let rwlockguard_bank_with_success_txs_hash = bank_with_success_txs.hash.read().unwrap();
8354 let bank_with_success_txs_hash = rwlockguard_bank_with_success_txs_hash.as_ref();
8355
8356 assert_eq!(bank_with_success_txs_hash, bank_hash);
8357 }
8358
8359 fn store_accounts_for_rent_test(
8360 bank: &Bank,
8361 keypairs: &mut [Keypair],
8362 mock_program_id: Pubkey,
8363 generic_rent_due_for_system_account: u64,
8364 ) {
8365 let mut account_pairs: Vec<TransactionAccount> = Vec::with_capacity(keypairs.len() - 1);
8366 account_pairs.push((
8367 keypairs[0].pubkey(),
8368 AccountSharedData::new(
8369 generic_rent_due_for_system_account + 2,
8370 0,
8371 &Pubkey::default(),
8372 ),
8373 ));
8374 account_pairs.push((
8375 keypairs[1].pubkey(),
8376 AccountSharedData::new(
8377 generic_rent_due_for_system_account + 2,
8378 0,
8379 &Pubkey::default(),
8380 ),
8381 ));
8382 account_pairs.push((
8383 keypairs[2].pubkey(),
8384 AccountSharedData::new(
8385 generic_rent_due_for_system_account + 2,
8386 0,
8387 &Pubkey::default(),
8388 ),
8389 ));
8390 account_pairs.push((
8391 keypairs[3].pubkey(),
8392 AccountSharedData::new(
8393 generic_rent_due_for_system_account + 2,
8394 0,
8395 &Pubkey::default(),
8396 ),
8397 ));
8398 account_pairs.push((
8399 keypairs[4].pubkey(),
8400 AccountSharedData::new(10, 0, &Pubkey::default()),
8401 ));
8402 account_pairs.push((
8403 keypairs[5].pubkey(),
8404 AccountSharedData::new(10, 0, &Pubkey::default()),
8405 ));
8406 account_pairs.push((
8407 keypairs[6].pubkey(),
8408 AccountSharedData::new(
8409 (2 * generic_rent_due_for_system_account) + 24,
8410 0,
8411 &Pubkey::default(),
8412 ),
8413 ));
8414
8415 account_pairs.push((
8416 keypairs[8].pubkey(),
8417 AccountSharedData::new(
8418 generic_rent_due_for_system_account + 2 + 929,
8419 0,
8420 &Pubkey::default(),
8421 ),
8422 ));
8423 account_pairs.push((
8424 keypairs[9].pubkey(),
8425 AccountSharedData::new(10, 0, &Pubkey::default()),
8426 ));
8427
8428 account_pairs.push((
8430 keypairs[10].pubkey(),
8431 AccountSharedData::new(
8432 generic_rent_due_for_system_account + 3,
8433 0,
8434 &Pubkey::default(),
8435 ),
8436 ));
8437 account_pairs.push((
8438 keypairs[11].pubkey(),
8439 AccountSharedData::new(generic_rent_due_for_system_account + 3, 0, &mock_program_id),
8440 ));
8441 account_pairs.push((
8442 keypairs[12].pubkey(),
8443 AccountSharedData::new(generic_rent_due_for_system_account + 3, 0, &mock_program_id),
8444 ));
8445 account_pairs.push((
8446 keypairs[13].pubkey(),
8447 AccountSharedData::new(14, 22, &mock_program_id),
8448 ));
8449
8450 for account_pair in account_pairs.iter() {
8451 bank.store_account(&account_pair.0, &account_pair.1);
8452 }
8453 }
8454
8455 fn create_child_bank_for_rent_test(
8456 root_bank: &Arc<Bank>,
8457 genesis_config: &GenesisConfig,
8458 ) -> Bank {
8459 let mut bank = Bank::new_from_parent(
8460 root_bank,
8461 &Pubkey::default(),
8462 years_as_slots(
8463 2.0,
8464 &genesis_config.poh_config.target_tick_duration,
8465 genesis_config.ticks_per_slot,
8466 ) as u64,
8467 );
8468 bank.rent_collector.slots_per_year = 421_812.0;
8469 bank
8470 }
8471
8472 fn assert_capitalization_diff(bank: &Bank, updater: impl Fn(), asserter: impl Fn(u64, u64)) {
8473 let old = bank.capitalization();
8474 updater();
8475 let new = bank.capitalization();
8476 asserter(old, new);
8477 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
8478 }
8479
8480 #[test]
8481 fn test_store_account_and_update_capitalization_missing() {
8482 let bank = create_simple_test_bank(0);
8483 let pubkey = solana_sdk::pubkey::new_rand();
8484
8485 let some_lamports = 400;
8486 let account = AccountSharedData::new(some_lamports, 0, &system_program::id());
8487
8488 assert_capitalization_diff(
8489 &bank,
8490 || bank.store_account_and_update_capitalization(&pubkey, &account),
8491 |old, new| assert_eq!(old + some_lamports, new),
8492 );
8493 assert_eq!(account, bank.get_account(&pubkey).unwrap());
8494 }
8495
8496 #[test]
8497 fn test_store_account_and_update_capitalization_increased() {
8498 let old_lamports = 400;
8499 let (genesis_config, mint_keypair) = create_genesis_config(old_lamports);
8500 let bank = Bank::new_for_tests(&genesis_config);
8501 let pubkey = mint_keypair.pubkey();
8502
8503 let new_lamports = 500;
8504 let account = AccountSharedData::new(new_lamports, 0, &system_program::id());
8505
8506 assert_capitalization_diff(
8507 &bank,
8508 || bank.store_account_and_update_capitalization(&pubkey, &account),
8509 |old, new| assert_eq!(old + 100, new),
8510 );
8511 assert_eq!(account, bank.get_account(&pubkey).unwrap());
8512 }
8513
8514 #[test]
8515 fn test_store_account_and_update_capitalization_decreased() {
8516 let old_lamports = 400;
8517 let (genesis_config, mint_keypair) = create_genesis_config(old_lamports);
8518 let bank = Bank::new_for_tests(&genesis_config);
8519 let pubkey = mint_keypair.pubkey();
8520
8521 let new_lamports = 100;
8522 let account = AccountSharedData::new(new_lamports, 0, &system_program::id());
8523
8524 assert_capitalization_diff(
8525 &bank,
8526 || bank.store_account_and_update_capitalization(&pubkey, &account),
8527 |old, new| assert_eq!(old - 300, new),
8528 );
8529 assert_eq!(account, bank.get_account(&pubkey).unwrap());
8530 }
8531
8532 #[test]
8533 fn test_store_account_and_update_capitalization_unchanged() {
8534 let lamports = 400;
8535 let (genesis_config, mint_keypair) = create_genesis_config(lamports);
8536 let bank = Bank::new_for_tests(&genesis_config);
8537 let pubkey = mint_keypair.pubkey();
8538
8539 let account = AccountSharedData::new(lamports, 1, &system_program::id());
8540
8541 assert_capitalization_diff(
8542 &bank,
8543 || bank.store_account_and_update_capitalization(&pubkey, &account),
8544 |old, new| assert_eq!(old, new),
8545 );
8546 assert_eq!(account, bank.get_account(&pubkey).unwrap());
8547 }
8548
8549 #[test]
8550 #[ignore]
8551 fn test_rent_distribution() {
8552 solana_logger::setup();
8553
8554 let bootstrap_validator_pubkey = solana_sdk::pubkey::new_rand();
8555 let bootstrap_validator_stake_lamports = 30;
8556 let mut genesis_config = create_genesis_config_with_leader(
8557 10,
8558 &bootstrap_validator_pubkey,
8559 bootstrap_validator_stake_lamports,
8560 )
8561 .genesis_config;
8562 genesis_config
8565 .accounts
8566 .remove(&feature_set::require_rent_exempt_accounts::id())
8567 .unwrap();
8568
8569 genesis_config.epoch_schedule = EpochSchedule::custom(
8570 MINIMUM_SLOTS_PER_EPOCH,
8571 genesis_config.epoch_schedule.leader_schedule_slot_offset,
8572 false,
8573 );
8574
8575 genesis_config.rent = rent_with_exemption_threshold(2.0);
8576
8577 let rent = Rent::free();
8578
8579 let validator_1_pubkey = solana_sdk::pubkey::new_rand();
8580 let validator_1_stake_lamports = 20;
8581 let validator_1_staking_keypair = Keypair::new();
8582 let validator_1_voting_keypair = Keypair::new();
8583
8584 let validator_1_vote_account = vote_state::create_account(
8585 &validator_1_voting_keypair.pubkey(),
8586 &validator_1_pubkey,
8587 0,
8588 validator_1_stake_lamports,
8589 );
8590
8591 let validator_1_stake_account = stake_state::create_account(
8592 &validator_1_staking_keypair.pubkey(),
8593 &validator_1_voting_keypair.pubkey(),
8594 &validator_1_vote_account,
8595 &rent,
8596 validator_1_stake_lamports,
8597 );
8598
8599 genesis_config.accounts.insert(
8600 validator_1_pubkey,
8601 Account::new(42, 0, &system_program::id()),
8602 );
8603 genesis_config.accounts.insert(
8604 validator_1_staking_keypair.pubkey(),
8605 Account::from(validator_1_stake_account),
8606 );
8607 genesis_config.accounts.insert(
8608 validator_1_voting_keypair.pubkey(),
8609 Account::from(validator_1_vote_account),
8610 );
8611
8612 let validator_2_pubkey = solana_sdk::pubkey::new_rand();
8613 let validator_2_stake_lamports = 20;
8614 let validator_2_staking_keypair = Keypair::new();
8615 let validator_2_voting_keypair = Keypair::new();
8616
8617 let validator_2_vote_account = vote_state::create_account(
8618 &validator_2_voting_keypair.pubkey(),
8619 &validator_2_pubkey,
8620 0,
8621 validator_2_stake_lamports,
8622 );
8623
8624 let validator_2_stake_account = stake_state::create_account(
8625 &validator_2_staking_keypair.pubkey(),
8626 &validator_2_voting_keypair.pubkey(),
8627 &validator_2_vote_account,
8628 &rent,
8629 validator_2_stake_lamports,
8630 );
8631
8632 genesis_config.accounts.insert(
8633 validator_2_pubkey,
8634 Account::new(42, 0, &system_program::id()),
8635 );
8636 genesis_config.accounts.insert(
8637 validator_2_staking_keypair.pubkey(),
8638 Account::from(validator_2_stake_account),
8639 );
8640 genesis_config.accounts.insert(
8641 validator_2_voting_keypair.pubkey(),
8642 Account::from(validator_2_vote_account),
8643 );
8644
8645 let validator_3_pubkey = solana_sdk::pubkey::new_rand();
8646 let validator_3_stake_lamports = 30;
8647 let validator_3_staking_keypair = Keypair::new();
8648 let validator_3_voting_keypair = Keypair::new();
8649
8650 let validator_3_vote_account = vote_state::create_account(
8651 &validator_3_voting_keypair.pubkey(),
8652 &validator_3_pubkey,
8653 0,
8654 validator_3_stake_lamports,
8655 );
8656
8657 let validator_3_stake_account = stake_state::create_account(
8658 &validator_3_staking_keypair.pubkey(),
8659 &validator_3_voting_keypair.pubkey(),
8660 &validator_3_vote_account,
8661 &rent,
8662 validator_3_stake_lamports,
8663 );
8664
8665 genesis_config.accounts.insert(
8666 validator_3_pubkey,
8667 Account::new(42, 0, &system_program::id()),
8668 );
8669 genesis_config.accounts.insert(
8670 validator_3_staking_keypair.pubkey(),
8671 Account::from(validator_3_stake_account),
8672 );
8673 genesis_config.accounts.insert(
8674 validator_3_voting_keypair.pubkey(),
8675 Account::from(validator_3_vote_account),
8676 );
8677
8678 genesis_config.rent = rent_with_exemption_threshold(10.0);
8679
8680 let mut bank = Bank::new_for_tests(&genesis_config);
8681 bank.rent_collector.epoch = 5;
8683 bank.rent_collector.slots_per_year = 192.0;
8684
8685 let payer = Keypair::new();
8686 let payer_account = AccountSharedData::new(400, 0, &system_program::id());
8687 bank.store_account_and_update_capitalization(&payer.pubkey(), &payer_account);
8688
8689 let payee = Keypair::new();
8690 let payee_account = AccountSharedData::new(70, 1, &system_program::id());
8691 bank.store_account_and_update_capitalization(&payee.pubkey(), &payee_account);
8692
8693 let bootstrap_validator_initial_balance = bank.get_balance(&bootstrap_validator_pubkey);
8694
8695 let tx = system_transaction::transfer(&payer, &payee.pubkey(), 180, genesis_config.hash());
8696
8697 let result = bank.process_transaction(&tx);
8698 assert_eq!(result, Ok(()));
8699
8700 let mut total_rent_deducted = 0;
8701
8702 assert_eq!(bank.get_balance(&payer.pubkey()), 92);
8704 total_rent_deducted += 128;
8705
8706 assert_eq!(bank.get_balance(&payee.pubkey()), 159);
8708 total_rent_deducted += 70 + 21;
8709
8710 let previous_capitalization = bank.capitalization.load(Relaxed);
8711
8712 bank.freeze();
8713
8714 assert_eq!(bank.collected_rent.load(Relaxed), total_rent_deducted);
8715
8716 let burned_portion =
8717 total_rent_deducted * u64::from(bank.rent_collector.rent.burn_percent) / 100;
8718 let rent_to_be_distributed = total_rent_deducted - burned_portion;
8719
8720 let bootstrap_validator_portion =
8721 ((bootstrap_validator_stake_lamports * rent_to_be_distributed) as f64 / 100.0) as u64
8722 + 1; assert_eq!(
8724 bank.get_balance(&bootstrap_validator_pubkey),
8725 bootstrap_validator_portion + bootstrap_validator_initial_balance
8726 );
8727
8728 let tweak_1 = u64::from(validator_1_pubkey > validator_2_pubkey);
8731 let validator_1_portion =
8732 ((validator_1_stake_lamports * rent_to_be_distributed) as f64 / 100.0) as u64 + tweak_1;
8733 assert_eq!(
8734 bank.get_balance(&validator_1_pubkey),
8735 validator_1_portion + 42 - tweak_1,
8736 );
8737
8738 let tweak_2 = u64::from(validator_2_pubkey > validator_1_pubkey);
8741 let validator_2_portion =
8742 ((validator_2_stake_lamports * rent_to_be_distributed) as f64 / 100.0) as u64 + tweak_2;
8743 assert_eq!(
8744 bank.get_balance(&validator_2_pubkey),
8745 validator_2_portion + 42 - tweak_2,
8746 );
8747
8748 let validator_3_portion =
8749 ((validator_3_stake_lamports * rent_to_be_distributed) as f64 / 100.0) as u64 + 1;
8750 assert_eq!(
8751 bank.get_balance(&validator_3_pubkey),
8752 validator_3_portion + 42
8753 );
8754
8755 let current_capitalization = bank.capitalization.load(Relaxed);
8756
8757 let sysvar_and_builtin_program_delta =
8759 min_rent_excempt_balance_for_sysvars(&bank, &[sysvar::slot_history::id()]);
8760 assert_eq!(
8761 previous_capitalization - (current_capitalization - sysvar_and_builtin_program_delta),
8762 burned_portion
8763 );
8764
8765 assert!(bank.calculate_and_verify_capitalization(true));
8766
8767 assert_eq!(
8768 rent_to_be_distributed,
8769 bank.rewards
8770 .read()
8771 .unwrap()
8772 .iter()
8773 .map(|(address, reward)| {
8774 if reward.lamports > 0 {
8775 assert_eq!(reward.reward_type, RewardType::Rent);
8776 if *address == validator_2_pubkey {
8777 assert_eq!(reward.post_balance, validator_2_portion + 42 - tweak_2);
8778 } else if *address == validator_3_pubkey {
8779 assert_eq!(reward.post_balance, validator_3_portion + 42);
8780 }
8781 reward.lamports as u64
8782 } else {
8783 0
8784 }
8785 })
8786 .sum::<u64>()
8787 );
8788 }
8789
8790 #[test]
8791 fn test_distribute_rent_to_validators_overflow() {
8792 solana_logger::setup();
8793
8794 const RENT_TO_BE_DISTRIBUTED: u64 = 120_525;
8796 const VALIDATOR_STAKE: u64 = 374_999_998_287_840;
8797
8798 let validator_pubkey = solana_sdk::pubkey::new_rand();
8799 let mut genesis_config =
8800 create_genesis_config_with_leader(10, &validator_pubkey, VALIDATOR_STAKE)
8801 .genesis_config;
8802
8803 let bank = Bank::new_for_tests(&genesis_config);
8804 let old_validator_lamports = bank.get_balance(&validator_pubkey);
8805 bank.distribute_rent_to_validators(&bank.vote_accounts(), RENT_TO_BE_DISTRIBUTED);
8806 let new_validator_lamports = bank.get_balance(&validator_pubkey);
8807 assert_eq!(
8808 new_validator_lamports,
8809 old_validator_lamports + RENT_TO_BE_DISTRIBUTED
8810 );
8811
8812 genesis_config
8813 .accounts
8814 .remove(&feature_set::no_overflow_rent_distribution::id())
8815 .unwrap();
8816 let bank = std::panic::AssertUnwindSafe(Bank::new_for_tests(&genesis_config));
8817 let old_validator_lamports = bank.get_balance(&validator_pubkey);
8818 let new_validator_lamports = std::panic::catch_unwind(|| {
8819 bank.distribute_rent_to_validators(&bank.vote_accounts(), RENT_TO_BE_DISTRIBUTED);
8820 bank.get_balance(&validator_pubkey)
8821 });
8822
8823 if let Ok(new_validator_lamports) = new_validator_lamports {
8824 info!("asserting overflowing incorrect rent distribution");
8825 assert_ne!(
8826 new_validator_lamports,
8827 old_validator_lamports + RENT_TO_BE_DISTRIBUTED
8828 );
8829 } else {
8830 info!("NOT-asserting overflowing incorrect rent distribution");
8831 }
8832 }
8833
8834 #[test]
8835 fn test_rent_exempt_executable_account() {
8836 let (mut genesis_config, mint_keypair) = create_genesis_config(100_000);
8837 genesis_config.rent = rent_with_exemption_threshold(1000.0);
8838
8839 let root_bank = Arc::new(Bank::new_for_tests(&genesis_config));
8840 let bank = create_child_bank_for_rent_test(&root_bank, &genesis_config);
8841
8842 let account_pubkey = solana_sdk::pubkey::new_rand();
8843 let account_balance = 1;
8844 let mut account =
8845 AccountSharedData::new(account_balance, 0, &solana_sdk::pubkey::new_rand());
8846 account.set_executable(true);
8847 bank.store_account(&account_pubkey, &account);
8848
8849 let transfer_lamports = 1;
8850 let tx = system_transaction::transfer(
8851 &mint_keypair,
8852 &account_pubkey,
8853 transfer_lamports,
8854 genesis_config.hash(),
8855 );
8856
8857 assert_eq!(
8858 bank.process_transaction(&tx),
8859 Err(TransactionError::InvalidWritableAccount)
8860 );
8861 assert_eq!(bank.get_balance(&account_pubkey), account_balance);
8862 }
8863
8864 #[test]
8865 #[ignore]
8866 #[allow(clippy::cognitive_complexity)]
8867 fn test_rent_complex() {
8868 solana_logger::setup();
8869 let mock_program_id = Pubkey::from([2u8; 32]);
8870
8871 #[derive(Serialize, Deserialize)]
8872 enum MockInstruction {
8873 Deduction,
8874 }
8875
8876 fn mock_process_instruction(
8877 _first_instruction_account: usize,
8878 invoke_context: &mut InvokeContext,
8879 ) -> result::Result<(), InstructionError> {
8880 let transaction_context = &invoke_context.transaction_context;
8881 let instruction_context = transaction_context.get_current_instruction_context()?;
8882 let instruction_data = instruction_context.get_instruction_data();
8883 if let Ok(instruction) = bincode::deserialize(instruction_data) {
8884 match instruction {
8885 MockInstruction::Deduction => {
8886 instruction_context
8887 .try_borrow_instruction_account(transaction_context, 1)?
8888 .checked_add_lamports(1)?;
8889 instruction_context
8890 .try_borrow_instruction_account(transaction_context, 2)?
8891 .checked_sub_lamports(1)?;
8892 Ok(())
8893 }
8894 }
8895 } else {
8896 Err(InstructionError::InvalidInstructionData)
8897 }
8898 }
8899
8900 let (mut genesis_config, _mint_keypair) = create_genesis_config(10);
8901 let mut keypairs: Vec<Keypair> = Vec::with_capacity(14);
8902 for _i in 0..14 {
8903 keypairs.push(Keypair::new());
8904 }
8905
8906 genesis_config.rent = rent_with_exemption_threshold(1000.0);
8907
8908 let root_bank = Bank::new_for_tests(&genesis_config);
8909 root_bank.restore_old_behavior_for_fragile_tests();
8912 let root_bank = Arc::new(root_bank);
8913 let mut bank = create_child_bank_for_rent_test(&root_bank, &genesis_config);
8914 bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
8915
8916 assert_eq!(bank.last_blockhash(), genesis_config.hash());
8917
8918 let slots_elapsed: u64 = (0..=bank.epoch)
8919 .map(|epoch| {
8920 bank.rent_collector
8921 .epoch_schedule
8922 .get_slots_in_epoch(epoch + 1)
8923 })
8924 .sum();
8925 let generic_rent_due_for_system_account = bank
8926 .rent_collector
8927 .rent
8928 .due(
8929 bank.get_minimum_balance_for_rent_exemption(0) - 1,
8930 0,
8931 slots_elapsed as f64 / bank.rent_collector.slots_per_year,
8932 )
8933 .lamports();
8934
8935 store_accounts_for_rent_test(
8936 &bank,
8937 &mut keypairs,
8938 mock_program_id,
8939 generic_rent_due_for_system_account,
8940 );
8941
8942 let magic_rent_number = 131; let t1 = system_transaction::transfer(
8945 &keypairs[0],
8946 &keypairs[1].pubkey(),
8947 1,
8948 genesis_config.hash(),
8949 );
8950 let t2 = system_transaction::transfer(
8951 &keypairs[2],
8952 &keypairs[3].pubkey(),
8953 1,
8954 genesis_config.hash(),
8955 );
8956 let t3 = system_transaction::transfer(
8957 &keypairs[4],
8958 &keypairs[5].pubkey(),
8959 1,
8960 genesis_config.hash(),
8961 );
8962 let t4 = system_transaction::transfer(
8963 &keypairs[6],
8964 &keypairs[7].pubkey(),
8965 generic_rent_due_for_system_account + 1,
8966 genesis_config.hash(),
8967 );
8968 let t5 = system_transaction::transfer(
8969 &keypairs[8],
8970 &keypairs[9].pubkey(),
8971 929,
8972 genesis_config.hash(),
8973 );
8974
8975 let account_metas = vec![
8976 AccountMeta::new(keypairs[10].pubkey(), true),
8977 AccountMeta::new(keypairs[11].pubkey(), true),
8978 AccountMeta::new(keypairs[12].pubkey(), true),
8979 AccountMeta::new_readonly(keypairs[13].pubkey(), false),
8980 ];
8981 let deduct_instruction = Instruction::new_with_bincode(
8982 mock_program_id,
8983 &MockInstruction::Deduction,
8984 account_metas,
8985 );
8986 let t6 = Transaction::new_signed_with_payer(
8987 &[deduct_instruction],
8988 Some(&keypairs[10].pubkey()),
8989 &[&keypairs[10], &keypairs[11], &keypairs[12]],
8990 genesis_config.hash(),
8991 );
8992
8993 let txs = vec![t6, t5, t1, t2, t3, t4];
8994 let res = bank.process_transactions(txs.iter());
8995
8996 assert_eq!(res.len(), 6);
8997 assert_eq!(res[0], Ok(()));
8998 assert_eq!(res[1], Ok(()));
8999 assert_eq!(res[2], Ok(()));
9000 assert_eq!(res[3], Ok(()));
9001 assert_eq!(res[4], Err(TransactionError::AccountNotFound));
9002 assert_eq!(res[5], Ok(()));
9003
9004 bank.freeze();
9005
9006 let mut rent_collected = 0;
9007
9008 assert_eq!(bank.get_balance(&keypairs[0].pubkey()), 1);
9010 rent_collected += generic_rent_due_for_system_account;
9011
9012 assert_eq!(bank.get_balance(&keypairs[1].pubkey()), 3);
9014 rent_collected += generic_rent_due_for_system_account;
9015
9016 assert_eq!(bank.get_balance(&keypairs[2].pubkey()), 1);
9018 rent_collected += generic_rent_due_for_system_account;
9019
9020 assert_eq!(bank.get_balance(&keypairs[3].pubkey()), 3);
9022 rent_collected += generic_rent_due_for_system_account;
9023
9024 assert_eq!(bank.get_balance(&keypairs[4].pubkey()), 10);
9026 assert_eq!(bank.get_balance(&keypairs[5].pubkey()), 10);
9027
9028 assert_eq!(bank.get_balance(&keypairs[6].pubkey()), 23);
9030 rent_collected += generic_rent_due_for_system_account;
9031
9032 assert_eq!(
9034 bank.get_balance(&keypairs[7].pubkey()),
9035 generic_rent_due_for_system_account + 1 - magic_rent_number
9036 );
9037
9038 let account8 = bank.get_account(&keypairs[7].pubkey()).unwrap();
9041 assert_eq!(account8.rent_epoch(), bank.epoch + 1);
9043 rent_collected += magic_rent_number;
9044
9045 assert_eq!(bank.get_balance(&keypairs[8].pubkey()), 2);
9047 rent_collected += generic_rent_due_for_system_account;
9048
9049 let account10 = bank.get_account(&keypairs[9].pubkey()).unwrap();
9050 assert_eq!(account10.rent_epoch(), bank.epoch + 1);
9053 assert_eq!(account10.data().len(), 0);
9055 assert_eq!(account10.lamports(), 929 - magic_rent_number);
9057 rent_collected += magic_rent_number + 10;
9058
9059 assert_eq!(bank.get_balance(&keypairs[10].pubkey()), 3);
9061 rent_collected += generic_rent_due_for_system_account;
9062
9063 assert_eq!(bank.get_balance(&keypairs[11].pubkey()), 4);
9065 rent_collected += generic_rent_due_for_system_account;
9066
9067 assert_eq!(bank.get_balance(&keypairs[12].pubkey()), 2);
9069 rent_collected += generic_rent_due_for_system_account;
9070
9071 assert_eq!(bank.get_balance(&keypairs[13].pubkey()), 14);
9073
9074 assert_eq!(bank.collected_rent.load(Relaxed), rent_collected);
9076 }
9077
9078 fn test_rent_collection_partitions(bank: &Bank) -> Vec<Partition> {
9079 let partitions = bank.rent_collection_partitions();
9080 let slot = bank.slot();
9081 if slot.saturating_sub(1) == bank.parent_slot() {
9082 let partition = Bank::variable_cycle_partition_from_previous_slot(
9083 bank.epoch_schedule(),
9084 bank.slot(),
9085 );
9086 assert_eq!(
9087 partitions.last().unwrap(),
9088 &partition,
9089 "slot: {}, slots per epoch: {}, partitions: {:?}",
9090 bank.slot(),
9091 bank.epoch_schedule().slots_per_epoch,
9092 partitions
9093 );
9094 }
9095 partitions
9096 }
9097
9098 #[test]
9099 fn test_rent_eager_across_epoch_without_gap() {
9100 let mut bank = create_simple_test_arc_bank(1);
9101 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
9102
9103 bank = Arc::new(new_from_parent(&bank));
9104 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 32)]);
9105 for _ in 2..32 {
9106 bank = Arc::new(new_from_parent(&bank));
9107 }
9108 assert_eq!(bank.rent_collection_partitions(), vec![(30, 31, 32)]);
9109 bank = Arc::new(new_from_parent(&bank));
9110 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 64)]);
9111 }
9112
9113 #[test]
9114 fn test_rent_eager_across_epoch_without_gap_mnb() {
9115 solana_logger::setup();
9116 let (mut genesis_config, _mint_keypair) = create_genesis_config(1);
9117 genesis_config.cluster_type = ClusterType::MainnetBeta;
9118
9119 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9120 assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 0, 32)]);
9121
9122 bank = Arc::new(new_from_parent(&bank));
9123 assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 1, 32)]);
9124 for _ in 2..32 {
9125 bank = Arc::new(new_from_parent(&bank));
9126 }
9127 assert_eq!(test_rent_collection_partitions(&bank), vec![(30, 31, 32)]);
9128 bank = Arc::new(new_from_parent(&bank));
9129 assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 0, 64)]);
9130 }
9131
9132 #[test]
9133 fn test_rent_eager_across_epoch_with_full_gap() {
9134 let (mut genesis_config, _mint_keypair) = create_genesis_config(1);
9135 activate_all_features(&mut genesis_config);
9136
9137 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9138 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
9139
9140 bank = Arc::new(new_from_parent(&bank));
9141 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 32)]);
9142 for _ in 2..15 {
9143 bank = Arc::new(new_from_parent(&bank));
9144 }
9145 assert_eq!(bank.rent_collection_partitions(), vec![(13, 14, 32)]);
9146 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 49));
9147 assert_eq!(
9148 bank.rent_collection_partitions(),
9149 vec![(14, 31, 32), (0, 0, 64), (0, 17, 64)]
9150 );
9151 bank = Arc::new(new_from_parent(&bank));
9152 assert_eq!(bank.rent_collection_partitions(), vec![(17, 18, 64)]);
9153 }
9154
9155 #[test]
9156 fn test_rent_eager_across_epoch_with_half_gap() {
9157 let (mut genesis_config, _mint_keypair) = create_genesis_config(1);
9158 activate_all_features(&mut genesis_config);
9159
9160 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9161 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
9162
9163 bank = Arc::new(new_from_parent(&bank));
9164 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 32)]);
9165 for _ in 2..15 {
9166 bank = Arc::new(new_from_parent(&bank));
9167 }
9168 assert_eq!(bank.rent_collection_partitions(), vec![(13, 14, 32)]);
9169 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 32));
9170 assert_eq!(
9171 bank.rent_collection_partitions(),
9172 vec![(14, 31, 32), (0, 0, 64)]
9173 );
9174 bank = Arc::new(new_from_parent(&bank));
9175 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 64)]);
9176 }
9177
9178 #[test]
9179 #[allow(clippy::cognitive_complexity)]
9180 fn test_rent_eager_across_epoch_without_gap_under_multi_epoch_cycle() {
9181 let leader_pubkey = solana_sdk::pubkey::new_rand();
9182 let leader_lamports = 3;
9183 let mut genesis_config =
9184 create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
9185 genesis_config.cluster_type = ClusterType::MainnetBeta;
9186
9187 const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64;
9188 const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
9189 genesis_config.epoch_schedule =
9190 EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, false);
9191
9192 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9193 assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
9194 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9195 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0));
9196 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9197
9198 bank = Arc::new(new_from_parent(&bank));
9199 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9200 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 1));
9201 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]);
9202
9203 for _ in 2..32 {
9204 bank = Arc::new(new_from_parent(&bank));
9205 }
9206 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9207 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 31));
9208 assert_eq!(bank.rent_collection_partitions(), vec![(30, 31, 432_000)]);
9209
9210 bank = Arc::new(new_from_parent(&bank));
9211 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9212 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1, 0));
9213 assert_eq!(bank.rent_collection_partitions(), vec![(31, 32, 432_000)]);
9214
9215 bank = Arc::new(new_from_parent(&bank));
9216 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9217 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1, 1));
9218 assert_eq!(bank.rent_collection_partitions(), vec![(32, 33, 432_000)]);
9219
9220 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 1000));
9221 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 1001));
9222 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9223 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (31, 9));
9224 assert_eq!(
9225 bank.rent_collection_partitions(),
9226 vec![(1000, 1001, 432_000)]
9227 );
9228
9229 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 431_998));
9230 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 431_999));
9231 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9232 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (13499, 31));
9233 assert_eq!(
9234 bank.rent_collection_partitions(),
9235 vec![(431_998, 431_999, 432_000)]
9236 );
9237
9238 bank = Arc::new(new_from_parent(&bank));
9239 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9240 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (13500, 0));
9241 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9242
9243 bank = Arc::new(new_from_parent(&bank));
9244 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9245 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (13500, 1));
9246 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]);
9247 }
9248
9249 #[test]
9250 fn test_rent_eager_across_epoch_with_gap_under_multi_epoch_cycle() {
9251 let leader_pubkey = solana_sdk::pubkey::new_rand();
9252 let leader_lamports = 3;
9253 let mut genesis_config =
9254 create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
9255 genesis_config.cluster_type = ClusterType::MainnetBeta;
9256
9257 const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64;
9258 const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
9259 genesis_config.epoch_schedule =
9260 EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, false);
9261
9262 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9263 assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
9264 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9265 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0));
9266 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9267
9268 bank = Arc::new(new_from_parent(&bank));
9269 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9270 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 1));
9271 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]);
9272
9273 for _ in 2..19 {
9274 bank = Arc::new(new_from_parent(&bank));
9275 }
9276 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9277 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 18));
9278 assert_eq!(bank.rent_collection_partitions(), vec![(17, 18, 432_000)]);
9279
9280 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 44));
9281 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9282 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1, 12));
9283 assert_eq!(
9284 bank.rent_collection_partitions(),
9285 vec![(18, 31, 432_000), (31, 31, 432_000), (31, 44, 432_000)]
9286 );
9287
9288 bank = Arc::new(new_from_parent(&bank));
9289 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9290 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1, 13));
9291 assert_eq!(bank.rent_collection_partitions(), vec![(44, 45, 432_000)]);
9292
9293 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 431_993));
9294 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 432_011));
9295 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9296 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (13500, 11));
9297 assert_eq!(
9298 bank.rent_collection_partitions(),
9299 vec![
9300 (431_993, 431_999, 432_000),
9301 (0, 0, 432_000),
9302 (0, 11, 432_000)
9303 ]
9304 );
9305 }
9306
9307 #[test]
9308 fn test_rent_eager_with_warmup_epochs_under_multi_epoch_cycle() {
9309 let leader_pubkey = solana_sdk::pubkey::new_rand();
9310 let leader_lamports = 3;
9311 let mut genesis_config =
9312 create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
9313 genesis_config.cluster_type = ClusterType::MainnetBeta;
9314
9315 const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64 * 8;
9316 const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
9317 genesis_config.epoch_schedule =
9318 EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, true);
9319
9320 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9321 assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
9322 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9323 assert_eq!(bank.first_normal_epoch(), 3);
9324 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0));
9325 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
9326
9327 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 222));
9328 bank = Arc::new(new_from_parent(&bank));
9329 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 128);
9330 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (2, 127));
9331 assert_eq!(bank.rent_collection_partitions(), vec![(126, 127, 128)]);
9332
9333 bank = Arc::new(new_from_parent(&bank));
9334 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9335 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (3, 0));
9336 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 431_872)]);
9337 assert_eq!(431_872 % bank.get_slots_in_epoch(bank.epoch()), 0);
9338
9339 bank = Arc::new(new_from_parent(&bank));
9340 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9341 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (3, 1));
9342 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 431_872)]);
9343
9344 bank = Arc::new(Bank::new_from_parent(
9345 &bank,
9346 &Pubkey::default(),
9347 431_872 + 223 - 1,
9348 ));
9349 bank = Arc::new(new_from_parent(&bank));
9350 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9351 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1689, 255));
9352 assert_eq!(
9353 bank.rent_collection_partitions(),
9354 vec![(431_870, 431_871, 431_872)]
9355 );
9356
9357 bank = Arc::new(new_from_parent(&bank));
9358 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9359 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1690, 0));
9360 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 431_872)]);
9361 }
9362
9363 #[test]
9364 fn test_rent_eager_under_fixed_cycle_for_development() {
9365 solana_logger::setup();
9366 let leader_pubkey = solana_sdk::pubkey::new_rand();
9367 let leader_lamports = 3;
9368 let mut genesis_config =
9369 create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
9370
9371 const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64 * 8;
9372 const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
9373 genesis_config.epoch_schedule =
9374 EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, true);
9375
9376 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9377 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9378 assert_eq!(bank.first_normal_epoch(), 3);
9379 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0));
9380 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9381
9382 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 222));
9383 bank = Arc::new(new_from_parent(&bank));
9384 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 128);
9385 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (2, 127));
9386 assert_eq!(bank.rent_collection_partitions(), vec![(222, 223, 432_000)]);
9387
9388 bank = Arc::new(new_from_parent(&bank));
9389 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9390 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (3, 0));
9391 assert_eq!(bank.rent_collection_partitions(), vec![(223, 224, 432_000)]);
9392
9393 bank = Arc::new(new_from_parent(&bank));
9394 assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9395 assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (3, 1));
9396 assert_eq!(bank.rent_collection_partitions(), vec![(224, 225, 432_000)]);
9397
9398 bank = Arc::new(Bank::new_from_parent(
9399 &bank,
9400 &Pubkey::default(),
9401 432_000 - 2,
9402 ));
9403 bank = Arc::new(new_from_parent(&bank));
9404 assert_eq!(
9405 bank.rent_collection_partitions(),
9406 vec![(431_998, 431_999, 432_000)]
9407 );
9408 bank = Arc::new(new_from_parent(&bank));
9409 assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9410 bank = Arc::new(new_from_parent(&bank));
9411 assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]);
9412
9413 bank = Arc::new(Bank::new_from_parent(
9414 &bank,
9415 &Pubkey::default(),
9416 864_000 - 20,
9417 ));
9418 bank = Arc::new(Bank::new_from_parent(
9419 &bank,
9420 &Pubkey::default(),
9421 864_000 + 39,
9422 ));
9423 assert_eq!(
9424 bank.rent_collection_partitions(),
9425 vec![
9426 (431_980, 431_999, 432_000),
9427 (0, 0, 432_000),
9428 (0, 39, 432_000)
9429 ]
9430 );
9431 }
9432
9433 #[test]
9434 fn test_rent_eager_pubkey_range_minimal() {
9435 let range = Bank::pubkey_range_from_partition((0, 0, 1));
9436 assert_eq!(
9437 range,
9438 Pubkey::new_from_array([0x00; 32])..=Pubkey::new_from_array([0xff; 32])
9439 );
9440 }
9441
9442 #[test]
9443 fn test_rent_eager_pubkey_range_maximum() {
9444 let max = !0;
9445
9446 let range = Bank::pubkey_range_from_partition((0, 0, max));
9447 assert_eq!(
9448 range,
9449 Pubkey::new_from_array([0x00; 32])
9450 ..=Pubkey::new_from_array([
9451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
9452 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9453 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9454 ])
9455 );
9456 let range = Bank::pubkey_range_from_partition((0, 1, max));
9457 const ONE: u8 = 0x01;
9458 assert_eq!(
9459 range,
9460 Pubkey::new_from_array([
9461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ONE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9463 0x00, 0x00, 0x00, 0x00,
9464 ])
9465 ..=Pubkey::new_from_array([
9466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
9467 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9468 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9469 ])
9470 );
9471 let range = Bank::pubkey_range_from_partition((max - 3, max - 2, max));
9472 const FD: u8 = 0xfd;
9473 assert_eq!(
9474 range,
9475 Pubkey::new_from_array([
9476 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9478 0x00, 0x00, 0x00, 0x00,
9479 ])
9480 ..=Pubkey::new_from_array([
9481 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, FD, 0xff, 0xff, 0xff, 0xff, 0xff,
9482 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9483 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9484 ])
9485 );
9486 let range = Bank::pubkey_range_from_partition((max - 2, max - 1, max));
9487 assert_eq!(
9488 range,
9489 Pubkey::new_from_array([
9490 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9492 0x00, 0x00, 0x00, 0x00,
9493 ])..=pubkey_max_value()
9494 );
9495
9496 fn should_cause_overflow(partition_count: u64) -> bool {
9497 (u64::max_value() - partition_count + 1) % partition_count == 0
9502 }
9503
9504 let max_exact = 64;
9505 assert!(should_cause_overflow(max_exact));
9507 let max_inexact = 10;
9509 assert!(!should_cause_overflow(max_inexact));
9510
9511 for max in &[max_exact, max_inexact] {
9512 let range = Bank::pubkey_range_from_partition((max - 1, max - 1, *max));
9513 assert_eq!(range, pubkey_max_value()..=pubkey_max_value());
9514 }
9515 }
9516
9517 fn map_to_test_bad_range() -> std::collections::BTreeMap<Pubkey, i8> {
9518 let mut map = std::collections::BTreeMap::new();
9519 map.insert(solana_sdk::pubkey::new_rand(), 1);
9521 map
9522 }
9523
9524 #[test]
9525 #[should_panic(expected = "range start is greater than range end in BTreeMap")]
9526 fn test_rent_eager_bad_range() {
9527 let test_map = map_to_test_bad_range();
9528 let _ = test_map.range(
9529 Pubkey::new_from_array([
9530 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9532 0x00, 0x00, 0x00, 0x01,
9533 ])
9534 ..=Pubkey::new_from_array([
9535 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
9536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9538 ]),
9539 );
9540 }
9541
9542 #[test]
9543 fn test_rent_eager_pubkey_range_noop_range() {
9544 let test_map = map_to_test_bad_range();
9545
9546 let range = Bank::pubkey_range_from_partition((0, 0, 3));
9547 assert_eq!(
9548 range,
9549 Pubkey::new_from_array([0x00; 32])
9550 ..=Pubkey::new_from_array([
9551 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0xff, 0xff, 0xff, 0xff, 0xff,
9552 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9553 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9554 ])
9555 );
9556 let _ = test_map.range(range);
9557
9558 let range = Bank::pubkey_range_from_partition((1, 1, 3));
9559 let same = Pubkey::new_from_array([
9560 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9562 0x00, 0x00, 0x00, 0x00,
9563 ]);
9564 assert_eq!(range, same..=same);
9565 let _ = test_map.range(range);
9566
9567 let range = Bank::pubkey_range_from_partition((2, 2, 3));
9568 assert_eq!(range, pubkey_max_value()..=pubkey_max_value());
9569 let _ = test_map.range(range);
9570 }
9571
9572 fn pubkey_max_value() -> Pubkey {
9573 let highest = Pubkey::from_str("JEKNVnkbo3jma5nREBBJCDoXFVeKkD56V3xKrvRmWxFG").unwrap();
9574 let arr = Pubkey::new_from_array([0xff; 32]);
9575 assert_eq!(highest, arr);
9576 arr
9577 }
9578
9579 #[test]
9580 fn test_rent_pubkey_range_max() {
9581 solana_logger::setup();
9583 let range = Bank::pubkey_range_from_partition((1, 1, 3));
9584 let p = Bank::partition_from_pubkey(range.start(), 3);
9585 assert_eq!(p, 2);
9586 let range = Bank::pubkey_range_from_partition((1, 2, 3));
9587 let p = Bank::partition_from_pubkey(range.start(), 3);
9588 assert_eq!(p, 2);
9589 let range = Bank::pubkey_range_from_partition((2, 2, 3));
9590 let p = Bank::partition_from_pubkey(range.start(), 3);
9591 assert_eq!(p, 2);
9592 let range = Bank::pubkey_range_from_partition((1, 1, 16));
9593 let p = Bank::partition_from_pubkey(range.start(), 16);
9594 assert_eq!(p, 2);
9595 let range = Bank::pubkey_range_from_partition((1, 2, 16));
9596 let p = Bank::partition_from_pubkey(range.start(), 16);
9597 assert_eq!(p, 2);
9598 let range = Bank::pubkey_range_from_partition((2, 2, 16));
9599 let p = Bank::partition_from_pubkey(range.start(), 16);
9600 assert_eq!(p, 3);
9601 let range = Bank::pubkey_range_from_partition((15, 15, 16));
9602 let p = Bank::partition_from_pubkey(range.start(), 16);
9603 assert_eq!(p, 15);
9604 }
9605
9606 #[test]
9607 fn test_rent_eager_pubkey_range_dividable() {
9608 let test_map = map_to_test_bad_range();
9609 let range = Bank::pubkey_range_from_partition((0, 0, 2));
9610
9611 assert_eq!(
9612 range,
9613 Pubkey::new_from_array([0x00; 32])
9614 ..=Pubkey::new_from_array([
9615 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9616 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9617 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9618 ])
9619 );
9620 let _ = test_map.range(range);
9621
9622 let range = Bank::pubkey_range_from_partition((0, 1, 2));
9623 assert_eq!(
9624 range,
9625 Pubkey::new_from_array([
9626 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9628 0x00, 0x00, 0x00, 0x00
9629 ])
9630 ..=Pubkey::new_from_array([
9631 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9632 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9633 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9634 ])
9635 );
9636 let _ = test_map.range(range);
9637 }
9638
9639 #[test]
9640 fn test_rent_eager_pubkey_range_not_dividable() {
9641 solana_logger::setup();
9642
9643 let test_map = map_to_test_bad_range();
9644 let range = Bank::pubkey_range_from_partition((0, 0, 3));
9645 assert_eq!(
9646 range,
9647 Pubkey::new_from_array([0x00; 32])
9648 ..=Pubkey::new_from_array([
9649 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0xff, 0xff, 0xff, 0xff, 0xff,
9650 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9651 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9652 ])
9653 );
9654 let _ = test_map.range(range);
9655
9656 let range = Bank::pubkey_range_from_partition((0, 1, 3));
9657 assert_eq!(
9658 range,
9659 Pubkey::new_from_array([
9660 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9662 0x00, 0x00, 0x00, 0x00
9663 ])
9664 ..=Pubkey::new_from_array([
9665 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa9, 0xff, 0xff, 0xff, 0xff, 0xff,
9666 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9667 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9668 ])
9669 );
9670 let _ = test_map.range(range);
9671
9672 let range = Bank::pubkey_range_from_partition((1, 2, 3));
9673 assert_eq!(
9674 range,
9675 Pubkey::new_from_array([
9676 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9678 0x00, 0x00, 0x00, 0x00
9679 ])
9680 ..=Pubkey::new_from_array([
9681 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9682 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9683 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9684 ])
9685 );
9686 let _ = test_map.range(range);
9687 }
9688
9689 #[test]
9690 fn test_rent_eager_pubkey_range_gap() {
9691 solana_logger::setup();
9692
9693 let test_map = map_to_test_bad_range();
9694 let range = Bank::pubkey_range_from_partition((120, 1023, 12345));
9695 assert_eq!(
9696 range,
9697 Pubkey::new_from_array([
9698 0x02, 0x82, 0x5a, 0x89, 0xd1, 0xac, 0x58, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9700 0x00, 0x00, 0x00, 0x00
9701 ])
9702 ..=Pubkey::new_from_array([
9703 0x15, 0x3c, 0x1d, 0xf1, 0xc6, 0x39, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9704 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9705 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9706 ])
9707 );
9708 let _ = test_map.range(range);
9709 }
9710
9711 impl Bank {
9712 fn slots_by_pubkey(&self, pubkey: &Pubkey, ancestors: &Ancestors) -> Vec<Slot> {
9713 let (locked_entry, _) = self
9714 .rc
9715 .accounts
9716 .accounts_db
9717 .accounts_index
9718 .get(pubkey, Some(ancestors), None)
9719 .unwrap();
9720 locked_entry
9721 .slot_list()
9722 .iter()
9723 .map(|(slot, _)| *slot)
9724 .collect::<Vec<Slot>>()
9725 }
9726 }
9727
9728 #[test]
9729 fn test_rent_eager_collect_rent_in_partition() {
9730 solana_logger::setup();
9731
9732 let (mut genesis_config, _mint_keypair) = create_genesis_config(1_000_000);
9733 activate_all_features(&mut genesis_config);
9734
9735 let zero_lamport_pubkey = solana_sdk::pubkey::new_rand();
9736 let rent_due_pubkey = solana_sdk::pubkey::new_rand();
9737 let rent_exempt_pubkey = solana_sdk::pubkey::new_rand();
9738
9739 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9740 let zero_lamports = 0;
9741 let little_lamports = 1234;
9742 let large_lamports = 123_456_789;
9743 let some_slot = MINIMUM_SLOTS_PER_EPOCH; let rent_collected = 1; bank.store_account(
9748 &zero_lamport_pubkey,
9749 &AccountSharedData::new(zero_lamports, 0, &Pubkey::default()),
9750 );
9751 bank.store_account(
9752 &rent_due_pubkey,
9753 &AccountSharedData::new(little_lamports, 0, &Pubkey::default()),
9754 );
9755 bank.store_account(
9756 &rent_exempt_pubkey,
9757 &AccountSharedData::new(large_lamports, 0, &Pubkey::default()),
9758 );
9759
9760 let genesis_slot = 0;
9761 let ancestors = vec![(some_slot, 0), (0, 1)].into_iter().collect();
9762
9763 let previous_epoch = bank.epoch();
9764 bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), some_slot));
9765 let current_epoch = bank.epoch();
9766 assert_eq!(previous_epoch + 1, current_epoch);
9767
9768 assert_eq!(bank.collected_rent.load(Relaxed), 0);
9769 assert_eq!(
9770 bank.get_account(&rent_due_pubkey).unwrap().lamports(),
9771 little_lamports
9772 );
9773 assert_eq!(bank.get_account(&rent_due_pubkey).unwrap().rent_epoch(), 0);
9774 assert_eq!(
9775 bank.slots_by_pubkey(&rent_due_pubkey, &ancestors),
9776 vec![genesis_slot]
9777 );
9778 assert_eq!(
9779 bank.slots_by_pubkey(&rent_exempt_pubkey, &ancestors),
9780 vec![genesis_slot]
9781 );
9782 assert_eq!(
9783 bank.slots_by_pubkey(&zero_lamport_pubkey, &ancestors),
9784 vec![genesis_slot]
9785 );
9786
9787 assert_eq!(bank.collected_rent.load(Relaxed), 0);
9788 assert!(bank.rewrites_skipped_this_slot.read().unwrap().is_empty());
9789 bank.collect_rent_in_partition((0, 0, 1), true, &RentMetrics::default());
9790 {
9791 let rewrites_skipped = bank.rewrites_skipped_this_slot.read().unwrap();
9792 assert_eq!(rewrites_skipped.len(), 1);
9800 assert!(!rewrites_skipped.contains_key(&rent_exempt_pubkey));
9804 assert!(!rewrites_skipped.contains_key(&rent_due_pubkey));
9806 }
9807
9808 assert_eq!(bank.collected_rent.load(Relaxed), 0);
9809 bank.collect_rent_in_partition((0, 0, 1), false, &RentMetrics::default()); assert_eq!(bank.collected_rent.load(Relaxed), rent_collected);
9812 assert_eq!(
9813 bank.get_account(&rent_due_pubkey).unwrap().lamports(),
9814 little_lamports - rent_collected
9815 );
9816 assert_eq!(
9817 bank.get_account(&rent_due_pubkey).unwrap().rent_epoch(),
9818 current_epoch + 1
9819 );
9820 assert_eq!(
9821 bank.get_account(&rent_exempt_pubkey).unwrap().lamports(),
9822 large_lamports
9823 );
9824 assert_eq!(
9827 bank.get_account(&rent_exempt_pubkey).unwrap().rent_epoch(),
9828 0
9829 );
9830 assert_eq!(
9831 bank.slots_by_pubkey(&rent_due_pubkey, &ancestors),
9832 vec![genesis_slot, some_slot]
9833 );
9834 assert_eq!(
9835 bank.slots_by_pubkey(&rent_exempt_pubkey, &ancestors),
9836 vec![genesis_slot, some_slot]
9837 );
9838 assert_eq!(
9839 bank.slots_by_pubkey(&zero_lamport_pubkey, &ancestors),
9840 vec![genesis_slot]
9841 );
9842 }
9843
9844 fn new_from_parent_next_epoch(parent: &Arc<Bank>, epochs: Epoch) -> Bank {
9845 let mut slot = parent.slot();
9846 let mut epoch = parent.epoch();
9847 for _ in 0..epochs {
9848 slot += parent.epoch_schedule().get_slots_in_epoch(epoch);
9849 epoch = parent.epoch_schedule().get_epoch(slot);
9850 }
9851
9852 Bank::new_from_parent(parent, &Pubkey::default(), slot)
9853 }
9854
9855 #[test]
9856 fn test_collect_rent_from_accounts() {
9858 solana_logger::setup();
9859
9860 let zero_lamport_pubkey = Pubkey::from([0; 32]);
9861
9862 let genesis_bank = create_simple_test_arc_bank(100000);
9863 let first_bank = Arc::new(new_from_parent(&genesis_bank));
9864 let first_slot = 1;
9865 assert_eq!(first_slot, first_bank.slot());
9866 let epoch_delta = 4;
9867 let later_bank = Arc::new(new_from_parent_next_epoch(&first_bank, epoch_delta)); let later_slot = later_bank.slot();
9869 assert!(later_bank.epoch() == genesis_bank.epoch() + epoch_delta);
9870
9871 let data_size = 0; let lamports = later_bank.get_minimum_balance_for_rent_exemption(data_size); let mut account = AccountSharedData::new(lamports, data_size, &Pubkey::default());
9874 account.set_rent_epoch(later_bank.epoch() - 1); let just_rewrites = true;
9877 let result = later_bank.collect_rent_from_accounts(
9881 vec![(zero_lamport_pubkey, account.clone(), later_slot)],
9882 just_rewrites,
9883 None,
9884 PartitionIndex::default(),
9885 );
9886 assert!(result.rewrites_skipped.is_empty());
9887 let result = later_bank.collect_rent_from_accounts(
9889 vec![(zero_lamport_pubkey, account, later_slot - 1)],
9890 just_rewrites,
9891 None,
9892 PartitionIndex::default(),
9893 );
9894 assert!(result.rewrites_skipped[0].0 == zero_lamport_pubkey);
9895 }
9896
9897 #[test]
9898 fn test_rent_eager_collect_rent_zero_lamport_deterministic() {
9899 solana_logger::setup();
9900
9901 let (genesis_config, _mint_keypair) = create_genesis_config(1);
9902
9903 let zero_lamport_pubkey = solana_sdk::pubkey::new_rand();
9904
9905 let genesis_bank1 = Arc::new(Bank::new_for_tests(&genesis_config));
9906 let genesis_bank2 = Arc::new(Bank::new_for_tests(&genesis_config));
9907 let bank1_with_zero = Arc::new(new_from_parent(&genesis_bank1));
9908 let bank1_without_zero = Arc::new(new_from_parent(&genesis_bank2));
9909
9910 let zero_lamports = 0;
9911 let data_size = 12345; let account = AccountSharedData::new(zero_lamports, data_size, &Pubkey::default());
9913 bank1_with_zero.store_account(&zero_lamport_pubkey, &account);
9914 bank1_without_zero.store_account(&zero_lamport_pubkey, &account);
9915
9916 bank1_without_zero
9917 .rc
9918 .accounts
9919 .accounts_db
9920 .accounts_index
9921 .add_root(genesis_bank1.slot() + 1, false);
9922 bank1_without_zero
9923 .rc
9924 .accounts
9925 .accounts_db
9926 .accounts_index
9927 .purge_roots(&zero_lamport_pubkey);
9928
9929 let some_slot = MINIMUM_SLOTS_PER_EPOCH; let bank2_with_zero = Arc::new(Bank::new_from_parent(
9932 &bank1_with_zero,
9933 &Pubkey::default(),
9934 some_slot,
9935 ));
9936 assert_eq!(bank1_with_zero.epoch() + 1, bank2_with_zero.epoch());
9937 let bank2_without_zero = Arc::new(Bank::new_from_parent(
9938 &bank1_without_zero,
9939 &Pubkey::default(),
9940 some_slot,
9941 ));
9942 let hash1_with_zero = bank1_with_zero.hash();
9943 let hash1_without_zero = bank1_without_zero.hash();
9944 assert_eq!(hash1_with_zero, hash1_without_zero);
9945 assert_ne!(hash1_with_zero, Hash::default());
9946
9947 bank2_with_zero.collect_rent_in_partition((0, 0, 1), false, &RentMetrics::default()); bank2_without_zero.collect_rent_in_partition((0, 0, 1), false, &RentMetrics::default()); bank2_with_zero.freeze();
9951 let hash2_with_zero = bank2_with_zero.hash();
9952 bank2_without_zero.freeze();
9953 let hash2_without_zero = bank2_without_zero.hash();
9954
9955 assert_eq!(hash2_with_zero, hash2_without_zero);
9956 assert_ne!(hash2_with_zero, Hash::default());
9957 }
9958
9959 #[test]
9960 fn test_bank_update_vote_stake_rewards() {
9961 let thread_pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
9962 check_bank_update_vote_stake_rewards(|bank: &Bank| {
9963 bank.load_vote_and_stake_accounts_with_thread_pool(&thread_pool, null_tracer())
9964 });
9965 check_bank_update_vote_stake_rewards(|bank: &Bank| {
9966 bank.load_vote_and_stake_accounts(&thread_pool, null_tracer())
9967 });
9968 }
9969
9970 fn check_bank_update_vote_stake_rewards<F>(load_vote_and_stake_accounts: F)
9971 where
9972 F: Fn(&Bank) -> LoadVoteAndStakeAccountsResult,
9973 {
9974 solana_logger::setup();
9975
9976 let bank0 = Arc::new(Bank::new_for_tests(&GenesisConfig {
9978 accounts: (0..42)
9979 .map(|_| {
9980 (
9981 solana_sdk::pubkey::new_rand(),
9982 Account::new(1_000_000_000, 0, &Pubkey::default()),
9983 )
9984 })
9985 .collect(),
9986 poh_config: PohConfig {
9988 target_tick_duration: Duration::from_secs(
9989 SECONDS_PER_YEAR as u64
9990 / MINIMUM_SLOTS_PER_EPOCH as u64
9991 / DEFAULT_TICKS_PER_SLOT,
9992 ),
9993 hashes_per_tick: None,
9994 target_tick_count: None,
9995 },
9996 cluster_type: ClusterType::MainnetBeta,
9997
9998 ..GenesisConfig::default()
9999 }));
10000
10001 bank0.restore_old_behavior_for_fragile_tests();
10004
10005 assert_eq!(
10006 bank0.capitalization(),
10007 42 * 1_000_000_000 + genesis_sysvar_and_builtin_program_lamports(),
10008 );
10009
10010 let ((vote_id, mut vote_account), (stake_id, stake_account)) =
10011 crate::stakes::tests::create_staked_node_accounts(10_000);
10012 let starting_vote_and_stake_balance = 10_000 + 1;
10013
10014 bank0.store_account_and_update_capitalization(&stake_id, &stake_account);
10016
10017 let mut vote_state = Some(VoteState::from(&vote_account).unwrap());
10019 for i in 0..MAX_LOCKOUT_HISTORY + 42 {
10020 if let Some(v) = vote_state.as_mut() {
10021 v.process_slot_vote_unchecked(i as u64)
10022 }
10023 let versioned = VoteStateVersions::Current(Box::new(vote_state.take().unwrap()));
10024 VoteState::to(&versioned, &mut vote_account).unwrap();
10025 bank0.store_account_and_update_capitalization(&vote_id, &vote_account);
10026 match versioned {
10027 VoteStateVersions::Current(v) => {
10028 vote_state = Some(*v);
10029 }
10030 _ => panic!("Has to be of type Current"),
10031 };
10032 }
10033 bank0.store_account_and_update_capitalization(&vote_id, &vote_account);
10034 bank0.freeze();
10035
10036 assert_eq!(
10037 bank0.capitalization(),
10038 42 * 1_000_000_000
10039 + genesis_sysvar_and_builtin_program_lamports()
10040 + starting_vote_and_stake_balance
10041 + bank0_sysvar_delta(),
10042 );
10043 assert!(bank0.rewards.read().unwrap().is_empty());
10044
10045 load_vote_and_stake_accounts(&bank0);
10046
10047 let bank1 = Bank::new_from_parent(
10049 &bank0,
10050 &Pubkey::default(),
10051 bank0.get_slots_in_epoch(bank0.epoch()) + 1,
10052 );
10053 assert_ne!(bank1.capitalization(), bank0.capitalization());
10055
10056 let paid_rewards = bank1.capitalization() - bank0.capitalization() - bank1_sysvar_delta();
10058
10059 let PrevEpochInflationRewards {
10061 validator_rewards, ..
10062 } = bank1.calculate_previous_epoch_inflation_rewards(bank0.capitalization(), bank0.epoch());
10063
10064 assert!(
10066 ((bank1.get_balance(&stake_id) - stake_account.lamports() + bank1.get_balance(&vote_id)
10067 - vote_account.lamports()) as f64
10068 - validator_rewards as f64)
10069 .abs()
10070 < 1.0
10071 );
10072
10073 assert!((validator_rewards as f64 - paid_rewards as f64).abs() < 1.0); assert_eq!(
10078 *bank1.rewards.read().unwrap(),
10079 vec![
10080 (
10081 vote_id,
10082 RewardInfo {
10083 reward_type: RewardType::Voting,
10084 lamports: 0,
10085 post_balance: bank1.get_balance(&vote_id),
10086 commission: Some(0),
10087 }
10088 ),
10089 (
10090 stake_id,
10091 RewardInfo {
10092 reward_type: RewardType::Staking,
10093 lamports: validator_rewards as i64,
10094 post_balance: bank1.get_balance(&stake_id),
10095 commission: Some(0),
10096 }
10097 )
10098 ]
10099 );
10100 bank1.freeze();
10101 assert!(bank1.calculate_and_verify_capitalization(true));
10102 }
10103
10104 fn do_test_bank_update_rewards_determinism() -> u64 {
10105 let bank = Arc::new(Bank::new_for_tests(&GenesisConfig {
10107 accounts: (0..42)
10108 .map(|_| {
10109 (
10110 solana_sdk::pubkey::new_rand(),
10111 Account::new(1_000_000_000, 0, &Pubkey::default()),
10112 )
10113 })
10114 .collect(),
10115 poh_config: PohConfig {
10117 target_tick_duration: Duration::from_secs(
10118 SECONDS_PER_YEAR as u64
10119 / MINIMUM_SLOTS_PER_EPOCH as u64
10120 / DEFAULT_TICKS_PER_SLOT,
10121 ),
10122 hashes_per_tick: None,
10123 target_tick_count: None,
10124 },
10125 cluster_type: ClusterType::MainnetBeta,
10126
10127 ..GenesisConfig::default()
10128 }));
10129
10130 bank.restore_old_behavior_for_fragile_tests();
10133
10134 assert_eq!(
10135 bank.capitalization(),
10136 42 * 1_000_000_000 + genesis_sysvar_and_builtin_program_lamports()
10137 );
10138
10139 let vote_id = solana_sdk::pubkey::new_rand();
10140 let mut vote_account =
10141 vote_state::create_account(&vote_id, &solana_sdk::pubkey::new_rand(), 0, 100);
10142 let (stake_id1, stake_account1) = crate::stakes::tests::create_stake_account(123, &vote_id);
10143 let (stake_id2, stake_account2) = crate::stakes::tests::create_stake_account(456, &vote_id);
10144
10145 bank.store_account_and_update_capitalization(&stake_id1, &stake_account1);
10147 bank.store_account_and_update_capitalization(&stake_id2, &stake_account2);
10148
10149 let mut vote_state = Some(VoteState::from(&vote_account).unwrap());
10151 for i in 0..MAX_LOCKOUT_HISTORY + 42 {
10152 if let Some(v) = vote_state.as_mut() {
10153 v.process_slot_vote_unchecked(i as u64)
10154 }
10155 let versioned = VoteStateVersions::Current(Box::new(vote_state.take().unwrap()));
10156 VoteState::to(&versioned, &mut vote_account).unwrap();
10157 bank.store_account_and_update_capitalization(&vote_id, &vote_account);
10158 match versioned {
10159 VoteStateVersions::Current(v) => {
10160 vote_state = Some(*v);
10161 }
10162 _ => panic!("Has to be of type Current"),
10163 };
10164 }
10165 bank.store_account_and_update_capitalization(&vote_id, &vote_account);
10166
10167 let bank1 = Bank::new_from_parent(
10169 &bank,
10170 &Pubkey::default(),
10171 bank.get_slots_in_epoch(bank.epoch()) + 1,
10172 );
10173 assert_ne!(bank1.capitalization(), bank.capitalization());
10175
10176 bank1.freeze();
10177 assert!(bank1.calculate_and_verify_capitalization(true));
10178
10179 let rewards = bank1.rewards.read().unwrap();
10181 rewards
10182 .iter()
10183 .find(|(_address, reward)| reward.reward_type == RewardType::Voting)
10184 .unwrap();
10185 rewards
10186 .iter()
10187 .find(|(_address, reward)| reward.reward_type == RewardType::Staking)
10188 .unwrap();
10189
10190 bank1.capitalization()
10191 }
10192
10193 #[test]
10194 fn test_bank_update_rewards_determinism() {
10195 solana_logger::setup();
10196
10197 let expected_capitalization = do_test_bank_update_rewards_determinism();
10199 for _ in 0..30 {
10202 let actual_capitalization = do_test_bank_update_rewards_determinism();
10203 assert_eq!(actual_capitalization, expected_capitalization);
10204 }
10205 }
10206
10207 impl VerifyBankHash {
10208 fn default_for_test() -> Self {
10209 Self {
10210 test_hash_calculation: true,
10211 can_cached_slot_be_unflushed: false,
10212 ignore_mismatch: false,
10213 require_rooted_bank: false,
10214 run_in_background: false,
10215 store_hash_raw_data_for_debug: false,
10216 }
10217 }
10218 }
10219
10220 #[test]
10222 fn test_purge_empty_accounts() {
10223 solana_logger::setup();
10224 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10225 let amount = genesis_config.rent.minimum_balance(0);
10226 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
10227 let mut bank = parent;
10228 for _ in 0..10 {
10229 let blockhash = bank.last_blockhash();
10230 let pubkey = solana_sdk::pubkey::new_rand();
10231 let tx = system_transaction::transfer(&mint_keypair, &pubkey, 0, blockhash);
10232 bank.process_transaction(&tx).unwrap();
10233 bank.freeze();
10234 bank.squash();
10235 bank = Arc::new(new_from_parent(&bank));
10236 }
10237
10238 bank.freeze();
10239 bank.squash();
10240 bank.force_flush_accounts_cache();
10241 let hash = bank.update_accounts_hash();
10242 bank.clean_accounts(false, false, None);
10243 assert_eq!(bank.update_accounts_hash(), hash);
10244
10245 let bank0 = Arc::new(new_from_parent(&bank));
10246 let blockhash = bank.last_blockhash();
10247 let keypair = Keypair::new();
10248 let tx = system_transaction::transfer(&mint_keypair, &keypair.pubkey(), amount, blockhash);
10249 bank0.process_transaction(&tx).unwrap();
10250
10251 let bank1 = Arc::new(new_from_parent(&bank0));
10252 let pubkey = solana_sdk::pubkey::new_rand();
10253 let blockhash = bank.last_blockhash();
10254 let tx = system_transaction::transfer(&keypair, &pubkey, amount, blockhash);
10255 bank1.process_transaction(&tx).unwrap();
10256
10257 assert_eq!(
10258 bank0.get_account(&keypair.pubkey()).unwrap().lamports(),
10259 amount
10260 );
10261 assert_eq!(bank1.get_account(&keypair.pubkey()), None);
10262
10263 info!("bank0 purge");
10264 let hash = bank0.update_accounts_hash();
10265 bank0.clean_accounts(false, false, None);
10266 assert_eq!(bank0.update_accounts_hash(), hash);
10267
10268 assert_eq!(
10269 bank0.get_account(&keypair.pubkey()).unwrap().lamports(),
10270 amount
10271 );
10272 assert_eq!(bank1.get_account(&keypair.pubkey()), None);
10273
10274 info!("bank1 purge");
10275 bank1.clean_accounts(false, false, None);
10276
10277 assert_eq!(
10278 bank0.get_account(&keypair.pubkey()).unwrap().lamports(),
10279 amount
10280 );
10281 assert_eq!(bank1.get_account(&keypair.pubkey()), None);
10282
10283 assert!(bank0.verify_bank_hash(VerifyBankHash::default_for_test()));
10284
10285 bank0.freeze();
10287 bank0.squash();
10288 assert!(bank0.verify_bank_hash(VerifyBankHash::default_for_test()));
10289
10290 bank1.freeze();
10291 bank1.squash();
10292 bank1.update_accounts_hash();
10293 assert!(bank1.verify_bank_hash(VerifyBankHash::default_for_test()));
10294
10295 assert_eq!(bank0.get_account(&keypair.pubkey()), None);
10297 assert_eq!(bank1.get_account(&keypair.pubkey()), None);
10298 bank1.force_flush_accounts_cache();
10299 bank1.clean_accounts(false, false, None);
10300
10301 assert!(bank1.verify_bank_hash(VerifyBankHash::default_for_test()));
10302 }
10303
10304 #[test]
10305 fn test_two_payments_to_one_party() {
10306 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10307 let pubkey = solana_sdk::pubkey::new_rand();
10308 let bank = Bank::new_for_tests(&genesis_config);
10309 let amount = genesis_config.rent.minimum_balance(0);
10310 assert_eq!(bank.last_blockhash(), genesis_config.hash());
10311
10312 bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
10313 assert_eq!(bank.get_balance(&pubkey), amount);
10314
10315 bank.transfer(amount * 2, &mint_keypair, &pubkey).unwrap();
10316 assert_eq!(bank.get_balance(&pubkey), amount * 3);
10317 assert_eq!(bank.transaction_count(), 2);
10318 }
10319
10320 #[test]
10321 fn test_one_source_two_tx_one_batch() {
10322 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10323 let key1 = solana_sdk::pubkey::new_rand();
10324 let key2 = solana_sdk::pubkey::new_rand();
10325 let bank = Bank::new_for_tests(&genesis_config);
10326 let amount = genesis_config.rent.minimum_balance(0);
10327 assert_eq!(bank.last_blockhash(), genesis_config.hash());
10328
10329 let t1 = system_transaction::transfer(&mint_keypair, &key1, amount, genesis_config.hash());
10330 let t2 = system_transaction::transfer(&mint_keypair, &key2, amount, genesis_config.hash());
10331 let txs = vec![t1.clone(), t2.clone()];
10332 let res = bank.process_transactions(txs.iter());
10333
10334 assert_eq!(res.len(), 2);
10335 assert_eq!(res[0], Ok(()));
10336 assert_eq!(res[1], Err(TransactionError::AccountInUse));
10337 assert_eq!(
10338 bank.get_balance(&mint_keypair.pubkey()),
10339 sol_to_lamports(1.) - amount
10340 );
10341 assert_eq!(bank.get_balance(&key1), amount);
10342 assert_eq!(bank.get_balance(&key2), 0);
10343 assert_eq!(bank.get_signature_status(&t1.signatures[0]), Some(Ok(())));
10344 assert_eq!(bank.get_signature_status(&t2.signatures[0]), None);
10347 }
10348
10349 #[test]
10350 fn test_one_tx_two_out_atomic_fail() {
10351 let amount = sol_to_lamports(1.);
10352 let (genesis_config, mint_keypair) = create_genesis_config(amount);
10353 let key1 = solana_sdk::pubkey::new_rand();
10354 let key2 = solana_sdk::pubkey::new_rand();
10355 let bank = Bank::new_for_tests(&genesis_config);
10356 let instructions = system_instruction::transfer_many(
10357 &mint_keypair.pubkey(),
10358 &[(key1, amount), (key2, amount)],
10359 );
10360 let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
10361 let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
10362 assert_eq!(
10363 bank.process_transaction(&tx).unwrap_err(),
10364 TransactionError::InstructionError(1, SystemError::ResultWithNegativeLamports.into())
10365 );
10366 assert_eq!(bank.get_balance(&mint_keypair.pubkey()), amount);
10367 assert_eq!(bank.get_balance(&key1), 0);
10368 assert_eq!(bank.get_balance(&key2), 0);
10369 }
10370
10371 #[test]
10372 fn test_one_tx_two_out_atomic_pass() {
10373 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10374 let key1 = solana_sdk::pubkey::new_rand();
10375 let key2 = solana_sdk::pubkey::new_rand();
10376 let bank = Bank::new_for_tests(&genesis_config);
10377 let amount = genesis_config.rent.minimum_balance(0);
10378 let instructions = system_instruction::transfer_many(
10379 &mint_keypair.pubkey(),
10380 &[(key1, amount), (key2, amount)],
10381 );
10382 let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
10383 let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
10384 bank.process_transaction(&tx).unwrap();
10385 assert_eq!(
10386 bank.get_balance(&mint_keypair.pubkey()),
10387 sol_to_lamports(1.) - (2 * amount)
10388 );
10389 assert_eq!(bank.get_balance(&key1), amount);
10390 assert_eq!(bank.get_balance(&key2), amount);
10391 }
10392
10393 #[test]
10395 fn test_detect_failed_duplicate_transactions() {
10396 let (mut genesis_config, mint_keypair) = create_genesis_config(10_000);
10397 genesis_config.fee_rate_governor = FeeRateGovernor::new(5_000, 0);
10398 let bank = Bank::new_for_tests(&genesis_config);
10399
10400 let dest = Keypair::new();
10401
10402 let tx = system_transaction::transfer(
10404 &mint_keypair,
10405 &dest.pubkey(),
10406 10_000,
10407 genesis_config.hash(),
10408 );
10409 let signature = tx.signatures[0];
10410 assert!(!bank.has_signature(&signature));
10411
10412 assert_eq!(
10413 bank.process_transaction(&tx),
10414 Err(TransactionError::InstructionError(
10415 0,
10416 SystemError::ResultWithNegativeLamports.into(),
10417 ))
10418 );
10419
10420 assert_eq!(bank.get_balance(&dest.pubkey()), 0);
10422
10423 assert_eq!(bank.get_balance(&mint_keypair.pubkey()), 5000);
10425 }
10426
10427 #[test]
10428 fn test_account_not_found() {
10429 solana_logger::setup();
10430 let (genesis_config, mint_keypair) = create_genesis_config(0);
10431 let bank = Bank::new_for_tests(&genesis_config);
10432 let keypair = Keypair::new();
10433 assert_eq!(
10434 bank.transfer(
10435 genesis_config.rent.minimum_balance(0),
10436 &keypair,
10437 &mint_keypair.pubkey()
10438 ),
10439 Err(TransactionError::AccountNotFound)
10440 );
10441 assert_eq!(bank.transaction_count(), 0);
10442 }
10443
10444 #[test]
10445 fn test_insufficient_funds() {
10446 let mint_amount = sol_to_lamports(1.);
10447 let (genesis_config, mint_keypair) = create_genesis_config(mint_amount);
10448 let bank = Bank::new_for_tests(&genesis_config);
10449 let pubkey = solana_sdk::pubkey::new_rand();
10450 let amount = genesis_config.rent.minimum_balance(0);
10451 bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
10452 assert_eq!(bank.transaction_count(), 1);
10453 assert_eq!(bank.get_balance(&pubkey), amount);
10454 assert_eq!(
10455 bank.transfer((mint_amount - amount) + 1, &mint_keypair, &pubkey),
10456 Err(TransactionError::InstructionError(
10457 0,
10458 SystemError::ResultWithNegativeLamports.into(),
10459 ))
10460 );
10461 assert_eq!(bank.transaction_count(), 1);
10462
10463 let mint_pubkey = mint_keypair.pubkey();
10464 assert_eq!(bank.get_balance(&mint_pubkey), mint_amount - amount);
10465 assert_eq!(bank.get_balance(&pubkey), amount);
10466 }
10467
10468 #[test]
10469 fn test_transfer_to_newb() {
10470 solana_logger::setup();
10471 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10472 let bank = Bank::new_for_tests(&genesis_config);
10473 let amount = genesis_config.rent.minimum_balance(0);
10474 let pubkey = solana_sdk::pubkey::new_rand();
10475 bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
10476 assert_eq!(bank.get_balance(&pubkey), amount);
10477 }
10478
10479 #[test]
10480 fn test_transfer_to_sysvar() {
10481 solana_logger::setup();
10482 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10483 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
10484 let amount = genesis_config.rent.minimum_balance(0);
10485
10486 let normal_pubkey = solana_sdk::pubkey::new_rand();
10487 let sysvar_pubkey = sysvar::clock::id();
10488 assert_eq!(bank.get_balance(&normal_pubkey), 0);
10489 assert_eq!(bank.get_balance(&sysvar_pubkey), 1_169_280);
10490
10491 bank.transfer(amount, &mint_keypair, &normal_pubkey)
10492 .unwrap();
10493 bank.transfer(amount, &mint_keypair, &sysvar_pubkey)
10494 .unwrap_err();
10495 assert_eq!(bank.get_balance(&normal_pubkey), amount);
10496 assert_eq!(bank.get_balance(&sysvar_pubkey), 1_169_280);
10497
10498 let bank = Arc::new(new_from_parent(&bank));
10499 assert_eq!(bank.get_balance(&normal_pubkey), amount);
10500 assert_eq!(bank.get_balance(&sysvar_pubkey), 1_169_280);
10501 }
10502
10503 #[test]
10504 fn test_bank_deposit() {
10505 let bank = create_simple_test_bank(100);
10506
10507 let key = Keypair::new();
10509 let new_balance = bank.deposit(&key.pubkey(), 10).unwrap();
10510 assert_eq!(new_balance, 10);
10511 assert_eq!(bank.get_balance(&key.pubkey()), 10);
10512
10513 let new_balance = bank.deposit(&key.pubkey(), 3).unwrap();
10515 assert_eq!(new_balance, 13);
10516 assert_eq!(bank.get_balance(&key.pubkey()), 13);
10517 }
10518
10519 #[test]
10520 fn test_bank_withdraw() {
10521 let bank = create_simple_test_bank(100);
10522
10523 let key = Keypair::new();
10525 assert_eq!(
10526 bank.withdraw(&key.pubkey(), 10),
10527 Err(TransactionError::AccountNotFound)
10528 );
10529
10530 bank.deposit(&key.pubkey(), 3).unwrap();
10531 assert_eq!(bank.get_balance(&key.pubkey()), 3);
10532
10533 assert_eq!(
10535 bank.withdraw(&key.pubkey(), 10),
10536 Err(TransactionError::InsufficientFundsForFee)
10537 );
10538
10539 assert_eq!(bank.withdraw(&key.pubkey(), 2), Ok(()));
10541 assert_eq!(bank.get_balance(&key.pubkey()), 1);
10542 }
10543
10544 #[test]
10545 fn test_bank_withdraw_from_nonce_account() {
10546 let (mut genesis_config, _mint_keypair) = create_genesis_config(100_000);
10547 genesis_config.rent.lamports_per_byte_year = 42;
10548 let bank = Bank::new_for_tests(&genesis_config);
10549
10550 let min_balance = bank.get_minimum_balance_for_rent_exemption(nonce::State::size());
10551 let nonce = Keypair::new();
10552 let nonce_account = AccountSharedData::new_data(
10553 min_balance + 42,
10554 &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::default())),
10555 &system_program::id(),
10556 )
10557 .unwrap();
10558 bank.store_account(&nonce.pubkey(), &nonce_account);
10559 assert_eq!(bank.get_balance(&nonce.pubkey()), min_balance + 42);
10560
10561 assert_eq!(
10563 bank.withdraw(&nonce.pubkey(), min_balance / 2),
10564 Err(TransactionError::InsufficientFundsForFee)
10565 );
10566 assert_eq!(bank.get_balance(&nonce.pubkey()), min_balance + 42);
10567
10568 bank.withdraw(&nonce.pubkey(), 42).unwrap();
10570 assert_eq!(bank.get_balance(&nonce.pubkey()), min_balance);
10571
10572 assert_eq!(
10574 bank.withdraw(&nonce.pubkey(), min_balance),
10575 Err(TransactionError::InsufficientFundsForFee),
10576 );
10577 }
10578
10579 #[test]
10580 fn test_bank_tx_fee() {
10581 solana_logger::setup();
10582
10583 let arbitrary_transfer_amount = 42_000;
10584 let mint = arbitrary_transfer_amount * 100;
10585 let leader = solana_sdk::pubkey::new_rand();
10586 let GenesisConfigInfo {
10587 mut genesis_config,
10588 mint_keypair,
10589 ..
10590 } = create_genesis_config_with_leader(mint, &leader, 3);
10591 genesis_config.fee_rate_governor = FeeRateGovernor::new(5000, 0); let expected_fee_paid = genesis_config
10594 .fee_rate_governor
10595 .create_fee_calculator()
10596 .lamports_per_signature;
10597 let (expected_fee_collected, expected_fee_burned) =
10598 genesis_config.fee_rate_governor.burn(expected_fee_paid);
10599
10600 let mut bank = Bank::new_for_tests(&genesis_config);
10601
10602 let capitalization = bank.capitalization();
10603
10604 let key = Keypair::new();
10605 let tx = system_transaction::transfer(
10606 &mint_keypair,
10607 &key.pubkey(),
10608 arbitrary_transfer_amount,
10609 bank.last_blockhash(),
10610 );
10611
10612 let initial_balance = bank.get_balance(&leader);
10613 assert_eq!(bank.process_transaction(&tx), Ok(()));
10614 assert_eq!(bank.get_balance(&key.pubkey()), arbitrary_transfer_amount);
10615 assert_eq!(
10616 bank.get_balance(&mint_keypair.pubkey()),
10617 mint - arbitrary_transfer_amount - expected_fee_paid
10618 );
10619
10620 assert_eq!(bank.get_balance(&leader), initial_balance);
10621 goto_end_of_slot(&mut bank);
10622 assert_eq!(bank.signature_count(), 1);
10623 assert_eq!(
10624 bank.get_balance(&leader),
10625 initial_balance + expected_fee_collected
10626 ); let sysvar_and_builtin_program_delta = 1;
10630 assert_eq!(
10631 capitalization - expected_fee_burned + sysvar_and_builtin_program_delta,
10632 bank.capitalization()
10633 );
10634
10635 assert_eq!(
10636 *bank.rewards.read().unwrap(),
10637 vec![(
10638 leader,
10639 RewardInfo {
10640 reward_type: RewardType::Fee,
10641 lamports: expected_fee_collected as i64,
10642 post_balance: initial_balance + expected_fee_collected,
10643 commission: None,
10644 }
10645 )]
10646 );
10647
10648 let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
10650 let mut tx =
10651 system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, bank.last_blockhash());
10652 tx.message.instructions[0].data[0] = 40;
10654
10655 bank.process_transaction(&tx)
10656 .expect_err("instruction error");
10657 assert_eq!(bank.get_balance(&key.pubkey()), arbitrary_transfer_amount); assert_eq!(
10659 bank.get_balance(&mint_keypair.pubkey()),
10660 mint - arbitrary_transfer_amount - 2 * expected_fee_paid
10661 ); goto_end_of_slot(&mut bank);
10663 assert_eq!(bank.signature_count(), 1);
10664
10665 assert_eq!(
10667 bank.get_balance(&leader),
10668 initial_balance + 2 * expected_fee_collected
10669 );
10670
10671 assert_eq!(
10672 *bank.rewards.read().unwrap(),
10673 vec![(
10674 leader,
10675 RewardInfo {
10676 reward_type: RewardType::Fee,
10677 lamports: expected_fee_collected as i64,
10678 post_balance: initial_balance + 2 * expected_fee_collected,
10679 commission: None,
10680 }
10681 )]
10682 );
10683 }
10684
10685 #[test]
10686 fn test_bank_tx_compute_unit_fee() {
10687 solana_logger::setup();
10688
10689 let key = Keypair::new();
10690 let arbitrary_transfer_amount = 42;
10691 let mint = arbitrary_transfer_amount * 10_000_000;
10692 let leader = solana_sdk::pubkey::new_rand();
10693 let GenesisConfigInfo {
10694 mut genesis_config,
10695 mint_keypair,
10696 ..
10697 } = create_genesis_config_with_leader(mint, &leader, 3);
10698 genesis_config.fee_rate_governor = FeeRateGovernor::new(4, 0); let expected_fee_paid = Bank::calculate_fee(
10701 &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(),
10702 genesis_config
10703 .fee_rate_governor
10704 .create_fee_calculator()
10705 .lamports_per_signature,
10706 &FeeStructure::default(),
10707 true,
10708 true,
10709 true,
10710 );
10711
10712 let (expected_fee_collected, expected_fee_burned) =
10713 genesis_config.fee_rate_governor.burn(expected_fee_paid);
10714
10715 let mut bank = Bank::new_for_tests(&genesis_config);
10716
10717 let capitalization = bank.capitalization();
10718
10719 let tx = system_transaction::transfer(
10720 &mint_keypair,
10721 &key.pubkey(),
10722 arbitrary_transfer_amount,
10723 bank.last_blockhash(),
10724 );
10725
10726 let initial_balance = bank.get_balance(&leader);
10727 assert_eq!(bank.process_transaction(&tx), Ok(()));
10728 assert_eq!(bank.get_balance(&key.pubkey()), arbitrary_transfer_amount);
10729 assert_eq!(
10730 bank.get_balance(&mint_keypair.pubkey()),
10731 mint - arbitrary_transfer_amount - expected_fee_paid
10732 );
10733
10734 assert_eq!(bank.get_balance(&leader), initial_balance);
10735 goto_end_of_slot(&mut bank);
10736 assert_eq!(bank.signature_count(), 1);
10737 assert_eq!(
10738 bank.get_balance(&leader),
10739 initial_balance + expected_fee_collected
10740 ); let sysvar_and_builtin_program_delta = 1;
10744 assert_eq!(
10745 capitalization - expected_fee_burned + sysvar_and_builtin_program_delta,
10746 bank.capitalization()
10747 );
10748
10749 assert_eq!(
10750 *bank.rewards.read().unwrap(),
10751 vec![(
10752 leader,
10753 RewardInfo {
10754 reward_type: RewardType::Fee,
10755 lamports: expected_fee_collected as i64,
10756 post_balance: initial_balance + expected_fee_collected,
10757 commission: None,
10758 }
10759 )]
10760 );
10761
10762 let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
10764 let mut tx =
10765 system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, bank.last_blockhash());
10766 tx.message.instructions[0].data[0] = 40;
10768
10769 bank.process_transaction(&tx)
10770 .expect_err("instruction error");
10771 assert_eq!(bank.get_balance(&key.pubkey()), arbitrary_transfer_amount); assert_eq!(
10773 bank.get_balance(&mint_keypair.pubkey()),
10774 mint - arbitrary_transfer_amount - 2 * expected_fee_paid
10775 ); goto_end_of_slot(&mut bank);
10777 assert_eq!(bank.signature_count(), 1);
10778
10779 assert_eq!(
10781 bank.get_balance(&leader),
10782 initial_balance + 2 * expected_fee_collected
10783 );
10784
10785 assert_eq!(
10786 *bank.rewards.read().unwrap(),
10787 vec![(
10788 leader,
10789 RewardInfo {
10790 reward_type: RewardType::Fee,
10791 lamports: expected_fee_collected as i64,
10792 post_balance: initial_balance + 2 * expected_fee_collected,
10793 commission: None,
10794 }
10795 )]
10796 );
10797 }
10798
10799 #[test]
10800 fn test_bank_blockhash_fee_structure() {
10801 let leader = solana_sdk::pubkey::new_rand();
10804 let GenesisConfigInfo {
10805 mut genesis_config,
10806 mint_keypair,
10807 ..
10808 } = create_genesis_config_with_leader(1_000_000, &leader, 3);
10809 genesis_config
10810 .fee_rate_governor
10811 .target_lamports_per_signature = 5000;
10812 genesis_config.fee_rate_governor.target_signatures_per_slot = 0;
10813
10814 let mut bank = Bank::new_for_tests(&genesis_config);
10815 goto_end_of_slot(&mut bank);
10816 let cheap_blockhash = bank.last_blockhash();
10817 let cheap_lamports_per_signature = bank.get_lamports_per_signature();
10818 assert_eq!(cheap_lamports_per_signature, 0);
10819
10820 let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
10821 goto_end_of_slot(&mut bank);
10822 let expensive_blockhash = bank.last_blockhash();
10823 let expensive_lamports_per_signature = bank.get_lamports_per_signature();
10824 assert!(cheap_lamports_per_signature < expensive_lamports_per_signature);
10825
10826 let bank = Bank::new_from_parent(&Arc::new(bank), &leader, 2);
10827
10828 let key = Keypair::new();
10830 let initial_mint_balance = bank.get_balance(&mint_keypair.pubkey());
10831 let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, cheap_blockhash);
10832 assert_eq!(bank.process_transaction(&tx), Ok(()));
10833 assert_eq!(bank.get_balance(&key.pubkey()), 1);
10834 assert_eq!(
10835 bank.get_balance(&mint_keypair.pubkey()),
10836 initial_mint_balance - 1 - cheap_lamports_per_signature
10837 );
10838
10839 let key = Keypair::new();
10841 let initial_mint_balance = bank.get_balance(&mint_keypair.pubkey());
10842 let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, expensive_blockhash);
10843 assert_eq!(bank.process_transaction(&tx), Ok(()));
10844 assert_eq!(bank.get_balance(&key.pubkey()), 1);
10845 assert_eq!(
10846 bank.get_balance(&mint_keypair.pubkey()),
10847 initial_mint_balance - 1 - expensive_lamports_per_signature
10848 );
10849 }
10850
10851 #[test]
10852 fn test_bank_blockhash_compute_unit_fee_structure() {
10853 let leader = solana_sdk::pubkey::new_rand();
10856 let GenesisConfigInfo {
10857 mut genesis_config,
10858 mint_keypair,
10859 ..
10860 } = create_genesis_config_with_leader(1_000_000_000, &leader, 3);
10861 genesis_config
10862 .fee_rate_governor
10863 .target_lamports_per_signature = 1000;
10864 genesis_config.fee_rate_governor.target_signatures_per_slot = 1;
10865
10866 let mut bank = Bank::new_for_tests(&genesis_config);
10867 goto_end_of_slot(&mut bank);
10868 let cheap_blockhash = bank.last_blockhash();
10869 let cheap_lamports_per_signature = bank.get_lamports_per_signature();
10870 assert_eq!(cheap_lamports_per_signature, 0);
10871
10872 let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
10873 goto_end_of_slot(&mut bank);
10874 let expensive_blockhash = bank.last_blockhash();
10875 let expensive_lamports_per_signature = bank.get_lamports_per_signature();
10876 assert!(cheap_lamports_per_signature < expensive_lamports_per_signature);
10877
10878 let bank = Bank::new_from_parent(&Arc::new(bank), &leader, 2);
10879
10880 let key = Keypair::new();
10882 let initial_mint_balance = bank.get_balance(&mint_keypair.pubkey());
10883 let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, cheap_blockhash);
10884 assert_eq!(bank.process_transaction(&tx), Ok(()));
10885 assert_eq!(bank.get_balance(&key.pubkey()), 1);
10886 let cheap_fee = Bank::calculate_fee(
10887 &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(),
10888 cheap_lamports_per_signature,
10889 &FeeStructure::default(),
10890 true,
10891 true,
10892 true,
10893 );
10894 assert_eq!(
10895 bank.get_balance(&mint_keypair.pubkey()),
10896 initial_mint_balance - 1 - cheap_fee
10897 );
10898
10899 let key = Keypair::new();
10901 let initial_mint_balance = bank.get_balance(&mint_keypair.pubkey());
10902 let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, expensive_blockhash);
10903 assert_eq!(bank.process_transaction(&tx), Ok(()));
10904 assert_eq!(bank.get_balance(&key.pubkey()), 1);
10905 let expensive_fee = Bank::calculate_fee(
10906 &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(),
10907 expensive_lamports_per_signature,
10908 &FeeStructure::default(),
10909 true,
10910 true,
10911 true,
10912 );
10913 assert_eq!(
10914 bank.get_balance(&mint_keypair.pubkey()),
10915 initial_mint_balance - 1 - expensive_fee
10916 );
10917 }
10918
10919 #[test]
10920 fn test_filter_program_errors_and_collect_fee() {
10921 let leader = solana_sdk::pubkey::new_rand();
10922 let GenesisConfigInfo {
10923 mut genesis_config,
10924 mint_keypair,
10925 ..
10926 } = create_genesis_config_with_leader(100_000, &leader, 3);
10927 genesis_config.fee_rate_governor = FeeRateGovernor::new(5000, 0);
10928 let bank = Bank::new_for_tests(&genesis_config);
10929
10930 let key = Keypair::new();
10931 let tx1 = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
10932 &mint_keypair,
10933 &key.pubkey(),
10934 2,
10935 genesis_config.hash(),
10936 ));
10937 let tx2 = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
10938 &mint_keypair,
10939 &key.pubkey(),
10940 5,
10941 genesis_config.hash(),
10942 ));
10943
10944 let results = vec![
10945 new_execution_result(Ok(()), None),
10946 new_execution_result(
10947 Err(TransactionError::InstructionError(
10948 1,
10949 SystemError::ResultWithNegativeLamports.into(),
10950 )),
10951 None,
10952 ),
10953 ];
10954 let initial_balance = bank.get_balance(&leader);
10955
10956 let results = bank.filter_program_errors_and_collect_fee(&[tx1, tx2], &results);
10957 bank.freeze();
10958 assert_eq!(
10959 bank.get_balance(&leader),
10960 initial_balance
10961 + bank
10962 .fee_rate_governor
10963 .burn(bank.fee_rate_governor.lamports_per_signature * 2)
10964 .0
10965 );
10966 assert_eq!(results[0], Ok(()));
10967 assert_eq!(results[1], Ok(()));
10968 }
10969
10970 #[test]
10971 fn test_filter_program_errors_and_collect_compute_unit_fee() {
10972 let leader = solana_sdk::pubkey::new_rand();
10973 let GenesisConfigInfo {
10974 mut genesis_config,
10975 mint_keypair,
10976 ..
10977 } = create_genesis_config_with_leader(1000000, &leader, 3);
10978 genesis_config.fee_rate_governor = FeeRateGovernor::new(2, 0);
10979 let bank = Bank::new_for_tests(&genesis_config);
10980
10981 let key = Keypair::new();
10982 let tx1 = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
10983 &mint_keypair,
10984 &key.pubkey(),
10985 2,
10986 genesis_config.hash(),
10987 ));
10988 let tx2 = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
10989 &mint_keypair,
10990 &key.pubkey(),
10991 5,
10992 genesis_config.hash(),
10993 ));
10994
10995 let results = vec![
10996 new_execution_result(Ok(()), None),
10997 new_execution_result(
10998 Err(TransactionError::InstructionError(
10999 1,
11000 SystemError::ResultWithNegativeLamports.into(),
11001 )),
11002 None,
11003 ),
11004 ];
11005 let initial_balance = bank.get_balance(&leader);
11006
11007 let results = bank.filter_program_errors_and_collect_fee(&[tx1, tx2], &results);
11008 bank.freeze();
11009 assert_eq!(
11010 bank.get_balance(&leader),
11011 initial_balance
11012 + bank
11013 .fee_rate_governor
11014 .burn(
11015 Bank::calculate_fee(
11016 &SanitizedMessage::try_from(Message::new(
11017 &[],
11018 Some(&Pubkey::new_unique())
11019 ))
11020 .unwrap(),
11021 genesis_config
11022 .fee_rate_governor
11023 .create_fee_calculator()
11024 .lamports_per_signature,
11025 &FeeStructure::default(),
11026 true,
11027 true,
11028 true,
11029 ) * 2
11030 )
11031 .0
11032 );
11033 assert_eq!(results[0], Ok(()));
11034 assert_eq!(results[1], Ok(()));
11035 }
11036
11037 #[test]
11038 fn test_debits_before_credits() {
11039 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(2.));
11040 let bank = Bank::new_for_tests(&genesis_config);
11041 let keypair = Keypair::new();
11042 let tx0 = system_transaction::transfer(
11043 &mint_keypair,
11044 &keypair.pubkey(),
11045 sol_to_lamports(2.),
11046 genesis_config.hash(),
11047 );
11048 let tx1 = system_transaction::transfer(
11049 &keypair,
11050 &mint_keypair.pubkey(),
11051 sol_to_lamports(1.),
11052 genesis_config.hash(),
11053 );
11054 let txs = vec![tx0, tx1];
11055 let results = bank.process_transactions(txs.iter());
11056 assert!(results[1].is_err());
11057
11058 assert_eq!(bank.transaction_count(), 1);
11060 }
11061
11062 #[test]
11063 fn test_readonly_accounts() {
11064 let GenesisConfigInfo {
11065 genesis_config,
11066 mint_keypair,
11067 ..
11068 } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 0);
11069 let bank = Bank::new_for_tests(&genesis_config);
11070
11071 let vote_pubkey0 = solana_sdk::pubkey::new_rand();
11072 let vote_pubkey1 = solana_sdk::pubkey::new_rand();
11073 let vote_pubkey2 = solana_sdk::pubkey::new_rand();
11074 let authorized_voter = Keypair::new();
11075 let payer0 = Keypair::new();
11076 let payer1 = Keypair::new();
11077
11078 let vote_account0 =
11080 vote_state::create_account(&vote_pubkey0, &authorized_voter.pubkey(), 0, 100);
11081 let vote_account1 =
11082 vote_state::create_account(&vote_pubkey1, &authorized_voter.pubkey(), 0, 100);
11083 let vote_account2 =
11084 vote_state::create_account(&vote_pubkey2, &authorized_voter.pubkey(), 0, 100);
11085 bank.store_account(&vote_pubkey0, &vote_account0);
11086 bank.store_account(&vote_pubkey1, &vote_account1);
11087 bank.store_account(&vote_pubkey2, &vote_account2);
11088
11089 bank.transfer(10, &mint_keypair, &payer0.pubkey()).unwrap();
11091 bank.transfer(10, &mint_keypair, &payer1.pubkey()).unwrap();
11092 bank.transfer(1, &mint_keypair, &authorized_voter.pubkey())
11093 .unwrap();
11094
11095 let vote = Vote::new(vec![1], Hash::default());
11096 let ix0 = vote_instruction::vote(&vote_pubkey0, &authorized_voter.pubkey(), vote.clone());
11097 let tx0 = Transaction::new_signed_with_payer(
11098 &[ix0],
11099 Some(&payer0.pubkey()),
11100 &[&payer0, &authorized_voter],
11101 bank.last_blockhash(),
11102 );
11103 let ix1 = vote_instruction::vote(&vote_pubkey1, &authorized_voter.pubkey(), vote.clone());
11104 let tx1 = Transaction::new_signed_with_payer(
11105 &[ix1],
11106 Some(&payer1.pubkey()),
11107 &[&payer1, &authorized_voter],
11108 bank.last_blockhash(),
11109 );
11110 let txs = vec![tx0, tx1];
11111 let results = bank.process_transactions(txs.iter());
11112
11113 assert_eq!(results[0], Ok(()));
11116 assert_eq!(results[1], Ok(()));
11117
11118 let ix0 = vote_instruction::vote(&vote_pubkey2, &authorized_voter.pubkey(), vote);
11119 let tx0 = Transaction::new_signed_with_payer(
11120 &[ix0],
11121 Some(&payer0.pubkey()),
11122 &[&payer0, &authorized_voter],
11123 bank.last_blockhash(),
11124 );
11125 let tx1 = system_transaction::transfer(
11126 &authorized_voter,
11127 &solana_sdk::pubkey::new_rand(),
11128 1,
11129 bank.last_blockhash(),
11130 );
11131 let txs = vec![tx0, tx1];
11132 let results = bank.process_transactions(txs.iter());
11133 assert_eq!(results[0], Ok(()));
11135 assert_eq!(results[1], Err(TransactionError::AccountInUse));
11136 }
11137
11138 #[test]
11139 fn test_interleaving_locks() {
11140 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11141 let bank = Bank::new_for_tests(&genesis_config);
11142 let alice = Keypair::new();
11143 let bob = Keypair::new();
11144 let amount = genesis_config.rent.minimum_balance(0);
11145
11146 let tx1 = system_transaction::transfer(
11147 &mint_keypair,
11148 &alice.pubkey(),
11149 amount,
11150 genesis_config.hash(),
11151 );
11152 let pay_alice = vec![tx1];
11153
11154 let lock_result = bank.prepare_batch_for_tests(pay_alice);
11155 let results_alice = bank
11156 .load_execute_and_commit_transactions(
11157 &lock_result,
11158 MAX_PROCESSING_AGE,
11159 false,
11160 false,
11161 false,
11162 false,
11163 &mut ExecuteTimings::default(),
11164 None,
11165 )
11166 .0
11167 .fee_collection_results;
11168 assert_eq!(results_alice[0], Ok(()));
11169
11170 assert_eq!(
11172 bank.transfer(amount, &mint_keypair, &bob.pubkey()),
11173 Err(TransactionError::AccountInUse)
11174 );
11175 assert_eq!(
11178 bank.transfer(amount, &mint_keypair, &bob.pubkey()),
11179 Err(TransactionError::AccountInUse)
11180 );
11181
11182 drop(lock_result);
11183
11184 assert!(bank
11185 .transfer(2 * amount, &mint_keypair, &bob.pubkey())
11186 .is_ok());
11187 }
11188
11189 #[test]
11190 fn test_readonly_relaxed_locks() {
11191 let (genesis_config, _) = create_genesis_config(3);
11192 let bank = Bank::new_for_tests(&genesis_config);
11193 let key0 = Keypair::new();
11194 let key1 = Keypair::new();
11195 let key2 = Keypair::new();
11196 let key3 = solana_sdk::pubkey::new_rand();
11197
11198 let message = Message {
11199 header: MessageHeader {
11200 num_required_signatures: 1,
11201 num_readonly_signed_accounts: 0,
11202 num_readonly_unsigned_accounts: 1,
11203 },
11204 account_keys: vec![key0.pubkey(), key3],
11205 recent_blockhash: Hash::default(),
11206 instructions: vec![],
11207 };
11208 let tx = Transaction::new(&[&key0], message, genesis_config.hash());
11209 let txs = vec![tx];
11210
11211 let batch0 = bank.prepare_batch_for_tests(txs);
11212 assert!(batch0.lock_results()[0].is_ok());
11213
11214 let message = Message {
11217 header: MessageHeader {
11218 num_required_signatures: 1,
11219 num_readonly_signed_accounts: 0,
11220 num_readonly_unsigned_accounts: 0,
11221 },
11222 account_keys: vec![key1.pubkey(), key3],
11223 recent_blockhash: Hash::default(),
11224 instructions: vec![],
11225 };
11226 let tx = Transaction::new(&[&key1], message, genesis_config.hash());
11227 let txs = vec![tx];
11228
11229 let batch1 = bank.prepare_batch_for_tests(txs);
11230 assert!(batch1.lock_results()[0].is_err());
11231
11232 let message = Message {
11234 header: MessageHeader {
11235 num_required_signatures: 1,
11236 num_readonly_signed_accounts: 0,
11237 num_readonly_unsigned_accounts: 1,
11238 },
11239 account_keys: vec![key2.pubkey(), key3],
11240 recent_blockhash: Hash::default(),
11241 instructions: vec![],
11242 };
11243 let tx = Transaction::new(&[&key2], message, genesis_config.hash());
11244 let txs = vec![tx];
11245
11246 let batch2 = bank.prepare_batch_for_tests(txs);
11247 assert!(batch2.lock_results()[0].is_ok());
11248 }
11249
11250 #[test]
11251 fn test_bank_invalid_account_index() {
11252 let (genesis_config, mint_keypair) = create_genesis_config(1);
11253 let keypair = Keypair::new();
11254 let bank = Bank::new_for_tests(&genesis_config);
11255
11256 let tx = system_transaction::transfer(
11257 &mint_keypair,
11258 &keypair.pubkey(),
11259 1,
11260 genesis_config.hash(),
11261 );
11262
11263 let mut tx_invalid_program_index = tx.clone();
11264 tx_invalid_program_index.message.instructions[0].program_id_index = 42;
11265 assert_eq!(
11266 bank.process_transaction(&tx_invalid_program_index),
11267 Err(TransactionError::SanitizeFailure)
11268 );
11269
11270 let mut tx_invalid_account_index = tx;
11271 tx_invalid_account_index.message.instructions[0].accounts[0] = 42;
11272 assert_eq!(
11273 bank.process_transaction(&tx_invalid_account_index),
11274 Err(TransactionError::SanitizeFailure)
11275 );
11276 }
11277
11278 #[test]
11279 fn test_bank_pay_to_self() {
11280 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11281 let key1 = Keypair::new();
11282 let bank = Bank::new_for_tests(&genesis_config);
11283 let amount = genesis_config.rent.minimum_balance(0);
11284
11285 bank.transfer(amount, &mint_keypair, &key1.pubkey())
11286 .unwrap();
11287 assert_eq!(bank.get_balance(&key1.pubkey()), amount);
11288 let tx = system_transaction::transfer(&key1, &key1.pubkey(), amount, genesis_config.hash());
11289 let _res = bank.process_transaction(&tx);
11290
11291 assert_eq!(bank.get_balance(&key1.pubkey()), amount);
11292 bank.get_signature_status(&tx.signatures[0])
11293 .unwrap()
11294 .unwrap();
11295 }
11296
11297 fn new_from_parent(parent: &Arc<Bank>) -> Bank {
11298 Bank::new_from_parent(parent, &Pubkey::default(), parent.slot() + 1)
11299 }
11300
11301 #[test]
11303 fn test_bank_parents() {
11304 let (genesis_config, _) = create_genesis_config(1);
11305 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11306
11307 let bank = new_from_parent(&parent);
11308 assert!(Arc::ptr_eq(&bank.parents()[0], &parent));
11309 }
11310
11311 #[test]
11313 fn test_tx_already_processed() {
11314 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11315 let bank = Bank::new_for_tests(&genesis_config);
11316
11317 let key1 = Keypair::new();
11318 let mut tx = system_transaction::transfer(
11319 &mint_keypair,
11320 &key1.pubkey(),
11321 genesis_config.rent.minimum_balance(0),
11322 genesis_config.hash(),
11323 );
11324
11325 assert_eq!(bank.process_transaction(&tx), Ok(()));
11327
11328 assert_eq!(
11330 bank.process_transaction(&tx),
11331 Err(TransactionError::AlreadyProcessed)
11332 );
11333
11334 tx.signatures[0] = Signature::default();
11337
11338 assert_eq!(
11340 bank.process_transaction(&tx),
11341 Err(TransactionError::AlreadyProcessed)
11342 );
11343 }
11344
11345 #[test]
11347 fn test_bank_parent_already_processed() {
11348 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11349 let key1 = Keypair::new();
11350 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11351 let amount = genesis_config.rent.minimum_balance(0);
11352
11353 let tx = system_transaction::transfer(
11354 &mint_keypair,
11355 &key1.pubkey(),
11356 amount,
11357 genesis_config.hash(),
11358 );
11359 assert_eq!(parent.process_transaction(&tx), Ok(()));
11360 let bank = new_from_parent(&parent);
11361 assert_eq!(
11362 bank.process_transaction(&tx),
11363 Err(TransactionError::AlreadyProcessed)
11364 );
11365 }
11366
11367 #[test]
11369 fn test_bank_parent_account_spend() {
11370 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
11371 let key1 = Keypair::new();
11372 let key2 = Keypair::new();
11373 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11374 let amount = genesis_config.rent.minimum_balance(0);
11375
11376 let tx = system_transaction::transfer(
11377 &mint_keypair,
11378 &key1.pubkey(),
11379 amount,
11380 genesis_config.hash(),
11381 );
11382 assert_eq!(parent.process_transaction(&tx), Ok(()));
11383 let bank = new_from_parent(&parent);
11384 let tx = system_transaction::transfer(&key1, &key2.pubkey(), amount, genesis_config.hash());
11385 assert_eq!(bank.process_transaction(&tx), Ok(()));
11386 assert_eq!(parent.get_signature_status(&tx.signatures[0]), None);
11387 }
11388
11389 #[test]
11390 fn test_bank_hash_internal_state() {
11391 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11392 let bank0 = Bank::new_for_tests(&genesis_config);
11393 let bank1 = Bank::new_for_tests(&genesis_config);
11394 let amount = genesis_config.rent.minimum_balance(0);
11395 let initial_state = bank0.hash_internal_state();
11396 assert_eq!(bank1.hash_internal_state(), initial_state);
11397
11398 let pubkey = solana_sdk::pubkey::new_rand();
11399 bank0.transfer(amount, &mint_keypair, &pubkey).unwrap();
11400 assert_ne!(bank0.hash_internal_state(), initial_state);
11401 bank1.transfer(amount, &mint_keypair, &pubkey).unwrap();
11402 assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
11403
11404 let bank2 = new_from_parent(&Arc::new(bank1));
11406 assert_ne!(bank0.hash_internal_state(), bank2.hash_internal_state());
11407
11408 let pubkey2 = solana_sdk::pubkey::new_rand();
11409 info!("transfer 2 {}", pubkey2);
11410 bank2.transfer(amount, &mint_keypair, &pubkey2).unwrap();
11411 bank2.update_accounts_hash();
11412 assert!(bank2.verify_bank_hash(VerifyBankHash::default_for_test()));
11413 }
11414
11415 #[test]
11416 fn test_bank_hash_internal_state_verify() {
11417 solana_logger::setup();
11418 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11419 let bank0 = Bank::new_for_tests(&genesis_config);
11420 let amount = genesis_config.rent.minimum_balance(0);
11421
11422 let pubkey = solana_sdk::pubkey::new_rand();
11423 info!("transfer 0 {} mint: {}", pubkey, mint_keypair.pubkey());
11424 bank0.transfer(amount, &mint_keypair, &pubkey).unwrap();
11425
11426 let bank0_state = bank0.hash_internal_state();
11427 let bank0 = Arc::new(bank0);
11428 let bank2 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 1);
11430 assert_ne!(bank0_state, bank2.hash_internal_state());
11431 assert_ne!(bank0_state, bank0.hash_internal_state());
11433
11434 let bank0_state = bank0.hash_internal_state();
11436 bank2.update_accounts_hash();
11437 assert!(bank2.verify_bank_hash(VerifyBankHash::default_for_test()));
11438 let bank3 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 2);
11439 assert_eq!(bank0_state, bank0.hash_internal_state());
11440 assert!(bank2.verify_bank_hash(VerifyBankHash::default_for_test()));
11441 bank3.update_accounts_hash();
11442 assert!(bank3.verify_bank_hash(VerifyBankHash::default_for_test()));
11443
11444 let pubkey2 = solana_sdk::pubkey::new_rand();
11445 info!("transfer 2 {}", pubkey2);
11446 bank2.transfer(amount, &mint_keypair, &pubkey2).unwrap();
11447 bank2.update_accounts_hash();
11448 assert!(bank2.verify_bank_hash(VerifyBankHash::default_for_test()));
11449 assert!(bank3.verify_bank_hash(VerifyBankHash::default_for_test()));
11450 }
11451
11452 #[test]
11453 #[should_panic(expected = "assertion failed: self.is_frozen()")]
11454 fn test_verify_hash_unfrozen() {
11455 let bank = create_simple_test_bank(2_000);
11456 assert!(bank.verify_hash());
11457 }
11458
11459 #[test]
11460 fn test_verify_snapshot_bank() {
11461 solana_logger::setup();
11462 let pubkey = solana_sdk::pubkey::new_rand();
11463 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11464 let bank = Bank::new_for_tests(&genesis_config);
11465 bank.transfer(
11466 genesis_config.rent.minimum_balance(0),
11467 &mint_keypair,
11468 &pubkey,
11469 )
11470 .unwrap();
11471 bank.freeze();
11472 bank.update_accounts_hash();
11473 assert!(bank.verify_snapshot_bank(true, false, None));
11474
11475 bank.increment_signature_count(1);
11477 assert!(!bank.verify_snapshot_bank(true, false, None));
11478 }
11479
11480 #[test]
11482 fn test_bank_hash_internal_state_same_account_different_fork() {
11483 solana_logger::setup();
11484 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11485 let amount = genesis_config.rent.minimum_balance(0);
11486 let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
11487 let initial_state = bank0.hash_internal_state();
11488 let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
11489 assert_ne!(bank1.hash_internal_state(), initial_state);
11490
11491 info!("transfer bank1");
11492 let pubkey = solana_sdk::pubkey::new_rand();
11493 bank1.transfer(amount, &mint_keypair, &pubkey).unwrap();
11494 assert_ne!(bank1.hash_internal_state(), initial_state);
11495
11496 info!("transfer bank2");
11497 let bank2 = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
11499 bank2.transfer(amount, &mint_keypair, &pubkey).unwrap();
11500 assert_ne!(bank2.hash_internal_state(), initial_state);
11501 assert_ne!(bank1.hash_internal_state(), bank2.hash_internal_state());
11502 }
11503
11504 #[test]
11505 fn test_hash_internal_state_genesis() {
11506 let bank0 = Bank::new_for_tests(&create_genesis_config(10).0);
11507 let bank1 = Bank::new_for_tests(&create_genesis_config(20).0);
11508 assert_ne!(bank0.hash_internal_state(), bank1.hash_internal_state());
11509 }
11510
11511 #[test]
11514 fn test_hash_internal_state_order() {
11515 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11516 let amount = genesis_config.rent.minimum_balance(0);
11517 let bank0 = Bank::new_for_tests(&genesis_config);
11518 let bank1 = Bank::new_for_tests(&genesis_config);
11519 assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
11520 let key0 = solana_sdk::pubkey::new_rand();
11521 let key1 = solana_sdk::pubkey::new_rand();
11522 bank0.transfer(amount, &mint_keypair, &key0).unwrap();
11523 bank0.transfer(amount * 2, &mint_keypair, &key1).unwrap();
11524
11525 bank1.transfer(amount * 2, &mint_keypair, &key1).unwrap();
11526 bank1.transfer(amount, &mint_keypair, &key0).unwrap();
11527
11528 assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
11529 }
11530
11531 #[test]
11532 fn test_hash_internal_state_error() {
11533 solana_logger::setup();
11534 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11535 let amount = genesis_config.rent.minimum_balance(0);
11536 let bank = Bank::new_for_tests(&genesis_config);
11537 let key0 = solana_sdk::pubkey::new_rand();
11538 bank.transfer(amount, &mint_keypair, &key0).unwrap();
11539 let orig = bank.hash_internal_state();
11540
11541 assert!(bank
11543 .transfer(sol_to_lamports(1.), &mint_keypair, &key0)
11544 .is_err());
11545 assert_ne!(orig, bank.hash_internal_state());
11546
11547 let orig = bank.hash_internal_state();
11548 let empty_keypair = Keypair::new();
11549 assert!(bank.transfer(amount, &empty_keypair, &key0).is_err());
11550 assert_eq!(orig, bank.hash_internal_state());
11551 }
11552
11553 #[test]
11554 fn test_bank_hash_internal_state_squash() {
11555 let collector_id = Pubkey::default();
11556 let bank0 = Arc::new(Bank::new_for_tests(&create_genesis_config(10).0));
11557 let hash0 = bank0.hash_internal_state();
11558 let bank1 = Bank::new_from_parent(&bank0, &collector_id, 1);
11562
11563 assert_ne!(hash0, bank1.hash_internal_state());
11565
11566 bank1.squash();
11568 assert!(bank1.parents().is_empty());
11569 }
11570
11571 #[test]
11573 fn test_bank_squash() {
11574 solana_logger::setup();
11575 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(2.));
11576 let key1 = Keypair::new();
11577 let key2 = Keypair::new();
11578 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11579 let amount = genesis_config.rent.minimum_balance(0);
11580
11581 let tx_transfer_mint_to_1 = system_transaction::transfer(
11582 &mint_keypair,
11583 &key1.pubkey(),
11584 amount,
11585 genesis_config.hash(),
11586 );
11587 trace!("parent process tx ");
11588 assert_eq!(parent.process_transaction(&tx_transfer_mint_to_1), Ok(()));
11589 trace!("done parent process tx ");
11590 assert_eq!(parent.transaction_count(), 1);
11591 assert_eq!(
11592 parent.get_signature_status(&tx_transfer_mint_to_1.signatures[0]),
11593 Some(Ok(()))
11594 );
11595
11596 trace!("new from parent");
11597 let bank = new_from_parent(&parent);
11598 trace!("done new from parent");
11599 assert_eq!(
11600 bank.get_signature_status(&tx_transfer_mint_to_1.signatures[0]),
11601 Some(Ok(()))
11602 );
11603
11604 assert_eq!(bank.transaction_count(), parent.transaction_count());
11605 let tx_transfer_1_to_2 =
11606 system_transaction::transfer(&key1, &key2.pubkey(), amount, genesis_config.hash());
11607 assert_eq!(bank.process_transaction(&tx_transfer_1_to_2), Ok(()));
11608 assert_eq!(bank.transaction_count(), 2);
11609 assert_eq!(parent.transaction_count(), 1);
11610 assert_eq!(
11611 parent.get_signature_status(&tx_transfer_1_to_2.signatures[0]),
11612 None
11613 );
11614
11615 for _ in 0..3 {
11616 assert_eq!(bank.get_balance(&key1.pubkey()), 0);
11618 assert_eq!(bank.get_account(&key1.pubkey()), None);
11619 assert_eq!(bank.get_balance(&key2.pubkey()), amount);
11620 trace!("start");
11621 assert_eq!(
11622 bank.get_signature_status(&tx_transfer_mint_to_1.signatures[0]),
11623 Some(Ok(()))
11624 );
11625 assert_eq!(
11626 bank.get_signature_status(&tx_transfer_1_to_2.signatures[0]),
11627 Some(Ok(()))
11628 );
11629
11630 trace!("SQUASH");
11632 bank.squash();
11633
11634 assert_eq!(parent.transaction_count(), 1);
11635 assert_eq!(bank.transaction_count(), 2);
11636 }
11637 }
11638
11639 #[test]
11640 fn test_bank_get_account_in_parent_after_squash() {
11641 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11642 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11643 let amount = genesis_config.rent.minimum_balance(0);
11644
11645 let key1 = Keypair::new();
11646
11647 parent
11648 .transfer(amount, &mint_keypair, &key1.pubkey())
11649 .unwrap();
11650 assert_eq!(parent.get_balance(&key1.pubkey()), amount);
11651 let bank = new_from_parent(&parent);
11652 bank.squash();
11653 assert_eq!(parent.get_balance(&key1.pubkey()), amount);
11654 }
11655
11656 #[test]
11657 fn test_bank_get_account_in_parent_after_squash2() {
11658 solana_logger::setup();
11659 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11660 let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
11661 let amount = genesis_config.rent.minimum_balance(0);
11662
11663 let key1 = Keypair::new();
11664
11665 bank0
11666 .transfer(amount, &mint_keypair, &key1.pubkey())
11667 .unwrap();
11668 assert_eq!(bank0.get_balance(&key1.pubkey()), amount);
11669
11670 let bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1));
11671 bank1
11672 .transfer(3 * amount, &mint_keypair, &key1.pubkey())
11673 .unwrap();
11674 let bank2 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 2));
11675 bank2
11676 .transfer(2 * amount, &mint_keypair, &key1.pubkey())
11677 .unwrap();
11678 let bank3 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 3));
11679 bank1.squash();
11680
11681 assert_eq!(bank0.get_balance(&key1.pubkey()), 4 * amount);
11685 assert_eq!(bank3.get_balance(&key1.pubkey()), 4 * amount);
11686 assert_eq!(bank2.get_balance(&key1.pubkey()), 3 * amount);
11687 bank3.squash();
11688 assert_eq!(bank1.get_balance(&key1.pubkey()), 4 * amount);
11689
11690 let bank4 = Arc::new(Bank::new_from_parent(&bank3, &Pubkey::default(), 4));
11691 bank4
11692 .transfer(4 * amount, &mint_keypair, &key1.pubkey())
11693 .unwrap();
11694 assert_eq!(bank4.get_balance(&key1.pubkey()), 8 * amount);
11695 assert_eq!(bank3.get_balance(&key1.pubkey()), 4 * amount);
11696 bank4.squash();
11697 let bank5 = Arc::new(Bank::new_from_parent(&bank4, &Pubkey::default(), 5));
11698 bank5.squash();
11699 let bank6 = Arc::new(Bank::new_from_parent(&bank5, &Pubkey::default(), 6));
11700 bank6.squash();
11701
11702 assert_eq!(bank3.get_balance(&key1.pubkey()), 8 * amount);
11706 assert_eq!(bank2.get_balance(&key1.pubkey()), 8 * amount);
11707
11708 assert_eq!(bank4.get_balance(&key1.pubkey()), 8 * amount);
11709 }
11710
11711 #[test]
11712 fn test_bank_get_account_modified_since_parent_with_fixed_root() {
11713 let pubkey = solana_sdk::pubkey::new_rand();
11714
11715 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11716 let amount = genesis_config.rent.minimum_balance(0);
11717 let bank1 = Arc::new(Bank::new_for_tests(&genesis_config));
11718 bank1.transfer(amount, &mint_keypair, &pubkey).unwrap();
11719 let result = bank1.get_account_modified_since_parent_with_fixed_root(&pubkey);
11720 assert!(result.is_some());
11721 let (account, slot) = result.unwrap();
11722 assert_eq!(account.lamports(), amount);
11723 assert_eq!(slot, 0);
11724
11725 let bank2 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 1));
11726 assert!(bank2
11727 .get_account_modified_since_parent_with_fixed_root(&pubkey)
11728 .is_none());
11729 bank2.transfer(2 * amount, &mint_keypair, &pubkey).unwrap();
11730 let result = bank1.get_account_modified_since_parent_with_fixed_root(&pubkey);
11731 assert!(result.is_some());
11732 let (account, slot) = result.unwrap();
11733 assert_eq!(account.lamports(), amount);
11734 assert_eq!(slot, 0);
11735 let result = bank2.get_account_modified_since_parent_with_fixed_root(&pubkey);
11736 assert!(result.is_some());
11737 let (account, slot) = result.unwrap();
11738 assert_eq!(account.lamports(), 3 * amount);
11739 assert_eq!(slot, 1);
11740
11741 bank1.squash();
11742
11743 let bank3 = Bank::new_from_parent(&bank2, &Pubkey::default(), 3);
11744 assert_eq!(
11745 None,
11746 bank3.get_account_modified_since_parent_with_fixed_root(&pubkey)
11747 );
11748 }
11749
11750 #[test]
11751 fn test_bank_update_sysvar_account() {
11752 use sysvar::clock::Clock;
11753
11754 let dummy_clock_id = solana_sdk::pubkey::new_rand();
11755 let dummy_rent_epoch = 44;
11756 let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
11757
11758 let expected_previous_slot = 3;
11759 let mut expected_next_slot = expected_previous_slot + 1;
11760
11761 activate_all_features(&mut genesis_config);
11763 let bank1 = Arc::new(Bank::new_for_tests(&genesis_config));
11764 assert_eq!(bank1.calculate_capitalization(true), bank1.capitalization());
11765
11766 assert_capitalization_diff(
11767 &bank1,
11768 || {
11769 bank1.update_sysvar_account(&dummy_clock_id, |optional_account| {
11770 assert!(optional_account.is_none());
11771
11772 let mut account = create_account(
11773 &Clock {
11774 slot: expected_previous_slot,
11775 ..Clock::default()
11776 },
11777 bank1.inherit_specially_retained_account_fields(optional_account),
11778 );
11779 account.set_rent_epoch(dummy_rent_epoch);
11780 account
11781 });
11782 let current_account = bank1.get_account(&dummy_clock_id).unwrap();
11783 assert_eq!(
11784 expected_previous_slot,
11785 from_account::<Clock, _>(¤t_account).unwrap().slot
11786 );
11787 assert_eq!(dummy_rent_epoch, current_account.rent_epoch());
11788 },
11789 |old, new| {
11790 assert_eq!(
11791 old + min_rent_excempt_balance_for_sysvars(&bank1, &[sysvar::clock::id()]),
11792 new
11793 );
11794 },
11795 );
11796
11797 assert_capitalization_diff(
11798 &bank1,
11799 || {
11800 bank1.update_sysvar_account(&dummy_clock_id, |optional_account| {
11801 assert!(optional_account.is_some());
11802
11803 create_account(
11804 &Clock {
11805 slot: expected_previous_slot,
11806 ..Clock::default()
11807 },
11808 bank1.inherit_specially_retained_account_fields(optional_account),
11809 )
11810 })
11811 },
11812 |old, new| {
11813 assert_eq!(old, new);
11815 },
11816 );
11817
11818 let bank2 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 1));
11820 assert_capitalization_diff(
11821 &bank2,
11822 || {
11823 bank2.update_sysvar_account(&dummy_clock_id, |optional_account| {
11824 let slot = from_account::<Clock, _>(optional_account.as_ref().unwrap())
11825 .unwrap()
11826 .slot
11827 + 1;
11828
11829 create_account(
11830 &Clock {
11831 slot,
11832 ..Clock::default()
11833 },
11834 bank2.inherit_specially_retained_account_fields(optional_account),
11835 )
11836 });
11837 let current_account = bank2.get_account(&dummy_clock_id).unwrap();
11838 assert_eq!(
11839 expected_next_slot,
11840 from_account::<Clock, _>(¤t_account).unwrap().slot
11841 );
11842 assert_eq!(dummy_rent_epoch, current_account.rent_epoch());
11843 },
11844 |old, new| {
11845 assert_eq!(old, new);
11847 },
11848 );
11849
11850 expected_next_slot += 1;
11853 assert_capitalization_diff(
11854 &bank2,
11855 || {
11856 bank2.update_sysvar_account(&dummy_clock_id, |optional_account| {
11857 let slot = from_account::<Clock, _>(optional_account.as_ref().unwrap())
11858 .unwrap()
11859 .slot
11860 + 1;
11861
11862 create_account(
11863 &Clock {
11864 slot,
11865 ..Clock::default()
11866 },
11867 bank2.inherit_specially_retained_account_fields(optional_account),
11868 )
11869 });
11870 let current_account = bank2.get_account(&dummy_clock_id).unwrap();
11871 assert_eq!(
11872 expected_next_slot,
11873 from_account::<Clock, _>(¤t_account).unwrap().slot
11874 );
11875 },
11876 |old, new| {
11877 assert_eq!(old, new);
11879 },
11880 );
11881 }
11882
11883 #[test]
11884 fn test_bank_epoch_vote_accounts() {
11885 let leader_pubkey = solana_sdk::pubkey::new_rand();
11886 let leader_lamports = 3;
11887 let mut genesis_config =
11888 create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
11889
11890 const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64;
11893 const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
11894 genesis_config.epoch_schedule =
11896 EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, false);
11897
11898 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11899 let mut leader_vote_stake: Vec<_> = parent
11900 .epoch_vote_accounts(0)
11901 .map(|accounts| {
11902 accounts
11903 .iter()
11904 .filter_map(|(pubkey, (stake, account))| {
11905 if let Ok(vote_state) = account.vote_state().as_ref() {
11906 if vote_state.node_pubkey == leader_pubkey {
11907 Some((*pubkey, *stake))
11908 } else {
11909 None
11910 }
11911 } else {
11912 None
11913 }
11914 })
11915 .collect()
11916 })
11917 .unwrap();
11918 assert_eq!(leader_vote_stake.len(), 1);
11919 let (leader_vote_account, leader_stake) = leader_vote_stake.pop().unwrap();
11920 assert!(leader_stake > 0);
11921
11922 let leader_stake = Stake {
11923 delegation: Delegation {
11924 stake: leader_lamports,
11925 activation_epoch: std::u64::MAX, ..Delegation::default()
11927 },
11928 ..Stake::default()
11929 };
11930
11931 let mut epoch = 1;
11932 loop {
11933 if epoch > LEADER_SCHEDULE_SLOT_OFFSET / SLOTS_PER_EPOCH {
11934 break;
11935 }
11936 let vote_accounts = parent.epoch_vote_accounts(epoch);
11937 assert!(vote_accounts.is_some());
11938
11939 assert_eq!(
11942 leader_stake.stake(0, None),
11943 vote_accounts.unwrap().get(&leader_vote_account).unwrap().0
11944 );
11945
11946 epoch += 1;
11947 }
11948
11949 let child = Bank::new_from_parent(
11951 &parent,
11952 &leader_pubkey,
11953 SLOTS_PER_EPOCH - (LEADER_SCHEDULE_SLOT_OFFSET % SLOTS_PER_EPOCH),
11954 );
11955
11956 assert!(child.epoch_vote_accounts(epoch).is_some());
11957 assert_eq!(
11958 leader_stake.stake(child.epoch(), None),
11959 child
11960 .epoch_vote_accounts(epoch)
11961 .unwrap()
11962 .get(&leader_vote_account)
11963 .unwrap()
11964 .0
11965 );
11966
11967 let child = Bank::new_from_parent(
11970 &parent,
11971 &leader_pubkey,
11972 SLOTS_PER_EPOCH - (LEADER_SCHEDULE_SLOT_OFFSET % SLOTS_PER_EPOCH) + 1,
11973 );
11974 assert!(child.epoch_vote_accounts(epoch).is_some());
11975 assert_eq!(
11976 leader_stake.stake(child.epoch(), None),
11977 child
11978 .epoch_vote_accounts(epoch)
11979 .unwrap()
11980 .get(&leader_vote_account)
11981 .unwrap()
11982 .0
11983 );
11984 }
11985
11986 #[test]
11987 fn test_zero_signatures() {
11988 solana_logger::setup();
11989 let (genesis_config, mint_keypair) = create_genesis_config(500);
11990 let mut bank = Bank::new_for_tests(&genesis_config);
11991 bank.fee_rate_governor.lamports_per_signature = 2;
11992 let key = Keypair::new();
11993
11994 let mut transfer_instruction =
11995 system_instruction::transfer(&mint_keypair.pubkey(), &key.pubkey(), 0);
11996 transfer_instruction.accounts[0].is_signer = false;
11997 let message = Message::new(&[transfer_instruction], None);
11998 let tx = Transaction::new(&[&Keypair::new(); 0], message, bank.last_blockhash());
11999
12000 assert_eq!(
12001 bank.process_transaction(&tx),
12002 Err(TransactionError::SanitizeFailure)
12003 );
12004 assert_eq!(bank.get_balance(&key.pubkey()), 0);
12005 }
12006
12007 #[test]
12008 fn test_bank_get_slots_in_epoch() {
12009 let (genesis_config, _) = create_genesis_config(500);
12010
12011 let bank = Bank::new_for_tests(&genesis_config);
12012
12013 assert_eq!(bank.get_slots_in_epoch(0), MINIMUM_SLOTS_PER_EPOCH as u64);
12014 assert_eq!(
12015 bank.get_slots_in_epoch(2),
12016 (MINIMUM_SLOTS_PER_EPOCH * 4) as u64
12017 );
12018 assert_eq!(
12019 bank.get_slots_in_epoch(5000),
12020 genesis_config.epoch_schedule.slots_per_epoch
12021 );
12022 }
12023
12024 #[test]
12025 fn test_is_delta_true() {
12026 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
12027 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12028 let key1 = Keypair::new();
12029 let tx_transfer_mint_to_1 = system_transaction::transfer(
12030 &mint_keypair,
12031 &key1.pubkey(),
12032 genesis_config.rent.minimum_balance(0),
12033 genesis_config.hash(),
12034 );
12035 assert_eq!(bank.process_transaction(&tx_transfer_mint_to_1), Ok(()));
12036 assert!(bank.is_delta.load(Relaxed));
12037
12038 let bank1 = new_from_parent(&bank);
12039 let hash1 = bank1.hash_internal_state();
12040 assert!(!bank1.is_delta.load(Relaxed));
12041 assert_ne!(hash1, bank.hash());
12042 bank1.register_tick(&Hash::default());
12044 assert!(!bank1.is_delta.load(Relaxed));
12045 assert_eq!(bank1.hash_internal_state(), hash1);
12046 }
12047
12048 #[test]
12049 fn test_is_empty() {
12050 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
12051 let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
12052 let key1 = Keypair::new();
12053
12054 assert!(bank0.is_empty());
12056
12057 let tx_transfer_mint_to_1 = system_transaction::transfer(
12059 &mint_keypair,
12060 &key1.pubkey(),
12061 genesis_config.rent.minimum_balance(0),
12062 genesis_config.hash(),
12063 );
12064 assert_eq!(bank0.process_transaction(&tx_transfer_mint_to_1), Ok(()));
12065 assert!(!bank0.is_empty());
12066 }
12067
12068 #[test]
12069 fn test_bank_inherit_tx_count() {
12070 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
12071 let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
12072
12073 let bank1 = Arc::new(Bank::new_from_parent(
12075 &bank0,
12076 &solana_sdk::pubkey::new_rand(),
12077 1,
12078 ));
12079 let bank2 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 2);
12081
12082 assert_eq!(
12084 bank1.process_transaction(&system_transaction::transfer(
12085 &mint_keypair,
12086 &Keypair::new().pubkey(),
12087 genesis_config.rent.minimum_balance(0),
12088 genesis_config.hash(),
12089 )),
12090 Ok(())
12091 );
12092
12093 assert_eq!(bank0.transaction_count(), 0);
12094 assert_eq!(bank2.transaction_count(), 0);
12095 assert_eq!(bank1.transaction_count(), 1);
12096
12097 bank1.squash();
12098
12099 assert_eq!(bank0.transaction_count(), 0);
12100 assert_eq!(bank2.transaction_count(), 0);
12101 assert_eq!(bank1.transaction_count(), 1);
12102
12103 let bank6 = Bank::new_from_parent(&bank1, &solana_sdk::pubkey::new_rand(), 3);
12104 assert_eq!(bank1.transaction_count(), 1);
12105 assert_eq!(bank6.transaction_count(), 1);
12106
12107 bank6.squash();
12108 assert_eq!(bank6.transaction_count(), 1);
12109 }
12110
12111 #[test]
12112 fn test_bank_inherit_fee_rate_governor() {
12113 let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
12114 genesis_config
12115 .fee_rate_governor
12116 .target_lamports_per_signature = 123;
12117
12118 let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
12119 let bank1 = Arc::new(new_from_parent(&bank0));
12120 assert_eq!(
12121 bank0.fee_rate_governor.target_lamports_per_signature / 2,
12122 bank1
12123 .fee_rate_governor
12124 .create_fee_calculator()
12125 .lamports_per_signature
12126 );
12127 }
12128
12129 #[test]
12130 fn test_bank_vote_accounts() {
12131 let GenesisConfigInfo {
12132 genesis_config,
12133 mint_keypair,
12134 ..
12135 } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 1);
12136 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12137
12138 let vote_accounts = bank.vote_accounts();
12139 assert_eq!(vote_accounts.len(), 1); let vote_keypair = Keypair::new();
12143 let instructions = vote_instruction::create_account(
12144 &mint_keypair.pubkey(),
12145 &vote_keypair.pubkey(),
12146 &VoteInit {
12147 node_pubkey: mint_keypair.pubkey(),
12148 authorized_voter: vote_keypair.pubkey(),
12149 authorized_withdrawer: vote_keypair.pubkey(),
12150 commission: 0,
12151 },
12152 10,
12153 );
12154
12155 let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
12156 let transaction = Transaction::new(
12157 &[&mint_keypair, &vote_keypair],
12158 message,
12159 bank.last_blockhash(),
12160 );
12161
12162 bank.process_transaction(&transaction).unwrap();
12163
12164 let vote_accounts = bank.vote_accounts();
12165
12166 assert_eq!(vote_accounts.len(), 2);
12167
12168 assert!(vote_accounts.get(&vote_keypair.pubkey()).is_some());
12169
12170 assert!(bank.withdraw(&vote_keypair.pubkey(), 10).is_ok());
12171
12172 let vote_accounts = bank.vote_accounts();
12173
12174 assert_eq!(vote_accounts.len(), 1);
12175 }
12176
12177 #[test]
12178 fn test_bank_cloned_stake_delegations() {
12179 let GenesisConfigInfo {
12180 mut genesis_config,
12181 mint_keypair,
12182 ..
12183 } = create_genesis_config_with_leader(
12184 123_456_000_000_000,
12185 &solana_sdk::pubkey::new_rand(),
12186 123_000_000_000,
12187 );
12188 genesis_config.rent = Rent::default();
12189 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12190
12191 let stake_delegations = bank.stakes_cache.stakes().stake_delegations().clone();
12192 assert_eq!(stake_delegations.len(), 1); let (vote_balance, stake_balance) = {
12196 let rent = &bank.rent_collector().rent;
12197 let vote_rent_exempt_reserve = rent.minimum_balance(VoteState::size_of());
12198 let stake_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of());
12199 let minimum_delegation =
12200 solana_stake_program::get_minimum_delegation(&bank.feature_set);
12201 (
12202 vote_rent_exempt_reserve,
12203 stake_rent_exempt_reserve + minimum_delegation,
12204 )
12205 };
12206
12207 let vote_keypair = Keypair::new();
12208 let mut instructions = vote_instruction::create_account(
12209 &mint_keypair.pubkey(),
12210 &vote_keypair.pubkey(),
12211 &VoteInit {
12212 node_pubkey: mint_keypair.pubkey(),
12213 authorized_voter: vote_keypair.pubkey(),
12214 authorized_withdrawer: vote_keypair.pubkey(),
12215 commission: 0,
12216 },
12217 vote_balance,
12218 );
12219
12220 let stake_keypair = Keypair::new();
12221 instructions.extend(stake_instruction::create_account_and_delegate_stake(
12222 &mint_keypair.pubkey(),
12223 &stake_keypair.pubkey(),
12224 &vote_keypair.pubkey(),
12225 &Authorized::auto(&stake_keypair.pubkey()),
12226 &Lockup::default(),
12227 stake_balance,
12228 ));
12229
12230 let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
12231 let transaction = Transaction::new(
12232 &[&mint_keypair, &vote_keypair, &stake_keypair],
12233 message,
12234 bank.last_blockhash(),
12235 );
12236
12237 bank.process_transaction(&transaction).unwrap();
12238
12239 let stake_delegations = bank.stakes_cache.stakes().stake_delegations().clone();
12240 assert_eq!(stake_delegations.len(), 2);
12241 assert!(stake_delegations.get(&stake_keypair.pubkey()).is_some());
12242 }
12243
12244 #[allow(deprecated)]
12245 #[test]
12246 fn test_bank_fees_account() {
12247 let (mut genesis_config, _) = create_genesis_config(500);
12248 genesis_config.fee_rate_governor = FeeRateGovernor::new(12345, 0);
12249 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12250
12251 let fees_account = bank.get_account(&sysvar::fees::id()).unwrap();
12252 let fees = from_account::<Fees, _>(&fees_account).unwrap();
12253 assert_eq!(
12254 bank.fee_rate_governor.lamports_per_signature,
12255 fees.fee_calculator.lamports_per_signature
12256 );
12257 assert_eq!(fees.fee_calculator.lamports_per_signature, 12345);
12258 }
12259
12260 #[test]
12261 fn test_is_delta_with_no_committables() {
12262 let (genesis_config, mint_keypair) = create_genesis_config(8000);
12263 let bank = Bank::new_for_tests(&genesis_config);
12264 bank.is_delta.store(false, Relaxed);
12265
12266 let keypair1 = Keypair::new();
12267 let keypair2 = Keypair::new();
12268 let fail_tx =
12269 system_transaction::transfer(&keypair1, &keypair2.pubkey(), 1, bank.last_blockhash());
12270
12271 assert_eq!(
12275 bank.process_transaction(&fail_tx),
12276 Err(TransactionError::AccountNotFound)
12277 );
12278
12279 assert!(!bank.is_delta.load(Relaxed));
12281
12282 assert_eq!(
12285 bank.transfer(10_001, &mint_keypair, &solana_sdk::pubkey::new_rand()),
12286 Err(TransactionError::InstructionError(
12287 0,
12288 SystemError::ResultWithNegativeLamports.into(),
12289 ))
12290 );
12291
12292 assert!(bank.is_delta.load(Relaxed));
12293 }
12294
12295 #[test]
12296 fn test_bank_get_program_accounts() {
12297 let (genesis_config, mint_keypair) = create_genesis_config(500);
12298 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
12299 parent.restore_old_behavior_for_fragile_tests();
12300
12301 let genesis_accounts: Vec<_> = parent.get_all_accounts_with_modified_slots().unwrap();
12302 assert!(
12303 genesis_accounts
12304 .iter()
12305 .any(|(pubkey, _, _)| *pubkey == mint_keypair.pubkey()),
12306 "mint pubkey not found"
12307 );
12308 assert!(
12309 genesis_accounts
12310 .iter()
12311 .any(|(pubkey, _, _)| solana_sdk::sysvar::is_sysvar_id(pubkey)),
12312 "no sysvars found"
12313 );
12314
12315 let bank0 = Arc::new(new_from_parent(&parent));
12316 let pubkey0 = solana_sdk::pubkey::new_rand();
12317 let program_id = Pubkey::from([2; 32]);
12318 let account0 = AccountSharedData::new(1, 0, &program_id);
12319 bank0.store_account(&pubkey0, &account0);
12320
12321 assert_eq!(
12322 bank0.get_program_accounts_modified_since_parent(&program_id),
12323 vec![(pubkey0, account0.clone())]
12324 );
12325
12326 let bank1 = Arc::new(new_from_parent(&bank0));
12327 bank1.squash();
12328 assert_eq!(
12329 bank0
12330 .get_program_accounts(&program_id, &ScanConfig::default(),)
12331 .unwrap(),
12332 vec![(pubkey0, account0.clone())]
12333 );
12334 assert_eq!(
12335 bank1
12336 .get_program_accounts(&program_id, &ScanConfig::default(),)
12337 .unwrap(),
12338 vec![(pubkey0, account0)]
12339 );
12340 assert_eq!(
12341 bank1.get_program_accounts_modified_since_parent(&program_id),
12342 vec![]
12343 );
12344
12345 let bank2 = Arc::new(new_from_parent(&bank1));
12346 let pubkey1 = solana_sdk::pubkey::new_rand();
12347 let account1 = AccountSharedData::new(3, 0, &program_id);
12348 bank2.store_account(&pubkey1, &account1);
12349 let pubkey2 = solana_sdk::pubkey::new_rand();
12351 let account2 = AccountSharedData::new(0, 0, &program_id);
12352 bank2.store_account(&pubkey2, &account2);
12353
12354 let bank3 = Arc::new(new_from_parent(&bank2));
12355 bank3.squash();
12356 assert_eq!(
12357 bank1
12358 .get_program_accounts(&program_id, &ScanConfig::default(),)
12359 .unwrap()
12360 .len(),
12361 2
12362 );
12363 assert_eq!(
12364 bank3
12365 .get_program_accounts(&program_id, &ScanConfig::default(),)
12366 .unwrap()
12367 .len(),
12368 2
12369 );
12370 }
12371
12372 #[test]
12373 fn test_get_filtered_indexed_accounts_limit_exceeded() {
12374 let (genesis_config, _mint_keypair) = create_genesis_config(500);
12375 let mut account_indexes = AccountSecondaryIndexes::default();
12376 account_indexes.indexes.insert(AccountIndex::ProgramId);
12377 let bank = Arc::new(Bank::new_with_config_for_tests(
12378 &genesis_config,
12379 account_indexes,
12380 false,
12381 AccountShrinkThreshold::default(),
12382 ));
12383
12384 let address = Pubkey::new_unique();
12385 let program_id = Pubkey::new_unique();
12386 let limit = 100;
12387 let account = AccountSharedData::new(1, limit, &program_id);
12388 bank.store_account(&address, &account);
12389
12390 assert!(bank
12391 .get_filtered_indexed_accounts(
12392 &IndexKey::ProgramId(program_id),
12393 |_| true,
12394 &ScanConfig::default(),
12395 Some(limit), )
12397 .is_err());
12398 }
12399
12400 #[test]
12401 fn test_get_filtered_indexed_accounts() {
12402 let (genesis_config, _mint_keypair) = create_genesis_config(500);
12403 let mut account_indexes = AccountSecondaryIndexes::default();
12404 account_indexes.indexes.insert(AccountIndex::ProgramId);
12405 let bank = Arc::new(Bank::new_with_config_for_tests(
12406 &genesis_config,
12407 account_indexes,
12408 false,
12409 AccountShrinkThreshold::default(),
12410 ));
12411
12412 let address = Pubkey::new_unique();
12413 let program_id = Pubkey::new_unique();
12414 let account = AccountSharedData::new(1, 0, &program_id);
12415 bank.store_account(&address, &account);
12416
12417 let indexed_accounts = bank
12418 .get_filtered_indexed_accounts(
12419 &IndexKey::ProgramId(program_id),
12420 |_| true,
12421 &ScanConfig::default(),
12422 None,
12423 )
12424 .unwrap();
12425 assert_eq!(indexed_accounts.len(), 1);
12426 assert_eq!(indexed_accounts[0], (address, account));
12427
12428 let another_program_id = Pubkey::new_unique();
12432 let new_account = AccountSharedData::new(1, 0, &another_program_id);
12433 let bank = Arc::new(new_from_parent(&bank));
12434 bank.store_account(&address, &new_account);
12435 let indexed_accounts = bank
12436 .get_filtered_indexed_accounts(
12437 &IndexKey::ProgramId(program_id),
12438 |_| true,
12439 &ScanConfig::default(),
12440 None,
12441 )
12442 .unwrap();
12443 assert_eq!(indexed_accounts.len(), 1);
12444 assert_eq!(indexed_accounts[0], (address, new_account.clone()));
12445 let indexed_accounts = bank
12446 .get_filtered_indexed_accounts(
12447 &IndexKey::ProgramId(another_program_id),
12448 |_| true,
12449 &ScanConfig::default(),
12450 None,
12451 )
12452 .unwrap();
12453 assert_eq!(indexed_accounts.len(), 1);
12454 assert_eq!(indexed_accounts[0], (address, new_account.clone()));
12455
12456 let indexed_accounts = bank
12458 .get_filtered_indexed_accounts(
12459 &IndexKey::ProgramId(program_id),
12460 |account| account.owner() == &program_id,
12461 &ScanConfig::default(),
12462 None,
12463 )
12464 .unwrap();
12465 assert!(indexed_accounts.is_empty());
12466 let indexed_accounts = bank
12467 .get_filtered_indexed_accounts(
12468 &IndexKey::ProgramId(another_program_id),
12469 |account| account.owner() == &another_program_id,
12470 &ScanConfig::default(),
12471 None,
12472 )
12473 .unwrap();
12474 assert_eq!(indexed_accounts.len(), 1);
12475 assert_eq!(indexed_accounts[0], (address, new_account));
12476 }
12477
12478 #[test]
12479 fn test_status_cache_ancestors() {
12480 solana_logger::setup();
12481 let parent = create_simple_test_arc_bank(500);
12482 let bank1 = Arc::new(new_from_parent(&parent));
12483 let mut bank = bank1;
12484 for _ in 0..MAX_CACHE_ENTRIES * 2 {
12485 bank = Arc::new(new_from_parent(&bank));
12486 bank.squash();
12487 }
12488
12489 let bank = new_from_parent(&bank);
12490 assert_eq!(
12491 bank.status_cache_ancestors(),
12492 (bank.slot() - MAX_CACHE_ENTRIES as u64..=bank.slot()).collect::<Vec<_>>()
12493 );
12494 }
12495
12496 #[test]
12497 fn test_add_builtin() {
12498 let (genesis_config, mint_keypair) = create_genesis_config(500);
12499 let mut bank = Bank::new_for_tests(&genesis_config);
12500
12501 fn mock_vote_program_id() -> Pubkey {
12502 Pubkey::from([42u8; 32])
12503 }
12504 fn mock_vote_processor(
12505 _first_instruction_account: usize,
12506 invoke_context: &mut InvokeContext,
12507 ) -> std::result::Result<(), InstructionError> {
12508 let transaction_context = &invoke_context.transaction_context;
12509 let instruction_context = transaction_context.get_current_instruction_context()?;
12510 let program_id = instruction_context.get_last_program_key(transaction_context)?;
12511 if mock_vote_program_id() != *program_id {
12512 return Err(InstructionError::IncorrectProgramId);
12513 }
12514 Err(InstructionError::Custom(42))
12515 }
12516
12517 assert!(bank.get_account(&mock_vote_program_id()).is_none());
12518 bank.add_builtin(
12519 "mock_vote_program",
12520 &mock_vote_program_id(),
12521 mock_vote_processor,
12522 );
12523 assert!(bank.get_account(&mock_vote_program_id()).is_some());
12524
12525 let mock_account = Keypair::new();
12526 let mock_validator_identity = Keypair::new();
12527 let mut instructions = vote_instruction::create_account(
12528 &mint_keypair.pubkey(),
12529 &mock_account.pubkey(),
12530 &VoteInit {
12531 node_pubkey: mock_validator_identity.pubkey(),
12532 ..VoteInit::default()
12533 },
12534 1,
12535 );
12536 instructions[1].program_id = mock_vote_program_id();
12537
12538 let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
12539 let transaction = Transaction::new(
12540 &[&mint_keypair, &mock_account, &mock_validator_identity],
12541 message,
12542 bank.last_blockhash(),
12543 );
12544
12545 assert_eq!(
12546 bank.process_transaction(&transaction),
12547 Err(TransactionError::InstructionError(
12548 1,
12549 InstructionError::Custom(42)
12550 ))
12551 );
12552 }
12553
12554 #[test]
12555 fn test_add_duplicate_static_program() {
12556 let GenesisConfigInfo {
12557 genesis_config,
12558 mint_keypair,
12559 ..
12560 } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 0);
12561 let mut bank = Bank::new_for_tests(&genesis_config);
12562
12563 fn mock_vote_processor(
12564 _first_instruction_account: usize,
12565 _invoke_context: &mut InvokeContext,
12566 ) -> std::result::Result<(), InstructionError> {
12567 Err(InstructionError::Custom(42))
12568 }
12569
12570 let mock_account = Keypair::new();
12571 let mock_validator_identity = Keypair::new();
12572 let instructions = vote_instruction::create_account(
12573 &mint_keypair.pubkey(),
12574 &mock_account.pubkey(),
12575 &VoteInit {
12576 node_pubkey: mock_validator_identity.pubkey(),
12577 ..VoteInit::default()
12578 },
12579 1,
12580 );
12581
12582 let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
12583 let transaction = Transaction::new(
12584 &[&mint_keypair, &mock_account, &mock_validator_identity],
12585 message,
12586 bank.last_blockhash(),
12587 );
12588
12589 let vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap();
12590 bank.add_builtin(
12591 "solana_vote_program",
12592 &solana_vote_program::id(),
12593 mock_vote_processor,
12594 );
12595 let new_vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap();
12596 assert_eq!(vote_loader_account.data(), new_vote_loader_account.data());
12598 assert_eq!(
12599 bank.process_transaction(&transaction),
12600 Err(TransactionError::InstructionError(
12601 1,
12602 InstructionError::Custom(42)
12603 ))
12604 );
12605 }
12606
12607 #[test]
12608 fn test_add_instruction_processor_for_existing_unrelated_accounts() {
12609 let mut bank = create_simple_test_bank(500);
12610
12611 fn mock_ix_processor(
12612 _first_instruction_account: usize,
12613 _invoke_context: &mut InvokeContext,
12614 ) -> std::result::Result<(), InstructionError> {
12615 Err(InstructionError::Custom(42))
12616 }
12617
12618 {
12620 let stakes = bank.stakes_cache.stakes();
12621 assert!(stakes.vote_accounts().as_ref().is_empty());
12622 }
12623 assert!(bank.stakes_cache.stakes().stake_delegations().is_empty());
12624 assert_eq!(bank.calculate_capitalization(true), bank.capitalization());
12625
12626 let ((vote_id, vote_account), (stake_id, stake_account)) =
12627 crate::stakes::tests::create_staked_node_accounts(1_0000);
12628 bank.capitalization
12629 .fetch_add(vote_account.lamports() + stake_account.lamports(), Relaxed);
12630 bank.store_account(&vote_id, &vote_account);
12631 bank.store_account(&stake_id, &stake_account);
12632 {
12633 let stakes = bank.stakes_cache.stakes();
12634 assert!(!stakes.vote_accounts().as_ref().is_empty());
12635 }
12636 assert!(!bank.stakes_cache.stakes().stake_delegations().is_empty());
12637 assert_eq!(bank.calculate_capitalization(true), bank.capitalization());
12638
12639 bank.add_builtin("mock_program1", &vote_id, mock_ix_processor);
12640 bank.add_builtin("mock_program2", &stake_id, mock_ix_processor);
12641 {
12642 let stakes = bank.stakes_cache.stakes();
12643 assert!(stakes.vote_accounts().as_ref().is_empty());
12644 }
12645 assert!(bank.stakes_cache.stakes().stake_delegations().is_empty());
12646 assert_eq!(bank.calculate_capitalization(true), bank.capitalization());
12647 assert_eq!(
12648 "mock_program1",
12649 String::from_utf8_lossy(bank.get_account(&vote_id).unwrap_or_default().data())
12650 );
12651 assert_eq!(
12652 "mock_program2",
12653 String::from_utf8_lossy(bank.get_account(&stake_id).unwrap_or_default().data())
12654 );
12655
12656 bank.update_accounts_hash();
12658 let old_hash = bank.get_accounts_hash();
12659 bank.add_builtin("mock_program1", &vote_id, mock_ix_processor);
12660 bank.add_builtin("mock_program2", &stake_id, mock_ix_processor);
12661 bank.update_accounts_hash();
12662 let new_hash = bank.get_accounts_hash();
12663 assert_eq!(old_hash, new_hash);
12664 {
12665 let stakes = bank.stakes_cache.stakes();
12666 assert!(stakes.vote_accounts().as_ref().is_empty());
12667 }
12668 assert!(bank.stakes_cache.stakes().stake_delegations().is_empty());
12669 assert_eq!(bank.calculate_capitalization(true), bank.capitalization());
12670 assert_eq!(
12671 "mock_program1",
12672 String::from_utf8_lossy(bank.get_account(&vote_id).unwrap_or_default().data())
12673 );
12674 assert_eq!(
12675 "mock_program2",
12676 String::from_utf8_lossy(bank.get_account(&stake_id).unwrap_or_default().data())
12677 );
12678 }
12679
12680 #[allow(deprecated)]
12681 #[test]
12682 fn test_recent_blockhashes_sysvar() {
12683 let mut bank = create_simple_test_arc_bank(500);
12684 for i in 1..5 {
12685 let bhq_account = bank.get_account(&sysvar::recent_blockhashes::id()).unwrap();
12686 let recent_blockhashes =
12687 from_account::<sysvar::recent_blockhashes::RecentBlockhashes, _>(&bhq_account)
12688 .unwrap();
12689 assert_eq!(recent_blockhashes.len(), i);
12691 let most_recent_hash = recent_blockhashes.iter().next().unwrap().blockhash;
12692 assert!(bank.is_hash_valid_for_age(&most_recent_hash, 0));
12694 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
12695 bank = Arc::new(new_from_parent(&bank));
12696 }
12697 }
12698
12699 #[allow(deprecated)]
12700 #[test]
12701 fn test_blockhash_queue_sysvar_consistency() {
12702 let mut bank = create_simple_test_arc_bank(100_000);
12703 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
12704
12705 let bhq_account = bank.get_account(&sysvar::recent_blockhashes::id()).unwrap();
12706 let recent_blockhashes =
12707 from_account::<sysvar::recent_blockhashes::RecentBlockhashes, _>(&bhq_account).unwrap();
12708
12709 let sysvar_recent_blockhash = recent_blockhashes[0].blockhash;
12710 let bank_last_blockhash = bank.last_blockhash();
12711 assert_eq!(sysvar_recent_blockhash, bank_last_blockhash);
12712 }
12713
12714 #[test]
12715 fn test_hash_internal_state_unchanged() {
12716 let (genesis_config, _) = create_genesis_config(500);
12717 let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
12718 bank0.freeze();
12719 let bank0_hash = bank0.hash();
12720 let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
12721 bank1.freeze();
12722 let bank1_hash = bank1.hash();
12723 assert_ne!(bank0_hash, bank1_hash);
12725 }
12726
12727 #[test]
12728 fn test_ticks_change_state() {
12729 let (genesis_config, _) = create_genesis_config(500);
12730 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12731 let bank1 = new_from_parent(&bank);
12732 let hash1 = bank1.hash_internal_state();
12733 for _ in 0..genesis_config.ticks_per_slot {
12735 assert_eq!(bank1.hash_internal_state(), hash1);
12736 bank1.register_tick(&Hash::default());
12737 }
12738 assert_ne!(bank1.hash_internal_state(), hash1);
12739 }
12740
12741 #[ignore]
12742 #[test]
12743 fn test_banks_leak() {
12744 fn add_lotsa_stake_accounts(genesis_config: &mut GenesisConfig) {
12745 const LOTSA: usize = 4_096;
12746
12747 (0..LOTSA).for_each(|_| {
12748 let pubkey = solana_sdk::pubkey::new_rand();
12749 genesis_config.add_account(
12750 pubkey,
12751 stake_state::create_lockup_stake_account(
12752 &Authorized::auto(&pubkey),
12753 &Lockup::default(),
12754 &Rent::default(),
12755 50_000_000,
12756 ),
12757 );
12758 });
12759 }
12760 solana_logger::setup();
12761 let (mut genesis_config, _) = create_genesis_config(100_000_000_000_000);
12762 add_lotsa_stake_accounts(&mut genesis_config);
12763 let mut bank = std::sync::Arc::new(Bank::new_for_tests(&genesis_config));
12764 let mut num_banks = 0;
12765 let pid = std::process::id();
12766 #[cfg(not(target_os = "linux"))]
12767 error!(
12768 "\nYou can run this to watch RAM:\n while read -p 'banks: '; do echo $(( $(ps -o vsize= -p {})/$REPLY));done", pid
12769 );
12770 loop {
12771 num_banks += 1;
12772 bank = std::sync::Arc::new(new_from_parent(&bank));
12773 if num_banks % 100 == 0 {
12774 #[cfg(target_os = "linux")]
12775 {
12776 let pages_consumed = std::fs::read_to_string(format!("/proc/{}/statm", pid))
12777 .unwrap()
12778 .split_whitespace()
12779 .next()
12780 .unwrap()
12781 .parse::<usize>()
12782 .unwrap();
12783 error!(
12784 "at {} banks: {} mem or {}kB/bank",
12785 num_banks,
12786 pages_consumed * 4096,
12787 (pages_consumed * 4) / num_banks
12788 );
12789 }
12790 #[cfg(not(target_os = "linux"))]
12791 {
12792 error!("{} banks, sleeping for 5 sec", num_banks);
12793 std::thread::sleep(Duration::new(5, 0));
12794 }
12795 }
12796 }
12797 }
12798
12799 fn get_nonce_blockhash(bank: &Bank, nonce_pubkey: &Pubkey) -> Option<Hash> {
12800 let account = bank.get_account(nonce_pubkey)?;
12801 let nonce_versions = StateMut::<nonce::state::Versions>::state(&account);
12802 match nonce_versions.ok()?.state() {
12803 nonce::State::Initialized(ref data) => Some(data.blockhash()),
12804 _ => None,
12805 }
12806 }
12807
12808 fn nonce_setup(
12809 bank: &mut Arc<Bank>,
12810 mint_keypair: &Keypair,
12811 custodian_lamports: u64,
12812 nonce_lamports: u64,
12813 nonce_authority: Option<Pubkey>,
12814 ) -> Result<(Keypair, Keypair)> {
12815 let custodian_keypair = Keypair::new();
12816 let nonce_keypair = Keypair::new();
12817 let mut setup_ixs = vec![system_instruction::transfer(
12819 &mint_keypair.pubkey(),
12820 &custodian_keypair.pubkey(),
12821 custodian_lamports,
12822 )];
12823 let nonce_authority = nonce_authority.unwrap_or_else(|| nonce_keypair.pubkey());
12824 setup_ixs.extend_from_slice(&system_instruction::create_nonce_account(
12825 &custodian_keypair.pubkey(),
12826 &nonce_keypair.pubkey(),
12827 &nonce_authority,
12828 nonce_lamports,
12829 ));
12830 let message = Message::new(&setup_ixs, Some(&mint_keypair.pubkey()));
12831 let setup_tx = Transaction::new(
12832 &[mint_keypair, &custodian_keypair, &nonce_keypair],
12833 message,
12834 bank.last_blockhash(),
12835 );
12836 bank.process_transaction(&setup_tx)?;
12837 Ok((custodian_keypair, nonce_keypair))
12838 }
12839
12840 fn setup_nonce_with_bank<F>(
12841 supply_lamports: u64,
12842 mut genesis_cfg_fn: F,
12843 custodian_lamports: u64,
12844 nonce_lamports: u64,
12845 nonce_authority: Option<Pubkey>,
12846 feature_set: FeatureSet,
12847 ) -> Result<(Arc<Bank>, Keypair, Keypair, Keypair)>
12848 where
12849 F: FnMut(&mut GenesisConfig),
12850 {
12851 let (mut genesis_config, mint_keypair) = create_genesis_config(supply_lamports);
12852 genesis_config.rent.lamports_per_byte_year = 0;
12853 genesis_cfg_fn(&mut genesis_config);
12854 let mut bank = Bank::new_for_tests(&genesis_config);
12855 bank.feature_set = Arc::new(feature_set);
12856 let mut bank = Arc::new(bank);
12857
12858 for _ in 0..2 {
12861 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
12862 bank = Arc::new(new_from_parent(&bank));
12863 }
12864
12865 let (custodian_keypair, nonce_keypair) = nonce_setup(
12866 &mut bank,
12867 &mint_keypair,
12868 custodian_lamports,
12869 nonce_lamports,
12870 nonce_authority,
12871 )?;
12872
12873 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
12876 bank = Arc::new(new_from_parent(&bank));
12877
12878 Ok((bank, mint_keypair, custodian_keypair, nonce_keypair))
12879 }
12880
12881 impl Bank {
12882 fn next_durable_nonce(&self) -> DurableNonce {
12883 let hash_queue = self.blockhash_queue.read().unwrap();
12884 let last_blockhash = hash_queue.last_hash();
12885 DurableNonce::from_blockhash(&last_blockhash)
12886 }
12887 }
12888
12889 #[test]
12890 fn test_check_transaction_for_nonce_ok() {
12891 let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
12892 10_000_000,
12893 |_| {},
12894 5_000_000,
12895 250_000,
12896 None,
12897 FeatureSet::all_enabled(),
12898 )
12899 .unwrap();
12900 let custodian_pubkey = custodian_keypair.pubkey();
12901 let nonce_pubkey = nonce_keypair.pubkey();
12902
12903 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
12904 let tx = Transaction::new_signed_with_payer(
12905 &[
12906 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
12907 system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
12908 ],
12909 Some(&custodian_pubkey),
12910 &[&custodian_keypair, &nonce_keypair],
12911 nonce_hash,
12912 );
12913 let nonce_account = bank.get_account(&nonce_pubkey).unwrap();
12914 assert_eq!(
12915 bank.check_transaction_for_nonce(
12916 &SanitizedTransaction::from_transaction_for_tests(tx),
12917 &bank.next_durable_nonce(),
12918 ),
12919 Some((nonce_pubkey, nonce_account))
12920 );
12921 }
12922
12923 #[test]
12924 fn test_check_transaction_for_nonce_not_nonce_fail() {
12925 let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
12926 10_000_000,
12927 |_| {},
12928 5_000_000,
12929 250_000,
12930 None,
12931 FeatureSet::all_enabled(),
12932 )
12933 .unwrap();
12934 let custodian_pubkey = custodian_keypair.pubkey();
12935 let nonce_pubkey = nonce_keypair.pubkey();
12936
12937 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
12938 let tx = Transaction::new_signed_with_payer(
12939 &[
12940 system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
12941 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
12942 ],
12943 Some(&custodian_pubkey),
12944 &[&custodian_keypair, &nonce_keypair],
12945 nonce_hash,
12946 );
12947 assert!(bank
12948 .check_transaction_for_nonce(
12949 &SanitizedTransaction::from_transaction_for_tests(tx,),
12950 &bank.next_durable_nonce(),
12951 )
12952 .is_none());
12953 }
12954
12955 #[test]
12956 fn test_check_transaction_for_nonce_missing_ix_pubkey_fail() {
12957 let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
12958 10_000_000,
12959 |_| {},
12960 5_000_000,
12961 250_000,
12962 None,
12963 FeatureSet::all_enabled(),
12964 )
12965 .unwrap();
12966 let custodian_pubkey = custodian_keypair.pubkey();
12967 let nonce_pubkey = nonce_keypair.pubkey();
12968
12969 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
12970 let mut tx = Transaction::new_signed_with_payer(
12971 &[
12972 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
12973 system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
12974 ],
12975 Some(&custodian_pubkey),
12976 &[&custodian_keypair, &nonce_keypair],
12977 nonce_hash,
12978 );
12979 tx.message.instructions[0].accounts.clear();
12980 assert!(bank
12981 .check_transaction_for_nonce(
12982 &SanitizedTransaction::from_transaction_for_tests(tx),
12983 &bank.next_durable_nonce(),
12984 )
12985 .is_none());
12986 }
12987
12988 #[test]
12989 fn test_check_transaction_for_nonce_nonce_acc_does_not_exist_fail() {
12990 let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
12991 10_000_000,
12992 |_| {},
12993 5_000_000,
12994 250_000,
12995 None,
12996 FeatureSet::all_enabled(),
12997 )
12998 .unwrap();
12999 let custodian_pubkey = custodian_keypair.pubkey();
13000 let nonce_pubkey = nonce_keypair.pubkey();
13001 let missing_keypair = Keypair::new();
13002 let missing_pubkey = missing_keypair.pubkey();
13003
13004 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13005 let tx = Transaction::new_signed_with_payer(
13006 &[
13007 system_instruction::advance_nonce_account(&missing_pubkey, &nonce_pubkey),
13008 system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
13009 ],
13010 Some(&custodian_pubkey),
13011 &[&custodian_keypair, &nonce_keypair],
13012 nonce_hash,
13013 );
13014 assert!(bank
13015 .check_transaction_for_nonce(
13016 &SanitizedTransaction::from_transaction_for_tests(tx),
13017 &bank.next_durable_nonce(),
13018 )
13019 .is_none());
13020 }
13021
13022 #[test]
13023 fn test_check_transaction_for_nonce_bad_tx_hash_fail() {
13024 let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13025 10_000_000,
13026 |_| {},
13027 5_000_000,
13028 250_000,
13029 None,
13030 FeatureSet::all_enabled(),
13031 )
13032 .unwrap();
13033 let custodian_pubkey = custodian_keypair.pubkey();
13034 let nonce_pubkey = nonce_keypair.pubkey();
13035
13036 let tx = Transaction::new_signed_with_payer(
13037 &[
13038 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13039 system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
13040 ],
13041 Some(&custodian_pubkey),
13042 &[&custodian_keypair, &nonce_keypair],
13043 Hash::default(),
13044 );
13045 assert!(bank
13046 .check_transaction_for_nonce(
13047 &SanitizedTransaction::from_transaction_for_tests(tx),
13048 &bank.next_durable_nonce(),
13049 )
13050 .is_none());
13051 }
13052
13053 #[test]
13054 fn test_assign_from_nonce_account_fail() {
13055 let bank = create_simple_test_arc_bank(100_000_000);
13056 let nonce = Keypair::new();
13057 let nonce_account = AccountSharedData::new_data(
13058 42_424_242,
13059 &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::default())),
13060 &system_program::id(),
13061 )
13062 .unwrap();
13063 let blockhash = bank.last_blockhash();
13064 bank.store_account(&nonce.pubkey(), &nonce_account);
13065
13066 let ix = system_instruction::assign(&nonce.pubkey(), &Pubkey::from([9u8; 32]));
13067 let message = Message::new(&[ix], Some(&nonce.pubkey()));
13068 let tx = Transaction::new(&[&nonce], message, blockhash);
13069
13070 let expect = Err(TransactionError::InstructionError(
13071 0,
13072 InstructionError::ModifiedProgramId,
13073 ));
13074 assert_eq!(bank.process_transaction(&tx), expect);
13075 }
13076
13077 #[test]
13078 fn test_nonce_must_be_advanceable() {
13079 let mut bank = create_simple_test_bank(100_000_000);
13080 bank.feature_set = Arc::new(FeatureSet::all_enabled());
13081 let bank = Arc::new(bank);
13082 let nonce_keypair = Keypair::new();
13083 let nonce_authority = nonce_keypair.pubkey();
13084 let durable_nonce = DurableNonce::from_blockhash(&bank.last_blockhash());
13085 let nonce_account = AccountSharedData::new_data(
13086 42_424_242,
13087 &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::new(
13088 nonce_authority,
13089 durable_nonce,
13090 5000,
13091 ))),
13092 &system_program::id(),
13093 )
13094 .unwrap();
13095 bank.store_account(&nonce_keypair.pubkey(), &nonce_account);
13096
13097 let ix =
13098 system_instruction::advance_nonce_account(&nonce_keypair.pubkey(), &nonce_authority);
13099 let message = Message::new(&[ix], Some(&nonce_keypair.pubkey()));
13100 let tx = Transaction::new(&[&nonce_keypair], message, *durable_nonce.as_hash());
13101 assert_eq!(
13102 bank.process_transaction(&tx),
13103 Err(TransactionError::BlockhashNotFound)
13104 );
13105 }
13106
13107 #[test]
13108 fn test_nonce_transaction() {
13109 let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13110 10_000_000,
13111 |_| {},
13112 5_000_000,
13113 250_000,
13114 None,
13115 FeatureSet::all_enabled(),
13116 )
13117 .unwrap();
13118 let alice_keypair = Keypair::new();
13119 let alice_pubkey = alice_keypair.pubkey();
13120 let custodian_pubkey = custodian_keypair.pubkey();
13121 let nonce_pubkey = nonce_keypair.pubkey();
13122
13123 assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
13124 assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
13125
13126 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13128
13129 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13131 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13132 bank = Arc::new(new_from_parent(&bank));
13133 }
13134
13135 assert_eq!(
13137 bank.process_transaction(&system_transaction::transfer(
13138 &custodian_keypair,
13139 &alice_pubkey,
13140 100_000,
13141 nonce_hash
13142 ),),
13143 Err(TransactionError::BlockhashNotFound),
13144 );
13145 assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
13147
13148 let nonce_tx = Transaction::new_signed_with_payer(
13150 &[
13151 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13152 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
13153 ],
13154 Some(&custodian_pubkey),
13155 &[&custodian_keypair, &nonce_keypair],
13156 nonce_hash,
13157 );
13158 assert_eq!(bank.process_transaction(&nonce_tx), Ok(()));
13159
13160 let mut recent_message = nonce_tx.message;
13162 recent_message.recent_blockhash = bank.last_blockhash();
13163 let mut expected_balance = 4_650_000
13164 - bank
13165 .get_fee_for_message(&recent_message.try_into().unwrap())
13166 .unwrap();
13167 assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13168 assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
13169 assert_eq!(bank.get_balance(&alice_pubkey), 100_000);
13170
13171 let new_nonce = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13173 assert_ne!(nonce_hash, new_nonce);
13174
13175 let nonce_tx = Transaction::new_signed_with_payer(
13177 &[
13178 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13179 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
13180 ],
13181 Some(&custodian_pubkey),
13182 &[&custodian_keypair, &nonce_keypair],
13183 nonce_hash,
13184 );
13185 assert_eq!(
13186 bank.process_transaction(&nonce_tx),
13187 Err(TransactionError::BlockhashNotFound)
13188 );
13189 assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13191 assert_eq!(
13192 new_nonce,
13193 get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13194 );
13195
13196 let nonce_hash = new_nonce;
13197
13198 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13200 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13201 bank = Arc::new(new_from_parent(&bank));
13202 }
13203
13204 let nonce_tx = Transaction::new_signed_with_payer(
13205 &[
13206 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13207 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
13208 ],
13209 Some(&custodian_pubkey),
13210 &[&custodian_keypair, &nonce_keypair],
13211 nonce_hash,
13212 );
13213 assert_eq!(
13214 bank.process_transaction(&nonce_tx),
13215 Err(TransactionError::InstructionError(
13216 1,
13217 system_instruction::SystemError::ResultWithNegativeLamports.into(),
13218 ))
13219 );
13220 let mut recent_message = nonce_tx.message.clone();
13222 recent_message.recent_blockhash = bank.last_blockhash();
13223 expected_balance -= bank
13224 .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap())
13225 .unwrap();
13226 assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13227 assert_ne!(
13228 nonce_hash,
13229 get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13230 );
13231 assert_eq!(
13235 bank.process_transaction(&nonce_tx),
13236 Err(TransactionError::BlockhashNotFound),
13237 );
13238 }
13239
13240 #[test]
13241 fn test_nonce_transaction_with_tx_wide_caps() {
13242 let feature_set = FeatureSet::all_enabled();
13243 let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) =
13244 setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None, feature_set)
13245 .unwrap();
13246 let alice_keypair = Keypair::new();
13247 let alice_pubkey = alice_keypair.pubkey();
13248 let custodian_pubkey = custodian_keypair.pubkey();
13249 let nonce_pubkey = nonce_keypair.pubkey();
13250
13251 assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
13252 assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
13253
13254 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13256
13257 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13259 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13260 bank = Arc::new(new_from_parent(&bank));
13261 }
13262
13263 assert_eq!(
13265 bank.process_transaction(&system_transaction::transfer(
13266 &custodian_keypair,
13267 &alice_pubkey,
13268 100_000,
13269 nonce_hash
13270 ),),
13271 Err(TransactionError::BlockhashNotFound),
13272 );
13273 assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
13275
13276 let nonce_tx = Transaction::new_signed_with_payer(
13278 &[
13279 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13280 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
13281 ],
13282 Some(&custodian_pubkey),
13283 &[&custodian_keypair, &nonce_keypair],
13284 nonce_hash,
13285 );
13286 assert_eq!(bank.process_transaction(&nonce_tx), Ok(()));
13287
13288 let mut recent_message = nonce_tx.message;
13290 recent_message.recent_blockhash = bank.last_blockhash();
13291 let mut expected_balance = 4_650_000
13292 - bank
13293 .get_fee_for_message(&recent_message.try_into().unwrap())
13294 .unwrap();
13295 assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13296 assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
13297 assert_eq!(bank.get_balance(&alice_pubkey), 100_000);
13298
13299 let new_nonce = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13301 assert_ne!(nonce_hash, new_nonce);
13302
13303 let nonce_tx = Transaction::new_signed_with_payer(
13305 &[
13306 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13307 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
13308 ],
13309 Some(&custodian_pubkey),
13310 &[&custodian_keypair, &nonce_keypair],
13311 nonce_hash,
13312 );
13313 assert_eq!(
13314 bank.process_transaction(&nonce_tx),
13315 Err(TransactionError::BlockhashNotFound)
13316 );
13317 assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13319 assert_eq!(
13320 new_nonce,
13321 get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13322 );
13323
13324 let nonce_hash = new_nonce;
13325
13326 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13328 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13329 bank = Arc::new(new_from_parent(&bank));
13330 }
13331
13332 let nonce_tx = Transaction::new_signed_with_payer(
13333 &[
13334 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13335 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
13336 ],
13337 Some(&custodian_pubkey),
13338 &[&custodian_keypair, &nonce_keypair],
13339 nonce_hash,
13340 );
13341 assert_eq!(
13342 bank.process_transaction(&nonce_tx),
13343 Err(TransactionError::InstructionError(
13344 1,
13345 system_instruction::SystemError::ResultWithNegativeLamports.into(),
13346 ))
13347 );
13348 let mut recent_message = nonce_tx.message.clone();
13350 recent_message.recent_blockhash = bank.last_blockhash();
13351 expected_balance -= bank
13352 .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap())
13353 .unwrap();
13354 assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13355 assert_ne!(
13356 nonce_hash,
13357 get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13358 );
13359 assert_eq!(
13363 bank.process_transaction(&nonce_tx),
13364 Err(TransactionError::BlockhashNotFound),
13365 );
13366 }
13367
13368 #[test]
13369 fn test_nonce_authority() {
13370 solana_logger::setup();
13371 let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13372 10_000_000,
13373 |_| {},
13374 5_000_000,
13375 250_000,
13376 None,
13377 FeatureSet::all_enabled(),
13378 )
13379 .unwrap();
13380 let alice_keypair = Keypair::new();
13381 let alice_pubkey = alice_keypair.pubkey();
13382 let custodian_pubkey = custodian_keypair.pubkey();
13383 let nonce_pubkey = nonce_keypair.pubkey();
13384 let bad_nonce_authority_keypair = Keypair::new();
13385 let bad_nonce_authority = bad_nonce_authority_keypair.pubkey();
13386 let custodian_account = bank.get_account(&custodian_pubkey).unwrap();
13387
13388 debug!("alice: {}", alice_pubkey);
13389 debug!("custodian: {}", custodian_pubkey);
13390 debug!("nonce: {}", nonce_pubkey);
13391 debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey));
13392 debug!("cust: {:?}", custodian_account);
13393 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13394
13395 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13396 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13397 bank = Arc::new(new_from_parent(&bank));
13398 }
13399
13400 let nonce_tx = Transaction::new_signed_with_payer(
13401 &[
13402 system_instruction::advance_nonce_account(&nonce_pubkey, &bad_nonce_authority),
13403 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 42),
13404 ],
13405 Some(&custodian_pubkey),
13406 &[&custodian_keypair, &bad_nonce_authority_keypair],
13407 nonce_hash,
13408 );
13409 debug!("{:?}", nonce_tx);
13410 let initial_custodian_balance = custodian_account.lamports();
13411 assert_eq!(
13412 bank.process_transaction(&nonce_tx),
13413 Err(TransactionError::BlockhashNotFound),
13414 );
13415 let mut recent_message = nonce_tx.message;
13417 recent_message.recent_blockhash = bank.last_blockhash();
13418 assert_eq!(
13419 bank.get_balance(&custodian_pubkey),
13420 initial_custodian_balance
13421 );
13422 assert_eq!(
13423 nonce_hash,
13424 get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13425 );
13426 }
13427
13428 #[test]
13429 fn test_nonce_payer() {
13430 solana_logger::setup();
13431 let nonce_starting_balance = 250_000;
13432 let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13433 10_000_000,
13434 |_| {},
13435 5_000_000,
13436 nonce_starting_balance,
13437 None,
13438 FeatureSet::all_enabled(),
13439 )
13440 .unwrap();
13441 let alice_keypair = Keypair::new();
13442 let alice_pubkey = alice_keypair.pubkey();
13443 let custodian_pubkey = custodian_keypair.pubkey();
13444 let nonce_pubkey = nonce_keypair.pubkey();
13445
13446 debug!("alice: {}", alice_pubkey);
13447 debug!("custodian: {}", custodian_pubkey);
13448 debug!("nonce: {}", nonce_pubkey);
13449 debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey));
13450 debug!("cust: {:?}", bank.get_account(&custodian_pubkey));
13451 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13452
13453 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13454 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13455 bank = Arc::new(new_from_parent(&bank));
13456 }
13457
13458 let nonce_tx = Transaction::new_signed_with_payer(
13459 &[
13460 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13461 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
13462 ],
13463 Some(&nonce_pubkey),
13464 &[&custodian_keypair, &nonce_keypair],
13465 nonce_hash,
13466 );
13467 debug!("{:?}", nonce_tx);
13468 assert_eq!(
13469 bank.process_transaction(&nonce_tx),
13470 Err(TransactionError::InstructionError(
13471 1,
13472 system_instruction::SystemError::ResultWithNegativeLamports.into(),
13473 ))
13474 );
13475 let mut recent_message = nonce_tx.message;
13477 recent_message.recent_blockhash = bank.last_blockhash();
13478 assert_eq!(
13479 bank.get_balance(&nonce_pubkey),
13480 nonce_starting_balance
13481 - bank
13482 .get_fee_for_message(&recent_message.try_into().unwrap())
13483 .unwrap()
13484 );
13485 assert_ne!(
13486 nonce_hash,
13487 get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13488 );
13489 }
13490
13491 #[test]
13492 fn test_nonce_payer_tx_wide_cap() {
13493 solana_logger::setup();
13494 let nonce_starting_balance =
13495 250_000 + FeeStructure::default().compute_fee_bins.last().unwrap().fee;
13496 let feature_set = FeatureSet::all_enabled();
13497 let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13498 10_000_000,
13499 |_| {},
13500 5_000_000,
13501 nonce_starting_balance,
13502 None,
13503 feature_set,
13504 )
13505 .unwrap();
13506 let alice_keypair = Keypair::new();
13507 let alice_pubkey = alice_keypair.pubkey();
13508 let custodian_pubkey = custodian_keypair.pubkey();
13509 let nonce_pubkey = nonce_keypair.pubkey();
13510
13511 debug!("alice: {}", alice_pubkey);
13512 debug!("custodian: {}", custodian_pubkey);
13513 debug!("nonce: {}", nonce_pubkey);
13514 debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey));
13515 debug!("cust: {:?}", bank.get_account(&custodian_pubkey));
13516 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13517
13518 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13519 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13520 bank = Arc::new(new_from_parent(&bank));
13521 }
13522
13523 let nonce_tx = Transaction::new_signed_with_payer(
13524 &[
13525 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13526 system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
13527 ],
13528 Some(&nonce_pubkey),
13529 &[&custodian_keypair, &nonce_keypair],
13530 nonce_hash,
13531 );
13532 debug!("{:?}", nonce_tx);
13533
13534 assert_eq!(
13535 bank.process_transaction(&nonce_tx),
13536 Err(TransactionError::InstructionError(
13537 1,
13538 system_instruction::SystemError::ResultWithNegativeLamports.into(),
13539 ))
13540 );
13541 let mut recent_message = nonce_tx.message;
13543 recent_message.recent_blockhash = bank.last_blockhash();
13544 assert_eq!(
13545 bank.get_balance(&nonce_pubkey),
13546 nonce_starting_balance
13547 - bank
13548 .get_fee_for_message(&recent_message.try_into().unwrap())
13549 .unwrap()
13550 );
13551 assert_ne!(
13552 nonce_hash,
13553 get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13554 );
13555 }
13556
13557 #[test]
13558 fn test_nonce_fee_calculator_updates() {
13559 let (mut genesis_config, mint_keypair) = create_genesis_config(1_000_000);
13560 genesis_config.rent.lamports_per_byte_year = 0;
13561 let mut bank = Bank::new_for_tests(&genesis_config);
13562 bank.feature_set = Arc::new(FeatureSet::all_enabled());
13563 let mut bank = Arc::new(bank);
13564
13565 let (custodian_keypair, nonce_keypair) =
13567 nonce_setup(&mut bank, &mint_keypair, 500_000, 100_000, None).unwrap();
13568 let custodian_pubkey = custodian_keypair.pubkey();
13569 let nonce_pubkey = nonce_keypair.pubkey();
13570
13571 let (stored_nonce_hash, stored_fee_calculator) = bank
13573 .get_account(&nonce_pubkey)
13574 .and_then(|acc| {
13575 let nonce_versions = StateMut::<nonce::state::Versions>::state(&acc);
13576 match nonce_versions.ok()?.state() {
13577 nonce::State::Initialized(ref data) => {
13578 Some((data.blockhash(), data.fee_calculator))
13579 }
13580 _ => None,
13581 }
13582 })
13583 .unwrap();
13584
13585 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13587 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13588 bank = Arc::new(new_from_parent(&bank));
13589 }
13590
13591 let nonce_tx = Transaction::new_signed_with_payer(
13593 &[
13594 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13595 system_instruction::transfer(
13596 &custodian_pubkey,
13597 &solana_sdk::pubkey::new_rand(),
13598 100_000,
13599 ),
13600 ],
13601 Some(&custodian_pubkey),
13602 &[&custodian_keypair, &nonce_keypair],
13603 stored_nonce_hash,
13604 );
13605 bank.process_transaction(&nonce_tx).unwrap();
13606
13607 let (nonce_hash, fee_calculator) = bank
13609 .get_account(&nonce_pubkey)
13610 .and_then(|acc| {
13611 let nonce_versions = StateMut::<nonce::state::Versions>::state(&acc);
13612 match nonce_versions.ok()?.state() {
13613 nonce::State::Initialized(ref data) => {
13614 Some((data.blockhash(), data.fee_calculator))
13615 }
13616 _ => None,
13617 }
13618 })
13619 .unwrap();
13620
13621 assert_ne!(stored_nonce_hash, nonce_hash);
13622 assert_ne!(stored_fee_calculator, fee_calculator);
13623 }
13624
13625 #[test]
13626 fn test_nonce_fee_calculator_updates_tx_wide_cap() {
13627 let (mut genesis_config, mint_keypair) = create_genesis_config(1_000_000);
13628 genesis_config.rent.lamports_per_byte_year = 0;
13629 let mut bank = Bank::new_for_tests(&genesis_config);
13630 bank.feature_set = Arc::new(FeatureSet::all_enabled());
13631 let mut bank = Arc::new(bank);
13632
13633 let (custodian_keypair, nonce_keypair) =
13635 nonce_setup(&mut bank, &mint_keypair, 500_000, 100_000, None).unwrap();
13636 let custodian_pubkey = custodian_keypair.pubkey();
13637 let nonce_pubkey = nonce_keypair.pubkey();
13638
13639 let (stored_nonce_hash, stored_fee_calculator) = bank
13641 .get_account(&nonce_pubkey)
13642 .and_then(|acc| {
13643 let nonce_versions = StateMut::<nonce::state::Versions>::state(&acc);
13644 match nonce_versions.ok()?.state() {
13645 nonce::State::Initialized(ref data) => {
13646 Some((data.blockhash(), data.fee_calculator))
13647 }
13648 _ => None,
13649 }
13650 })
13651 .unwrap();
13652
13653 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13655 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13656 bank = Arc::new(new_from_parent(&bank));
13657 }
13658
13659 let nonce_tx = Transaction::new_signed_with_payer(
13661 &[
13662 system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13663 system_instruction::transfer(
13664 &custodian_pubkey,
13665 &solana_sdk::pubkey::new_rand(),
13666 100_000,
13667 ),
13668 ],
13669 Some(&custodian_pubkey),
13670 &[&custodian_keypair, &nonce_keypair],
13671 stored_nonce_hash,
13672 );
13673 bank.process_transaction(&nonce_tx).unwrap();
13674
13675 let (nonce_hash, fee_calculator) = bank
13677 .get_account(&nonce_pubkey)
13678 .and_then(|acc| {
13679 let nonce_versions = StateMut::<nonce::state::Versions>::state(&acc);
13680 match nonce_versions.ok()?.state() {
13681 nonce::State::Initialized(ref data) => {
13682 Some((data.blockhash(), data.fee_calculator))
13683 }
13684 _ => None,
13685 }
13686 })
13687 .unwrap();
13688
13689 assert_ne!(stored_nonce_hash, nonce_hash);
13690 assert_ne!(stored_fee_calculator, fee_calculator);
13691 }
13692
13693 #[test]
13694 fn test_check_ro_durable_nonce_fails() {
13695 let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13696 10_000_000,
13697 |_| {},
13698 5_000_000,
13699 250_000,
13700 None,
13701 FeatureSet::all_enabled(),
13702 )
13703 .unwrap();
13704 let custodian_pubkey = custodian_keypair.pubkey();
13705 let nonce_pubkey = nonce_keypair.pubkey();
13706
13707 let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13708 let account_metas = vec![
13709 AccountMeta::new_readonly(nonce_pubkey, false),
13710 #[allow(deprecated)]
13711 AccountMeta::new_readonly(sysvar::recent_blockhashes::id(), false),
13712 AccountMeta::new_readonly(nonce_pubkey, true),
13713 ];
13714 let nonce_instruction = Instruction::new_with_bincode(
13715 system_program::id(),
13716 &system_instruction::SystemInstruction::AdvanceNonceAccount,
13717 account_metas,
13718 );
13719 let tx = Transaction::new_signed_with_payer(
13720 &[nonce_instruction],
13721 Some(&custodian_pubkey),
13722 &[&custodian_keypair, &nonce_keypair],
13723 nonce_hash,
13724 );
13725 assert_eq!(
13730 bank.process_transaction(&tx),
13731 Err(TransactionError::BlockhashNotFound),
13732 );
13733 for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13735 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13736 bank = Arc::new(new_from_parent(&bank));
13737 }
13738 assert_eq!(
13740 bank.process_transaction(&tx),
13741 Err(TransactionError::BlockhashNotFound)
13742 );
13743 assert_eq!(
13744 bank.check_transaction_for_nonce(
13745 &SanitizedTransaction::from_transaction_for_tests(tx),
13746 &bank.next_durable_nonce(),
13747 ),
13748 None
13749 );
13750 }
13751
13752 #[test]
13753 fn test_collect_balances() {
13754 let parent = create_simple_test_arc_bank(500);
13755 let bank0 = Arc::new(new_from_parent(&parent));
13756
13757 let keypair = Keypair::new();
13758 let pubkey0 = solana_sdk::pubkey::new_rand();
13759 let pubkey1 = solana_sdk::pubkey::new_rand();
13760 let program_id = Pubkey::from([2; 32]);
13761 let keypair_account = AccountSharedData::new(8, 0, &program_id);
13762 let account0 = AccountSharedData::new(11, 0, &program_id);
13763 let program_account = AccountSharedData::new(1, 10, &Pubkey::default());
13764 bank0.store_account(&keypair.pubkey(), &keypair_account);
13765 bank0.store_account(&pubkey0, &account0);
13766 bank0.store_account(&program_id, &program_account);
13767
13768 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
13769 let tx0 = Transaction::new_with_compiled_instructions(
13770 &[&keypair],
13771 &[pubkey0],
13772 Hash::default(),
13773 vec![program_id],
13774 instructions,
13775 );
13776 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
13777 let tx1 = Transaction::new_with_compiled_instructions(
13778 &[&keypair],
13779 &[pubkey1],
13780 Hash::default(),
13781 vec![program_id],
13782 instructions,
13783 );
13784 let txs = vec![tx0, tx1];
13785 let batch = bank0.prepare_batch_for_tests(txs.clone());
13786 let balances = bank0.collect_balances(&batch);
13787 assert_eq!(balances.len(), 2);
13788 assert_eq!(balances[0], vec![8, 11, 1]);
13789 assert_eq!(balances[1], vec![8, 0, 1]);
13790
13791 let txs: Vec<_> = txs.into_iter().rev().collect();
13792 let batch = bank0.prepare_batch_for_tests(txs);
13793 let balances = bank0.collect_balances(&batch);
13794 assert_eq!(balances.len(), 2);
13795 assert_eq!(balances[0], vec![8, 0, 1]);
13796 assert_eq!(balances[1], vec![8, 11, 1]);
13797 }
13798
13799 #[test]
13800 fn test_pre_post_transaction_balances() {
13801 let (mut genesis_config, _mint_keypair) = create_genesis_config(500_000);
13802 let fee_rate_governor = FeeRateGovernor::new(5000, 0);
13803 genesis_config.fee_rate_governor = fee_rate_governor;
13804 let parent = Arc::new(Bank::new_for_tests(&genesis_config));
13805 let bank0 = Arc::new(new_from_parent(&parent));
13806
13807 let keypair0 = Keypair::new();
13808 let keypair1 = Keypair::new();
13809 let pubkey0 = solana_sdk::pubkey::new_rand();
13810 let pubkey1 = solana_sdk::pubkey::new_rand();
13811 let pubkey2 = solana_sdk::pubkey::new_rand();
13812 let keypair0_account = AccountSharedData::new(8_000, 0, &Pubkey::default());
13813 let keypair1_account = AccountSharedData::new(9_000, 0, &Pubkey::default());
13814 let account0 = AccountSharedData::new(11_000, 0, &Pubkey::default());
13815 bank0.store_account(&keypair0.pubkey(), &keypair0_account);
13816 bank0.store_account(&keypair1.pubkey(), &keypair1_account);
13817 bank0.store_account(&pubkey0, &account0);
13818
13819 let blockhash = bank0.last_blockhash();
13820
13821 let tx0 = system_transaction::transfer(&keypair0, &pubkey0, 2_000, blockhash);
13822 let tx1 = system_transaction::transfer(&Keypair::new(), &pubkey1, 2_000, blockhash);
13823 let tx2 = system_transaction::transfer(&keypair1, &pubkey2, 12_000, blockhash);
13824 let txs = vec![tx0, tx1, tx2];
13825
13826 let lock_result = bank0.prepare_batch_for_tests(txs);
13827 let (transaction_results, transaction_balances_set) = bank0
13828 .load_execute_and_commit_transactions(
13829 &lock_result,
13830 MAX_PROCESSING_AGE,
13831 true,
13832 false,
13833 false,
13834 false,
13835 &mut ExecuteTimings::default(),
13836 None,
13837 );
13838
13839 assert_eq!(transaction_balances_set.pre_balances.len(), 3);
13840 assert_eq!(transaction_balances_set.post_balances.len(), 3);
13841
13842 assert!(transaction_results.execution_results[0].was_executed_successfully());
13843 assert_eq!(
13844 transaction_balances_set.pre_balances[0],
13845 vec![8_000, 11_000, 1]
13846 );
13847 assert_eq!(
13848 transaction_balances_set.post_balances[0],
13849 vec![1_000, 13_000, 1]
13850 );
13851
13852 assert!(matches!(
13855 transaction_results.execution_results[1],
13856 TransactionExecutionResult::NotExecuted(TransactionError::AccountNotFound),
13857 ));
13858 assert_eq!(transaction_balances_set.pre_balances[1], vec![0, 0, 1]);
13859 assert_eq!(transaction_balances_set.post_balances[1], vec![0, 0, 1]);
13860
13861 assert!(matches!(
13864 transaction_results.execution_results[2],
13865 TransactionExecutionResult::Executed {
13866 details: TransactionExecutionDetails {
13867 status: Err(TransactionError::InstructionError(
13868 0,
13869 InstructionError::Custom(1),
13870 )),
13871 ..
13872 },
13873 ..
13874 },
13875 ));
13876 assert_eq!(transaction_balances_set.pre_balances[2], vec![9_000, 0, 1]);
13877 assert_eq!(transaction_balances_set.post_balances[2], vec![4_000, 0, 1]);
13878 }
13879
13880 #[test]
13881 fn test_transaction_with_duplicate_accounts_in_instruction() {
13882 let (genesis_config, mint_keypair) = create_genesis_config(500);
13883 let mut bank = Bank::new_for_tests(&genesis_config);
13884
13885 fn mock_process_instruction(
13886 _first_instruction_account: usize,
13887 invoke_context: &mut InvokeContext,
13888 ) -> result::Result<(), InstructionError> {
13889 let transaction_context = &invoke_context.transaction_context;
13890 let instruction_context = transaction_context.get_current_instruction_context()?;
13891 let instruction_data = instruction_context.get_instruction_data();
13892 let lamports = u64::from_le_bytes(instruction_data.try_into().unwrap());
13893 instruction_context
13894 .try_borrow_instruction_account(transaction_context, 2)?
13895 .checked_sub_lamports(lamports)?;
13896 instruction_context
13897 .try_borrow_instruction_account(transaction_context, 1)?
13898 .checked_add_lamports(lamports)?;
13899 instruction_context
13900 .try_borrow_instruction_account(transaction_context, 0)?
13901 .checked_sub_lamports(lamports)?;
13902 instruction_context
13903 .try_borrow_instruction_account(transaction_context, 1)?
13904 .checked_add_lamports(lamports)?;
13905 Ok(())
13906 }
13907
13908 let mock_program_id = Pubkey::from([2u8; 32]);
13909 bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
13910
13911 let from_pubkey = solana_sdk::pubkey::new_rand();
13912 let to_pubkey = solana_sdk::pubkey::new_rand();
13913 let dup_pubkey = from_pubkey;
13914 let from_account = AccountSharedData::new(sol_to_lamports(100.), 1, &mock_program_id);
13915 let to_account = AccountSharedData::new(0, 1, &mock_program_id);
13916 bank.store_account(&from_pubkey, &from_account);
13917 bank.store_account(&to_pubkey, &to_account);
13918
13919 let account_metas = vec![
13920 AccountMeta::new(from_pubkey, false),
13921 AccountMeta::new(to_pubkey, false),
13922 AccountMeta::new(dup_pubkey, false),
13923 ];
13924 let instruction =
13925 Instruction::new_with_bincode(mock_program_id, &sol_to_lamports(10.), account_metas);
13926 let tx = Transaction::new_signed_with_payer(
13927 &[instruction],
13928 Some(&mint_keypair.pubkey()),
13929 &[&mint_keypair],
13930 bank.last_blockhash(),
13931 );
13932
13933 let result = bank.process_transaction(&tx);
13934 assert_eq!(result, Ok(()));
13935 assert_eq!(bank.get_balance(&from_pubkey), sol_to_lamports(80.));
13936 assert_eq!(bank.get_balance(&to_pubkey), sol_to_lamports(20.));
13937 }
13938
13939 #[test]
13940 fn test_transaction_with_program_ids_passed_to_programs() {
13941 let (genesis_config, mint_keypair) = create_genesis_config(500);
13942 let mut bank = Bank::new_for_tests(&genesis_config);
13943
13944 #[allow(clippy::unnecessary_wraps)]
13945 fn mock_process_instruction(
13946 _first_instruction_account: usize,
13947 _invoke_context: &mut InvokeContext,
13948 ) -> result::Result<(), InstructionError> {
13949 Ok(())
13950 }
13951
13952 let mock_program_id = Pubkey::from([2u8; 32]);
13953 bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
13954
13955 let from_pubkey = solana_sdk::pubkey::new_rand();
13956 let to_pubkey = solana_sdk::pubkey::new_rand();
13957 let dup_pubkey = from_pubkey;
13958 let from_account = AccountSharedData::new(100, 1, &mock_program_id);
13959 let to_account = AccountSharedData::new(0, 1, &mock_program_id);
13960 bank.store_account(&from_pubkey, &from_account);
13961 bank.store_account(&to_pubkey, &to_account);
13962
13963 let account_metas = vec![
13964 AccountMeta::new(from_pubkey, false),
13965 AccountMeta::new(to_pubkey, false),
13966 AccountMeta::new(dup_pubkey, false),
13967 AccountMeta::new(mock_program_id, false),
13968 ];
13969 let instruction = Instruction::new_with_bincode(mock_program_id, &10, account_metas);
13970 let tx = Transaction::new_signed_with_payer(
13971 &[instruction],
13972 Some(&mint_keypair.pubkey()),
13973 &[&mint_keypair],
13974 bank.last_blockhash(),
13975 );
13976
13977 let result = bank.process_transaction(&tx);
13978 assert_eq!(result, Ok(()));
13979 }
13980
13981 #[test]
13982 fn test_account_ids_after_program_ids() {
13983 solana_logger::setup();
13984 let (genesis_config, mint_keypair) = create_genesis_config(500);
13985 let mut bank = Bank::new_for_tests(&genesis_config);
13986
13987 let from_pubkey = solana_sdk::pubkey::new_rand();
13988 let to_pubkey = solana_sdk::pubkey::new_rand();
13989
13990 let account_metas = vec![
13991 AccountMeta::new(from_pubkey, false),
13992 AccountMeta::new(to_pubkey, false),
13993 ];
13994
13995 let instruction =
13996 Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
13997 let mut tx = Transaction::new_signed_with_payer(
13998 &[instruction],
13999 Some(&mint_keypair.pubkey()),
14000 &[&mint_keypair],
14001 bank.last_blockhash(),
14002 );
14003
14004 tx.message.account_keys.push(solana_sdk::pubkey::new_rand());
14005
14006 bank.add_builtin(
14007 "mock_vote",
14008 &solana_vote_program::id(),
14009 mock_ok_vote_processor,
14010 );
14011 let result = bank.process_transaction(&tx);
14012 assert_eq!(result, Ok(()));
14013 let account = bank.get_account(&solana_vote_program::id()).unwrap();
14014 info!("account: {:?}", account);
14015 assert!(account.executable());
14016 }
14017
14018 #[test]
14019 fn test_incinerator() {
14020 let (genesis_config, mint_keypair) = create_genesis_config(1_000_000_000_000);
14021 let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
14022
14023 let bank = Bank::new_from_parent(
14025 &bank0,
14026 &Pubkey::default(),
14027 genesis_config.epoch_schedule.first_normal_slot,
14028 );
14029 let pre_capitalization = bank.capitalization();
14030
14031 let burn_amount = bank.get_minimum_balance_for_rent_exemption(0) - 1;
14033
14034 assert_eq!(bank.get_balance(&incinerator::id()), 0);
14035 bank.transfer(burn_amount, &mint_keypair, &incinerator::id())
14036 .unwrap();
14037 assert_eq!(bank.get_balance(&incinerator::id()), burn_amount);
14038 bank.freeze();
14039 assert_eq!(bank.get_balance(&incinerator::id()), 0);
14040
14041 assert_eq!(bank.capitalization(), pre_capitalization - burn_amount);
14044 }
14045
14046 #[test]
14047 fn test_duplicate_account_key() {
14048 solana_logger::setup();
14049 let (genesis_config, mint_keypair) = create_genesis_config(500);
14050 let mut bank = Bank::new_for_tests(&genesis_config);
14051
14052 let from_pubkey = solana_sdk::pubkey::new_rand();
14053 let to_pubkey = solana_sdk::pubkey::new_rand();
14054
14055 let account_metas = vec![
14056 AccountMeta::new(from_pubkey, false),
14057 AccountMeta::new(to_pubkey, false),
14058 ];
14059
14060 bank.add_builtin(
14061 "mock_vote",
14062 &solana_vote_program::id(),
14063 mock_ok_vote_processor,
14064 );
14065
14066 let instruction =
14067 Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
14068 let mut tx = Transaction::new_signed_with_payer(
14069 &[instruction],
14070 Some(&mint_keypair.pubkey()),
14071 &[&mint_keypair],
14072 bank.last_blockhash(),
14073 );
14074 tx.message.account_keys.push(from_pubkey);
14075
14076 let result = bank.process_transaction(&tx);
14077 assert_eq!(result, Err(TransactionError::AccountLoadedTwice));
14078 }
14079
14080 #[test]
14081 fn test_process_transaction_with_too_many_account_locks() {
14082 solana_logger::setup();
14083 let (genesis_config, mint_keypair) = create_genesis_config(500);
14084 let mut bank = Bank::new_for_tests(&genesis_config);
14085
14086 let from_pubkey = solana_sdk::pubkey::new_rand();
14087 let to_pubkey = solana_sdk::pubkey::new_rand();
14088
14089 let account_metas = vec![
14090 AccountMeta::new(from_pubkey, false),
14091 AccountMeta::new(to_pubkey, false),
14092 ];
14093
14094 bank.add_builtin(
14095 "mock_vote",
14096 &solana_vote_program::id(),
14097 mock_ok_vote_processor,
14098 );
14099
14100 let instruction =
14101 Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
14102 let mut tx = Transaction::new_signed_with_payer(
14103 &[instruction],
14104 Some(&mint_keypair.pubkey()),
14105 &[&mint_keypair],
14106 bank.last_blockhash(),
14107 );
14108
14109 let transaction_account_lock_limit = bank.get_transaction_account_lock_limit();
14110 while tx.message.account_keys.len() <= transaction_account_lock_limit {
14111 tx.message.account_keys.push(solana_sdk::pubkey::new_rand());
14112 }
14113
14114 let result = bank.process_transaction(&tx);
14115 assert_eq!(result, Err(TransactionError::TooManyAccountLocks));
14116 }
14117
14118 #[test]
14119 fn test_program_id_as_payer() {
14120 solana_logger::setup();
14121 let (genesis_config, mint_keypair) = create_genesis_config(500);
14122 let mut bank = Bank::new_for_tests(&genesis_config);
14123
14124 let from_pubkey = solana_sdk::pubkey::new_rand();
14125 let to_pubkey = solana_sdk::pubkey::new_rand();
14126
14127 let account_metas = vec![
14128 AccountMeta::new(from_pubkey, false),
14129 AccountMeta::new(to_pubkey, false),
14130 ];
14131
14132 bank.add_builtin(
14133 "mock_vote",
14134 &solana_vote_program::id(),
14135 mock_ok_vote_processor,
14136 );
14137
14138 let instruction =
14139 Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
14140 let mut tx = Transaction::new_signed_with_payer(
14141 &[instruction],
14142 Some(&mint_keypair.pubkey()),
14143 &[&mint_keypair],
14144 bank.last_blockhash(),
14145 );
14146
14147 info!(
14148 "mint: {} account keys: {:?}",
14149 mint_keypair.pubkey(),
14150 tx.message.account_keys
14151 );
14152 assert_eq!(tx.message.account_keys.len(), 4);
14153 tx.message.account_keys.clear();
14154 tx.message.account_keys.push(solana_vote_program::id());
14155 tx.message.account_keys.push(mint_keypair.pubkey());
14156 tx.message.account_keys.push(from_pubkey);
14157 tx.message.account_keys.push(to_pubkey);
14158 tx.message.instructions[0].program_id_index = 0;
14159 tx.message.instructions[0].accounts.clear();
14160 tx.message.instructions[0].accounts.push(2);
14161 tx.message.instructions[0].accounts.push(3);
14162
14163 let result = bank.process_transaction(&tx);
14164 assert_eq!(result, Err(TransactionError::SanitizeFailure));
14165 }
14166
14167 #[allow(clippy::unnecessary_wraps)]
14168 fn mock_ok_vote_processor(
14169 _first_instruction_account: usize,
14170 _invoke_context: &mut InvokeContext,
14171 ) -> std::result::Result<(), InstructionError> {
14172 Ok(())
14173 }
14174
14175 #[test]
14176 fn test_ref_account_key_after_program_id() {
14177 let (genesis_config, mint_keypair) = create_genesis_config(500);
14178 let mut bank = Bank::new_for_tests(&genesis_config);
14179
14180 let from_pubkey = solana_sdk::pubkey::new_rand();
14181 let to_pubkey = solana_sdk::pubkey::new_rand();
14182
14183 let account_metas = vec![
14184 AccountMeta::new(from_pubkey, false),
14185 AccountMeta::new(to_pubkey, false),
14186 ];
14187
14188 bank.add_builtin(
14189 "mock_vote",
14190 &solana_vote_program::id(),
14191 mock_ok_vote_processor,
14192 );
14193
14194 let instruction =
14195 Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
14196 let mut tx = Transaction::new_signed_with_payer(
14197 &[instruction],
14198 Some(&mint_keypair.pubkey()),
14199 &[&mint_keypair],
14200 bank.last_blockhash(),
14201 );
14202
14203 tx.message.account_keys.push(solana_sdk::pubkey::new_rand());
14204 assert_eq!(tx.message.account_keys.len(), 5);
14205 tx.message.instructions[0].accounts.remove(0);
14206 tx.message.instructions[0].accounts.push(4);
14207
14208 let result = bank.process_transaction(&tx);
14209 assert_eq!(result, Ok(()));
14210 }
14211
14212 #[test]
14213 fn test_fuzz_instructions() {
14214 solana_logger::setup();
14215 use rand::{thread_rng, Rng};
14216 let mut bank = create_simple_test_bank(1_000_000_000);
14217
14218 let max_programs = 5;
14219 let program_keys: Vec<_> = (0..max_programs)
14220 .enumerate()
14221 .map(|i| {
14222 let key = solana_sdk::pubkey::new_rand();
14223 let name = format!("program{:?}", i);
14224 bank.add_builtin(&name, &key, mock_ok_vote_processor);
14225 (key, name.as_bytes().to_vec())
14226 })
14227 .collect();
14228 let max_keys = 100;
14229 let keys: Vec<_> = (0..max_keys)
14230 .enumerate()
14231 .map(|_| {
14232 let key = solana_sdk::pubkey::new_rand();
14233 let balance = if thread_rng().gen_ratio(9, 10) {
14234 let lamports = if thread_rng().gen_ratio(1, 5) {
14235 thread_rng().gen_range(0, 10)
14236 } else {
14237 thread_rng().gen_range(20, 100)
14238 };
14239 let space = thread_rng().gen_range(0, 10);
14240 let owner = Pubkey::default();
14241 let account = AccountSharedData::new(lamports, space, &owner);
14242 bank.store_account(&key, &account);
14243 lamports
14244 } else {
14245 0
14246 };
14247 (key, balance)
14248 })
14249 .collect();
14250 let mut results = HashMap::new();
14251 for _ in 0..2_000 {
14252 let num_keys = if thread_rng().gen_ratio(1, 5) {
14253 thread_rng().gen_range(0, max_keys)
14254 } else {
14255 thread_rng().gen_range(1, 4)
14256 };
14257 let num_instructions = thread_rng().gen_range(0, max_keys - num_keys);
14258
14259 let mut account_keys: Vec<_> = if thread_rng().gen_ratio(1, 5) {
14260 (0..num_keys)
14261 .map(|_| {
14262 let idx = thread_rng().gen_range(0, keys.len());
14263 keys[idx].0
14264 })
14265 .collect()
14266 } else {
14267 let mut inserted = HashSet::new();
14268 (0..num_keys)
14269 .map(|_| {
14270 let mut idx;
14271 loop {
14272 idx = thread_rng().gen_range(0, keys.len());
14273 if !inserted.contains(&idx) {
14274 break;
14275 }
14276 }
14277 inserted.insert(idx);
14278 keys[idx].0
14279 })
14280 .collect()
14281 };
14282
14283 let instructions: Vec<_> = if num_keys > 0 {
14284 (0..num_instructions)
14285 .map(|_| {
14286 let num_accounts_to_pass = thread_rng().gen_range(0, num_keys);
14287 let account_indexes = (0..num_accounts_to_pass)
14288 .map(|_| thread_rng().gen_range(0, num_keys))
14289 .collect();
14290 let program_index: u8 = thread_rng().gen_range(0, num_keys) as u8;
14291 if thread_rng().gen_ratio(4, 5) {
14292 let programs_index = thread_rng().gen_range(0, program_keys.len());
14293 account_keys[program_index as usize] = program_keys[programs_index].0;
14294 }
14295 CompiledInstruction::new(program_index, &10, account_indexes)
14296 })
14297 .collect()
14298 } else {
14299 vec![]
14300 };
14301
14302 let account_keys_len = std::cmp::max(account_keys.len(), 2);
14303 let num_signatures = if thread_rng().gen_ratio(1, 5) {
14304 thread_rng().gen_range(0, account_keys_len + 10)
14305 } else {
14306 thread_rng().gen_range(1, account_keys_len)
14307 };
14308
14309 let num_required_signatures = if thread_rng().gen_ratio(1, 5) {
14310 thread_rng().gen_range(0, account_keys_len + 10) as u8
14311 } else {
14312 thread_rng().gen_range(1, std::cmp::max(2, num_signatures)) as u8
14313 };
14314 let num_readonly_signed_accounts = if thread_rng().gen_ratio(1, 5) {
14315 thread_rng().gen_range(0, account_keys_len) as u8
14316 } else {
14317 let max = if num_required_signatures > 1 {
14318 num_required_signatures - 1
14319 } else {
14320 1
14321 };
14322 thread_rng().gen_range(0, max) as u8
14323 };
14324
14325 let num_readonly_unsigned_accounts = if thread_rng().gen_ratio(1, 5)
14326 || (num_required_signatures as usize) >= account_keys_len
14327 {
14328 thread_rng().gen_range(0, account_keys_len) as u8
14329 } else {
14330 thread_rng().gen_range(0, account_keys_len - num_required_signatures as usize) as u8
14331 };
14332
14333 let header = MessageHeader {
14334 num_required_signatures,
14335 num_readonly_signed_accounts,
14336 num_readonly_unsigned_accounts,
14337 };
14338 let message = Message {
14339 header,
14340 account_keys,
14341 recent_blockhash: bank.last_blockhash(),
14342 instructions,
14343 };
14344
14345 let tx = Transaction {
14346 signatures: vec![Signature::default(); num_signatures],
14347 message,
14348 };
14349
14350 let result = bank.process_transaction(&tx);
14351 for (key, balance) in &keys {
14352 assert_eq!(bank.get_balance(key), *balance);
14353 }
14354 for (key, name) in &program_keys {
14355 let account = bank.get_account(key).unwrap();
14356 assert!(account.executable());
14357 assert_eq!(account.data(), name);
14358 }
14359 info!("result: {:?}", result);
14360 let result_key = format!("{:?}", result);
14361 *results.entry(result_key).or_insert(0) += 1;
14362 }
14363 info!("results: {:?}", results);
14364 }
14365
14366 #[test]
14367 fn test_bank_hash_consistency() {
14368 solana_logger::setup();
14369
14370 let mut genesis_config = GenesisConfig::new(
14371 &[(
14372 Pubkey::from([42; 32]),
14373 AccountSharedData::new(1_000_000_000_000, 0, &system_program::id()),
14374 )],
14375 &[],
14376 );
14377 genesis_config.creation_time = 0;
14378 genesis_config.cluster_type = ClusterType::MainnetBeta;
14379 genesis_config.rent.burn_percent = 100;
14380 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
14381 assert_eq!(bank.get_slots_in_epoch(0), 32);
14383 loop {
14384 goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
14385 if bank.slot == 0 {
14386 assert_eq!(
14387 bank.hash().to_string(),
14388 "9tLrxkBoNE7zEUZ2g72ZwE4fTfhUQnhC8A4Xt4EmYhP1"
14389 );
14390 }
14391 if bank.slot == 32 {
14392 assert_eq!(
14393 bank.hash().to_string(),
14394 "AxphC8xDj9gmFosor5gyiovNvPVMydJCFRUTxn2wFiQf"
14395 );
14396 }
14397 if bank.slot == 64 {
14398 assert_eq!(
14399 bank.hash().to_string(),
14400 "4vZCSbBuL8xjE43rCy9Cm3dCh1BMj45heMiMb6n6qgzA"
14401 );
14402 }
14403 if bank.slot == 128 {
14404 assert_eq!(
14405 bank.hash().to_string(),
14406 "46LUpeBdJuisnfwgYisvh4x7jnxzBaLfHF614GtcTs59"
14407 );
14408 break;
14409 }
14410 bank = Arc::new(new_from_parent(&bank));
14411 }
14412 }
14413
14414 #[test]
14415 fn test_same_program_id_uses_unqiue_executable_accounts() {
14416 fn nested_processor(
14417 _first_instruction_account: usize,
14418 invoke_context: &mut InvokeContext,
14419 ) -> result::Result<(), InstructionError> {
14420 let transaction_context = &invoke_context.transaction_context;
14421 let instruction_context = transaction_context.get_current_instruction_context()?;
14422 let _ = instruction_context
14423 .try_borrow_program_account(transaction_context, 1)?
14424 .checked_add_lamports(1);
14425 Ok(())
14426 }
14427
14428 let (genesis_config, mint_keypair) = create_genesis_config(50000);
14429 let mut bank = Bank::new_for_tests(&genesis_config);
14430
14431 let program1_pubkey = solana_sdk::pubkey::new_rand();
14433 bank.add_builtin("program", &program1_pubkey, nested_processor);
14434
14435 let program2_pubkey = solana_sdk::pubkey::new_rand();
14437 let mut program2_account = AccountSharedData::new(42, 1, &program1_pubkey);
14438 program2_account.set_executable(true);
14439 bank.store_account(&program2_pubkey, &program2_account);
14440
14441 let instruction = Instruction::new_with_bincode(program2_pubkey, &10, vec![]);
14442 let tx = Transaction::new_signed_with_payer(
14443 &[instruction.clone(), instruction],
14444 Some(&mint_keypair.pubkey()),
14445 &[&mint_keypair],
14446 bank.last_blockhash(),
14447 );
14448 assert!(bank.process_transaction(&tx).is_ok());
14449 assert_eq!(1, bank.get_balance(&program1_pubkey));
14450 assert_eq!(42, bank.get_balance(&program2_pubkey));
14451 }
14452
14453 fn get_shrink_account_size() -> usize {
14454 let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000_000);
14455
14456 let mut bank0 = Arc::new(Bank::new_with_config_for_tests(
14459 &genesis_config,
14460 AccountSecondaryIndexes::default(),
14461 false,
14462 AccountShrinkThreshold::default(),
14463 ));
14464 bank0.restore_old_behavior_for_fragile_tests();
14465 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank0).unwrap());
14466 bank0.freeze();
14467 bank0.squash();
14468
14469 let sizes = bank0
14470 .rc
14471 .accounts
14472 .scan_slot(0, |stored_account| Some(stored_account.stored_size()));
14473
14474 let bank0_total_size: usize = sizes.into_iter().sum();
14477 let pubkey0_size = (bank0_total_size as f64 / (1.0 - DEFAULT_ACCOUNTS_SHRINK_RATIO)).ceil();
14478 assert!(
14479 pubkey0_size / (pubkey0_size + bank0_total_size as f64) > DEFAULT_ACCOUNTS_SHRINK_RATIO
14480 );
14481 pubkey0_size as usize
14482 }
14483
14484 #[test]
14485 fn test_clean_nonrooted() {
14486 solana_logger::setup();
14487
14488 let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000_000);
14489 let pubkey0 = Pubkey::from([0; 32]);
14490 let pubkey1 = Pubkey::from([1; 32]);
14491
14492 info!("pubkey0: {}", pubkey0);
14493 info!("pubkey1: {}", pubkey1);
14494
14495 let mut bank0 = Arc::new(Bank::new_with_config_for_tests(
14497 &genesis_config,
14498 AccountSecondaryIndexes::default(),
14499 true,
14500 AccountShrinkThreshold::default(),
14501 ));
14502
14503 let account_zero = AccountSharedData::new(0, 0, &Pubkey::new_unique());
14504
14505 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank0).unwrap());
14506 bank0.freeze();
14507 bank0.squash();
14508 bank0.force_flush_accounts_cache();
14511
14512 let some_lamports = 123;
14514 let mut bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1));
14515 bank1.deposit(&pubkey0, some_lamports).unwrap();
14516 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank1).unwrap());
14517 bank1.freeze();
14518 bank1.flush_accounts_cache_slot();
14519
14520 bank1.print_accounts_stats();
14521
14522 let mut bank2 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 2));
14525 bank2.deposit(&pubkey1, some_lamports).unwrap();
14526 bank2.store_account(&pubkey0, &account_zero);
14527 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank2).unwrap());
14528 bank2.freeze();
14529 bank2.squash();
14530 bank2.force_flush_accounts_cache();
14531
14532 bank2.print_accounts_stats();
14533 drop(bank1);
14534
14535 bank2.clean_accounts(false, false, None);
14538
14539 let mut bank3 = Arc::new(Bank::new_from_parent(&bank2, &Pubkey::default(), 3));
14540 bank3.deposit(&pubkey1, some_lamports + 1).unwrap();
14541 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank3).unwrap());
14542 bank3.freeze();
14543 bank3.squash();
14544 bank3.force_flush_accounts_cache();
14545
14546 bank3.clean_accounts(false, false, None);
14547 assert_eq!(
14548 bank3.rc.accounts.accounts_db.ref_count_for_pubkey(&pubkey0),
14549 2
14550 );
14551 assert!(bank3
14552 .rc
14553 .accounts
14554 .accounts_db
14555 .storage
14556 .get_slot_stores(1)
14557 .is_none());
14558
14559 bank3.print_accounts_stats();
14560 }
14561
14562 #[test]
14563 fn test_shrink_candidate_slots_cached() {
14564 solana_logger::setup();
14565
14566 let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000_000);
14567 let pubkey0 = solana_sdk::pubkey::new_rand();
14568 let pubkey1 = solana_sdk::pubkey::new_rand();
14569 let pubkey2 = solana_sdk::pubkey::new_rand();
14570
14571 let mut bank0 = Arc::new(Bank::new_with_config_for_tests(
14573 &genesis_config,
14574 AccountSecondaryIndexes::default(),
14575 true,
14576 AccountShrinkThreshold::default(),
14577 ));
14578 bank0.restore_old_behavior_for_fragile_tests();
14579
14580 let pubkey0_size = get_shrink_account_size();
14581
14582 let account0 = AccountSharedData::new(1000, pubkey0_size as usize, &Pubkey::new_unique());
14583 bank0.store_account(&pubkey0, &account0);
14584
14585 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank0).unwrap());
14586 bank0.freeze();
14587 bank0.squash();
14588 bank0.force_flush_accounts_cache();
14591
14592 let some_lamports = 123;
14594 let mut bank1 = Arc::new(new_from_parent(&bank0));
14595 bank1.deposit(&pubkey1, some_lamports).unwrap();
14596 bank1.deposit(&pubkey2, some_lamports).unwrap();
14597 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank1).unwrap());
14598 bank1.freeze();
14599 bank1.squash();
14600 bank1.force_flush_accounts_cache();
14603
14604 let mut bank2 = Arc::new(new_from_parent(&bank1));
14606 bank2.deposit(&pubkey1, some_lamports).unwrap();
14607 bank2.store_account(&pubkey0, &account0);
14608 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank2).unwrap());
14609 bank2.freeze();
14610 bank2.squash();
14611 bank2.force_flush_accounts_cache();
14612
14613 bank2.clean_accounts(false, false, None);
14616
14617 assert_eq!(bank2.shrink_candidate_slots(), 2);
14621 let alive_counts: Vec<usize> = (0..3)
14622 .map(|slot| {
14623 bank2
14624 .rc
14625 .accounts
14626 .accounts_db
14627 .alive_account_count_in_slot(slot)
14628 })
14629 .collect();
14630
14631 assert_eq!(bank2.shrink_candidate_slots(), 0);
14633 assert_eq!(alive_counts, vec![9, 1, 7]);
14635 }
14636
14637 #[test]
14638 fn test_process_stale_slot_with_budget() {
14639 solana_logger::setup();
14640 let pubkey1 = solana_sdk::pubkey::new_rand();
14641 let pubkey2 = solana_sdk::pubkey::new_rand();
14642
14643 let mut bank = create_simple_test_arc_bank(1_000_000_000);
14644 bank.restore_old_behavior_for_fragile_tests();
14645 assert_eq!(bank.process_stale_slot_with_budget(0, 0), 0);
14646 assert_eq!(bank.process_stale_slot_with_budget(133, 0), 133);
14647
14648 assert_eq!(bank.process_stale_slot_with_budget(0, 100), 0);
14649 assert_eq!(bank.process_stale_slot_with_budget(33, 100), 0);
14650 assert_eq!(bank.process_stale_slot_with_budget(133, 100), 33);
14651
14652 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank).unwrap());
14653
14654 bank.squash();
14655
14656 let some_lamports = 123;
14657 let mut bank = Arc::new(new_from_parent(&bank));
14658 bank.deposit(&pubkey1, some_lamports).unwrap();
14659 bank.deposit(&pubkey2, some_lamports).unwrap();
14660
14661 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank).unwrap());
14662
14663 let mut bank = Arc::new(new_from_parent(&bank));
14664 bank.deposit(&pubkey1, some_lamports).unwrap();
14665
14666 goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank).unwrap());
14667
14668 bank.squash();
14669 bank.clean_accounts(false, false, None);
14670 let force_to_return_alive_account = 0;
14671 assert_eq!(
14672 bank.process_stale_slot_with_budget(22, force_to_return_alive_account),
14673 22
14674 );
14675
14676 let consumed_budgets: usize = (0..3)
14677 .map(|_| bank.process_stale_slot_with_budget(0, force_to_return_alive_account))
14678 .sum();
14679 assert_eq!(consumed_budgets, 10);
14681 }
14682
14683 #[test]
14684 fn test_add_builtin_no_overwrite() {
14685 #[allow(clippy::unnecessary_wraps)]
14686 fn mock_ix_processor(
14687 _first_instruction_account: usize,
14688 _invoke_context: &mut InvokeContext,
14689 ) -> std::result::Result<(), InstructionError> {
14690 Ok(())
14691 }
14692
14693 let slot = 123;
14694 let program_id = solana_sdk::pubkey::new_rand();
14695
14696 let mut bank = Arc::new(Bank::new_from_parent(
14697 &create_simple_test_arc_bank(100_000),
14698 &Pubkey::default(),
14699 slot,
14700 ));
14701 assert_eq!(bank.get_account_modified_slot(&program_id), None);
14702
14703 Arc::get_mut(&mut bank).unwrap().add_builtin(
14704 "mock_program",
14705 &program_id,
14706 mock_ix_processor,
14707 );
14708 assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14709
14710 let mut bank = Arc::new(new_from_parent(&bank));
14711 Arc::get_mut(&mut bank).unwrap().add_builtin(
14712 "mock_program",
14713 &program_id,
14714 mock_ix_processor,
14715 );
14716 assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14717 }
14718
14719 #[test]
14720 fn test_add_builtin_loader_no_overwrite() {
14721 #[allow(clippy::unnecessary_wraps)]
14722 fn mock_ix_processor(
14723 _first_instruction_account: usize,
14724 _context: &mut InvokeContext,
14725 ) -> std::result::Result<(), InstructionError> {
14726 Ok(())
14727 }
14728
14729 let slot = 123;
14730 let loader_id = solana_sdk::pubkey::new_rand();
14731
14732 let mut bank = Arc::new(Bank::new_from_parent(
14733 &create_simple_test_arc_bank(100_000),
14734 &Pubkey::default(),
14735 slot,
14736 ));
14737 assert_eq!(bank.get_account_modified_slot(&loader_id), None);
14738
14739 Arc::get_mut(&mut bank)
14740 .unwrap()
14741 .add_builtin("mock_program", &loader_id, mock_ix_processor);
14742 assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot);
14743
14744 let mut bank = Arc::new(new_from_parent(&bank));
14745 Arc::get_mut(&mut bank)
14746 .unwrap()
14747 .add_builtin("mock_program", &loader_id, mock_ix_processor);
14748 assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot);
14749 }
14750
14751 #[test]
14752 fn test_add_builtin_account() {
14753 let (mut genesis_config, _mint_keypair) = create_genesis_config(100_000);
14754 activate_all_features(&mut genesis_config);
14755
14756 let slot = 123;
14757 let program_id = solana_sdk::pubkey::new_rand();
14758
14759 let bank = Arc::new(Bank::new_from_parent(
14760 &Arc::new(Bank::new_for_tests(&genesis_config)),
14761 &Pubkey::default(),
14762 slot,
14763 ));
14764 assert_eq!(bank.get_account_modified_slot(&program_id), None);
14765
14766 assert_capitalization_diff(
14767 &bank,
14768 || bank.add_builtin_account("mock_program", &program_id, false),
14769 |old, new| {
14770 assert_eq!(old + 1, new);
14771 },
14772 );
14773
14774 assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14775
14776 let bank = Arc::new(new_from_parent(&bank));
14777 assert_capitalization_diff(
14778 &bank,
14779 || bank.add_builtin_account("mock_program", &program_id, false),
14780 |old, new| assert_eq!(old, new),
14781 );
14782
14783 assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14784
14785 let bank = Arc::new(new_from_parent(&bank));
14786 assert_capitalization_diff(
14789 &bank,
14790 || bank.add_builtin_account("mock_program v2", &program_id, true),
14791 |old, new| assert_eq!(old, new),
14792 );
14793
14794 assert_eq!(
14795 bank.get_account_modified_slot(&program_id).unwrap().1,
14796 bank.slot()
14797 );
14798
14799 let bank = Arc::new(new_from_parent(&bank));
14800 assert_capitalization_diff(
14801 &bank,
14802 || bank.add_builtin_account("mock_program v2", &program_id, true),
14803 |old, new| assert_eq!(old, new),
14804 );
14805
14806 assert_eq!(
14808 bank.get_account_modified_slot(&program_id).unwrap().1,
14809 bank.parent_slot()
14810 );
14811 }
14812
14813 #[test]
14814 fn test_add_builtin_account_inherited_cap_while_replacing() {
14815 let (genesis_config, mint_keypair) = create_genesis_config(100_000);
14816 let bank = Bank::new_for_tests(&genesis_config);
14817 let program_id = solana_sdk::pubkey::new_rand();
14818
14819 bank.add_builtin_account("mock_program", &program_id, false);
14820 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14821
14822 bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
14824 assert_ne!(bank.capitalization(), bank.calculate_capitalization(true));
14825 bank.deposit(&program_id, 10).unwrap();
14826 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14827
14828 bank.add_builtin_account("mock_program v2", &program_id, true);
14829 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14830 }
14831
14832 #[test]
14833 fn test_add_builtin_account_squatted_while_not_replacing() {
14834 let (genesis_config, mint_keypair) = create_genesis_config(100_000);
14835 let bank = Bank::new_for_tests(&genesis_config);
14836 let program_id = solana_sdk::pubkey::new_rand();
14837
14838 bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
14840 assert_ne!(bank.capitalization(), bank.calculate_capitalization(true));
14841 bank.deposit(&program_id, 10).unwrap();
14842 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14843
14844 bank.add_builtin_account("mock_program", &program_id, false);
14845 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14846 }
14847
14848 #[test]
14849 #[should_panic(
14850 expected = "Can't change frozen bank by adding not-existing new builtin \
14851 program (mock_program, EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK). \
14852 Maybe, inconsistent program activation is detected on snapshot restore?"
14853 )]
14854 fn test_add_builtin_account_after_frozen() {
14855 let slot = 123;
14856 let program_id = Pubkey::from_str("EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK").unwrap();
14857
14858 let bank = Bank::new_from_parent(
14859 &create_simple_test_arc_bank(100_000),
14860 &Pubkey::default(),
14861 slot,
14862 );
14863 bank.freeze();
14864
14865 bank.add_builtin_account("mock_program", &program_id, false);
14866 }
14867
14868 #[test]
14869 #[should_panic(
14870 expected = "There is no account to replace with builtin program (mock_program, \
14871 EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK)."
14872 )]
14873 fn test_add_builtin_account_replace_none() {
14874 let slot = 123;
14875 let program_id = Pubkey::from_str("EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK").unwrap();
14876
14877 let bank = Bank::new_from_parent(
14878 &create_simple_test_arc_bank(100_000),
14879 &Pubkey::default(),
14880 slot,
14881 );
14882
14883 bank.add_builtin_account("mock_program", &program_id, true);
14884 }
14885
14886 #[test]
14887 fn test_add_precompiled_account() {
14888 let (mut genesis_config, _mint_keypair) = create_genesis_config(100_000);
14889 activate_all_features(&mut genesis_config);
14890
14891 let slot = 123;
14892 let program_id = solana_sdk::pubkey::new_rand();
14893
14894 let bank = Arc::new(Bank::new_from_parent(
14895 &Arc::new(Bank::new_for_tests(&genesis_config)),
14896 &Pubkey::default(),
14897 slot,
14898 ));
14899 assert_eq!(bank.get_account_modified_slot(&program_id), None);
14900
14901 assert_capitalization_diff(
14902 &bank,
14903 || bank.add_precompiled_account(&program_id),
14904 |old, new| {
14905 assert_eq!(old + 1, new);
14906 },
14907 );
14908
14909 assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14910
14911 let bank = Arc::new(new_from_parent(&bank));
14912 assert_capitalization_diff(
14913 &bank,
14914 || bank.add_precompiled_account(&program_id),
14915 |old, new| assert_eq!(old, new),
14916 );
14917
14918 assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14919 }
14920
14921 #[test]
14922 fn test_add_precompiled_account_inherited_cap_while_replacing() {
14923 let (genesis_config, mint_keypair) = create_genesis_config(100_000);
14924 let bank = Bank::new_for_tests(&genesis_config);
14925 let program_id = solana_sdk::pubkey::new_rand();
14926
14927 bank.add_precompiled_account(&program_id);
14928 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14929
14930 bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
14932 assert_ne!(bank.capitalization(), bank.calculate_capitalization(true));
14933 bank.deposit(&program_id, 10).unwrap();
14934 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14935
14936 bank.add_precompiled_account(&program_id);
14937 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14938 }
14939
14940 #[test]
14941 fn test_add_precompiled_account_squatted_while_not_replacing() {
14942 let (genesis_config, mint_keypair) = create_genesis_config(100_000);
14943 let bank = Bank::new_for_tests(&genesis_config);
14944 let program_id = solana_sdk::pubkey::new_rand();
14945
14946 bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
14948 assert_ne!(bank.capitalization(), bank.calculate_capitalization(true));
14949 bank.deposit(&program_id, 10).unwrap();
14950 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14951
14952 bank.add_precompiled_account(&program_id);
14953 assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14954 }
14955
14956 #[test]
14957 #[should_panic(
14958 expected = "Can't change frozen bank by adding not-existing new precompiled \
14959 program (EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK). \
14960 Maybe, inconsistent program activation is detected on snapshot restore?"
14961 )]
14962 fn test_add_precompiled_account_after_frozen() {
14963 let slot = 123;
14964 let program_id = Pubkey::from_str("EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK").unwrap();
14965
14966 let bank = Bank::new_from_parent(
14967 &create_simple_test_arc_bank(100_000),
14968 &Pubkey::default(),
14969 slot,
14970 );
14971 bank.freeze();
14972
14973 bank.add_precompiled_account(&program_id);
14974 }
14975
14976 #[test]
14977 fn test_reconfigure_token2_native_mint() {
14978 solana_logger::setup();
14979
14980 let mut genesis_config =
14981 create_genesis_config_with_leader(5, &solana_sdk::pubkey::new_rand(), 0).genesis_config;
14982
14983 assert_eq!(genesis_config.cluster_type, ClusterType::Development);
14985 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
14986 assert_eq!(
14987 bank.get_balance(&inline_safe_token::native_mint::id()),
14988 1000000000
14989 );
14990
14991 genesis_config.cluster_type = ClusterType::Testnet;
14993 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
14994 assert_eq!(bank.get_balance(&inline_safe_token::native_mint::id()), 0);
14995 bank.deposit(&inline_safe_token::native_mint::id(), 4200000000)
14996 .unwrap();
14997
14998 let bank = Bank::new_from_parent(
14999 &bank,
15000 &Pubkey::default(),
15001 genesis_config.epoch_schedule.get_first_slot_in_epoch(93),
15002 );
15003
15004 let native_mint_account = bank
15005 .get_account(&inline_safe_token::native_mint::id())
15006 .unwrap();
15007 assert_eq!(native_mint_account.data().len(), 82);
15008 assert_eq!(
15009 bank.get_balance(&inline_safe_token::native_mint::id()),
15010 4200000000
15011 );
15012 assert_eq!(native_mint_account.owner(), &inline_safe_token::id());
15013
15014 genesis_config.cluster_type = ClusterType::MainnetBeta;
15016 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
15017 assert_eq!(bank.get_balance(&inline_safe_token::native_mint::id()), 0);
15018 bank.deposit(&inline_safe_token::native_mint::id(), 4200000000)
15019 .unwrap();
15020
15021 let bank = Bank::new_from_parent(
15022 &bank,
15023 &Pubkey::default(),
15024 genesis_config.epoch_schedule.get_first_slot_in_epoch(75),
15025 );
15026
15027 let native_mint_account = bank
15028 .get_account(&inline_safe_token::native_mint::id())
15029 .unwrap();
15030 assert_eq!(native_mint_account.data().len(), 82);
15031 assert_eq!(
15032 bank.get_balance(&inline_safe_token::native_mint::id()),
15033 4200000000
15034 );
15035 assert_eq!(native_mint_account.owner(), &inline_safe_token::id());
15036 }
15037
15038 #[test]
15039 fn test_ensure_no_storage_rewards_pool() {
15040 solana_logger::setup();
15041
15042 let mut genesis_config =
15043 create_genesis_config_with_leader(5, &solana_sdk::pubkey::new_rand(), 0).genesis_config;
15044
15045 genesis_config.cluster_type = ClusterType::Testnet;
15048 genesis_config.inflation = Inflation::default();
15049 let reward_pubkey = solana_sdk::pubkey::new_rand();
15050 genesis_config.rewards_pools.insert(
15051 reward_pubkey,
15052 Account::new(u64::MAX, 0, &solana_sdk::pubkey::new_rand()),
15053 );
15054 let bank0 = Bank::new_for_tests(&genesis_config);
15055 bank0.capitalization.fetch_sub(1, Relaxed);
15058 let bank0 = Arc::new(bank0);
15059 assert_eq!(bank0.get_balance(&reward_pubkey), u64::MAX,);
15060
15061 let bank1 = Bank::new_from_parent(
15062 &bank0,
15063 &Pubkey::default(),
15064 genesis_config.epoch_schedule.get_first_slot_in_epoch(93),
15065 );
15066
15067 assert!(bank1.get_account(&reward_pubkey).is_none());
15069 let sysvar_and_builtin_program_delta = 1;
15070 assert_eq!(
15071 bank0.capitalization() + 1 + 1_000_000_000 + sysvar_and_builtin_program_delta,
15072 bank1.capitalization()
15073 );
15074 assert_eq!(bank1.capitalization(), bank1.calculate_capitalization(true));
15075
15076 let bank0 = std::panic::AssertUnwindSafe(bank0);
15079 let overflowing_capitalization =
15080 std::panic::catch_unwind(|| bank0.calculate_capitalization(true));
15081 if let Ok(overflowing_capitalization) = overflowing_capitalization {
15082 info!("asserting overflowing capitalization for bank0");
15083 assert_eq!(overflowing_capitalization, bank0.capitalization());
15084 } else {
15085 info!("NOT-asserting overflowing capitalization for bank0");
15086 }
15087 }
15088
15089 #[derive(Debug)]
15090 struct TestExecutor {}
15091 impl Executor for TestExecutor {
15092 fn execute(
15093 &self,
15094 _first_instruction_account: usize,
15095 _invoke_context: &mut InvokeContext,
15096 ) -> std::result::Result<(), InstructionError> {
15097 Ok(())
15098 }
15099 }
15100
15101 #[test]
15102 fn test_bank_executor_cache() {
15103 solana_logger::setup();
15104
15105 let (genesis_config, _) = create_genesis_config(1);
15106 let bank = Bank::new_for_tests(&genesis_config);
15107
15108 let key1 = solana_sdk::pubkey::new_rand();
15109 let key2 = solana_sdk::pubkey::new_rand();
15110 let key3 = solana_sdk::pubkey::new_rand();
15111 let key4 = solana_sdk::pubkey::new_rand();
15112 let key5 = solana_sdk::pubkey::new_rand();
15113 let executor: Arc<dyn Executor> = Arc::new(TestExecutor {});
15114
15115 fn new_executable_account(owner: Pubkey) -> AccountSharedData {
15116 AccountSharedData::from(Account {
15117 owner,
15118 executable: true,
15119 ..Account::default()
15120 })
15121 }
15122
15123 let accounts = &[
15124 (key1, new_executable_account(bpf_loader_upgradeable::id())),
15125 (key2, new_executable_account(bpf_loader::id())),
15126 (key3, new_executable_account(bpf_loader_deprecated::id())),
15127 (key4, new_executable_account(native_loader::id())),
15128 (key5, AccountSharedData::default()),
15129 ];
15130
15131 let mut executors = Executors::default();
15133 executors.insert(key1, TransactionExecutor::new_cached(executor.clone()));
15134 executors.insert(key2, TransactionExecutor::new_cached(executor.clone()));
15135 executors.insert(key3, TransactionExecutor::new_cached(executor.clone()));
15136 executors.insert(key4, TransactionExecutor::new_cached(executor.clone()));
15137 let executors = Rc::new(RefCell::new(executors));
15138 bank.store_missing_executors(&executors);
15139 bank.store_updated_executors(&executors);
15140 let executors = bank.get_executors(accounts);
15141 assert_eq!(executors.borrow().len(), 0);
15142
15143 let mut executors = Executors::default();
15145 executors.insert(key1, TransactionExecutor::new_miss(executor.clone()));
15146 executors.insert(key2, TransactionExecutor::new_miss(executor.clone()));
15147 executors.insert(key3, TransactionExecutor::new_updated(executor.clone()));
15148 executors.insert(key4, TransactionExecutor::new_miss(executor.clone()));
15149 let executors = Rc::new(RefCell::new(executors));
15150
15151 bank.store_missing_executors(&executors);
15153 let stored_executors = bank.get_executors(accounts);
15154 assert_eq!(stored_executors.borrow().len(), 2);
15155 assert!(stored_executors.borrow().contains_key(&key1));
15156 assert!(stored_executors.borrow().contains_key(&key2));
15157
15158 bank.store_updated_executors(&executors);
15160 let stored_executors = bank.get_executors(accounts);
15161 assert_eq!(stored_executors.borrow().len(), 3);
15162 assert!(stored_executors.borrow().contains_key(&key1));
15163 assert!(stored_executors.borrow().contains_key(&key2));
15164 assert!(stored_executors.borrow().contains_key(&key3));
15165
15166 let bank = Bank::new_from_parent(&Arc::new(bank), &solana_sdk::pubkey::new_rand(), 1);
15168 let executors = bank.get_executors(accounts);
15169 assert_eq!(executors.borrow().len(), 3);
15170 assert!(executors.borrow().contains_key(&key1));
15171 assert!(executors.borrow().contains_key(&key2));
15172 assert!(executors.borrow().contains_key(&key3));
15173
15174 bank.remove_executor(&key1);
15176 bank.remove_executor(&key2);
15177 bank.remove_executor(&key3);
15178 bank.remove_executor(&key4);
15179 let executors = bank.get_executors(accounts);
15180 assert_eq!(executors.borrow().len(), 0);
15181 }
15182
15183 #[test]
15184 fn test_bank_executor_cow() {
15185 solana_logger::setup();
15186
15187 let (genesis_config, _) = create_genesis_config(1);
15188 let root = Arc::new(Bank::new_for_tests(&genesis_config));
15189
15190 let key1 = solana_sdk::pubkey::new_rand();
15191 let key2 = solana_sdk::pubkey::new_rand();
15192 let executor: Arc<dyn Executor> = Arc::new(TestExecutor {});
15193 let executable_account = AccountSharedData::from(Account {
15194 owner: bpf_loader_upgradeable::id(),
15195 executable: true,
15196 ..Account::default()
15197 });
15198
15199 let accounts = &[
15200 (key1, executable_account.clone()),
15201 (key2, executable_account),
15202 ];
15203
15204 let mut executors = Executors::default();
15206 executors.insert(key1, TransactionExecutor::new_miss(executor.clone()));
15207 let executors = Rc::new(RefCell::new(executors));
15208 root.store_missing_executors(&executors);
15209 let executors = root.get_executors(accounts);
15210 assert_eq!(executors.borrow().len(), 1);
15211
15212 let fork1 = Bank::new_from_parent(&root, &Pubkey::default(), 1);
15213 let fork2 = Bank::new_from_parent(&root, &Pubkey::default(), 2);
15214
15215 let executors = fork1.get_executors(accounts);
15216 assert_eq!(executors.borrow().len(), 1);
15217 let executors = fork2.get_executors(accounts);
15218 assert_eq!(executors.borrow().len(), 1);
15219
15220 let mut executors = Executors::default();
15221 executors.insert(key2, TransactionExecutor::new_miss(executor.clone()));
15222 let executors = Rc::new(RefCell::new(executors));
15223 fork1.store_missing_executors(&executors);
15224
15225 let executors = fork1.get_executors(accounts);
15226 assert_eq!(executors.borrow().len(), 2);
15227 let executors = fork2.get_executors(accounts);
15228 assert_eq!(executors.borrow().len(), 1);
15229
15230 fork1.remove_executor(&key1);
15231
15232 let executors = fork1.get_executors(accounts);
15233 assert_eq!(executors.borrow().len(), 1);
15234 let executors = fork2.get_executors(accounts);
15235 assert_eq!(executors.borrow().len(), 1);
15236 }
15237
15238 #[test]
15239 fn test_compute_active_feature_set() {
15240 let bank0 = create_simple_test_arc_bank(100_000);
15241 let mut bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
15242
15243 let test_feature = "TestFeature11111111111111111111111111111111"
15244 .parse::<Pubkey>()
15245 .unwrap();
15246 let mut feature_set = FeatureSet::default();
15247 feature_set.inactive.insert(test_feature);
15248 bank.feature_set = Arc::new(feature_set.clone());
15249
15250 let new_activations = bank.compute_active_feature_set(true);
15251 assert!(new_activations.is_empty());
15252 assert!(!bank.feature_set.is_active(&test_feature));
15253
15254 bank.deposit(&test_feature, 42).unwrap();
15256 let new_activations = bank.compute_active_feature_set(true);
15257 assert!(new_activations.is_empty());
15258 assert!(!bank.feature_set.is_active(&test_feature));
15259
15260 let feature = Feature::default();
15262 assert_eq!(feature.activated_at, None);
15263 bank.store_account(&test_feature, &feature::create_account(&feature, 42));
15264
15265 let new_activations = bank.compute_active_feature_set(false);
15267 assert!(new_activations.is_empty());
15268 assert!(!bank.feature_set.is_active(&test_feature));
15269 let feature = feature::from_account(&bank.get_account(&test_feature).expect("get_account"))
15270 .expect("from_account");
15271 assert_eq!(feature.activated_at, None);
15272
15273 let new_activations = bank.compute_active_feature_set(true);
15275 assert_eq!(new_activations.len(), 1);
15276 assert!(bank.feature_set.is_active(&test_feature));
15277 let feature = feature::from_account(&bank.get_account(&test_feature).expect("get_account"))
15278 .expect("from_account");
15279 assert_eq!(feature.activated_at, Some(1));
15280
15281 bank.feature_set = Arc::new(feature_set);
15283 assert!(!bank.feature_set.is_active(&test_feature));
15284
15285 let new_activations = bank.compute_active_feature_set(true);
15288 assert!(new_activations.is_empty());
15289 assert!(bank.feature_set.is_active(&test_feature));
15290 }
15291
15292 #[test]
15293 fn test_program_replacement() {
15294 let mut bank = create_simple_test_bank(0);
15295
15296 let old_address = Pubkey::new_unique();
15298 let new_address = Pubkey::new_unique();
15299 bank.store_account_and_update_capitalization(
15300 &old_address,
15301 &AccountSharedData::from(Account {
15302 lamports: 100,
15303 ..Account::default()
15304 }),
15305 );
15306 assert_eq!(bank.get_balance(&old_address), 100);
15307
15308 let new_program_account = AccountSharedData::from(Account {
15310 lamports: 123,
15311 ..Account::default()
15312 });
15313 bank.store_account_and_update_capitalization(&new_address, &new_program_account);
15314 assert_eq!(bank.get_balance(&new_address), 123);
15315
15316 let original_capitalization = bank.capitalization();
15317
15318 bank.replace_program_account(&old_address, &new_address, "bank-apply_program_replacement");
15319
15320 assert_eq!(bank.get_balance(&new_address), 0);
15322
15323 assert_eq!(bank.get_account(&old_address), Some(new_program_account));
15325
15326 assert_eq!(bank.capitalization(), original_capitalization - 100);
15328 }
15329
15330 pub fn update_vote_account_timestamp(
15331 timestamp: BlockTimestamp,
15332 bank: &Bank,
15333 vote_pubkey: &Pubkey,
15334 ) {
15335 let mut vote_account = bank.get_account(vote_pubkey).unwrap_or_default();
15336 let mut vote_state = VoteState::from(&vote_account).unwrap_or_default();
15337 vote_state.last_timestamp = timestamp;
15338 let versioned = VoteStateVersions::new_current(vote_state);
15339 VoteState::to(&versioned, &mut vote_account).unwrap();
15340 bank.store_account(vote_pubkey, &vote_account);
15341 }
15342
15343 fn min_rent_excempt_balance_for_sysvars(bank: &Bank, sysvar_ids: &[Pubkey]) -> u64 {
15344 sysvar_ids
15345 .iter()
15346 .map(|sysvar_id| {
15347 trace!("min_rent_excempt_balance_for_sysvars: {}", sysvar_id);
15348 bank.get_minimum_balance_for_rent_exemption(
15349 bank.get_account(sysvar_id).unwrap().data().len(),
15350 )
15351 })
15352 .sum()
15353 }
15354
15355 #[test]
15356 fn test_adjust_sysvar_balance_for_rent() {
15357 let bank = create_simple_test_bank(0);
15358 let mut smaller_sample_sysvar = AccountSharedData::new(1, 0, &Pubkey::default());
15359 assert_eq!(smaller_sample_sysvar.lamports(), 1);
15360 bank.adjust_sysvar_balance_for_rent(&mut smaller_sample_sysvar);
15361 assert_eq!(
15362 smaller_sample_sysvar.lamports(),
15363 bank.get_minimum_balance_for_rent_exemption(smaller_sample_sysvar.data().len()),
15364 );
15365
15366 let mut bigger_sample_sysvar = AccountSharedData::new(
15367 1,
15368 smaller_sample_sysvar.data().len() + 1,
15369 &Pubkey::default(),
15370 );
15371 bank.adjust_sysvar_balance_for_rent(&mut bigger_sample_sysvar);
15372 assert!(smaller_sample_sysvar.lamports() < bigger_sample_sysvar.lamports());
15373
15374 let excess_lamports = smaller_sample_sysvar.lamports() + 999;
15376 smaller_sample_sysvar.set_lamports(excess_lamports);
15377 bank.adjust_sysvar_balance_for_rent(&mut smaller_sample_sysvar);
15378 assert_eq!(smaller_sample_sysvar.lamports(), excess_lamports);
15379 }
15380
15381 #[test]
15382 fn test_update_clock_timestamp() {
15383 let leader_pubkey = solana_sdk::pubkey::new_rand();
15384 let GenesisConfigInfo {
15385 genesis_config,
15386 voting_keypair,
15387 ..
15388 } = create_genesis_config_with_leader(5, &leader_pubkey, 3);
15389 let mut bank = Bank::new_for_tests(&genesis_config);
15390 bank = new_from_parent(&Arc::new(bank));
15392 bank = new_from_parent(&Arc::new(bank));
15393 assert_eq!(
15394 bank.clock().unix_timestamp,
15395 bank.unix_timestamp_from_genesis()
15396 );
15397
15398 bank.update_clock(None);
15399 assert_eq!(
15400 bank.clock().unix_timestamp,
15401 bank.unix_timestamp_from_genesis()
15402 );
15403
15404 update_vote_account_timestamp(
15405 BlockTimestamp {
15406 slot: bank.slot(),
15407 timestamp: bank.unix_timestamp_from_genesis() - 1,
15408 },
15409 &bank,
15410 &voting_keypair.pubkey(),
15411 );
15412 bank.update_clock(None);
15413 assert_eq!(
15414 bank.clock().unix_timestamp,
15415 bank.unix_timestamp_from_genesis()
15416 );
15417
15418 update_vote_account_timestamp(
15419 BlockTimestamp {
15420 slot: bank.slot(),
15421 timestamp: bank.unix_timestamp_from_genesis(),
15422 },
15423 &bank,
15424 &voting_keypair.pubkey(),
15425 );
15426 bank.update_clock(None);
15427 assert_eq!(
15428 bank.clock().unix_timestamp,
15429 bank.unix_timestamp_from_genesis()
15430 );
15431
15432 update_vote_account_timestamp(
15433 BlockTimestamp {
15434 slot: bank.slot(),
15435 timestamp: bank.unix_timestamp_from_genesis() + 1,
15436 },
15437 &bank,
15438 &voting_keypair.pubkey(),
15439 );
15440 bank.update_clock(None);
15441 assert_eq!(
15442 bank.clock().unix_timestamp,
15443 bank.unix_timestamp_from_genesis() + 1
15444 );
15445
15446 bank = new_from_parent(&Arc::new(bank));
15448 update_vote_account_timestamp(
15449 BlockTimestamp {
15450 slot: bank.slot(),
15451 timestamp: bank.unix_timestamp_from_genesis() - 1,
15452 },
15453 &bank,
15454 &voting_keypair.pubkey(),
15455 );
15456 bank.update_clock(None);
15457 assert_eq!(
15458 bank.clock().unix_timestamp,
15459 bank.unix_timestamp_from_genesis()
15460 );
15461 }
15462
15463 fn poh_estimate_offset(bank: &Bank) -> Duration {
15464 let mut epoch_start_slot = bank.epoch_schedule.get_first_slot_in_epoch(bank.epoch());
15465 if epoch_start_slot == bank.slot() {
15466 epoch_start_slot = bank
15467 .epoch_schedule
15468 .get_first_slot_in_epoch(bank.epoch() - 1);
15469 }
15470 bank.slot().saturating_sub(epoch_start_slot) as u32
15471 * Duration::from_nanos(bank.ns_per_slot as u64)
15472 }
15473
15474 #[test]
15475 fn test_timestamp_slow() {
15476 fn max_allowable_delta_since_epoch(bank: &Bank, max_allowable_drift: u32) -> i64 {
15477 let poh_estimate_offset = poh_estimate_offset(bank);
15478 (poh_estimate_offset.as_secs()
15479 + (poh_estimate_offset * max_allowable_drift / 100).as_secs()) as i64
15480 }
15481
15482 let leader_pubkey = solana_sdk::pubkey::new_rand();
15483 let GenesisConfigInfo {
15484 mut genesis_config,
15485 voting_keypair,
15486 ..
15487 } = create_genesis_config_with_leader(5, &leader_pubkey, 3);
15488 let slots_in_epoch = 32;
15489 genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
15490 let mut bank = Bank::new_for_tests(&genesis_config);
15491 let slot_duration = Duration::from_nanos(bank.ns_per_slot as u64);
15492
15493 let recent_timestamp: UnixTimestamp = bank.unix_timestamp_from_genesis();
15494 let additional_secs = ((slot_duration * MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2 * 32) / 100)
15495 .as_secs() as i64
15496 + 1; update_vote_account_timestamp(
15498 BlockTimestamp {
15499 slot: bank.slot(),
15500 timestamp: recent_timestamp + additional_secs,
15501 },
15502 &bank,
15503 &voting_keypair.pubkey(),
15504 );
15505
15506 for _ in 0..31 {
15509 bank = new_from_parent(&Arc::new(bank));
15510 assert_eq!(
15511 bank.clock().unix_timestamp,
15512 bank.clock().epoch_start_timestamp
15513 + max_allowable_delta_since_epoch(
15514 &bank,
15515 MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2
15516 ),
15517 );
15518 assert_eq!(bank.clock().epoch_start_timestamp, recent_timestamp);
15519 }
15520 }
15521
15522 #[test]
15523 fn test_timestamp_fast() {
15524 fn max_allowable_delta_since_epoch(bank: &Bank, max_allowable_drift: u32) -> i64 {
15525 let poh_estimate_offset = poh_estimate_offset(bank);
15526 (poh_estimate_offset.as_secs()
15527 - (poh_estimate_offset * max_allowable_drift / 100).as_secs()) as i64
15528 }
15529
15530 let leader_pubkey = solana_sdk::pubkey::new_rand();
15531 let GenesisConfigInfo {
15532 mut genesis_config,
15533 voting_keypair,
15534 ..
15535 } = create_genesis_config_with_leader(5, &leader_pubkey, 3);
15536 let slots_in_epoch = 32;
15537 genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
15538 let mut bank = Bank::new_for_tests(&genesis_config);
15539
15540 let recent_timestamp: UnixTimestamp = bank.unix_timestamp_from_genesis();
15541 let additional_secs = 5; update_vote_account_timestamp(
15543 BlockTimestamp {
15544 slot: bank.slot(),
15545 timestamp: recent_timestamp - additional_secs,
15546 },
15547 &bank,
15548 &voting_keypair.pubkey(),
15549 );
15550
15551 for _ in 0..31 {
15554 bank = new_from_parent(&Arc::new(bank));
15555 assert_eq!(
15556 bank.clock().unix_timestamp,
15557 bank.clock().epoch_start_timestamp
15558 + max_allowable_delta_since_epoch(&bank, MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST),
15559 );
15560 assert_eq!(bank.clock().epoch_start_timestamp, recent_timestamp);
15561 }
15562 }
15563
15564 #[test]
15565 fn test_program_is_native_loader() {
15566 let (genesis_config, mint_keypair) = create_genesis_config(50000);
15567 let bank = Bank::new_for_tests(&genesis_config);
15568
15569 let tx = Transaction::new_signed_with_payer(
15570 &[Instruction::new_with_bincode(
15571 native_loader::id(),
15572 &(),
15573 vec![],
15574 )],
15575 Some(&mint_keypair.pubkey()),
15576 &[&mint_keypair],
15577 bank.last_blockhash(),
15578 );
15579 assert_eq!(
15580 bank.process_transaction(&tx),
15581 Err(TransactionError::InstructionError(
15582 0,
15583 InstructionError::UnsupportedProgramId
15584 ))
15585 );
15586 }
15587
15588 #[test]
15589 fn test_debug_bank() {
15590 let (genesis_config, _mint_keypair) = create_genesis_config(50000);
15591 let mut bank = Bank::new_for_tests(&genesis_config);
15592 bank.finish_init(&genesis_config, None, false);
15593 let debug = format!("{:#?}", bank);
15594 assert!(!debug.is_empty());
15595 }
15596
15597 #[derive(Debug)]
15598 enum AcceptableScanResults {
15599 DroppedSlotError,
15600 NoFailure,
15601 Both,
15602 }
15603
15604 fn test_store_scan_consistency<F: 'static>(
15605 accounts_db_caching_enabled: bool,
15606 update_f: F,
15607 drop_callback: Option<Box<dyn DropCallback + Send + Sync>>,
15608 acceptable_scan_results: AcceptableScanResults,
15609 ) where
15610 F: Fn(
15611 Arc<Bank>,
15612 crossbeam_channel::Sender<Arc<Bank>>,
15613 crossbeam_channel::Receiver<BankId>,
15614 Arc<HashSet<Pubkey>>,
15615 Pubkey,
15616 u64,
15617 ) + std::marker::Send,
15618 {
15619 solana_logger::setup();
15620 let mut genesis_config = create_genesis_config_with_leader(
15622 10,
15623 &solana_sdk::pubkey::new_rand(),
15624 374_999_998_287_840,
15625 )
15626 .genesis_config;
15627 genesis_config.rent = Rent::free();
15628 let bank0 = Arc::new(Bank::new_with_config_for_tests(
15629 &genesis_config,
15630 AccountSecondaryIndexes::default(),
15631 accounts_db_caching_enabled,
15632 AccountShrinkThreshold::default(),
15633 ));
15634 bank0.set_callback(drop_callback);
15635
15636 let total_pubkeys = ITER_BATCH_SIZE * 10;
15638 let total_pubkeys_to_modify = 10;
15639 let all_pubkeys: Vec<Pubkey> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
15640 .take(total_pubkeys)
15641 .collect();
15642 let program_id = system_program::id();
15643 let starting_lamports = 1;
15644 let starting_account = AccountSharedData::new(starting_lamports, 0, &program_id);
15645
15646 for key in &all_pubkeys {
15648 bank0.store_account(key, &starting_account);
15649 }
15650
15651 let pubkeys_to_modify: Arc<HashSet<Pubkey>> = Arc::new(
15653 all_pubkeys
15654 .into_iter()
15655 .take(total_pubkeys_to_modify)
15656 .collect(),
15657 );
15658 let exit = Arc::new(AtomicBool::new(false));
15659
15660 let pubkeys_to_modify_ = pubkeys_to_modify.clone();
15663
15664 let (bank_to_scan_sender, bank_to_scan_receiver): (
15666 crossbeam_channel::Sender<Arc<Bank>>,
15667 crossbeam_channel::Receiver<Arc<Bank>>,
15668 ) = bounded(1);
15669
15670 let (scan_finished_sender, scan_finished_receiver): (
15671 crossbeam_channel::Sender<BankId>,
15672 crossbeam_channel::Receiver<BankId>,
15673 ) = unbounded();
15674 let num_banks_scanned = Arc::new(AtomicU64::new(0));
15675 let scan_thread = {
15676 let exit = exit.clone();
15677 let num_banks_scanned = num_banks_scanned.clone();
15678 Builder::new()
15679 .name("scan".to_string())
15680 .spawn(move || {
15681 loop {
15682 info!("starting scan iteration");
15683 if exit.load(Relaxed) {
15684 info!("scan exiting");
15685 return;
15686 }
15687 if let Ok(bank_to_scan) =
15688 bank_to_scan_receiver.recv_timeout(Duration::from_millis(10))
15689 {
15690 info!("scanning program accounts for slot {}", bank_to_scan.slot());
15691 let accounts_result = bank_to_scan
15692 .get_program_accounts(&program_id, &ScanConfig::default());
15693 let _ = scan_finished_sender.send(bank_to_scan.bank_id());
15694 num_banks_scanned.fetch_add(1, Relaxed);
15695 match (&acceptable_scan_results, accounts_result.is_err()) {
15696 (AcceptableScanResults::DroppedSlotError, _)
15697 | (AcceptableScanResults::Both, true) => {
15698 assert_eq!(
15699 accounts_result,
15700 Err(ScanError::SlotRemoved {
15701 slot: bank_to_scan.slot(),
15702 bank_id: bank_to_scan.bank_id()
15703 })
15704 );
15705 }
15706 (AcceptableScanResults::NoFailure, _)
15707 | (AcceptableScanResults::Both, false) => {
15708 assert!(accounts_result.is_ok())
15709 }
15710 }
15711
15712 if let Ok(accounts) = accounts_result {
15716 assert!(!accounts.is_empty());
15717 let mut expected_lamports = None;
15718 let mut target_accounts_found = HashSet::new();
15719 for (pubkey, account) in accounts {
15720 let account_balance = account.lamports();
15721 if pubkeys_to_modify_.contains(&pubkey) {
15722 target_accounts_found.insert(pubkey);
15723 if let Some(expected_lamports) = expected_lamports {
15724 assert_eq!(account_balance, expected_lamports);
15725 } else {
15726 expected_lamports = Some(account_balance);
15728 }
15729 }
15730 }
15731
15732 assert_eq!(target_accounts_found.len(), total_pubkeys_to_modify);
15735 }
15736 }
15737 }
15738 })
15739 .unwrap()
15740 };
15741
15742 let update_thread = Builder::new()
15745 .name("update".to_string())
15746 .spawn(move || {
15747 update_f(
15748 bank0,
15749 bank_to_scan_sender,
15750 scan_finished_receiver,
15751 pubkeys_to_modify,
15752 program_id,
15753 starting_lamports,
15754 );
15755 })
15756 .unwrap();
15757
15758 let min_expected_number_of_scans = 5;
15760 std::thread::sleep(Duration::new(5, 0));
15761 let mut remaining_loops = 2000;
15764 loop {
15765 if num_banks_scanned.load(Relaxed) > min_expected_number_of_scans {
15766 break;
15767 } else {
15768 std::thread::sleep(Duration::from_millis(100));
15769 }
15770 remaining_loops -= 1;
15771 if remaining_loops == 0 {
15772 break; }
15774 }
15775 exit.store(true, Relaxed);
15776 scan_thread.join().unwrap();
15777 update_thread.join().unwrap();
15778 assert!(remaining_loops > 0, "test timed out");
15779 }
15780
15781 #[test]
15782 fn test_store_scan_consistency_unrooted() {
15783 for accounts_db_caching_enabled in &[false, true] {
15784 let (pruned_banks_sender, pruned_banks_receiver) = unbounded();
15785 let abs_request_handler = AbsRequestHandler {
15786 snapshot_request_handler: None,
15787 pruned_banks_receiver,
15788 };
15789 test_store_scan_consistency(
15790 *accounts_db_caching_enabled,
15791 move |bank0,
15792 bank_to_scan_sender,
15793 _scan_finished_receiver,
15794 pubkeys_to_modify,
15795 program_id,
15796 starting_lamports| {
15797 let mut current_major_fork_bank = bank0;
15798 loop {
15799 let mut current_minor_fork_bank = current_major_fork_bank.clone();
15800 let num_new_banks = 2;
15801 let lamports = current_minor_fork_bank.slot() + starting_lamports + 1;
15802 for pubkeys_to_modify in &pubkeys_to_modify
15804 .iter()
15805 .chunks(pubkeys_to_modify.len() / num_new_banks)
15806 {
15807 current_minor_fork_bank = Arc::new(Bank::new_from_parent(
15808 ¤t_minor_fork_bank,
15809 &solana_sdk::pubkey::new_rand(),
15810 current_minor_fork_bank.slot() + 2,
15811 ));
15812 let account = AccountSharedData::new(lamports, 0, &program_id);
15813 for key in pubkeys_to_modify {
15816 current_minor_fork_bank.store_account(key, &account);
15817 }
15818 current_minor_fork_bank.freeze();
15819 }
15820
15821 assert_eq!(
15825 current_minor_fork_bank.clone().parents_inclusive().len(),
15826 num_new_banks + 1,
15827 );
15828
15829 current_major_fork_bank = Arc::new(Bank::new_from_parent(
15833 ¤t_major_fork_bank,
15834 &solana_sdk::pubkey::new_rand(),
15835 current_minor_fork_bank.slot() - 1,
15836 ));
15837 let lamports = current_major_fork_bank.slot() + starting_lamports + 1;
15838 let account = AccountSharedData::new(lamports, 0, &program_id);
15839 for key in pubkeys_to_modify.iter() {
15840 current_major_fork_bank.store_account(key, &account);
15843 }
15844
15845 if bank_to_scan_sender.send(current_minor_fork_bank).is_err() {
15860 return;
15862 }
15863 current_major_fork_bank.freeze();
15864 current_major_fork_bank.squash();
15865 current_major_fork_bank.force_flush_accounts_cache();
15867 current_major_fork_bank.clean_accounts(false, false, None);
15868 abs_request_handler.handle_pruned_banks(¤t_major_fork_bank, true);
15871 }
15872 },
15873 Some(Box::new(SendDroppedBankCallback::new(
15874 pruned_banks_sender.clone(),
15875 ))),
15876 AcceptableScanResults::NoFailure,
15877 )
15878 }
15879 }
15880
15881 #[test]
15882 fn test_store_scan_consistency_root() {
15883 for accounts_db_caching_enabled in &[false, true] {
15884 test_store_scan_consistency(
15885 *accounts_db_caching_enabled,
15886 |bank0,
15887 bank_to_scan_sender,
15888 _scan_finished_receiver,
15889 pubkeys_to_modify,
15890 program_id,
15891 starting_lamports| {
15892 let mut current_bank = bank0.clone();
15893 let mut prev_bank = bank0;
15894 loop {
15895 let lamports_this_round = current_bank.slot() + starting_lamports + 1;
15896 let account = AccountSharedData::new(lamports_this_round, 0, &program_id);
15897 for key in pubkeys_to_modify.iter() {
15898 current_bank.store_account(key, &account);
15899 }
15900 current_bank.freeze();
15901 if bank_to_scan_sender.send(prev_bank).is_err() {
15909 return;
15911 }
15912 current_bank.squash();
15913 if current_bank.slot() % 2 == 0 {
15914 current_bank.force_flush_accounts_cache();
15915 current_bank.clean_accounts(true, false, None);
15916 }
15917 prev_bank = current_bank.clone();
15918 current_bank = Arc::new(Bank::new_from_parent(
15919 ¤t_bank,
15920 &solana_sdk::pubkey::new_rand(),
15921 current_bank.slot() + 1,
15922 ));
15923 }
15924 },
15925 None,
15926 AcceptableScanResults::NoFailure,
15927 );
15928 }
15929 }
15930
15931 fn setup_banks_on_fork_to_remove(
15932 bank0: Arc<Bank>,
15933 pubkeys_to_modify: Arc<HashSet<Pubkey>>,
15934 program_id: &Pubkey,
15935 starting_lamports: u64,
15936 num_banks_on_fork: usize,
15937 step_size: usize,
15938 ) -> (Arc<Bank>, Vec<(Slot, BankId)>, Ancestors) {
15939 assert!(pubkeys_to_modify.len() > 1);
15942
15943 let mut bank_at_fork_tip = bank0;
15945
15946 let mut slots_on_fork = Vec::with_capacity(num_banks_on_fork);
15948
15949 assert!(num_banks_on_fork >= 2);
15954 assert!(step_size >= 2);
15955 let pubkeys_to_modify: Vec<Pubkey> = pubkeys_to_modify.iter().cloned().collect();
15956 let pubkeys_to_modify_per_slot = (pubkeys_to_modify.len() / step_size).max(1);
15957 for _ in (0..num_banks_on_fork).step_by(step_size) {
15958 let mut lamports_this_round = 0;
15959 for i in 0..step_size {
15960 bank_at_fork_tip = Arc::new(Bank::new_from_parent(
15961 &bank_at_fork_tip,
15962 &solana_sdk::pubkey::new_rand(),
15963 bank_at_fork_tip.slot() + 1,
15964 ));
15965 if lamports_this_round == 0 {
15966 lamports_this_round = bank_at_fork_tip.bank_id() + starting_lamports + 1;
15967 }
15968 let pubkey_to_modify_starting_index = i * pubkeys_to_modify_per_slot;
15969 let account = AccountSharedData::new(lamports_this_round, 0, program_id);
15970 for pubkey_index_to_modify in pubkey_to_modify_starting_index
15971 ..pubkey_to_modify_starting_index + pubkeys_to_modify_per_slot
15972 {
15973 let key = pubkeys_to_modify[pubkey_index_to_modify % pubkeys_to_modify.len()];
15974 bank_at_fork_tip.store_account(&key, &account);
15975 }
15976 bank_at_fork_tip.freeze();
15977 slots_on_fork.push((bank_at_fork_tip.slot(), bank_at_fork_tip.bank_id()));
15978 }
15979 }
15980
15981 let ancestors: Vec<(Slot, usize)> = slots_on_fork.iter().map(|(s, _)| (*s, 0)).collect();
15982 let ancestors = Ancestors::from(ancestors);
15983
15984 (bank_at_fork_tip, slots_on_fork, ancestors)
15985 }
15986
15987 #[test]
15988 fn test_remove_unrooted_before_scan() {
15989 for accounts_db_caching_enabled in &[false, true] {
15990 test_store_scan_consistency(
15991 *accounts_db_caching_enabled,
15992 |bank0,
15993 bank_to_scan_sender,
15994 scan_finished_receiver,
15995 pubkeys_to_modify,
15996 program_id,
15997 starting_lamports| {
15998 loop {
15999 let (bank_at_fork_tip, slots_on_fork, ancestors) =
16000 setup_banks_on_fork_to_remove(
16001 bank0.clone(),
16002 pubkeys_to_modify.clone(),
16003 &program_id,
16004 starting_lamports,
16005 10,
16006 2,
16007 );
16008 for k in pubkeys_to_modify.iter() {
16011 assert!(bank_at_fork_tip.load_slow(&ancestors, k).is_some());
16012 }
16013 bank_at_fork_tip.remove_unrooted_slots(&slots_on_fork);
16014
16015 for k in pubkeys_to_modify.iter() {
16017 assert!(bank_at_fork_tip.load_slow(&ancestors, k).is_none());
16018 }
16019 if bank_to_scan_sender.send(bank_at_fork_tip.clone()).is_err() {
16020 return;
16021 }
16022
16023 let finished_scan_bank_id = scan_finished_receiver.recv();
16025 if finished_scan_bank_id.is_err() {
16026 return;
16027 }
16028 assert_eq!(finished_scan_bank_id.unwrap(), bank_at_fork_tip.bank_id());
16029 }
16030 },
16031 None,
16032 AcceptableScanResults::DroppedSlotError,
16034 );
16035 }
16036 }
16037
16038 #[test]
16039 fn test_remove_unrooted_scan_then_recreate_same_slot_before_scan() {
16040 for accounts_db_caching_enabled in &[false, true] {
16041 test_store_scan_consistency(
16042 *accounts_db_caching_enabled,
16043 |bank0,
16044 bank_to_scan_sender,
16045 scan_finished_receiver,
16046 pubkeys_to_modify,
16047 program_id,
16048 starting_lamports| {
16049 let mut prev_bank = bank0.clone();
16050 loop {
16051 let start = Instant::now();
16052 let (bank_at_fork_tip, slots_on_fork, ancestors) =
16053 setup_banks_on_fork_to_remove(
16054 bank0.clone(),
16055 pubkeys_to_modify.clone(),
16056 &program_id,
16057 starting_lamports,
16058 10,
16059 2,
16060 );
16061 info!("setting up banks elapsed: {}", start.elapsed().as_millis());
16062 if prev_bank.slot() != 0 {
16067 info!(
16068 "sending bank with slot: {:?}, elapsed: {}",
16069 prev_bank.slot(),
16070 start.elapsed().as_millis()
16071 );
16072 for k in pubkeys_to_modify.iter() {
16076 assert!(bank_at_fork_tip.load_slow(&ancestors, k).is_some());
16077 }
16078
16079 if bank_to_scan_sender.send(prev_bank.clone()).is_err() {
16083 return;
16084 }
16085
16086 let finished_scan_bank_id = scan_finished_receiver.recv();
16087 if finished_scan_bank_id.is_err() {
16088 return;
16089 }
16090 assert_eq!(finished_scan_bank_id.unwrap(), prev_bank.bank_id());
16092 }
16093 bank_at_fork_tip.remove_unrooted_slots(&slots_on_fork);
16094 prev_bank = bank_at_fork_tip;
16095 }
16096 },
16097 None,
16098 AcceptableScanResults::DroppedSlotError,
16100 );
16101 }
16102 }
16103
16104 #[test]
16105 fn test_remove_unrooted_scan_interleaved_with_remove_unrooted_slots() {
16106 for accounts_db_caching_enabled in &[false, true] {
16107 test_store_scan_consistency(
16108 *accounts_db_caching_enabled,
16109 |bank0,
16110 bank_to_scan_sender,
16111 scan_finished_receiver,
16112 pubkeys_to_modify,
16113 program_id,
16114 starting_lamports| {
16115 loop {
16116 let step_size = 2;
16117 let (bank_at_fork_tip, slots_on_fork, ancestors) =
16118 setup_banks_on_fork_to_remove(
16119 bank0.clone(),
16120 pubkeys_to_modify.clone(),
16121 &program_id,
16122 starting_lamports,
16123 10,
16124 step_size,
16125 );
16126 for k in pubkeys_to_modify.iter() {
16130 assert!(bank_at_fork_tip.load_slow(&ancestors, k).is_some());
16131 }
16132
16133 if bank_to_scan_sender.send(bank_at_fork_tip.clone()).is_err() {
16137 return;
16138 }
16139
16140 let slot_to_remove = *slots_on_fork.last().unwrap();
16144 bank_at_fork_tip.remove_unrooted_slots(&[slot_to_remove]);
16145
16146 let finished_scan_bank_id = scan_finished_receiver.recv();
16148 if finished_scan_bank_id.is_err() {
16149 return;
16150 }
16151 assert_eq!(finished_scan_bank_id.unwrap(), bank_at_fork_tip.bank_id());
16152
16153 for (slot, bank_id) in slots_on_fork {
16155 bank_at_fork_tip.remove_unrooted_slots(&[(slot, bank_id)]);
16156 }
16157 }
16158 },
16159 None,
16160 AcceptableScanResults::Both,
16162 );
16163 }
16164 }
16165
16166 #[test]
16167 fn test_get_inflation_start_slot_devnet_testnet() {
16168 let GenesisConfigInfo {
16169 mut genesis_config, ..
16170 } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16171 genesis_config
16172 .accounts
16173 .remove(&feature_set::pico_inflation::id())
16174 .unwrap();
16175 genesis_config
16176 .accounts
16177 .remove(&feature_set::full_inflation::devnet_and_testnet::id())
16178 .unwrap();
16179 for pair in feature_set::FULL_INFLATION_FEATURE_PAIRS.iter() {
16180 genesis_config.accounts.remove(&pair.vote_id).unwrap();
16181 genesis_config.accounts.remove(&pair.enable_id).unwrap();
16182 }
16183
16184 let bank = Bank::new_for_tests(&genesis_config);
16185
16186 let mut bank = new_from_parent(&Arc::new(bank));
16188 bank = new_from_parent(&Arc::new(bank));
16189 assert_eq!(bank.get_inflation_start_slot(), 0);
16190 assert_eq!(bank.slot(), 2);
16191
16192 bank.store_account(
16194 &feature_set::pico_inflation::id(),
16195 &feature::create_account(
16196 &Feature {
16197 activated_at: Some(1),
16198 },
16199 42,
16200 ),
16201 );
16202 bank.compute_active_feature_set(true);
16203 assert_eq!(bank.get_inflation_start_slot(), 1);
16204
16205 bank = new_from_parent(&Arc::new(bank));
16207 assert_eq!(bank.slot(), 3);
16208
16209 bank.store_account(
16212 &feature_set::full_inflation::devnet_and_testnet::id(),
16213 &feature::create_account(
16214 &Feature {
16215 activated_at: Some(2),
16216 },
16217 42,
16218 ),
16219 );
16220 bank.compute_active_feature_set(true);
16221 assert_eq!(bank.get_inflation_start_slot(), 2);
16222
16223 bank.store_account(
16226 &feature_set::full_inflation::mainnet::certusone::vote::id(),
16227 &feature::create_account(
16228 &Feature {
16229 activated_at: Some(3),
16230 },
16231 42,
16232 ),
16233 );
16234 bank.store_account(
16235 &feature_set::full_inflation::mainnet::certusone::enable::id(),
16236 &feature::create_account(
16237 &Feature {
16238 activated_at: Some(3),
16239 },
16240 42,
16241 ),
16242 );
16243 bank.compute_active_feature_set(true);
16244 assert_eq!(bank.get_inflation_start_slot(), 2);
16245 }
16246
16247 #[test]
16248 fn test_get_inflation_start_slot_mainnet() {
16249 let GenesisConfigInfo {
16250 mut genesis_config, ..
16251 } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16252 genesis_config
16253 .accounts
16254 .remove(&feature_set::pico_inflation::id())
16255 .unwrap();
16256 genesis_config
16257 .accounts
16258 .remove(&feature_set::full_inflation::devnet_and_testnet::id())
16259 .unwrap();
16260 for pair in feature_set::FULL_INFLATION_FEATURE_PAIRS.iter() {
16261 genesis_config.accounts.remove(&pair.vote_id).unwrap();
16262 genesis_config.accounts.remove(&pair.enable_id).unwrap();
16263 }
16264
16265 let bank = Bank::new_for_tests(&genesis_config);
16266
16267 let mut bank = new_from_parent(&Arc::new(bank));
16269 bank = new_from_parent(&Arc::new(bank));
16270 assert_eq!(bank.get_inflation_start_slot(), 0);
16271 assert_eq!(bank.slot(), 2);
16272
16273 bank.store_account(
16275 &feature_set::pico_inflation::id(),
16276 &feature::create_account(
16277 &Feature {
16278 activated_at: Some(1),
16279 },
16280 42,
16281 ),
16282 );
16283 bank.compute_active_feature_set(true);
16284 assert_eq!(bank.get_inflation_start_slot(), 1);
16285
16286 bank = new_from_parent(&Arc::new(bank));
16288 assert_eq!(bank.slot(), 3);
16289
16290 bank.store_account(
16293 &feature_set::full_inflation::mainnet::certusone::vote::id(),
16294 &feature::create_account(
16295 &Feature {
16296 activated_at: Some(2),
16297 },
16298 42,
16299 ),
16300 );
16301 bank.store_account(
16302 &feature_set::full_inflation::mainnet::certusone::enable::id(),
16303 &feature::create_account(
16304 &Feature {
16305 activated_at: Some(2),
16306 },
16307 42,
16308 ),
16309 );
16310 bank.compute_active_feature_set(true);
16311 assert_eq!(bank.get_inflation_start_slot(), 2);
16312
16313 bank = new_from_parent(&Arc::new(bank));
16315 assert_eq!(bank.slot(), 4);
16316
16317 bank.store_account(
16320 &feature_set::full_inflation::devnet_and_testnet::id(),
16321 &feature::create_account(
16322 &Feature {
16323 activated_at: Some(bank.slot()),
16324 },
16325 42,
16326 ),
16327 );
16328 bank.compute_active_feature_set(true);
16329 assert_eq!(bank.get_inflation_start_slot(), 2);
16330 }
16331
16332 #[test]
16333 fn test_get_inflation_num_slots_with_activations() {
16334 let GenesisConfigInfo {
16335 mut genesis_config, ..
16336 } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16337 let slots_per_epoch = 32;
16338 genesis_config.epoch_schedule = EpochSchedule::new(slots_per_epoch);
16339 genesis_config
16340 .accounts
16341 .remove(&feature_set::pico_inflation::id())
16342 .unwrap();
16343 genesis_config
16344 .accounts
16345 .remove(&feature_set::full_inflation::devnet_and_testnet::id())
16346 .unwrap();
16347 for pair in feature_set::FULL_INFLATION_FEATURE_PAIRS.iter() {
16348 genesis_config.accounts.remove(&pair.vote_id).unwrap();
16349 genesis_config.accounts.remove(&pair.enable_id).unwrap();
16350 }
16351
16352 let mut bank = Bank::new_for_tests(&genesis_config);
16353 assert_eq!(bank.get_inflation_num_slots(), 0);
16354 for _ in 0..2 * slots_per_epoch {
16355 bank = new_from_parent(&Arc::new(bank));
16356 }
16357 assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
16358
16359 let pico_inflation_activation_slot = bank.slot();
16361 bank.store_account(
16362 &feature_set::pico_inflation::id(),
16363 &feature::create_account(
16364 &Feature {
16365 activated_at: Some(pico_inflation_activation_slot),
16366 },
16367 42,
16368 ),
16369 );
16370 bank.compute_active_feature_set(true);
16371 assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
16372 for _ in 0..slots_per_epoch {
16373 bank = new_from_parent(&Arc::new(bank));
16374 }
16375 assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
16376
16377 let full_inflation_activation_slot = bank.slot();
16379 bank.store_account(
16380 &feature_set::full_inflation::devnet_and_testnet::id(),
16381 &feature::create_account(
16382 &Feature {
16383 activated_at: Some(full_inflation_activation_slot),
16384 },
16385 42,
16386 ),
16387 );
16388 bank.compute_active_feature_set(true);
16389 assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
16390 for _ in 0..slots_per_epoch {
16391 bank = new_from_parent(&Arc::new(bank));
16392 }
16393 assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
16394 }
16395
16396 #[test]
16397 fn test_get_inflation_num_slots_already_activated() {
16398 let GenesisConfigInfo {
16399 mut genesis_config, ..
16400 } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16401 let slots_per_epoch = 32;
16402 genesis_config.epoch_schedule = EpochSchedule::new(slots_per_epoch);
16403 let mut bank = Bank::new_for_tests(&genesis_config);
16404 assert_eq!(bank.get_inflation_num_slots(), 0);
16405 for _ in 0..slots_per_epoch {
16406 bank = new_from_parent(&Arc::new(bank));
16407 }
16408 assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
16409 for _ in 0..slots_per_epoch {
16410 bank = new_from_parent(&Arc::new(bank));
16411 }
16412 assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
16413 }
16414
16415 #[test]
16416 fn test_stake_vote_account_validity() {
16417 let thread_pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
16418 check_stake_vote_account_validity(
16419 true, |bank: &Bank| {
16421 bank.load_vote_and_stake_accounts_with_thread_pool(&thread_pool, null_tracer())
16422 },
16423 );
16424 check_stake_vote_account_validity(
16428 false, |bank: &Bank| bank.load_vote_and_stake_accounts(&thread_pool, null_tracer()),
16430 );
16431 }
16432
16433 fn check_stake_vote_account_validity<F>(
16434 check_owner_change: bool,
16435 load_vote_and_stake_accounts: F,
16436 ) where
16437 F: Fn(&Bank) -> LoadVoteAndStakeAccountsResult,
16438 {
16439 let validator_vote_keypairs0 = ValidatorVoteKeypairs::new_rand();
16440 let validator_vote_keypairs1 = ValidatorVoteKeypairs::new_rand();
16441 let validator_keypairs = vec![&validator_vote_keypairs0, &validator_vote_keypairs1];
16442 let GenesisConfigInfo { genesis_config, .. } = create_genesis_config_with_vote_accounts(
16443 1_000_000_000,
16444 &validator_keypairs,
16445 vec![LAMPORTS_PER_SAFE; 2],
16446 );
16447 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
16448 let vote_and_stake_accounts =
16449 load_vote_and_stake_accounts(&bank).vote_with_stake_delegations_map;
16450 assert_eq!(vote_and_stake_accounts.len(), 2);
16451
16452 let mut vote_account = bank
16453 .get_account(&validator_vote_keypairs0.vote_keypair.pubkey())
16454 .unwrap_or_default();
16455 let original_lamports = vote_account.lamports();
16456 vote_account.set_lamports(0);
16457 bank.store_account(
16459 &validator_vote_keypairs0.vote_keypair.pubkey(),
16460 &vote_account,
16461 );
16462
16463 let bogus_vote_program = Pubkey::new_unique();
16466 vote_account.set_lamports(original_lamports);
16467 vote_account.set_owner(bogus_vote_program);
16468 bank.store_account(
16469 &validator_vote_keypairs0.vote_keypair.pubkey(),
16470 &vote_account,
16471 );
16472
16473 assert_eq!(bank.vote_accounts().len(), 1);
16474
16475 let bogus_stake_program = Pubkey::new_unique();
16478 let mut stake_account = bank
16479 .get_account(&validator_vote_keypairs1.stake_keypair.pubkey())
16480 .unwrap_or_default();
16481 stake_account.set_owner(bogus_stake_program);
16482 bank.store_account(
16483 &validator_vote_keypairs1.stake_keypair.pubkey(),
16484 &stake_account,
16485 );
16486
16487 let vote_and_stake_accounts =
16489 load_vote_and_stake_accounts(&bank).vote_with_stake_delegations_map;
16490 assert_eq!(
16491 vote_and_stake_accounts.len(),
16492 usize::from(!check_owner_change)
16493 );
16494 }
16495
16496 #[test]
16497 fn test_vote_epoch_panic() {
16498 let GenesisConfigInfo {
16499 genesis_config,
16500 mint_keypair,
16501 ..
16502 } = create_genesis_config_with_leader(
16503 1_000_000_000_000_000,
16504 &Pubkey::new_unique(),
16505 bootstrap_validator_stake_lamports(),
16506 );
16507 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
16508
16509 let vote_keypair = keypair_from_seed(&[1u8; 32]).unwrap();
16510 let stake_keypair = keypair_from_seed(&[2u8; 32]).unwrap();
16511
16512 let mut setup_ixs = Vec::new();
16513 setup_ixs.extend(
16514 vote_instruction::create_account(
16515 &mint_keypair.pubkey(),
16516 &vote_keypair.pubkey(),
16517 &VoteInit {
16518 node_pubkey: mint_keypair.pubkey(),
16519 authorized_voter: vote_keypair.pubkey(),
16520 authorized_withdrawer: mint_keypair.pubkey(),
16521 commission: 0,
16522 },
16523 1_000_000_000,
16524 )
16525 .into_iter(),
16526 );
16527 setup_ixs.extend(
16528 stake_instruction::create_account_and_delegate_stake(
16529 &mint_keypair.pubkey(),
16530 &stake_keypair.pubkey(),
16531 &vote_keypair.pubkey(),
16532 &Authorized::auto(&mint_keypair.pubkey()),
16533 &Lockup::default(),
16534 1_000_000_000_000,
16535 )
16536 .into_iter(),
16537 );
16538 setup_ixs.push(vote_instruction::withdraw(
16539 &vote_keypair.pubkey(),
16540 &mint_keypair.pubkey(),
16541 1_000_000_000,
16542 &mint_keypair.pubkey(),
16543 ));
16544 setup_ixs.push(system_instruction::transfer(
16545 &mint_keypair.pubkey(),
16546 &vote_keypair.pubkey(),
16547 1_000_000_000,
16548 ));
16549
16550 let result = bank.process_transaction(&Transaction::new(
16551 &[&mint_keypair, &vote_keypair, &stake_keypair],
16552 Message::new(&setup_ixs, Some(&mint_keypair.pubkey())),
16553 bank.last_blockhash(),
16554 ));
16555 assert!(result.is_ok());
16556
16557 let _bank = Bank::new_from_parent(
16558 &bank,
16559 &mint_keypair.pubkey(),
16560 genesis_config.epoch_schedule.get_first_slot_in_epoch(1),
16561 );
16562 }
16563
16564 #[test]
16565 fn test_tx_log_order() {
16566 let GenesisConfigInfo {
16567 genesis_config,
16568 mint_keypair,
16569 ..
16570 } = create_genesis_config_with_leader(
16571 1_000_000_000_000_000,
16572 &Pubkey::new_unique(),
16573 bootstrap_validator_stake_lamports(),
16574 );
16575 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
16576 *bank.transaction_log_collector_config.write().unwrap() = TransactionLogCollectorConfig {
16577 mentioned_addresses: HashSet::new(),
16578 filter: TransactionLogCollectorFilter::All,
16579 };
16580 let blockhash = bank.last_blockhash();
16581
16582 let sender0 = Keypair::new();
16583 let sender1 = Keypair::new();
16584 bank.transfer(100, &mint_keypair, &sender0.pubkey())
16585 .unwrap();
16586 bank.transfer(100, &mint_keypair, &sender1.pubkey())
16587 .unwrap();
16588
16589 let recipient0 = Pubkey::new_unique();
16590 let recipient1 = Pubkey::new_unique();
16591 let tx0 = system_transaction::transfer(&sender0, &recipient0, 10, blockhash);
16592 let success_sig = tx0.signatures[0];
16593 let tx1 = system_transaction::transfer(&sender1, &recipient1, 110, blockhash); let failure_sig = tx1.signatures[0];
16595 let tx2 = system_transaction::transfer(&sender0, &recipient0, 1, blockhash);
16596 let txs = vec![tx0, tx1, tx2];
16597 let batch = bank.prepare_batch_for_tests(txs);
16598
16599 let execution_results = bank
16600 .load_execute_and_commit_transactions(
16601 &batch,
16602 MAX_PROCESSING_AGE,
16603 false,
16604 false,
16605 true,
16606 false,
16607 &mut ExecuteTimings::default(),
16608 None,
16609 )
16610 .0
16611 .execution_results;
16612
16613 assert_eq!(execution_results.len(), 3);
16614
16615 assert!(execution_results[0].details().is_some());
16616 assert!(execution_results[0]
16617 .details()
16618 .unwrap()
16619 .log_messages
16620 .as_ref()
16621 .unwrap()[1]
16622 .contains(&"success".to_string()));
16623 assert!(execution_results[1].details().is_some());
16624 assert!(execution_results[1]
16625 .details()
16626 .unwrap()
16627 .log_messages
16628 .as_ref()
16629 .unwrap()[2]
16630 .contains(&"failed".to_string()));
16631 assert!(!execution_results[2].was_executed());
16632
16633 let stored_logs = &bank.transaction_log_collector.read().unwrap().logs;
16634 let success_log_info = stored_logs
16635 .iter()
16636 .find(|transaction_log_info| transaction_log_info.signature == success_sig)
16637 .unwrap();
16638 assert!(success_log_info.result.is_ok());
16639 let success_log = success_log_info.log_messages.clone().pop().unwrap();
16640 assert!(success_log.contains(&"success".to_string()));
16641 let failure_log_info = stored_logs
16642 .iter()
16643 .find(|transaction_log_info| transaction_log_info.signature == failure_sig)
16644 .unwrap();
16645 assert!(failure_log_info.result.is_err());
16646 let failure_log = failure_log_info.log_messages.clone().pop().unwrap();
16647 assert!(failure_log.contains(&"failed".to_string()));
16648 }
16649
16650 #[test]
16651 fn test_tx_return_data() {
16652 solana_logger::setup();
16653 let GenesisConfigInfo {
16654 genesis_config,
16655 mint_keypair,
16656 ..
16657 } = create_genesis_config_with_leader(
16658 1_000_000_000_000_000,
16659 &Pubkey::new_unique(),
16660 bootstrap_validator_stake_lamports(),
16661 );
16662 let mut bank = Bank::new_for_tests(&genesis_config);
16663
16664 let mock_program_id = Pubkey::from([2u8; 32]);
16665 fn mock_process_instruction(
16666 _first_instruction_account: usize,
16667 invoke_context: &mut InvokeContext,
16668 ) -> result::Result<(), InstructionError> {
16669 let mock_program_id = Pubkey::from([2u8; 32]);
16670 let transaction_context = &mut invoke_context.transaction_context;
16671 let instruction_context = transaction_context.get_current_instruction_context()?;
16672 let instruction_data = instruction_context.get_instruction_data();
16673 let mut return_data = [0u8; MAX_RETURN_DATA];
16674 if !instruction_data.is_empty() {
16675 let index = usize::from_le_bytes(instruction_data.try_into().unwrap());
16676 return_data[index] = 1;
16677 transaction_context
16678 .set_return_data(mock_program_id, return_data.to_vec())
16679 .unwrap();
16680 }
16681 Ok(())
16682 }
16683 let blockhash = bank.last_blockhash();
16684 bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
16685
16686 for index in [
16687 None,
16688 Some(0),
16689 Some(MAX_RETURN_DATA / 2),
16690 Some(MAX_RETURN_DATA - 1),
16691 ] {
16692 let data = if let Some(index) = index {
16693 usize::to_le_bytes(index).to_vec()
16694 } else {
16695 Vec::new()
16696 };
16697 let txs = vec![Transaction::new_signed_with_payer(
16698 &[Instruction {
16699 program_id: mock_program_id,
16700 data,
16701 accounts: vec![AccountMeta::new(Pubkey::new_unique(), false)],
16702 }],
16703 Some(&mint_keypair.pubkey()),
16704 &[&mint_keypair],
16705 blockhash,
16706 )];
16707 let batch = bank.prepare_batch_for_tests(txs);
16708 let return_data = bank
16709 .load_execute_and_commit_transactions(
16710 &batch,
16711 MAX_PROCESSING_AGE,
16712 false,
16713 false,
16714 false,
16715 true,
16716 &mut ExecuteTimings::default(),
16717 None,
16718 )
16719 .0
16720 .execution_results[0]
16721 .details()
16722 .unwrap()
16723 .return_data
16724 .clone();
16725 if let Some(index) = index {
16726 let return_data = return_data.unwrap();
16727 assert_eq!(return_data.program_id, mock_program_id);
16728 let mut expected_data = vec![0u8; index];
16729 expected_data.push(1u8);
16730 assert_eq!(return_data.data, expected_data);
16731 } else {
16732 assert!(return_data.is_none());
16733 }
16734 }
16735 }
16736
16737 #[test]
16738 fn test_get_largest_accounts() {
16739 let GenesisConfigInfo { genesis_config, .. } =
16740 create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16741 let bank = Bank::new_for_tests(&genesis_config);
16742
16743 let pubkeys: Vec<_> = (0..5).map(|_| Pubkey::new_unique()).collect();
16744 let pubkeys_hashset: HashSet<_> = pubkeys.iter().cloned().collect();
16745
16746 let pubkeys_balances: Vec<_> = pubkeys
16747 .iter()
16748 .cloned()
16749 .zip(vec![
16750 sol_to_lamports(2.0),
16751 sol_to_lamports(3.0),
16752 sol_to_lamports(3.0),
16753 sol_to_lamports(4.0),
16754 sol_to_lamports(5.0),
16755 ])
16756 .collect();
16757
16758 let account0 = AccountSharedData::new(pubkeys_balances[0].1, 0, &Pubkey::default());
16760 bank.store_account(&pubkeys_balances[0].0, &account0);
16761 let account1 = AccountSharedData::new(pubkeys_balances[1].1, 0, &Pubkey::default());
16762 bank.store_account(&pubkeys_balances[1].0, &account1);
16763 let account2 = AccountSharedData::new(pubkeys_balances[2].1, 0, &Pubkey::default());
16764 bank.store_account(&pubkeys_balances[2].0, &account2);
16765 let account3 = AccountSharedData::new(pubkeys_balances[3].1, 0, &Pubkey::default());
16766 bank.store_account(&pubkeys_balances[3].0, &account3);
16767 let account4 = AccountSharedData::new(pubkeys_balances[4].1, 0, &Pubkey::default());
16768 bank.store_account(&pubkeys_balances[4].0, &account4);
16769
16770 let exclude4: HashSet<_> = pubkeys[4..].iter().cloned().collect();
16772
16773 let mut sorted_accounts = pubkeys_balances.clone();
16774 sorted_accounts.sort_by(|a, b| a.1.cmp(&b.1).reverse());
16775
16776 assert_eq!(
16778 bank.get_largest_accounts(1, &pubkeys_hashset, AccountAddressFilter::Include)
16779 .unwrap(),
16780 vec![(pubkeys[4], sol_to_lamports(5.0))]
16781 );
16782 assert_eq!(
16783 bank.get_largest_accounts(1, &HashSet::new(), AccountAddressFilter::Exclude)
16784 .unwrap(),
16785 vec![(pubkeys[4], sol_to_lamports(5.0))]
16786 );
16787 assert_eq!(
16788 bank.get_largest_accounts(1, &exclude4, AccountAddressFilter::Exclude)
16789 .unwrap(),
16790 vec![(pubkeys[3], sol_to_lamports(4.0))]
16791 );
16792
16793 let results = bank
16795 .get_largest_accounts(10, &pubkeys_hashset, AccountAddressFilter::Include)
16796 .unwrap();
16797 assert_eq!(results.len(), sorted_accounts.len());
16798 for pubkey_balance in sorted_accounts.iter() {
16799 assert!(results.contains(pubkey_balance));
16800 }
16801 let mut sorted_results = results.clone();
16802 sorted_results.sort_by(|a, b| a.1.cmp(&b.1).reverse());
16803 assert_eq!(sorted_results, results);
16804
16805 let expected_accounts = sorted_accounts[1..].to_vec();
16806 let results = bank
16807 .get_largest_accounts(10, &exclude4, AccountAddressFilter::Exclude)
16808 .unwrap();
16809 assert_eq!(results.len(), 10);
16811 for pubkey_balance in expected_accounts.iter() {
16812 assert!(results.contains(pubkey_balance));
16813 }
16814 let mut sorted_results = results.clone();
16815 sorted_results.sort_by(|a, b| a.1.cmp(&b.1).reverse());
16816 assert_eq!(sorted_results, results);
16817
16818 let expected_accounts = sorted_accounts[0..4].to_vec();
16820 let results = bank
16821 .get_largest_accounts(4, &pubkeys_hashset, AccountAddressFilter::Include)
16822 .unwrap();
16823 assert_eq!(results.len(), expected_accounts.len());
16824 for pubkey_balance in expected_accounts.iter() {
16825 assert!(results.contains(pubkey_balance));
16826 }
16827
16828 let expected_accounts = expected_accounts[1..4].to_vec();
16829 let results = bank
16830 .get_largest_accounts(3, &exclude4, AccountAddressFilter::Exclude)
16831 .unwrap();
16832 assert_eq!(results.len(), expected_accounts.len());
16833 for pubkey_balance in expected_accounts.iter() {
16834 assert!(results.contains(pubkey_balance));
16835 }
16836
16837 let exclude: HashSet<_> = vec![pubkeys[0], pubkeys[2], pubkeys[4]]
16839 .iter()
16840 .cloned()
16841 .collect();
16842 assert_eq!(
16843 bank.get_largest_accounts(2, &exclude, AccountAddressFilter::Exclude)
16844 .unwrap(),
16845 vec![pubkeys_balances[3], pubkeys_balances[1]]
16846 );
16847 }
16848
16849 #[test]
16850 fn test_transfer_sysvar() {
16851 solana_logger::setup();
16852 let GenesisConfigInfo {
16853 genesis_config,
16854 mint_keypair,
16855 ..
16856 } = create_genesis_config_with_leader(
16857 1_000_000_000_000_000,
16858 &Pubkey::new_unique(),
16859 bootstrap_validator_stake_lamports(),
16860 );
16861 let mut bank = Bank::new_for_tests(&genesis_config);
16862
16863 fn mock_ix_processor(
16864 _first_instruction_account: usize,
16865 invoke_context: &mut InvokeContext,
16866 ) -> std::result::Result<(), InstructionError> {
16867 let transaction_context = &invoke_context.transaction_context;
16868 let instruction_context = transaction_context.get_current_instruction_context()?;
16869 instruction_context
16870 .try_borrow_instruction_account(transaction_context, 1)?
16871 .set_data(&[0; 40])?;
16872 Ok(())
16873 }
16874
16875 let program_id = solana_sdk::pubkey::new_rand();
16876 bank.add_builtin("mock_program1", &program_id, mock_ix_processor);
16877
16878 let blockhash = bank.last_blockhash();
16879 #[allow(deprecated)]
16880 let blockhash_sysvar = sysvar::clock::id();
16881 #[allow(deprecated)]
16882 let orig_lamports = bank.get_account(&sysvar::clock::id()).unwrap().lamports();
16883 let tx = system_transaction::transfer(&mint_keypair, &blockhash_sysvar, 10, blockhash);
16884 assert_eq!(
16885 bank.process_transaction(&tx),
16886 Err(TransactionError::InstructionError(
16887 0,
16888 InstructionError::ReadonlyLamportChange
16889 ))
16890 );
16891 assert_eq!(
16892 bank.get_account(&sysvar::clock::id()).unwrap().lamports(),
16893 orig_lamports
16894 );
16895
16896 let accounts = vec![
16897 AccountMeta::new(mint_keypair.pubkey(), true),
16898 AccountMeta::new(blockhash_sysvar, false),
16899 ];
16900 let ix = Instruction::new_with_bincode(program_id, &0, accounts);
16901 let message = Message::new(&[ix], Some(&mint_keypair.pubkey()));
16902 let tx = Transaction::new(&[&mint_keypair], message, blockhash);
16903 assert_eq!(
16904 bank.process_transaction(&tx),
16905 Err(TransactionError::InstructionError(
16906 0,
16907 InstructionError::ReadonlyDataModified
16908 ))
16909 );
16910 }
16911
16912 #[test]
16913 fn test_clean_dropped_unrooted_frozen_banks() {
16914 solana_logger::setup();
16915 do_test_clean_dropped_unrooted_banks(FreezeBank1::Yes);
16916 }
16917
16918 #[test]
16919 fn test_clean_dropped_unrooted_unfrozen_banks() {
16920 solana_logger::setup();
16921 do_test_clean_dropped_unrooted_banks(FreezeBank1::No);
16922 }
16923
16924 enum FreezeBank1 {
16926 No,
16927 Yes,
16928 }
16929
16930 fn do_test_clean_dropped_unrooted_banks(freeze_bank1: FreezeBank1) {
16931 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
16954 let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
16955 let amount = genesis_config.rent.minimum_balance(0);
16956
16957 let collector = Pubkey::new_unique();
16958 let owner = Pubkey::new_unique();
16959
16960 let key1 = Keypair::new(); let key2 = Keypair::new(); let key3 = Keypair::new(); let key4 = Keypair::new(); let key5 = Keypair::new(); bank0
16966 .transfer(amount, &mint_keypair, &key2.pubkey())
16967 .unwrap();
16968 bank0.freeze();
16969
16970 let slot = 1;
16971 let bank1 = Bank::new_from_parent(&bank0, &collector, slot);
16972 bank1
16973 .transfer(amount, &mint_keypair, &key1.pubkey())
16974 .unwrap();
16975 bank1.store_account(&key4.pubkey(), &AccountSharedData::new(0, 0, &owner));
16976 bank1.store_account(&key5.pubkey(), &AccountSharedData::new(0, 0, &owner));
16977
16978 if let FreezeBank1::Yes = freeze_bank1 {
16979 bank1.freeze();
16980 }
16981
16982 let slot = slot + 1;
16983 let bank2 = Bank::new_from_parent(&bank0, &collector, slot);
16984 bank2
16985 .transfer(amount * 2, &mint_keypair, &key2.pubkey())
16986 .unwrap();
16987 bank2
16988 .transfer(amount, &mint_keypair, &key3.pubkey())
16989 .unwrap();
16990 bank2.store_account(&key5.pubkey(), &AccountSharedData::new(0, 0, &owner));
16991
16992 bank2.freeze(); bank2.squash();
16994
16995 drop(bank1);
16996 bank2.clean_accounts(false, false, None);
16997
16998 let expected_ref_count_for_cleaned_up_keys = 0;
16999 let expected_ref_count_for_keys_in_both_slot1_and_slot2 = 1;
17000
17001 assert_eq!(
17002 bank2
17003 .rc
17004 .accounts
17005 .accounts_db
17006 .accounts_index
17007 .ref_count_from_storage(&key1.pubkey()),
17008 expected_ref_count_for_cleaned_up_keys
17009 );
17010 assert_ne!(
17011 bank2
17012 .rc
17013 .accounts
17014 .accounts_db
17015 .accounts_index
17016 .ref_count_from_storage(&key3.pubkey()),
17017 expected_ref_count_for_cleaned_up_keys
17018 );
17019 assert_eq!(
17020 bank2
17021 .rc
17022 .accounts
17023 .accounts_db
17024 .accounts_index
17025 .ref_count_from_storage(&key4.pubkey()),
17026 expected_ref_count_for_cleaned_up_keys
17027 );
17028 assert_eq!(
17029 bank2
17030 .rc
17031 .accounts
17032 .accounts_db
17033 .accounts_index
17034 .ref_count_from_storage(&key5.pubkey()),
17035 expected_ref_count_for_keys_in_both_slot1_and_slot2,
17036 );
17037
17038 assert_eq!(
17039 bank2.rc.accounts.accounts_db.alive_account_count_in_slot(1),
17040 0
17041 );
17042 }
17043
17044 #[test]
17045 fn test_rent_debits() {
17046 let mut rent_debits = RentDebits::default();
17047
17048 rent_debits.insert(&Pubkey::new_unique(), 0, 0);
17050 assert_eq!(rent_debits.0.len(), 0);
17051
17052 rent_debits.insert(&Pubkey::new_unique(), 1, 0);
17054 assert_eq!(rent_debits.0.len(), 1);
17055 rent_debits.insert(&Pubkey::new_unique(), i64::MAX as u64, 0);
17056 assert_eq!(rent_debits.0.len(), 2);
17057 }
17058
17059 #[test]
17060 fn test_compute_budget_program_noop() {
17061 solana_logger::setup();
17062 let GenesisConfigInfo {
17063 genesis_config,
17064 mint_keypair,
17065 ..
17066 } = create_genesis_config_with_leader(
17067 1_000_000_000_000_000,
17068 &Pubkey::new_unique(),
17069 bootstrap_validator_stake_lamports(),
17070 );
17071 let mut bank = Bank::new_for_tests(&genesis_config);
17072
17073 fn mock_ix_processor(
17074 _first_instruction_account: usize,
17075 invoke_context: &mut InvokeContext,
17076 ) -> std::result::Result<(), InstructionError> {
17077 let compute_budget = invoke_context.get_compute_budget();
17078 assert_eq!(
17079 *compute_budget,
17080 ComputeBudget {
17081 compute_unit_limit: 1,
17082 heap_size: Some(48 * 1024),
17083 ..ComputeBudget::default()
17084 }
17085 );
17086 Ok(())
17087 }
17088 let program_id = solana_sdk::pubkey::new_rand();
17089 bank.add_builtin("mock_program", &program_id, mock_ix_processor);
17090
17091 let message = Message::new(
17092 &[
17093 ComputeBudgetInstruction::set_compute_unit_limit(1),
17094 ComputeBudgetInstruction::request_heap_frame(48 * 1024),
17095 Instruction::new_with_bincode(program_id, &0, vec![]),
17096 ],
17097 Some(&mint_keypair.pubkey()),
17098 );
17099 let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash());
17100 bank.process_transaction(&tx).unwrap();
17101 }
17102
17103 #[test]
17104 fn test_compute_request_instruction() {
17105 solana_logger::setup();
17106 let GenesisConfigInfo {
17107 genesis_config,
17108 mint_keypair,
17109 ..
17110 } = create_genesis_config_with_leader(
17111 1_000_000_000_000_000,
17112 &Pubkey::new_unique(),
17113 bootstrap_validator_stake_lamports(),
17114 );
17115 let mut bank = Bank::new_for_tests(&genesis_config);
17116
17117 fn mock_ix_processor(
17118 _first_instruction_account: usize,
17119 invoke_context: &mut InvokeContext,
17120 ) -> std::result::Result<(), InstructionError> {
17121 let compute_budget = invoke_context.get_compute_budget();
17122 assert_eq!(
17123 *compute_budget,
17124 ComputeBudget {
17125 compute_unit_limit: 1,
17126 heap_size: Some(48 * 1024),
17127 ..ComputeBudget::default()
17128 }
17129 );
17130 Ok(())
17131 }
17132 let program_id = solana_sdk::pubkey::new_rand();
17133 bank.add_builtin("mock_program", &program_id, mock_ix_processor);
17134
17135 let message = Message::new(
17136 &[
17137 ComputeBudgetInstruction::set_compute_unit_limit(1),
17138 ComputeBudgetInstruction::request_heap_frame(48 * 1024),
17139 Instruction::new_with_bincode(program_id, &0, vec![]),
17140 ],
17141 Some(&mint_keypair.pubkey()),
17142 );
17143 let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash());
17144 bank.process_transaction(&tx).unwrap();
17145 }
17146
17147 #[test]
17148 fn test_failed_compute_request_instruction() {
17149 solana_logger::setup();
17150 let GenesisConfigInfo {
17151 genesis_config,
17152 mint_keypair,
17153 ..
17154 } = create_genesis_config_with_leader(
17155 1_000_000_000_000_000,
17156 &Pubkey::new_unique(),
17157 bootstrap_validator_stake_lamports(),
17158 );
17159 let mut bank = Bank::new_for_tests(&genesis_config);
17160
17161 let payer0_keypair = Keypair::new();
17162 let payer1_keypair = Keypair::new();
17163 bank.transfer(10, &mint_keypair, &payer0_keypair.pubkey())
17164 .unwrap();
17165 bank.transfer(10, &mint_keypair, &payer1_keypair.pubkey())
17166 .unwrap();
17167
17168 fn mock_ix_processor(
17169 _first_instruction_account: usize,
17170 invoke_context: &mut InvokeContext,
17171 ) -> std::result::Result<(), InstructionError> {
17172 let compute_budget = invoke_context.get_compute_budget();
17173 assert_eq!(
17174 *compute_budget,
17175 ComputeBudget {
17176 compute_unit_limit: 1,
17177 heap_size: Some(48 * 1024),
17178 ..ComputeBudget::default()
17179 }
17180 );
17181 Ok(())
17182 }
17183 let program_id = solana_sdk::pubkey::new_rand();
17184 bank.add_builtin("mock_program", &program_id, mock_ix_processor);
17185
17186 let message0 = Message::new(
17188 &[
17189 ComputeBudgetInstruction::request_heap_frame(1),
17190 Instruction::new_with_bincode(program_id, &0, vec![]),
17191 ],
17192 Some(&payer0_keypair.pubkey()),
17193 );
17194 let message1 = Message::new(
17196 &[
17197 ComputeBudgetInstruction::set_compute_unit_limit(1),
17198 ComputeBudgetInstruction::request_heap_frame(48 * 1024),
17199 Instruction::new_with_bincode(program_id, &0, vec![]),
17200 ],
17201 Some(&payer1_keypair.pubkey()),
17202 );
17203 let txs = vec![
17204 Transaction::new(&[&payer0_keypair], message0, bank.last_blockhash()),
17205 Transaction::new(&[&payer1_keypair], message1, bank.last_blockhash()),
17206 ];
17207 let results = bank.process_transactions(txs.iter());
17208
17209 assert_eq!(
17210 results[0],
17211 Err(TransactionError::InstructionError(
17212 0,
17213 InstructionError::InvalidInstructionData
17214 ))
17215 );
17216 assert_eq!(results[1], Ok(()));
17217 assert_eq!(bank.signature_count(), 3);
17219 }
17220
17221 #[test]
17222 fn test_verify_and_hash_transaction_sig_len() {
17223 let GenesisConfigInfo {
17224 mut genesis_config, ..
17225 } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
17226
17227 activate_all_features(&mut genesis_config);
17229 genesis_config
17230 .accounts
17231 .remove(&feature_set::verify_tx_signatures_len::id());
17232 let bank = Bank::new_for_tests(&genesis_config);
17233
17234 let mut rng = rand::thread_rng();
17235 let recent_blockhash = hash::new_rand(&mut rng);
17236 let from_keypair = Keypair::new();
17237 let to_keypair = Keypair::new();
17238 let from_pubkey = from_keypair.pubkey();
17239 let to_pubkey = to_keypair.pubkey();
17240
17241 enum TestCase {
17242 AddSignature,
17243 RemoveSignature,
17244 }
17245
17246 let make_transaction = |case: TestCase| {
17247 let message = Message::new(
17248 &[system_instruction::transfer(&from_pubkey, &to_pubkey, 1)],
17249 Some(&from_pubkey),
17250 );
17251 let mut tx = Transaction::new(&[&from_keypair], message, recent_blockhash);
17252 assert_eq!(tx.message.header.num_required_signatures, 1);
17253 match case {
17254 TestCase::AddSignature => {
17255 let signature = to_keypair.sign_message(&tx.message.serialize());
17256 tx.signatures.push(signature);
17257 }
17258 TestCase::RemoveSignature => {
17259 tx.signatures.remove(0);
17260 }
17261 }
17262 tx
17263 };
17264
17265 {
17267 let tx = make_transaction(TestCase::RemoveSignature);
17268 assert_eq!(
17269 bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17270 .err(),
17271 Some(TransactionError::SanitizeFailure),
17272 );
17273 }
17274 {
17276 let tx = make_transaction(TestCase::AddSignature);
17277 assert_eq!(
17278 bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17279 .err(),
17280 Some(TransactionError::SanitizeFailure),
17281 );
17282 }
17283 }
17284
17285 #[test]
17286 fn test_verify_transactions_packet_data_size() {
17287 let GenesisConfigInfo { genesis_config, .. } =
17288 create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
17289 let bank = Bank::new_for_tests(&genesis_config);
17290
17291 let mut rng = rand::thread_rng();
17292 let recent_blockhash = hash::new_rand(&mut rng);
17293 let keypair = Keypair::new();
17294 let pubkey = keypair.pubkey();
17295 let make_transaction = |size| {
17296 let ixs: Vec<_> = std::iter::repeat_with(|| {
17297 system_instruction::transfer(&pubkey, &Pubkey::new_unique(), 1)
17298 })
17299 .take(size)
17300 .collect();
17301 let message = Message::new(&ixs[..], Some(&pubkey));
17302 Transaction::new(&[&keypair], message, recent_blockhash)
17303 };
17304 {
17306 let tx = make_transaction(5);
17307 assert!(bincode::serialized_size(&tx).unwrap() <= PACKET_DATA_SIZE as u64);
17308 assert!(bank
17309 .verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17310 .is_ok(),);
17311 }
17312 {
17314 let tx = make_transaction(25);
17315 assert!(bincode::serialized_size(&tx).unwrap() > PACKET_DATA_SIZE as u64);
17316 assert_eq!(
17317 bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17318 .err(),
17319 Some(TransactionError::SanitizeFailure),
17320 );
17321 }
17322 for size in 1..30 {
17325 let tx = make_transaction(size);
17326 assert_eq!(
17327 bincode::serialized_size(&tx).unwrap() <= PACKET_DATA_SIZE as u64,
17328 bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17329 .is_ok(),
17330 );
17331 }
17332 }
17333
17334 #[test]
17335 fn test_call_precomiled_program() {
17336 let GenesisConfigInfo {
17337 mut genesis_config,
17338 mint_keypair,
17339 ..
17340 } = create_genesis_config_with_leader(42, &Pubkey::new_unique(), 42);
17341 activate_all_features(&mut genesis_config);
17342 let bank = Bank::new_for_tests(&genesis_config);
17343
17344 let secp_privkey = libsecp256k1::SecretKey::random(&mut rand::thread_rng());
17346 let message_arr = b"hello";
17347 let instruction = solana_sdk::secp256k1_instruction::new_secp256k1_instruction(
17348 &secp_privkey,
17349 message_arr,
17350 );
17351 let tx = Transaction::new_signed_with_payer(
17352 &[instruction],
17353 Some(&mint_keypair.pubkey()),
17354 &[&mint_keypair],
17355 bank.last_blockhash(),
17356 );
17357 bank.process_transaction(&tx).unwrap();
17360
17361 let privkey = ed25519_dalek::Keypair::generate(&mut rand::thread_rng());
17363 let message_arr = b"hello";
17364 let instruction =
17365 solana_sdk::ed25519_instruction::new_ed25519_instruction(&privkey, message_arr);
17366 let tx = Transaction::new_signed_with_payer(
17367 &[instruction],
17368 Some(&mint_keypair.pubkey()),
17369 &[&mint_keypair],
17370 bank.last_blockhash(),
17371 );
17372 bank.process_transaction(&tx).unwrap();
17375 }
17376
17377 #[test]
17378 fn test_calculate_fee() {
17379 let message =
17381 SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap();
17382 assert_eq!(
17383 Bank::calculate_fee(
17384 &message,
17385 0,
17386 &FeeStructure {
17387 lamports_per_signature: 0,
17388 ..FeeStructure::default()
17389 },
17390 true,
17391 true,
17392 true,
17393 ),
17394 0
17395 );
17396
17397 assert_eq!(
17399 Bank::calculate_fee(
17400 &message,
17401 1,
17402 &FeeStructure {
17403 lamports_per_signature: 1,
17404 ..FeeStructure::default()
17405 },
17406 true,
17407 true,
17408 true,
17409 ),
17410 1
17411 );
17412
17413 let key0 = Pubkey::new_unique();
17415 let key1 = Pubkey::new_unique();
17416 let ix0 = system_instruction::transfer(&key0, &key1, 1);
17417 let ix1 = system_instruction::transfer(&key1, &key0, 1);
17418 let message = SanitizedMessage::try_from(Message::new(&[ix0, ix1], Some(&key0))).unwrap();
17419 assert_eq!(
17420 Bank::calculate_fee(
17421 &message,
17422 2,
17423 &FeeStructure {
17424 lamports_per_signature: 2,
17425 ..FeeStructure::default()
17426 },
17427 true,
17428 true,
17429 true,
17430 ),
17431 4
17432 );
17433 }
17434
17435 #[test]
17436 fn test_calculate_fee_compute_units() {
17437 let fee_structure = FeeStructure {
17438 lamports_per_signature: 1,
17439 ..FeeStructure::default()
17440 };
17441 let max_fee = fee_structure.compute_fee_bins.last().unwrap().fee;
17442 let lamports_per_signature = fee_structure.lamports_per_signature;
17443
17444 let message =
17447 SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap();
17448 assert_eq!(
17449 Bank::calculate_fee(&message, 1, &fee_structure, true, true, true),
17450 max_fee + lamports_per_signature
17451 );
17452
17453 let ix0 = system_instruction::transfer(&Pubkey::new_unique(), &Pubkey::new_unique(), 1);
17456 let ix1 = system_instruction::transfer(&Pubkey::new_unique(), &Pubkey::new_unique(), 1);
17457 let message =
17458 SanitizedMessage::try_from(Message::new(&[ix0, ix1], Some(&Pubkey::new_unique())))
17459 .unwrap();
17460 assert_eq!(
17461 Bank::calculate_fee(&message, 1, &fee_structure, true, true, true),
17462 max_fee + 3 * lamports_per_signature
17463 );
17464
17465 for requested_compute_units in [
17468 0,
17469 5_000,
17470 10_000,
17471 100_000,
17472 300_000,
17473 500_000,
17474 700_000,
17475 900_000,
17476 1_100_000,
17477 1_300_000,
17478 MAX_COMPUTE_UNIT_LIMIT,
17479 ] {
17480 const PRIORITIZATION_FEE_RATE: u64 = 42;
17481 let prioritization_fee_details = PrioritizationFeeDetails::new(
17482 PrioritizationFeeType::ComputeUnitPrice(PRIORITIZATION_FEE_RATE),
17483 requested_compute_units as u64,
17484 );
17485 let message = SanitizedMessage::try_from(Message::new(
17486 &[
17487 ComputeBudgetInstruction::set_compute_unit_limit(requested_compute_units),
17488 ComputeBudgetInstruction::set_compute_unit_price(PRIORITIZATION_FEE_RATE),
17489 Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
17490 ],
17491 Some(&Pubkey::new_unique()),
17492 ))
17493 .unwrap();
17494 let fee = Bank::calculate_fee(&message, 1, &fee_structure, true, true, true);
17495 assert_eq!(
17496 fee,
17497 lamports_per_signature + prioritization_fee_details.get_fee()
17498 );
17499 }
17500 }
17501
17502 #[test]
17503 fn test_calculate_fee_secp256k1() {
17504 let fee_structure = FeeStructure {
17505 lamports_per_signature: 1,
17506 ..FeeStructure::default()
17507 };
17508 let key0 = Pubkey::new_unique();
17509 let key1 = Pubkey::new_unique();
17510 let ix0 = system_instruction::transfer(&key0, &key1, 1);
17511
17512 let mut secp_instruction1 = Instruction {
17513 program_id: secp256k1_program::id(),
17514 accounts: vec![],
17515 data: vec![],
17516 };
17517 let mut secp_instruction2 = Instruction {
17518 program_id: secp256k1_program::id(),
17519 accounts: vec![],
17520 data: vec![1],
17521 };
17522
17523 let message = SanitizedMessage::try_from(Message::new(
17524 &[
17525 ix0.clone(),
17526 secp_instruction1.clone(),
17527 secp_instruction2.clone(),
17528 ],
17529 Some(&key0),
17530 ))
17531 .unwrap();
17532 assert_eq!(
17533 Bank::calculate_fee(&message, 1, &fee_structure, true, true, true),
17534 2
17535 );
17536
17537 secp_instruction1.data = vec![0];
17538 secp_instruction2.data = vec![10];
17539 let message = SanitizedMessage::try_from(Message::new(
17540 &[ix0, secp_instruction1, secp_instruction2],
17541 Some(&key0),
17542 ))
17543 .unwrap();
17544 assert_eq!(
17545 Bank::calculate_fee(&message, 1, &fee_structure, true, true, true),
17546 11
17547 );
17548 }
17549
17550 #[test]
17551 fn test_an_empty_instruction_without_program() {
17552 let (genesis_config, mint_keypair) = create_genesis_config(1);
17553 let destination = solana_sdk::pubkey::new_rand();
17554 let mut ix = system_instruction::transfer(&mint_keypair.pubkey(), &destination, 0);
17555 ix.program_id = native_loader::id(); let message = Message::new(&[ix], Some(&mint_keypair.pubkey()));
17557 let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
17558
17559 let bank = Bank::new_for_tests(&genesis_config);
17560 assert_eq!(
17561 bank.process_transaction(&tx).unwrap_err(),
17562 TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId),
17563 );
17564 }
17565
17566 #[test]
17567 fn test_transaction_log_collector_get_logs_for_address() {
17568 let address = Pubkey::new_unique();
17569 let mut mentioned_address_map = HashMap::new();
17570 mentioned_address_map.insert(address, vec![0]);
17571 let transaction_log_collector = TransactionLogCollector {
17572 mentioned_address_map,
17573 ..TransactionLogCollector::default()
17574 };
17575 assert_eq!(
17576 transaction_log_collector.get_logs_for_address(Some(&address)),
17577 Some(Vec::<TransactionLogInfo>::new()),
17578 );
17579 }
17580
17581 #[test]
17583 fn test_max_accounts_data_size_exceeded() {
17584 const NUM_ACCOUNTS: u64 = 20;
17585 const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH / (NUM_ACCOUNTS + 1);
17586 const REMAINING_ACCOUNTS_DATA_SIZE: u64 = NUM_ACCOUNTS * ACCOUNT_SIZE;
17587
17588 let (genesis_config, mint_keypair) = create_genesis_config(1_000_000_000_000);
17589 let mut bank = Bank::new_for_tests(&genesis_config);
17590 bank.activate_feature(&feature_set::cap_accounts_data_len::id());
17591 bank.accounts_data_size_initial = bank.accounts_data_size_limit()
17592 - REMAINING_ACCOUNTS_DATA_SIZE
17593 - bank.load_accounts_data_size_delta() as u64;
17594
17595 let mut i = 0;
17596 let result = loop {
17597 let txn = system_transaction::create_account(
17598 &mint_keypair,
17599 &Keypair::new(),
17600 bank.last_blockhash(),
17601 genesis_config
17602 .rent
17603 .minimum_balance(ACCOUNT_SIZE.try_into().unwrap()),
17604 ACCOUNT_SIZE,
17605 &solana_sdk::system_program::id(),
17606 );
17607
17608 let accounts_data_size_before = bank.load_accounts_data_size();
17609 let result = bank.process_transaction(&txn);
17610 let accounts_data_size_after = bank.load_accounts_data_size();
17611 assert!(accounts_data_size_after <= bank.accounts_data_size_limit());
17612 if result.is_err() {
17613 assert_eq!(i, NUM_ACCOUNTS);
17614 break result;
17615 }
17616
17617 assert_eq!(
17618 accounts_data_size_after - accounts_data_size_before,
17619 ACCOUNT_SIZE,
17620 );
17621 assert!(
17622 i <= NUM_ACCOUNTS,
17623 "test must complete within bounded limits"
17624 );
17625 i += 1;
17626 };
17627
17628 assert!(matches!(
17629 result,
17630 Err(TransactionError::InstructionError(
17631 _,
17632 solana_sdk::instruction::InstructionError::MaxAccountsDataSizeExceeded,
17633 ))
17634 ));
17635 }
17636
17637 #[test]
17639 fn test_accounts_data_size_with_good_transaction() {
17640 const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH;
17641 let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1_000.));
17642 let mut bank = Bank::new_for_tests(&genesis_config);
17643 bank.activate_feature(&feature_set::cap_accounts_data_len::id());
17644 let transaction = system_transaction::create_account(
17645 &mint_keypair,
17646 &Keypair::new(),
17647 bank.last_blockhash(),
17648 genesis_config
17649 .rent
17650 .minimum_balance(ACCOUNT_SIZE.try_into().unwrap()),
17651 ACCOUNT_SIZE,
17652 &solana_sdk::system_program::id(),
17653 );
17654
17655 let accounts_data_size_before = bank.load_accounts_data_size();
17656 let accounts_data_size_delta_before = bank.load_accounts_data_size_delta();
17657 let accounts_data_size_delta_on_chain_before =
17658 bank.load_accounts_data_size_delta_on_chain();
17659 let result = bank.process_transaction(&transaction);
17660 let accounts_data_size_after = bank.load_accounts_data_size();
17661 let accounts_data_size_delta_after = bank.load_accounts_data_size_delta();
17662 let accounts_data_size_delta_on_chain_after = bank.load_accounts_data_size_delta_on_chain();
17663
17664 assert!(result.is_ok());
17665 assert_eq!(
17666 accounts_data_size_after - accounts_data_size_before,
17667 ACCOUNT_SIZE,
17668 );
17669 assert_eq!(
17670 accounts_data_size_delta_after - accounts_data_size_delta_before,
17671 ACCOUNT_SIZE as i64,
17672 );
17673 assert_eq!(
17674 accounts_data_size_delta_on_chain_after - accounts_data_size_delta_on_chain_before,
17675 ACCOUNT_SIZE as i64,
17676 );
17677 }
17678
17679 #[test]
17681 fn test_accounts_data_size_with_bad_transaction() {
17682 const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH;
17683 let mut bank = create_simple_test_bank(1_000_000_000_000);
17684 bank.activate_feature(&feature_set::cap_accounts_data_len::id());
17685 let transaction = system_transaction::create_account(
17686 &Keypair::new(),
17687 &Keypair::new(),
17688 bank.last_blockhash(),
17689 LAMPORTS_PER_SAFE,
17690 ACCOUNT_SIZE,
17691 &solana_sdk::system_program::id(),
17692 );
17693
17694 let accounts_data_size_before = bank.load_accounts_data_size();
17695 let accounts_data_size_delta_before = bank.load_accounts_data_size_delta();
17696 let accounts_data_size_delta_on_chain_before =
17697 bank.load_accounts_data_size_delta_on_chain();
17698 let result = bank.process_transaction(&transaction);
17699 let accounts_data_size_after = bank.load_accounts_data_size();
17700 let accounts_data_size_delta_after = bank.load_accounts_data_size_delta();
17701 let accounts_data_size_delta_on_chain_after = bank.load_accounts_data_size_delta_on_chain();
17702
17703 assert!(result.is_err());
17704 assert_eq!(accounts_data_size_after, accounts_data_size_before,);
17705 assert_eq!(
17706 accounts_data_size_delta_after,
17707 accounts_data_size_delta_before,
17708 );
17709 assert_eq!(
17710 accounts_data_size_delta_on_chain_after,
17711 accounts_data_size_delta_on_chain_before,
17712 );
17713 }
17714
17715 #[derive(Serialize, Deserialize)]
17716 enum MockTransferInstruction {
17717 Transfer(u64),
17718 }
17719
17720 fn mock_transfer_process_instruction(
17721 _first_instruction_account: usize,
17722 invoke_context: &mut InvokeContext,
17723 ) -> result::Result<(), InstructionError> {
17724 let transaction_context = &invoke_context.transaction_context;
17725 let instruction_context = transaction_context.get_current_instruction_context()?;
17726 let instruction_data = instruction_context.get_instruction_data();
17727 if let Ok(instruction) = bincode::deserialize(instruction_data) {
17728 match instruction {
17729 MockTransferInstruction::Transfer(amount) => {
17730 instruction_context
17731 .try_borrow_instruction_account(transaction_context, 1)?
17732 .checked_sub_lamports(amount)?;
17733 instruction_context
17734 .try_borrow_instruction_account(transaction_context, 2)?
17735 .checked_add_lamports(amount)?;
17736 Ok(())
17737 }
17738 }
17739 } else {
17740 Err(InstructionError::InvalidInstructionData)
17741 }
17742 }
17743
17744 fn create_mock_transfer(
17745 payer: &Keypair,
17746 from: &Keypair,
17747 to: &Keypair,
17748 amount: u64,
17749 mock_program_id: Pubkey,
17750 recent_blockhash: Hash,
17751 ) -> Transaction {
17752 let account_metas = vec![
17753 AccountMeta::new(payer.pubkey(), true),
17754 AccountMeta::new(from.pubkey(), true),
17755 AccountMeta::new(to.pubkey(), true),
17756 ];
17757 let transfer_instruction = Instruction::new_with_bincode(
17758 mock_program_id,
17759 &MockTransferInstruction::Transfer(amount),
17760 account_metas,
17761 );
17762 Transaction::new_signed_with_payer(
17763 &[transfer_instruction],
17764 Some(&payer.pubkey()),
17765 &[payer, from, to],
17766 recent_blockhash,
17767 )
17768 }
17769
17770 #[test]
17771 fn test_invalid_rent_state_changes_existing_accounts() {
17772 let GenesisConfigInfo {
17773 mut genesis_config,
17774 mint_keypair,
17775 ..
17776 } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
17777 genesis_config.rent = Rent::default();
17778
17779 let mock_program_id = Pubkey::new_unique();
17780 let account_data_size = 100;
17781 let rent_exempt_minimum = genesis_config.rent.minimum_balance(account_data_size);
17782
17783 let rent_paying_account = Keypair::new();
17785 genesis_config.accounts.insert(
17786 rent_paying_account.pubkey(),
17787 Account::new_rent_epoch(
17788 rent_exempt_minimum - 1,
17789 account_data_size,
17790 &mock_program_id,
17791 INITIAL_RENT_EPOCH + 1,
17792 ),
17793 );
17794 let rent_exempt_account = Keypair::new();
17795 genesis_config.accounts.insert(
17796 rent_exempt_account.pubkey(),
17797 Account::new_rent_epoch(
17798 rent_exempt_minimum,
17799 account_data_size,
17800 &mock_program_id,
17801 INITIAL_RENT_EPOCH + 1,
17802 ),
17803 );
17804
17805 let mut bank = Bank::new_for_tests(&genesis_config);
17806 bank.add_builtin(
17807 "mock_program",
17808 &mock_program_id,
17809 mock_transfer_process_instruction,
17810 );
17811 let recent_blockhash = bank.last_blockhash();
17812
17813 let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
17814 let account = bank.get_account(pubkey).unwrap();
17815 Rent::default().is_exempt(account.lamports(), account.data().len())
17816 };
17817
17818 let tx = create_mock_transfer(
17820 &mint_keypair, &rent_paying_account, &mint_keypair, 1,
17824 mock_program_id,
17825 recent_blockhash,
17826 );
17827 let result = bank.process_transaction(&tx);
17828 assert!(result.is_ok());
17829 assert!(!check_account_is_rent_exempt(&rent_paying_account.pubkey()));
17830 let tx = create_mock_transfer(
17831 &mint_keypair, &rent_paying_account, &mint_keypair, rent_exempt_minimum - 2,
17835 mock_program_id,
17836 recent_blockhash,
17837 );
17838 let result = bank.process_transaction(&tx);
17839 assert!(result.is_ok());
17840 assert!(bank.get_account(&rent_paying_account.pubkey()).is_none());
17841
17842 bank.store_account(
17843 &rent_paying_account.pubkey(),
17845 &AccountSharedData::new(rent_exempt_minimum - 1, account_data_size, &mock_program_id),
17846 );
17847 let result = bank.transfer(1, &mint_keypair, &rent_paying_account.pubkey());
17848 assert!(result.is_ok());
17849 assert!(check_account_is_rent_exempt(&rent_paying_account.pubkey()));
17850
17851 let tx = create_mock_transfer(
17853 &mint_keypair, &rent_exempt_account, &mint_keypair, 1,
17857 mock_program_id,
17858 recent_blockhash,
17859 );
17860 let result = bank.process_transaction(&tx);
17861 assert!(result.is_err());
17862 assert!(check_account_is_rent_exempt(&rent_exempt_account.pubkey()));
17863 let result = bank.transfer(1, &mint_keypair, &rent_exempt_account.pubkey());
17864 assert!(result.is_ok());
17865 assert!(check_account_is_rent_exempt(&rent_exempt_account.pubkey()));
17866 let tx = create_mock_transfer(
17867 &mint_keypair, &rent_exempt_account, &mint_keypair, rent_exempt_minimum + 1,
17871 mock_program_id,
17872 recent_blockhash,
17873 );
17874 let result = bank.process_transaction(&tx);
17875 assert!(result.is_ok());
17876 assert!(bank.get_account(&rent_exempt_account.pubkey()).is_none());
17877 }
17878
17879 #[test]
17880 fn test_invalid_rent_state_changes_new_accounts() {
17881 let GenesisConfigInfo {
17882 mut genesis_config,
17883 mint_keypair,
17884 ..
17885 } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
17886 genesis_config.rent = Rent::default();
17887
17888 let mock_program_id = Pubkey::new_unique();
17889 let account_data_size = 100;
17890 let rent_exempt_minimum = genesis_config.rent.minimum_balance(account_data_size);
17891
17892 let mut bank = Bank::new_for_tests(&genesis_config);
17893 bank.add_builtin(
17894 "mock_program",
17895 &mock_program_id,
17896 mock_transfer_process_instruction,
17897 );
17898 let recent_blockhash = bank.last_blockhash();
17899
17900 let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
17901 let account = bank.get_account(pubkey).unwrap();
17902 Rent::default().is_exempt(account.lamports(), account.data().len())
17903 };
17904
17905 let rent_paying_account = Keypair::new();
17907 let tx = system_transaction::create_account(
17908 &mint_keypair,
17909 &rent_paying_account,
17910 recent_blockhash,
17911 rent_exempt_minimum - 1,
17912 account_data_size as u64,
17913 &mock_program_id,
17914 );
17915 let result = bank.process_transaction(&tx);
17916 assert!(result.is_err());
17917 assert!(bank.get_account(&rent_paying_account.pubkey()).is_none());
17918
17919 let rent_exempt_account = Keypair::new();
17921 let tx = system_transaction::create_account(
17922 &mint_keypair,
17923 &rent_exempt_account,
17924 recent_blockhash,
17925 rent_exempt_minimum,
17926 account_data_size as u64,
17927 &mock_program_id,
17928 );
17929 let result = bank.process_transaction(&tx);
17930 assert!(result.is_ok());
17931 assert!(check_account_is_rent_exempt(&rent_exempt_account.pubkey()));
17932 }
17933
17934 #[test]
17935 fn test_drained_created_account() {
17936 let GenesisConfigInfo {
17937 mut genesis_config,
17938 mint_keypair,
17939 ..
17940 } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
17941 genesis_config.rent = Rent::default();
17942 activate_all_features(&mut genesis_config);
17943
17944 let mock_program_id = Pubkey::new_unique();
17945 let data_size_no_rent = 100;
17948 let data_size_rent = 10000;
17950 let lamports_to_transfer = 100;
17951
17952 let created_keypair = Keypair::new();
17954
17955 let mut bank = Bank::new_for_tests(&genesis_config);
17956 bank.add_builtin(
17957 "mock_program",
17958 &mock_program_id,
17959 mock_transfer_process_instruction,
17960 );
17961 let recent_blockhash = bank.last_blockhash();
17962
17963 let create_instruction = system_instruction::create_account(
17965 &mint_keypair.pubkey(),
17966 &created_keypair.pubkey(),
17967 lamports_to_transfer,
17968 data_size_no_rent,
17969 &mock_program_id,
17970 );
17971 let account_metas = vec![
17972 AccountMeta::new(mint_keypair.pubkey(), true),
17973 AccountMeta::new(created_keypair.pubkey(), true),
17974 AccountMeta::new(mint_keypair.pubkey(), false),
17975 ];
17976 let transfer_from_instruction = Instruction::new_with_bincode(
17977 mock_program_id,
17978 &MockTransferInstruction::Transfer(lamports_to_transfer),
17979 account_metas,
17980 );
17981 let tx = Transaction::new_signed_with_payer(
17982 &[create_instruction, transfer_from_instruction],
17983 Some(&mint_keypair.pubkey()),
17984 &[&mint_keypair, &created_keypair],
17985 recent_blockhash,
17986 );
17987
17988 let result = bank.process_transaction(&tx);
17989 assert!(result.is_ok());
17990 assert!(bank.get_account(&created_keypair.pubkey()).is_none());
17993
17994 let create_instruction = system_instruction::create_account(
17996 &mint_keypair.pubkey(),
17997 &created_keypair.pubkey(),
17998 lamports_to_transfer,
17999 data_size_rent,
18000 &mock_program_id,
18001 );
18002 let account_metas = vec![
18003 AccountMeta::new(mint_keypair.pubkey(), true),
18004 AccountMeta::new(created_keypair.pubkey(), true),
18005 AccountMeta::new(mint_keypair.pubkey(), false),
18006 ];
18007 let transfer_from_instruction = Instruction::new_with_bincode(
18008 mock_program_id,
18009 &MockTransferInstruction::Transfer(lamports_to_transfer),
18010 account_metas,
18011 );
18012 let tx = Transaction::new_signed_with_payer(
18013 &[create_instruction, transfer_from_instruction],
18014 Some(&mint_keypair.pubkey()),
18015 &[&mint_keypair, &created_keypair],
18016 recent_blockhash,
18017 );
18018
18019 let result = bank.process_transaction(&tx);
18020 assert!(result.is_ok());
18021 assert!(bank.get_account(&created_keypair.pubkey()).is_none());
18023 }
18024
18025 #[test]
18026 fn test_rent_state_changes_sysvars() {
18027 let GenesisConfigInfo {
18028 mut genesis_config,
18029 mint_keypair,
18030 ..
18031 } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
18032 genesis_config.rent = Rent::default();
18033
18034 let validator_pubkey = solana_sdk::pubkey::new_rand();
18035 let validator_stake_lamports = sol_to_lamports(1.);
18036 let validator_staking_keypair = Keypair::new();
18037 let validator_voting_keypair = Keypair::new();
18038
18039 let validator_vote_account = vote_state::create_account(
18040 &validator_voting_keypair.pubkey(),
18041 &validator_pubkey,
18042 0,
18043 validator_stake_lamports,
18044 );
18045
18046 let validator_stake_account = stake_state::create_account(
18047 &validator_staking_keypair.pubkey(),
18048 &validator_voting_keypair.pubkey(),
18049 &validator_vote_account,
18050 &genesis_config.rent,
18051 validator_stake_lamports,
18052 );
18053
18054 genesis_config.accounts.insert(
18055 validator_pubkey,
18056 Account::new(
18057 genesis_config.rent.minimum_balance(0),
18058 0,
18059 &system_program::id(),
18060 ),
18061 );
18062 genesis_config.accounts.insert(
18063 validator_staking_keypair.pubkey(),
18064 Account::from(validator_stake_account),
18065 );
18066 genesis_config.accounts.insert(
18067 validator_voting_keypair.pubkey(),
18068 Account::from(validator_vote_account),
18069 );
18070
18071 let bank = Bank::new_for_tests(&genesis_config);
18072
18073 let tx = Transaction::new_signed_with_payer(
18075 &[stake_instruction::deactivate_stake(
18076 &validator_staking_keypair.pubkey(),
18077 &validator_staking_keypair.pubkey(),
18078 )],
18079 Some(&mint_keypair.pubkey()),
18080 &[&mint_keypair, &validator_staking_keypair],
18081 bank.last_blockhash(),
18082 );
18083 let result = bank.process_transaction(&tx);
18084 assert!(result.is_ok());
18085 }
18086
18087 #[test]
18088 fn test_invalid_rent_state_changes_fee_payer() {
18089 let GenesisConfigInfo {
18090 mut genesis_config,
18091 mint_keypair,
18092 ..
18093 } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
18094 genesis_config.rent = Rent::default();
18095 genesis_config.fee_rate_governor = FeeRateGovernor::new(
18096 solana_sdk::fee_calculator::DEFAULT_TARGET_LAMPORTS_PER_SIGNATURE,
18097 solana_sdk::fee_calculator::DEFAULT_TARGET_SIGNATURES_PER_SLOT,
18098 );
18099 let rent_exempt_minimum = genesis_config.rent.minimum_balance(0);
18100
18101 let rent_paying_fee_payer = Keypair::new();
18103 genesis_config.accounts.insert(
18104 rent_paying_fee_payer.pubkey(),
18105 Account::new(rent_exempt_minimum - 1, 0, &system_program::id()),
18106 );
18107 let recipient = Pubkey::new_unique();
18109 genesis_config.accounts.insert(
18110 recipient,
18111 Account::new(rent_exempt_minimum, 0, &system_program::id()),
18112 );
18113
18114 let bank = Bank::new_for_tests(&genesis_config);
18115 let recent_blockhash = bank.last_blockhash();
18116
18117 let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
18118 let account = bank.get_account(pubkey).unwrap();
18119 Rent::default().is_exempt(account.lamports(), account.data().len())
18120 };
18121
18122 let rent_exempt_fee_payer = Keypair::new();
18124 bank.transfer(
18125 rent_exempt_minimum,
18126 &mint_keypair,
18127 &rent_exempt_fee_payer.pubkey(),
18128 )
18129 .unwrap();
18130
18131 let dummy_message = SanitizedMessage::try_from(Message::new_with_blockhash(
18133 &[system_instruction::transfer(
18134 &rent_exempt_fee_payer.pubkey(),
18135 &recipient,
18136 sol_to_lamports(1.),
18137 )],
18138 Some(&rent_exempt_fee_payer.pubkey()),
18139 &recent_blockhash,
18140 ))
18141 .unwrap();
18142 let fee = bank.get_fee_for_message(&dummy_message).unwrap();
18143
18144 let tx = Transaction::new(
18146 &[&rent_paying_fee_payer, &mint_keypair],
18147 Message::new(
18148 &[system_instruction::transfer(
18149 &mint_keypair.pubkey(),
18150 &recipient,
18151 rent_exempt_minimum,
18152 )],
18153 Some(&rent_paying_fee_payer.pubkey()),
18154 ),
18155 recent_blockhash,
18156 );
18157 let result = bank.process_transaction(&tx);
18158 assert!(result.is_ok());
18159 assert!(!check_account_is_rent_exempt(
18160 &rent_paying_fee_payer.pubkey()
18161 ));
18162
18163 let sender = Keypair::new();
18165 let fee_payer_balance = bank.get_balance(&rent_paying_fee_payer.pubkey());
18166 let tx = Transaction::new(
18167 &[&rent_paying_fee_payer, &sender],
18168 Message::new(
18169 &[system_instruction::transfer(
18170 &sender.pubkey(),
18171 &recipient,
18172 rent_exempt_minimum,
18173 )],
18174 Some(&rent_paying_fee_payer.pubkey()),
18175 ),
18176 recent_blockhash,
18177 );
18178 let result = bank.process_transaction(&tx);
18179 assert_eq!(
18180 result.unwrap_err(),
18181 TransactionError::InstructionError(0, InstructionError::Custom(1))
18182 );
18183 assert_ne!(
18184 fee_payer_balance,
18185 bank.get_balance(&rent_paying_fee_payer.pubkey())
18186 );
18187 assert!(!check_account_is_rent_exempt(
18188 &rent_paying_fee_payer.pubkey()
18189 ));
18190
18191 let tx = Transaction::new(
18193 &[&rent_paying_fee_payer],
18194 Message::new(
18195 &[system_instruction::transfer(
18196 &rent_paying_fee_payer.pubkey(),
18197 &recipient,
18198 bank.get_balance(&rent_paying_fee_payer.pubkey()) - fee,
18199 )],
18200 Some(&rent_paying_fee_payer.pubkey()),
18201 ),
18202 recent_blockhash,
18203 );
18204 let result = bank.process_transaction(&tx);
18205 assert!(result.is_ok());
18206 assert_eq!(0, bank.get_balance(&rent_paying_fee_payer.pubkey()));
18207
18208 let tx = Transaction::new(
18210 &[&rent_exempt_fee_payer, &mint_keypair],
18211 Message::new(
18212 &[system_instruction::transfer(
18213 &mint_keypair.pubkey(),
18214 &recipient,
18215 rent_exempt_minimum,
18216 )],
18217 Some(&rent_exempt_fee_payer.pubkey()),
18218 ),
18219 recent_blockhash,
18220 );
18221 let result = bank.process_transaction(&tx);
18222 assert_eq!(
18223 result.unwrap_err(),
18224 TransactionError::InsufficientFundsForRent { account_index: 0 }
18225 );
18226 assert!(check_account_is_rent_exempt(
18227 &rent_exempt_fee_payer.pubkey()
18228 ));
18229
18230 let tx = Transaction::new(
18232 &[&rent_exempt_fee_payer, &sender],
18233 Message::new(
18234 &[system_instruction::transfer(
18235 &sender.pubkey(),
18236 &recipient,
18237 rent_exempt_minimum,
18238 )],
18239 Some(&rent_exempt_fee_payer.pubkey()),
18240 ),
18241 recent_blockhash,
18242 );
18243 let result = bank.process_transaction(&tx);
18244 assert_eq!(
18245 result.unwrap_err(),
18246 TransactionError::InsufficientFundsForRent { account_index: 0 }
18247 );
18248 assert!(check_account_is_rent_exempt(
18249 &rent_exempt_fee_payer.pubkey()
18250 ));
18251
18252 bank.transfer(fee, &mint_keypair, &rent_exempt_fee_payer.pubkey())
18255 .unwrap();
18256 let fee_payer_balance = bank.get_balance(&rent_exempt_fee_payer.pubkey());
18257 assert_eq!(fee_payer_balance, rent_exempt_minimum + fee);
18258 let tx = Transaction::new(
18259 &[&rent_exempt_fee_payer],
18260 Message::new(
18261 &[system_instruction::transfer(
18262 &rent_exempt_fee_payer.pubkey(),
18263 &recipient,
18264 fee,
18265 )],
18266 Some(&rent_exempt_fee_payer.pubkey()),
18267 ),
18268 recent_blockhash,
18269 );
18270 let result = bank.process_transaction(&tx);
18271 assert_eq!(
18272 result.unwrap_err(),
18273 TransactionError::InsufficientFundsForRent { account_index: 0 }
18274 );
18275 assert_eq!(
18276 fee_payer_balance - fee,
18277 bank.get_balance(&rent_exempt_fee_payer.pubkey())
18278 );
18279 assert!(check_account_is_rent_exempt(
18280 &rent_exempt_fee_payer.pubkey()
18281 ));
18282
18283 bank.transfer(fee + 1, &mint_keypair, &rent_exempt_fee_payer.pubkey())
18285 .unwrap();
18286 assert!(bank.get_balance(&rent_exempt_fee_payer.pubkey()) > rent_exempt_minimum + fee);
18287 let tx = Transaction::new(
18288 &[&rent_exempt_fee_payer],
18289 Message::new(
18290 &[system_instruction::transfer(
18291 &rent_exempt_fee_payer.pubkey(),
18292 &recipient,
18293 bank.get_balance(&rent_exempt_fee_payer.pubkey()) - fee,
18294 )],
18295 Some(&rent_exempt_fee_payer.pubkey()),
18296 ),
18297 recent_blockhash,
18298 );
18299 let result = bank.process_transaction(&tx);
18300 assert!(result.is_ok());
18301 assert_eq!(0, bank.get_balance(&rent_exempt_fee_payer.pubkey()));
18302
18303 bank.transfer(
18305 rent_exempt_minimum + 1,
18306 &mint_keypair,
18307 &rent_exempt_fee_payer.pubkey(),
18308 )
18309 .unwrap();
18310 assert!(bank.get_balance(&rent_exempt_fee_payer.pubkey()) < rent_exempt_minimum + fee);
18311 let tx = Transaction::new(
18312 &[&rent_exempt_fee_payer],
18313 Message::new(
18314 &[system_instruction::transfer(
18315 &rent_exempt_fee_payer.pubkey(),
18316 &recipient,
18317 bank.get_balance(&rent_exempt_fee_payer.pubkey()) - fee,
18318 )],
18319 Some(&rent_exempt_fee_payer.pubkey()),
18320 ),
18321 recent_blockhash,
18322 );
18323 let result = bank.process_transaction(&tx);
18324 assert_eq!(
18325 result.unwrap_err(),
18326 TransactionError::InsufficientFundsForRent { account_index: 0 }
18327 );
18328 assert!(check_account_is_rent_exempt(
18329 &rent_exempt_fee_payer.pubkey()
18330 ));
18331 }
18332
18333 #[test]
18335 fn test_rent_state_incinerator() {
18336 let GenesisConfigInfo {
18337 mut genesis_config,
18338 mint_keypair,
18339 ..
18340 } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
18341 genesis_config.rent = Rent::default();
18342 let rent_exempt_minimum = genesis_config.rent.minimum_balance(0);
18343
18344 let bank = Bank::new_for_tests(&genesis_config);
18345
18346 for amount in [rent_exempt_minimum - 1, rent_exempt_minimum] {
18347 bank.transfer(amount, &mint_keypair, &solana_sdk::incinerator::id())
18348 .unwrap();
18349 }
18350 }
18351
18352 #[test]
18353 fn test_rent_state_list_len() {
18354 let GenesisConfigInfo {
18355 mut genesis_config,
18356 mint_keypair,
18357 ..
18358 } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
18359 genesis_config.rent = Rent::default();
18360
18361 let bank = Bank::new_for_tests(&genesis_config);
18362 let recipient = Pubkey::new_unique();
18363 let tx = system_transaction::transfer(
18364 &mint_keypair,
18365 &recipient,
18366 sol_to_lamports(1.),
18367 bank.last_blockhash(),
18368 );
18369 let number_of_instructions_at_transaction_level = tx.message().instructions.len();
18370 let num_accounts = tx.message().account_keys.len();
18371 let sanitized_tx = SanitizedTransaction::try_from_legacy_transaction(tx).unwrap();
18372 let mut error_counters = TransactionErrorMetrics::default();
18373 let loaded_txs = bank.rc.accounts.load_accounts(
18374 &bank.ancestors,
18375 &[sanitized_tx.clone()],
18376 vec![(Ok(()), None)],
18377 &bank.blockhash_queue.read().unwrap(),
18378 &mut error_counters,
18379 &bank.rent_collector,
18380 &bank.feature_set,
18381 &FeeStructure::default(),
18382 None,
18383 );
18384
18385 let compute_budget = bank.compute_budget.unwrap_or_else(|| {
18386 ComputeBudget::new(compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64)
18387 });
18388 let transaction_context = TransactionContext::new(
18389 loaded_txs[0].0.as_ref().unwrap().accounts.clone(),
18390 Some(Rent::default()),
18391 compute_budget.max_invoke_depth.saturating_add(1),
18392 number_of_instructions_at_transaction_level,
18393 );
18394
18395 assert_eq!(
18396 bank.get_transaction_account_state_info(&transaction_context, sanitized_tx.message())
18397 .len(),
18398 num_accounts,
18399 );
18400 }
18401
18402 #[test]
18403 fn test_update_accounts_data_size() {
18404 {
18406 let bank = create_simple_test_bank(100);
18407 let initial_data_size = bank.load_accounts_data_size() as i64;
18408 let data_size = 567;
18409 bank.accounts_data_size_delta_on_chain
18410 .store(data_size, Release);
18411 bank.update_accounts_data_size_delta_on_chain(
18412 (initial_data_size + data_size + 1).saturating_neg(),
18413 );
18414 assert_eq!(bank.load_accounts_data_size(), 0);
18415 }
18416
18417 {
18419 let mut bank = create_simple_test_bank(100);
18420 let data_size_remaining = 567;
18421 bank.accounts_data_size_initial = u64::MAX - data_size_remaining;
18422 bank.accounts_data_size_delta_off_chain
18423 .store((data_size_remaining + 1) as i64, Release);
18424 assert_eq!(bank.load_accounts_data_size(), u64::MAX);
18425 }
18426
18427 {
18429 let mut bank = create_simple_test_bank(100);
18432 bank.accounts_data_size_initial = u32::MAX as u64;
18433 let mut rng = rand::thread_rng();
18434 for _ in 0..100 {
18435 let initial = bank.load_accounts_data_size() as i64;
18436 let delta1 = rng.gen_range(-500, 500);
18437 bank.update_accounts_data_size_delta_on_chain(delta1);
18438 let delta2 = rng.gen_range(-500, 500);
18439 bank.update_accounts_data_size_delta_off_chain(delta2);
18440 assert_eq!(
18441 bank.load_accounts_data_size() as i64,
18442 initial.saturating_add(delta1).saturating_add(delta2),
18443 );
18444 }
18445 }
18446 }
18447
18448 #[test]
18449 fn test_skip_rewrite() {
18450 solana_logger::setup();
18451 let mut account = AccountSharedData::default();
18452 let bank_slot = 10;
18453 for account_rent_epoch in 0..3 {
18454 account.set_rent_epoch(account_rent_epoch);
18455 for rent_amount in [0, 1] {
18456 for loaded_slot in (bank_slot - 1)..=bank_slot {
18457 for old_rent_epoch in account_rent_epoch.saturating_sub(1)..=account_rent_epoch
18458 {
18459 let skip = Bank::skip_rewrite(
18460 bank_slot,
18461 rent_amount,
18462 loaded_slot,
18463 old_rent_epoch,
18464 &account,
18465 );
18466 let mut should_skip = true;
18467 if rent_amount != 0
18468 || account_rent_epoch == 0
18469 || (account_rent_epoch != old_rent_epoch && loaded_slot == bank_slot)
18470 {
18471 should_skip = false;
18472 }
18473 assert_eq!(
18474 skip,
18475 should_skip,
18476 "{:?}",
18477 (
18478 account_rent_epoch,
18479 old_rent_epoch,
18480 rent_amount,
18481 loaded_slot,
18482 old_rent_epoch
18483 )
18484 );
18485 }
18486 }
18487 }
18488 }
18489 }
18490
18491 #[test]
18492 fn test_remember_skipped_rewrites() {
18493 let GenesisConfigInfo {
18494 mut genesis_config, ..
18495 } = create_genesis_config_with_leader(1_000_000_000, &Pubkey::new_unique(), 42);
18496 genesis_config.rent = Rent::default();
18497 activate_all_features(&mut genesis_config);
18498
18499 let bank = Bank::new_for_tests(&genesis_config);
18500
18501 assert!(bank.rewrites_skipped_this_slot.read().unwrap().is_empty());
18502 bank.remember_skipped_rewrites(Vec::default());
18503 assert!(bank.rewrites_skipped_this_slot.read().unwrap().is_empty());
18504
18505 let mut test = vec![(Pubkey::from([4; 32]), Hash::new(&[5; 32]))];
18507 bank.remember_skipped_rewrites(test.clone());
18508 assert_eq!(
18509 *bank.rewrites_skipped_this_slot.read().unwrap(),
18510 test.clone().into_iter().collect()
18511 );
18512
18513 test.push((Pubkey::from([6; 32]), Hash::new(&[7; 32])));
18515 bank.remember_skipped_rewrites(test[1..].to_vec());
18516 assert_eq!(
18517 *bank.rewrites_skipped_this_slot.read().unwrap(),
18518 test.clone().into_iter().collect()
18519 );
18520
18521 bank.remember_skipped_rewrites(test[1..].to_vec());
18523 assert_eq!(
18524 *bank.rewrites_skipped_this_slot.read().unwrap(),
18525 test.clone().into_iter().collect()
18526 );
18527
18528 test[0].1 = Hash::new(&[8; 32]);
18530 test[1].1 = Hash::new(&[9; 32]);
18531 bank.remember_skipped_rewrites(test.to_vec());
18532 assert_eq!(
18533 *bank.rewrites_skipped_this_slot.read().unwrap(),
18534 test.into_iter().collect()
18535 );
18536 }
18537
18538 #[test]
18539 fn test_inner_instructions_list_from_instruction_trace() {
18540 let instruction_trace = vec![
18541 vec![
18542 InstructionContext::new(0, 0, &[], &[], &[1]),
18543 InstructionContext::new(1, 0, &[], &[], &[2]),
18544 ],
18545 vec![],
18546 vec![
18547 InstructionContext::new(0, 0, &[], &[], &[3]),
18548 InstructionContext::new(1, 0, &[], &[], &[4]),
18549 InstructionContext::new(2, 0, &[], &[], &[5]),
18550 InstructionContext::new(1, 0, &[], &[], &[6]),
18551 ],
18552 ];
18553
18554 let inner_instructions = inner_instructions_list_from_instruction_trace(&instruction_trace);
18555
18556 assert_eq!(
18557 inner_instructions,
18558 vec![
18559 vec![CompiledInstruction::new_from_raw_parts(0, vec![2], vec![])],
18560 vec![],
18561 vec![
18562 CompiledInstruction::new_from_raw_parts(0, vec![4], vec![]),
18563 CompiledInstruction::new_from_raw_parts(0, vec![5], vec![]),
18564 CompiledInstruction::new_from_raw_parts(0, vec![6], vec![])
18565 ]
18566 ]
18567 );
18568 }
18569
18570 #[derive(Serialize, Deserialize)]
18571 enum MockReallocInstruction {
18572 Realloc(usize, u64, Pubkey),
18573 }
18574
18575 fn mock_realloc_process_instruction(
18576 _first_instruction_account: usize,
18577 invoke_context: &mut InvokeContext,
18578 ) -> result::Result<(), InstructionError> {
18579 let transaction_context = &invoke_context.transaction_context;
18580 let instruction_context = transaction_context.get_current_instruction_context()?;
18581 let instruction_data = instruction_context.get_instruction_data();
18582 if let Ok(instruction) = bincode::deserialize(instruction_data) {
18583 match instruction {
18584 MockReallocInstruction::Realloc(new_size, new_balance, _) => {
18585 instruction_context
18587 .try_borrow_instruction_account(transaction_context, 1)?
18588 .set_data_length(new_size)?;
18589
18590 let current_balance = instruction_context
18592 .try_borrow_instruction_account(transaction_context, 1)?
18593 .get_lamports();
18594 let diff_balance = (new_balance as i64).saturating_sub(current_balance as i64);
18595 let amount = diff_balance.unsigned_abs();
18596 if diff_balance.is_positive() {
18597 instruction_context
18598 .try_borrow_instruction_account(transaction_context, 0)?
18599 .checked_sub_lamports(amount)?;
18600 instruction_context
18601 .try_borrow_instruction_account(transaction_context, 1)?
18602 .set_lamports(new_balance)?;
18603 } else {
18604 instruction_context
18605 .try_borrow_instruction_account(transaction_context, 0)?
18606 .checked_add_lamports(amount)?;
18607 instruction_context
18608 .try_borrow_instruction_account(transaction_context, 1)?
18609 .set_lamports(new_balance)?;
18610 }
18611 Ok(())
18612 }
18613 }
18614 } else {
18615 Err(InstructionError::InvalidInstructionData)
18616 }
18617 }
18618
18619 fn create_mock_realloc_tx(
18620 payer: &Keypair,
18621 funder: &Keypair,
18622 reallocd: &Pubkey,
18623 new_size: usize,
18624 new_balance: u64,
18625 mock_program_id: Pubkey,
18626 recent_blockhash: Hash,
18627 ) -> Transaction {
18628 let account_metas = vec![
18629 AccountMeta::new(funder.pubkey(), false),
18630 AccountMeta::new(*reallocd, false),
18631 ];
18632 let instruction = Instruction::new_with_bincode(
18633 mock_program_id,
18634 &MockReallocInstruction::Realloc(new_size, new_balance, Pubkey::new_unique()),
18635 account_metas,
18636 );
18637 Transaction::new_signed_with_payer(
18638 &[instruction],
18639 Some(&payer.pubkey()),
18640 &[payer],
18641 recent_blockhash,
18642 )
18643 }
18644
18645 #[test]
18646 fn test_resize_and_rent() {
18647 let GenesisConfigInfo {
18648 mut genesis_config,
18649 mint_keypair,
18650 ..
18651 } = create_genesis_config_with_leader(1_000_000_000, &Pubkey::new_unique(), 42);
18652 genesis_config.rent = Rent::default();
18653 activate_all_features(&mut genesis_config);
18654
18655 let mut bank = Bank::new_for_tests(&genesis_config);
18656
18657 let mock_program_id = Pubkey::new_unique();
18658 bank.add_builtin(
18659 "mock_realloc_program",
18660 &mock_program_id,
18661 mock_realloc_process_instruction,
18662 );
18663 let recent_blockhash = bank.last_blockhash();
18664
18665 let account_data_size_small = 1024;
18666 let rent_exempt_minimum_small =
18667 genesis_config.rent.minimum_balance(account_data_size_small);
18668 let account_data_size_large = 2048;
18669 let rent_exempt_minimum_large =
18670 genesis_config.rent.minimum_balance(account_data_size_large);
18671
18672 let funding_keypair = Keypair::new();
18673 bank.store_account(
18674 &funding_keypair.pubkey(),
18675 &AccountSharedData::new(1_000_000_000, 0, &mock_program_id),
18676 );
18677
18678 let rent_paying_pubkey = solana_sdk::pubkey::new_rand();
18679 let mut rent_paying_account = AccountSharedData::new(
18680 rent_exempt_minimum_small - 1,
18681 account_data_size_small,
18682 &mock_program_id,
18683 );
18684 rent_paying_account.set_rent_epoch(1);
18685
18686 bank.store_account(&rent_paying_pubkey, &rent_paying_account);
18688
18689 let tx = create_mock_realloc_tx(
18691 &mint_keypair,
18692 &funding_keypair,
18693 &rent_paying_pubkey,
18694 account_data_size_large,
18695 rent_exempt_minimum_small - 1,
18696 mock_program_id,
18697 recent_blockhash,
18698 );
18699 let expected_err = {
18700 let account_index = tx
18701 .message
18702 .account_keys
18703 .iter()
18704 .position(|key| key == &rent_paying_pubkey)
18705 .unwrap() as u8;
18706 TransactionError::InsufficientFundsForRent { account_index }
18707 };
18708 assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18709 assert_eq!(
18710 rent_exempt_minimum_small - 1,
18711 bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18712 );
18713
18714 let tx = create_mock_realloc_tx(
18716 &mint_keypair,
18717 &funding_keypair,
18718 &rent_paying_pubkey,
18719 account_data_size_large,
18720 rent_exempt_minimum_large,
18721 mock_program_id,
18722 recent_blockhash,
18723 );
18724 let result = bank.process_transaction(&tx);
18725 assert!(result.is_ok());
18726 assert_eq!(
18727 rent_exempt_minimum_large,
18728 bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18729 );
18730
18731 let tx = create_mock_realloc_tx(
18733 &mint_keypair,
18734 &funding_keypair,
18735 &rent_paying_pubkey,
18736 account_data_size_small,
18737 rent_exempt_minimum_small - 1,
18738 mock_program_id,
18739 recent_blockhash,
18740 );
18741 let expected_err = {
18742 let account_index = tx
18743 .message
18744 .account_keys
18745 .iter()
18746 .position(|key| key == &rent_paying_pubkey)
18747 .unwrap() as u8;
18748 TransactionError::InsufficientFundsForRent { account_index }
18749 };
18750 assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18751 assert_eq!(
18752 rent_exempt_minimum_large,
18753 bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18754 );
18755
18756 let tx = create_mock_realloc_tx(
18758 &mint_keypair,
18759 &funding_keypair,
18760 &rent_paying_pubkey,
18761 account_data_size_small,
18762 rent_exempt_minimum_small,
18763 mock_program_id,
18764 recent_blockhash,
18765 );
18766 let result = bank.process_transaction(&tx);
18767 assert!(result.is_ok());
18768 assert_eq!(
18769 rent_exempt_minimum_small,
18770 bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18771 );
18772
18773 let tx = create_mock_realloc_tx(
18775 &mint_keypair,
18776 &funding_keypair,
18777 &rent_paying_pubkey,
18778 account_data_size_large,
18779 rent_exempt_minimum_large - 1,
18780 mock_program_id,
18781 recent_blockhash,
18782 );
18783 let expected_err = {
18784 let account_index = tx
18785 .message
18786 .account_keys
18787 .iter()
18788 .position(|key| key == &rent_paying_pubkey)
18789 .unwrap() as u8;
18790 TransactionError::InsufficientFundsForRent { account_index }
18791 };
18792 assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18793 assert_eq!(
18794 rent_exempt_minimum_small,
18795 bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18796 );
18797
18798 let tx = create_mock_realloc_tx(
18800 &mint_keypair,
18801 &funding_keypair,
18802 &rent_paying_pubkey,
18803 account_data_size_large,
18804 rent_exempt_minimum_large,
18805 mock_program_id,
18806 recent_blockhash,
18807 );
18808 let result = bank.process_transaction(&tx);
18809 assert!(result.is_ok());
18810 assert_eq!(
18811 rent_exempt_minimum_large,
18812 bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18813 );
18814
18815 let created_keypair = Keypair::new();
18816
18817 let tx = system_transaction::create_account(
18819 &mint_keypair,
18820 &created_keypair,
18821 recent_blockhash,
18822 rent_exempt_minimum_small - 1,
18823 account_data_size_small as u64,
18824 &system_program::id(),
18825 );
18826 let expected_err = {
18827 let account_index = tx
18828 .message
18829 .account_keys
18830 .iter()
18831 .position(|key| key == &created_keypair.pubkey())
18832 .unwrap() as u8;
18833 TransactionError::InsufficientFundsForRent { account_index }
18834 };
18835 assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18836
18837 let tx = system_transaction::create_account(
18839 &mint_keypair,
18840 &created_keypair,
18841 recent_blockhash,
18842 rent_exempt_minimum_small,
18843 account_data_size_small as u64,
18844 &system_program::id(),
18845 );
18846 let result = bank.process_transaction(&tx);
18847 assert!(result.is_ok());
18848 assert_eq!(
18849 rent_exempt_minimum_small,
18850 bank.get_account(&created_keypair.pubkey())
18851 .unwrap()
18852 .lamports()
18853 );
18854
18855 let created_keypair = Keypair::new();
18856 let tx = system_transaction::create_account(
18858 &mint_keypair,
18859 &created_keypair,
18860 recent_blockhash,
18861 rent_exempt_minimum_small - 1,
18862 0,
18863 &system_program::id(),
18864 );
18865 let result = bank.process_transaction(&tx);
18866 assert!(result.is_ok());
18867 assert_eq!(
18868 rent_exempt_minimum_small - 1,
18869 bank.get_account(&created_keypair.pubkey())
18870 .unwrap()
18871 .lamports()
18872 );
18873
18874 let tx = system_transaction::allocate(
18876 &mint_keypair,
18877 &created_keypair,
18878 recent_blockhash,
18879 (account_data_size_small + 1) as u64,
18880 );
18881 let expected_err = {
18882 let account_index = tx
18883 .message
18884 .account_keys
18885 .iter()
18886 .position(|key| key == &created_keypair.pubkey())
18887 .unwrap() as u8;
18888 TransactionError::InsufficientFundsForRent { account_index }
18889 };
18890 assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18891
18892 let tx = system_transaction::transfer(
18894 &mint_keypair,
18895 &created_keypair.pubkey(),
18896 1,
18897 recent_blockhash,
18898 );
18899 let result = bank.process_transaction(&tx);
18900 assert!(result.is_ok());
18901 assert_eq!(
18902 rent_exempt_minimum_small,
18903 bank.get_account(&created_keypair.pubkey())
18904 .unwrap()
18905 .lamports()
18906 );
18907
18908 let tx = system_transaction::allocate(
18910 &mint_keypair,
18911 &created_keypair,
18912 recent_blockhash,
18913 account_data_size_small as u64,
18914 );
18915 let result = bank.process_transaction(&tx);
18916 assert!(result.is_ok());
18917 assert_eq!(
18918 rent_exempt_minimum_small,
18919 bank.get_account(&created_keypair.pubkey())
18920 .unwrap()
18921 .lamports()
18922 );
18923 }
18924
18925 #[test]
18927 fn test_accounts_data_size_and_resize_transactions() {
18928 let GenesisConfigInfo {
18929 genesis_config,
18930 mint_keypair,
18931 ..
18932 } = genesis_utils::create_genesis_config(100 * LAMPORTS_PER_SAFE);
18933 let mut bank = Bank::new_for_tests(&genesis_config);
18934 let mock_program_id = Pubkey::new_unique();
18935 bank.add_builtin(
18936 "mock_realloc_program",
18937 &mock_program_id,
18938 mock_realloc_process_instruction,
18939 );
18940 let recent_blockhash = bank.last_blockhash();
18941
18942 let funding_keypair = Keypair::new();
18943 bank.store_account(
18944 &funding_keypair.pubkey(),
18945 &AccountSharedData::new(10 * LAMPORTS_PER_SAFE, 0, &mock_program_id),
18946 );
18947
18948 let mut rng = rand::thread_rng();
18949
18950 {
18952 let account_pubkey = Pubkey::new_unique();
18953 let account_balance = LAMPORTS_PER_SAFE;
18954 let account_size = rng.gen_range(1, MAX_PERMITTED_DATA_LENGTH) as usize;
18955 let account_data =
18956 AccountSharedData::new(account_balance, account_size, &mock_program_id);
18957 bank.store_account(&account_pubkey, &account_data);
18958
18959 let accounts_data_size_before = bank.load_accounts_data_size();
18960 let account_grow_size = rng.gen_range(1, MAX_PERMITTED_DATA_INCREASE);
18961 let transaction = create_mock_realloc_tx(
18962 &mint_keypair,
18963 &funding_keypair,
18964 &account_pubkey,
18965 account_size + account_grow_size,
18966 account_balance,
18967 mock_program_id,
18968 recent_blockhash,
18969 );
18970 let result = bank.process_transaction(&transaction);
18971 assert!(result.is_ok());
18972 let accounts_data_size_after = bank.load_accounts_data_size();
18973 assert_eq!(
18974 accounts_data_size_after,
18975 accounts_data_size_before.saturating_add(account_grow_size as u64),
18976 );
18977 }
18978
18979 {
18981 let account_pubkey = Pubkey::new_unique();
18982 let account_balance = LAMPORTS_PER_SAFE;
18983 let account_size =
18984 rng.gen_range(MAX_PERMITTED_DATA_LENGTH / 2, MAX_PERMITTED_DATA_LENGTH) as usize;
18985 let account_data =
18986 AccountSharedData::new(account_balance, account_size, &mock_program_id);
18987 bank.store_account(&account_pubkey, &account_data);
18988
18989 let accounts_data_size_before = bank.load_accounts_data_size();
18990 let account_shrink_size = rng.gen_range(1, account_size);
18991 let transaction = create_mock_realloc_tx(
18992 &mint_keypair,
18993 &funding_keypair,
18994 &account_pubkey,
18995 account_size - account_shrink_size,
18996 account_balance,
18997 mock_program_id,
18998 recent_blockhash,
18999 );
19000 let result = bank.process_transaction(&transaction);
19001 assert!(result.is_ok());
19002 let accounts_data_size_after = bank.load_accounts_data_size();
19003 assert_eq!(
19004 accounts_data_size_after,
19005 accounts_data_size_before.saturating_sub(account_shrink_size as u64),
19006 );
19007 }
19008 }
19009
19010 #[test]
19011 fn test_get_partition_end_indexes() {
19012 for n in 5..7 {
19013 assert_eq!(vec![0], Bank::get_partition_end_indexes(&(0, 0, n)));
19014 assert!(Bank::get_partition_end_indexes(&(1, 1, n)).is_empty());
19015 assert_eq!(vec![1], Bank::get_partition_end_indexes(&(0, 1, n)));
19016 assert_eq!(vec![1, 2], Bank::get_partition_end_indexes(&(0, 2, n)));
19017 assert_eq!(vec![3, 4], Bank::get_partition_end_indexes(&(2, 4, n)));
19018 }
19019 }
19020
19021 #[test]
19022 fn test_get_rent_paying_pubkeys() {
19023 let lamports = 1;
19024 let bank = create_simple_test_bank(lamports);
19025
19026 let n = 432_000;
19027 assert!(bank.get_rent_paying_pubkeys(&(0, 1, n)).is_none());
19028 assert!(bank.get_rent_paying_pubkeys(&(0, 2, n)).is_none());
19029 assert!(bank.get_rent_paying_pubkeys(&(0, 0, n)).is_none());
19030
19031 let pk1 = Pubkey::from([2; 32]);
19032 let pk2 = Pubkey::from([3; 32]);
19033 let index1 = Bank::partition_from_pubkey(&pk1, n);
19034 let index2 = Bank::partition_from_pubkey(&pk2, n);
19035 assert!(index1 > 0, "{}", index1);
19036 assert!(index2 > index1, "{}, {}", index2, index1);
19037
19038 let epoch_schedule = EpochSchedule::custom(n, 0, false);
19039
19040 let mut rent_paying_accounts_by_partition =
19041 RentPayingAccountsByPartition::new(&epoch_schedule);
19042 rent_paying_accounts_by_partition.add_account(&pk1);
19043 rent_paying_accounts_by_partition.add_account(&pk2);
19044
19045 bank.rc
19046 .accounts
19047 .accounts_db
19048 .accounts_index
19049 .rent_paying_accounts_by_partition
19050 .set(rent_paying_accounts_by_partition)
19051 .unwrap();
19052
19053 assert_eq!(
19054 bank.get_rent_paying_pubkeys(&(0, 1, n)),
19055 Some(HashSet::default())
19056 );
19057 assert_eq!(
19058 bank.get_rent_paying_pubkeys(&(0, 2, n)),
19059 Some(HashSet::default())
19060 );
19061 assert_eq!(
19062 bank.get_rent_paying_pubkeys(&(index1.saturating_sub(1), index1, n)),
19063 Some(HashSet::from([pk1]))
19064 );
19065 assert_eq!(
19066 bank.get_rent_paying_pubkeys(&(index2.saturating_sub(1), index2, n)),
19067 Some(HashSet::from([pk2]))
19068 );
19069 assert_eq!(
19070 bank.get_rent_paying_pubkeys(&(index1.saturating_sub(1), index2, n)),
19071 Some(HashSet::from([pk2, pk1]))
19072 );
19073 assert_eq!(
19074 bank.get_rent_paying_pubkeys(&(0, 0, n)),
19075 Some(HashSet::default())
19076 );
19077 }
19078
19079 #[test]
19081 fn test_accounts_data_size_and_rent_collection() {
19082 let GenesisConfigInfo {
19083 mut genesis_config, ..
19084 } = genesis_utils::create_genesis_config(100 * LAMPORTS_PER_SAFE);
19085 genesis_config.rent = Rent::default();
19086 activate_all_features(&mut genesis_config);
19087 let bank = Arc::new(Bank::new_for_tests(&genesis_config));
19088 let bank = Arc::new(Bank::new_from_parent(
19089 &bank,
19090 &Pubkey::default(),
19091 bank.slot() + bank.slot_count_per_normal_epoch(),
19092 ));
19093
19094 let bank = Arc::new(Bank::new_from_parent(
19097 &bank,
19098 &Pubkey::default(),
19099 bank.slot() + bank.slot_count_per_normal_epoch(),
19100 ));
19101
19102 let data_size = 123;
19104 let mut account = AccountSharedData::new(1, data_size, &Pubkey::default());
19105 let keypair = Keypair::new();
19106 bank.store_account(&keypair.pubkey(), &account);
19107
19108 {
19110 let info = bank.rent_collector.collect_from_existing_account(
19111 &keypair.pubkey(),
19112 &mut account,
19113 None,
19114 true, );
19116 assert_eq!(info.account_data_len_reclaimed, data_size as u64);
19117 }
19118
19119 let accounts_data_size_delta_before_collecting_rent = bank.load_accounts_data_size_delta();
19121 bank.collect_rent_eagerly(false);
19122 let accounts_data_size_delta_after_collecting_rent = bank.load_accounts_data_size_delta();
19123
19124 let accounts_data_size_delta_delta = accounts_data_size_delta_after_collecting_rent as i64
19125 - accounts_data_size_delta_before_collecting_rent as i64;
19126 assert!(accounts_data_size_delta_delta < 0);
19127 let reclaimed_data_size = accounts_data_size_delta_delta.saturating_neg() as usize;
19128
19129 assert_eq!(reclaimed_data_size, data_size,);
19131 }
19132
19133 #[test]
19134 fn test_accounts_data_size_with_default_bank() {
19135 let bank = Bank::default_for_tests();
19136 assert_eq!(
19137 bank.load_accounts_data_size() as usize,
19138 bank.get_total_accounts_stats().unwrap().data_len
19139 );
19140 }
19141
19142 #[test]
19143 fn test_accounts_data_size_from_genesis() {
19144 let GenesisConfigInfo {
19145 mut genesis_config,
19146 mint_keypair,
19147 ..
19148 } = genesis_utils::create_genesis_config_with_leader(
19149 1_000_000 * LAMPORTS_PER_SAFE,
19150 &Pubkey::new_unique(),
19151 100 * LAMPORTS_PER_SAFE,
19152 );
19153 genesis_config.rent = Rent::default();
19154 genesis_config.ticks_per_slot = 3;
19155
19156 let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
19157 assert_eq!(
19158 bank.load_accounts_data_size() as usize,
19159 bank.get_total_accounts_stats().unwrap().data_len
19160 );
19161
19162 for _ in 0..10 {
19164 bank = Arc::new(Bank::new_from_parent(
19165 &bank,
19166 &Pubkey::default(),
19167 bank.slot() + 1,
19168 ));
19169
19170 let data_size = rand::thread_rng().gen_range(3333, 4444);
19172 let transaction = system_transaction::create_account(
19173 &mint_keypair,
19174 &Keypair::new(),
19175 bank.last_blockhash(),
19176 genesis_config.rent.minimum_balance(data_size),
19177 data_size as u64,
19178 &solana_sdk::system_program::id(),
19179 );
19180 bank.process_transaction(&transaction).unwrap();
19181 bank.fill_bank_with_ticks_for_tests();
19182
19183 assert_eq!(
19184 bank.load_accounts_data_size() as usize,
19185 bank.get_total_accounts_stats().unwrap().data_len,
19186 );
19187 }
19188 }
19189
19190 #[test]
19191 fn test_calculate_fee_with_request_heap_frame_flag() {
19192 let key0 = Pubkey::new_unique();
19193 let key1 = Pubkey::new_unique();
19194 let lamports_per_signature: u64 = 5_000;
19195 let signature_fee: u64 = 10;
19196 let request_cu: u64 = 1;
19197 let lamports_per_cu: u64 = 5;
19198 let fee_structure = FeeStructure {
19199 lamports_per_signature: signature_fee,
19200 ..FeeStructure::default()
19201 };
19202 let message = SanitizedMessage::try_from(Message::new(
19203 &[
19204 system_instruction::transfer(&key0, &key1, 1),
19205 ComputeBudgetInstruction::set_compute_unit_limit(request_cu as u32),
19206 ComputeBudgetInstruction::request_heap_frame(40 * 1024),
19207 ComputeBudgetInstruction::set_compute_unit_price(lamports_per_cu * 1_000_000),
19208 ],
19209 Some(&key0),
19210 ))
19211 .unwrap();
19212
19213 let mut enable_request_heap_frame_ix = true;
19216 assert_eq!(
19217 Bank::calculate_fee(
19218 &message,
19219 lamports_per_signature,
19220 &fee_structure,
19221 true,
19222 true,
19223 enable_request_heap_frame_ix,
19224 ),
19225 signature_fee + request_cu * lamports_per_cu
19226 );
19227
19228 enable_request_heap_frame_ix = false;
19231 assert_eq!(
19232 Bank::calculate_fee(
19233 &message,
19234 lamports_per_signature,
19235 &fee_structure,
19236 true,
19237 true,
19238 enable_request_heap_frame_ix,
19239 ),
19240 signature_fee
19241 );
19242 }
19243}