1use {
37 crate::{
38 account_saver::collect_accounts_to_store,
39 bank::{
40 metrics::*,
41 partitioned_epoch_rewards::{EpochRewardStatus, StakeRewards, VoteRewardsAccounts},
42 },
43 bank_forks::BankForks,
44 epoch_stakes::{split_epoch_stakes, EpochStakes, NodeVoteAccounts, VersionedEpochStakes},
45 installed_scheduler_pool::{BankWithScheduler, InstalledSchedulerRwLock},
46 rent_collector::RentCollectorWithMetrics,
47 runtime_config::RuntimeConfig,
48 serde_snapshot::BankIncrementalSnapshotPersistence,
49 snapshot_hash::SnapshotHash,
50 stake_account::StakeAccount,
51 stake_weighted_timestamp::{
52 calculate_stake_weighted_timestamp, MaxAllowableDrift,
53 MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST, MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
54 },
55 stakes::{Stakes, StakesCache, StakesEnum},
56 status_cache::{SlotDelta, StatusCache},
57 transaction_batch::{OwnedOrBorrowed, TransactionBatch},
58 verify_precompiles::verify_precompiles,
59 },
60 accounts_lt_hash::{CacheValue as AccountsLtHashCacheValue, Stats as AccountsLtHashStats},
61 ahash::AHashSet,
62 dashmap::{DashMap, DashSet},
63 log::*,
64 rayon::{
65 iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator},
66 ThreadPoolBuilder,
67 },
68 serde::Serialize,
69 solana_accounts_db::{
70 account_locks::validate_account_locks,
71 accounts::{AccountAddressFilter, Accounts, PubkeyAccountSlot},
72 accounts_db::{
73 AccountStorageEntry, AccountsDb, AccountsDbConfig, CalcAccountsHashDataSource,
74 DuplicatesLtHash, OldStoragesPolicy, PubkeyHashAccount,
75 VerifyAccountsHashAndLamportsConfig,
76 },
77 accounts_hash::{
78 AccountHash, AccountsHash, AccountsLtHash, CalcAccountsHashConfig, HashStats,
79 IncrementalAccountsHash, MerkleOrLatticeAccountsHash,
80 },
81 accounts_index::{IndexKey, ScanConfig, ScanResult},
82 accounts_partition::{self, Partition, PartitionIndex},
83 accounts_update_notifier_interface::AccountsUpdateNotifier,
84 ancestors::{Ancestors, AncestorsForSerialization},
85 blockhash_queue::BlockhashQueue,
86 epoch_accounts_hash::EpochAccountsHash,
87 sorted_storages::SortedStorages,
88 storable_accounts::StorableAccounts,
89 },
90 solana_bpf_loader_program::syscalls::{
91 create_program_runtime_environment_v1, create_program_runtime_environment_v2,
92 },
93 solana_builtins::{prototype::BuiltinPrototype, BUILTINS, STATELESS_BUILTINS},
94 solana_compute_budget::compute_budget::ComputeBudget,
95 solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions,
96 solana_cost_model::{block_cost_limits::simd_0207_block_limits, cost_tracker::CostTracker},
97 solana_feature_set::{self as feature_set, reward_full_priority_fee, FeatureSet},
98 solana_fee::FeeFeatures,
99 solana_lattice_hash::lt_hash::LtHash,
100 solana_measure::{meas_dur, measure::Measure, measure_time, measure_us},
101 solana_program_runtime::{
102 invoke_context::BuiltinFunctionWithContext, loaded_programs::ProgramCacheEntry,
103 },
104 solana_runtime_transaction::{
105 runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta,
106 },
107 solana_sdk::{
108 account::{
109 create_account_shared_data_with_fields as create_account, from_account, Account,
110 AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
111 },
112 bpf_loader_upgradeable,
113 clock::{
114 BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_HASHES_PER_TICK,
115 DEFAULT_TICKS_PER_SECOND, INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE,
116 MAX_TRANSACTION_FORWARDING_DELAY, SECONDS_PER_DAY, UPDATED_HASHES_PER_TICK2,
117 UPDATED_HASHES_PER_TICK3, UPDATED_HASHES_PER_TICK4, UPDATED_HASHES_PER_TICK5,
118 UPDATED_HASHES_PER_TICK6,
119 },
120 epoch_info::EpochInfo,
121 epoch_schedule::EpochSchedule,
122 feature,
123 fee::{FeeBudgetLimits, FeeDetails, FeeStructure},
124 fee_calculator::FeeRateGovernor,
125 genesis_config::{ClusterType, GenesisConfig},
126 hard_forks::HardForks,
127 hash::{extend_and_hash, hashv, Hash},
128 incinerator,
129 inflation::Inflation,
130 inner_instruction::InnerInstructions,
131 message::{AccountKeys, SanitizedMessage},
132 native_loader,
133 native_token::LAMPORTS_PER_SOL,
134 packet::PACKET_DATA_SIZE,
135 precompiles::get_precompiles,
136 pubkey::Pubkey,
137 rent_collector::{CollectedInfo, RentCollector},
138 rent_debits::RentDebits,
139 reserved_account_keys::ReservedAccountKeys,
140 reward_info::RewardInfo,
141 signature::{Keypair, Signature},
142 slot_hashes::SlotHashes,
143 slot_history::{Check, SlotHistory},
144 stake::state::Delegation,
145 system_transaction,
146 sysvar::{self, last_restart_slot::LastRestartSlot, Sysvar, SysvarId},
147 timing::years_as_slots,
148 transaction::{
149 MessageHash, Result, SanitizedTransaction, Transaction, TransactionError,
150 TransactionVerificationMode, VersionedTransaction, MAX_TX_ACCOUNT_LOCKS,
151 },
152 transaction_context::{TransactionAccount, TransactionReturnData},
153 },
154 solana_stake_program::points::InflationPointCalculationEvent,
155 solana_svm::{
156 account_loader::{collect_rent_from_account, LoadedTransaction},
157 account_overrides::AccountOverrides,
158 transaction_commit_result::{CommittedTransaction, TransactionCommitResult},
159 transaction_error_metrics::TransactionErrorMetrics,
160 transaction_execution_result::{
161 TransactionExecutionDetails, TransactionLoadedAccountsStats,
162 },
163 transaction_processing_callback::{AccountState, TransactionProcessingCallback},
164 transaction_processing_result::{
165 ProcessedTransaction, TransactionProcessingResult,
166 TransactionProcessingResultExtensions,
167 },
168 transaction_processor::{
169 ExecutionRecordingConfig, TransactionBatchProcessor, TransactionLogMessages,
170 TransactionProcessingConfig, TransactionProcessingEnvironment,
171 },
172 },
173 solana_svm_transaction::svm_message::SVMMessage,
174 solana_timings::{ExecuteTimingType, ExecuteTimings},
175 solana_vote::vote_account::{VoteAccount, VoteAccountsHashMap},
176 std::{
177 collections::{HashMap, HashSet},
178 convert::TryFrom,
179 fmt,
180 ops::{AddAssign, RangeFull, RangeInclusive},
181 path::PathBuf,
182 slice,
183 sync::{
184 atomic::{
185 AtomicBool, AtomicI64, AtomicU64, AtomicUsize,
186 Ordering::{AcqRel, Acquire, Relaxed},
187 },
188 Arc, LockResult, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak,
189 },
190 thread::Builder,
191 time::{Duration, Instant},
192 },
193};
194pub use {
195 partitioned_epoch_rewards::KeyedRewardsAndNumPartitions, solana_sdk::reward_type::RewardType,
196};
197#[cfg(feature = "dev-context-only-utils")]
198use {
199 solana_accounts_db::accounts_db::{
200 ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
201 },
202 solana_nonce_account::{get_system_account_kind, SystemAccountKind},
203 solana_program_runtime::{loaded_programs::ProgramCacheForTxBatch, sysvar_cache::SysvarCache},
204 solana_sdk::nonce,
205 solana_svm::program_loader::load_program_with_pubkey,
206};
207
208struct VerifyAccountsHashConfig {
210 test_hash_calculation: bool,
211 ignore_mismatch: bool,
212 require_rooted_bank: bool,
213 run_in_background: bool,
214 store_hash_raw_data_for_debug: bool,
215}
216
217mod accounts_lt_hash;
218mod address_lookup_table;
219pub mod bank_hash_details;
220mod builtin_programs;
221pub mod builtins;
222mod check_transactions;
223pub mod epoch_accounts_hash_utils;
224mod fee_distribution;
225mod metrics;
226pub(crate) mod partitioned_epoch_rewards;
227mod recent_blockhashes_account;
228mod serde_snapshot;
229mod sysvar_cache;
230pub(crate) mod tests;
231
232pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0;
233
234pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5;
235
236#[derive(Default)]
237struct RentMetrics {
238 hold_range_us: AtomicU64,
239 load_us: AtomicU64,
240 collect_us: AtomicU64,
241 hash_us: AtomicU64,
242 store_us: AtomicU64,
243 count: AtomicUsize,
244}
245
246pub type BankStatusCache = StatusCache<Result<()>>;
247#[cfg_attr(
248 feature = "frozen-abi",
249 frozen_abi(digest = "4e7a7AAsQrM5Lp5bhREdVZ5QGZfyETbBthhWjYMYb6zS")
250)]
251pub type BankSlotDelta = SlotDelta<Result<()>>;
252
253#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
254pub struct SquashTiming {
255 pub squash_accounts_ms: u64,
256 pub squash_accounts_cache_ms: u64,
257 pub squash_accounts_index_ms: u64,
258 pub squash_accounts_store_ms: u64,
259
260 pub squash_cache_ms: u64,
261}
262
263impl AddAssign for SquashTiming {
264 fn add_assign(&mut self, rhs: Self) {
265 self.squash_accounts_ms += rhs.squash_accounts_ms;
266 self.squash_accounts_cache_ms += rhs.squash_accounts_cache_ms;
267 self.squash_accounts_index_ms += rhs.squash_accounts_index_ms;
268 self.squash_accounts_store_ms += rhs.squash_accounts_store_ms;
269 self.squash_cache_ms += rhs.squash_cache_ms;
270 }
271}
272
273#[derive(Debug, Default, PartialEq)]
274pub(crate) struct CollectorFeeDetails {
275 transaction_fee: u64,
276 priority_fee: u64,
277}
278
279impl CollectorFeeDetails {
280 pub(crate) fn accumulate(&mut self, fee_details: &FeeDetails) {
281 self.transaction_fee = self
282 .transaction_fee
283 .saturating_add(fee_details.transaction_fee());
284 self.priority_fee = self
285 .priority_fee
286 .saturating_add(fee_details.prioritization_fee());
287 }
288
289 pub(crate) fn total(&self) -> u64 {
290 self.transaction_fee.saturating_add(self.priority_fee)
291 }
292}
293
294impl From<FeeDetails> for CollectorFeeDetails {
295 fn from(fee_details: FeeDetails) -> Self {
296 CollectorFeeDetails {
297 transaction_fee: fee_details.transaction_fee(),
298 priority_fee: fee_details.prioritization_fee(),
299 }
300 }
301}
302
303#[derive(Debug)]
304pub struct BankRc {
305 pub accounts: Arc<Accounts>,
307
308 pub(crate) parent: RwLock<Option<Arc<Bank>>>,
310
311 pub(crate) bank_id_generator: Arc<AtomicU64>,
312}
313
314impl BankRc {
315 pub(crate) fn new(accounts: Accounts) -> Self {
316 Self {
317 accounts: Arc::new(accounts),
318 parent: RwLock::new(None),
319 bank_id_generator: Arc::new(AtomicU64::new(0)),
320 }
321 }
322}
323
324pub struct LoadAndExecuteTransactionsOutput {
325 pub processing_results: Vec<TransactionProcessingResult>,
328 pub processed_counts: ProcessedTransactionCounts,
331}
332
333#[derive(Debug, PartialEq)]
334pub struct TransactionSimulationResult {
335 pub result: Result<()>,
336 pub logs: TransactionLogMessages,
337 pub post_simulation_accounts: Vec<TransactionAccount>,
338 pub units_consumed: u64,
339 pub return_data: Option<TransactionReturnData>,
340 pub inner_instructions: Option<Vec<InnerInstructions>>,
341}
342
343#[derive(Clone, Debug)]
344pub struct TransactionBalancesSet {
345 pub pre_balances: TransactionBalances,
346 pub post_balances: TransactionBalances,
347}
348
349impl TransactionBalancesSet {
350 pub fn new(pre_balances: TransactionBalances, post_balances: TransactionBalances) -> Self {
351 assert_eq!(pre_balances.len(), post_balances.len());
352 Self {
353 pre_balances,
354 post_balances,
355 }
356 }
357}
358pub type TransactionBalances = Vec<Vec<u64>>;
359
360pub type PreCommitResult<'a> = Result<Option<RwLockReadGuard<'a, Hash>>>;
361
362#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
363pub enum TransactionLogCollectorFilter {
364 All,
365 AllWithVotes,
366 None,
367 OnlyMentionedAddresses,
368}
369
370impl Default for TransactionLogCollectorFilter {
371 fn default() -> Self {
372 Self::None
373 }
374}
375
376#[derive(Debug, Default)]
377pub struct TransactionLogCollectorConfig {
378 pub mentioned_addresses: HashSet<Pubkey>,
379 pub filter: TransactionLogCollectorFilter,
380}
381
382#[derive(Clone, Debug, PartialEq, Eq)]
383pub struct TransactionLogInfo {
384 pub signature: Signature,
385 pub result: Result<()>,
386 pub is_vote: bool,
387 pub log_messages: TransactionLogMessages,
388}
389
390#[derive(Default, Debug)]
391pub struct TransactionLogCollector {
392 pub logs: Vec<TransactionLogInfo>,
395
396 pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
399}
400
401impl TransactionLogCollector {
402 pub fn get_logs_for_address(
403 &self,
404 address: Option<&Pubkey>,
405 ) -> Option<Vec<TransactionLogInfo>> {
406 match address {
407 None => Some(self.logs.clone()),
408 Some(address) => self.mentioned_address_map.get(address).map(|log_indices| {
409 log_indices
410 .iter()
411 .filter_map(|i| self.logs.get(*i).cloned())
412 .collect()
413 }),
414 }
415 }
416}
417
418#[derive(Clone, Debug, Default)]
426#[cfg_attr(feature = "dev-context-only-utils", derive(PartialEq))]
427pub struct BankFieldsToDeserialize {
428 pub(crate) blockhash_queue: BlockhashQueue,
429 pub(crate) ancestors: AncestorsForSerialization,
430 pub(crate) hash: Hash,
431 pub(crate) parent_hash: Hash,
432 pub(crate) parent_slot: Slot,
433 pub(crate) hard_forks: HardForks,
434 pub(crate) transaction_count: u64,
435 pub(crate) tick_height: u64,
436 pub(crate) signature_count: u64,
437 pub(crate) capitalization: u64,
438 pub(crate) max_tick_height: u64,
439 pub(crate) hashes_per_tick: Option<u64>,
440 pub(crate) ticks_per_slot: u64,
441 pub(crate) ns_per_slot: u128,
442 pub(crate) genesis_creation_time: UnixTimestamp,
443 pub(crate) slots_per_year: f64,
444 pub(crate) slot: Slot,
445 pub(crate) epoch: Epoch,
446 pub(crate) block_height: u64,
447 pub(crate) collector_id: Pubkey,
448 pub(crate) collector_fees: u64,
449 pub(crate) fee_rate_governor: FeeRateGovernor,
450 pub(crate) collected_rent: u64,
451 pub(crate) rent_collector: RentCollector,
452 pub(crate) epoch_schedule: EpochSchedule,
453 pub(crate) inflation: Inflation,
454 pub(crate) stakes: Stakes<Delegation>,
455 pub(crate) epoch_stakes: HashMap<Epoch, EpochStakes>,
456 pub(crate) is_delta: bool,
457 pub(crate) accounts_data_len: u64,
458 pub(crate) incremental_snapshot_persistence: Option<BankIncrementalSnapshotPersistence>,
459 pub(crate) epoch_accounts_hash: Option<Hash>,
460 pub(crate) accounts_lt_hash: Option<AccountsLtHash>,
462 pub(crate) bank_hash_stats: BankHashStats,
463}
464
465#[derive(Debug)]
474pub struct BankFieldsToSerialize {
475 pub blockhash_queue: BlockhashQueue,
476 pub ancestors: AncestorsForSerialization,
477 pub hash: Hash,
478 pub parent_hash: Hash,
479 pub parent_slot: Slot,
480 pub hard_forks: HardForks,
481 pub transaction_count: u64,
482 pub tick_height: u64,
483 pub signature_count: u64,
484 pub capitalization: u64,
485 pub max_tick_height: u64,
486 pub hashes_per_tick: Option<u64>,
487 pub ticks_per_slot: u64,
488 pub ns_per_slot: u128,
489 pub genesis_creation_time: UnixTimestamp,
490 pub slots_per_year: f64,
491 pub slot: Slot,
492 pub epoch: Epoch,
493 pub block_height: u64,
494 pub collector_id: Pubkey,
495 pub collector_fees: u64,
496 pub fee_rate_governor: FeeRateGovernor,
497 pub collected_rent: u64,
498 pub rent_collector: RentCollector,
499 pub epoch_schedule: EpochSchedule,
500 pub inflation: Inflation,
501 pub stakes: StakesEnum,
502 pub epoch_stakes: HashMap<Epoch, EpochStakes>,
503 pub is_delta: bool,
504 pub accounts_data_len: u64,
505 pub versioned_epoch_stakes: HashMap<u64, VersionedEpochStakes>,
506 pub accounts_lt_hash: Option<AccountsLtHash>,
508}
509
510#[cfg(feature = "dev-context-only-utils")]
512impl PartialEq for Bank {
513 fn eq(&self, other: &Self) -> bool {
514 if std::ptr::eq(self, other) {
515 return true;
516 }
517 #[rustfmt::skip]
519 let Self {
520 skipped_rewrites: _,
521 rc: _,
522 status_cache: _,
523 blockhash_queue,
524 ancestors,
525 hash,
526 parent_hash,
527 parent_slot,
528 hard_forks,
529 transaction_count,
530 non_vote_transaction_count_since_restart: _,
531 transaction_error_count: _,
532 transaction_entries_count: _,
533 transactions_per_entry_max: _,
534 tick_height,
535 signature_count,
536 capitalization,
537 max_tick_height,
538 hashes_per_tick,
539 ticks_per_slot,
540 ns_per_slot,
541 genesis_creation_time,
542 slots_per_year,
543 slot,
544 bank_id: _,
545 epoch,
546 block_height,
547 collector_id,
548 collector_fees,
549 fee_rate_governor,
550 collected_rent,
551 rent_collector,
552 epoch_schedule,
553 inflation,
554 stakes_cache,
555 epoch_stakes,
556 is_delta,
557 #[cfg(feature = "dev-context-only-utils")]
558 hash_overrides,
559 accounts_lt_hash,
560 rewards: _,
562 cluster_type: _,
563 lazy_rent_collection: _,
564 rewards_pool_pubkeys: _,
565 transaction_debug_keys: _,
566 transaction_log_collector_config: _,
567 transaction_log_collector: _,
568 feature_set: _,
569 reserved_account_keys: _,
570 drop_callback: _,
571 freeze_started: _,
572 vote_only_bank: _,
573 cost_tracker: _,
574 accounts_data_size_initial: _,
575 accounts_data_size_delta_on_chain: _,
576 accounts_data_size_delta_off_chain: _,
577 epoch_reward_status: _,
578 transaction_processor: _,
579 check_program_modification_slot: _,
580 collector_fee_details: _,
581 compute_budget: _,
582 transaction_account_lock_limit: _,
583 fee_structure: _,
584 cache_for_accounts_lt_hash: _,
585 stats_for_accounts_lt_hash: _,
586 block_id,
587 bank_hash_stats: _,
588 } = self;
592 *blockhash_queue.read().unwrap() == *other.blockhash_queue.read().unwrap()
593 && ancestors == &other.ancestors
594 && *hash.read().unwrap() == *other.hash.read().unwrap()
595 && parent_hash == &other.parent_hash
596 && parent_slot == &other.parent_slot
597 && *hard_forks.read().unwrap() == *other.hard_forks.read().unwrap()
598 && transaction_count.load(Relaxed) == other.transaction_count.load(Relaxed)
599 && tick_height.load(Relaxed) == other.tick_height.load(Relaxed)
600 && signature_count.load(Relaxed) == other.signature_count.load(Relaxed)
601 && capitalization.load(Relaxed) == other.capitalization.load(Relaxed)
602 && max_tick_height == &other.max_tick_height
603 && hashes_per_tick == &other.hashes_per_tick
604 && ticks_per_slot == &other.ticks_per_slot
605 && ns_per_slot == &other.ns_per_slot
606 && genesis_creation_time == &other.genesis_creation_time
607 && slots_per_year == &other.slots_per_year
608 && slot == &other.slot
609 && epoch == &other.epoch
610 && block_height == &other.block_height
611 && collector_id == &other.collector_id
612 && collector_fees.load(Relaxed) == other.collector_fees.load(Relaxed)
613 && fee_rate_governor == &other.fee_rate_governor
614 && collected_rent.load(Relaxed) == other.collected_rent.load(Relaxed)
615 && rent_collector == &other.rent_collector
616 && epoch_schedule == &other.epoch_schedule
617 && *inflation.read().unwrap() == *other.inflation.read().unwrap()
618 && *stakes_cache.stakes() == *other.stakes_cache.stakes()
619 && epoch_stakes == &other.epoch_stakes
620 && is_delta.load(Relaxed) == other.is_delta.load(Relaxed)
621 && (Arc::ptr_eq(hash_overrides, &other.hash_overrides) ||
624 *hash_overrides.lock().unwrap() == *other.hash_overrides.lock().unwrap())
625 && !(self.is_accounts_lt_hash_enabled() && other.is_accounts_lt_hash_enabled()
626 && *accounts_lt_hash.lock().unwrap() != *other.accounts_lt_hash.lock().unwrap())
627 && *block_id.read().unwrap() == *other.block_id.read().unwrap()
628 }
629}
630
631#[cfg(feature = "dev-context-only-utils")]
632impl BankFieldsToSerialize {
633 pub fn default_for_tests() -> Self {
636 Self {
637 blockhash_queue: BlockhashQueue::default(),
638 ancestors: AncestorsForSerialization::default(),
639 hash: Hash::default(),
640 parent_hash: Hash::default(),
641 parent_slot: Slot::default(),
642 hard_forks: HardForks::default(),
643 transaction_count: u64::default(),
644 tick_height: u64::default(),
645 signature_count: u64::default(),
646 capitalization: u64::default(),
647 max_tick_height: u64::default(),
648 hashes_per_tick: Option::default(),
649 ticks_per_slot: u64::default(),
650 ns_per_slot: u128::default(),
651 genesis_creation_time: UnixTimestamp::default(),
652 slots_per_year: f64::default(),
653 slot: Slot::default(),
654 epoch: Epoch::default(),
655 block_height: u64::default(),
656 collector_id: Pubkey::default(),
657 collector_fees: u64::default(),
658 fee_rate_governor: FeeRateGovernor::default(),
659 collected_rent: u64::default(),
660 rent_collector: RentCollector::default(),
661 epoch_schedule: EpochSchedule::default(),
662 inflation: Inflation::default(),
663 stakes: Stakes::<Delegation>::default().into(),
664 epoch_stakes: HashMap::default(),
665 is_delta: bool::default(),
666 accounts_data_len: u64::default(),
667 versioned_epoch_stakes: HashMap::default(),
668 accounts_lt_hash: Some(AccountsLtHash(LtHash([0x7E57; LtHash::NUM_ELEMENTS]))),
669 }
670 }
671}
672
673#[derive(Debug)]
674pub enum RewardCalculationEvent<'a, 'b> {
675 Staking(&'a Pubkey, &'b InflationPointCalculationEvent),
676}
677
678pub trait RewardCalcTracer: Fn(&RewardCalculationEvent) + Send + Sync {}
682
683impl<T: Fn(&RewardCalculationEvent) + Send + Sync> RewardCalcTracer for T {}
684
685fn null_tracer() -> Option<impl RewardCalcTracer> {
686 None::<fn(&RewardCalculationEvent)>
687}
688
689pub trait DropCallback: fmt::Debug {
690 fn callback(&self, b: &Bank);
691 fn clone_box(&self) -> Box<dyn DropCallback + Send + Sync>;
692}
693
694#[derive(Debug, Default)]
695pub struct OptionalDropCallback(Option<Box<dyn DropCallback + Send + Sync>>);
696
697#[derive(Default, Debug, Clone, PartialEq)]
698#[cfg(feature = "dev-context-only-utils")]
699pub struct HashOverrides {
700 hashes: HashMap<Slot, HashOverride>,
701}
702
703#[cfg(feature = "dev-context-only-utils")]
704impl HashOverrides {
705 fn get_hash_override(&self, slot: Slot) -> Option<&HashOverride> {
706 self.hashes.get(&slot)
707 }
708
709 fn get_blockhash_override(&self, slot: Slot) -> Option<&Hash> {
710 self.get_hash_override(slot)
711 .map(|hash_override| &hash_override.blockhash)
712 }
713
714 fn get_bank_hash_override(&self, slot: Slot) -> Option<&Hash> {
715 self.get_hash_override(slot)
716 .map(|hash_override| &hash_override.bank_hash)
717 }
718
719 pub fn add_override(&mut self, slot: Slot, blockhash: Hash, bank_hash: Hash) {
720 let is_new = self
721 .hashes
722 .insert(
723 slot,
724 HashOverride {
725 blockhash,
726 bank_hash,
727 },
728 )
729 .is_none();
730 assert!(is_new);
731 }
732}
733
734#[derive(Debug, Clone, PartialEq)]
735#[cfg(feature = "dev-context-only-utils")]
736struct HashOverride {
737 blockhash: Hash,
738 bank_hash: Hash,
739}
740
741#[derive(Debug)]
743pub struct Bank {
744 pub rc: BankRc,
746
747 pub status_cache: Arc<RwLock<BankStatusCache>>,
749
750 blockhash_queue: RwLock<BlockhashQueue>,
752
753 pub ancestors: Ancestors,
755
756 hash: RwLock<Hash>,
758
759 parent_hash: Hash,
761
762 parent_slot: Slot,
764
765 hard_forks: Arc<RwLock<HardForks>>,
767
768 transaction_count: AtomicU64,
770
771 non_vote_transaction_count_since_restart: AtomicU64,
776
777 transaction_error_count: AtomicU64,
779
780 transaction_entries_count: AtomicU64,
782
783 transactions_per_entry_max: AtomicU64,
785
786 tick_height: AtomicU64,
788
789 signature_count: AtomicU64,
791
792 capitalization: AtomicU64,
794
795 max_tick_height: u64,
797
798 hashes_per_tick: Option<u64>,
800
801 ticks_per_slot: u64,
803
804 pub ns_per_slot: u128,
806
807 genesis_creation_time: UnixTimestamp,
809
810 slots_per_year: f64,
812
813 slot: Slot,
815
816 bank_id: BankId,
817
818 epoch: Epoch,
820
821 block_height: u64,
823
824 collector_id: Pubkey,
826
827 collector_fees: AtomicU64,
829
830 pub(crate) fee_rate_governor: FeeRateGovernor,
832
833 collected_rent: AtomicU64,
835
836 rent_collector: RentCollector,
838
839 pub(crate) epoch_schedule: EpochSchedule,
841
842 inflation: Arc<RwLock<Inflation>>,
844
845 stakes_cache: StakesCache,
847
848 epoch_stakes: HashMap<Epoch, EpochStakes>,
851
852 is_delta: AtomicBool,
855
856 pub rewards: RwLock<Vec<(Pubkey, RewardInfo)>>,
858
859 pub cluster_type: Option<ClusterType>,
860
861 pub lazy_rent_collection: AtomicBool,
862
863 pub rewards_pool_pubkeys: Arc<HashSet<Pubkey>>,
865
866 transaction_debug_keys: Option<Arc<HashSet<Pubkey>>>,
867
868 pub transaction_log_collector_config: Arc<RwLock<TransactionLogCollectorConfig>>,
870
871 pub transaction_log_collector: Arc<RwLock<TransactionLogCollector>>,
874
875 pub feature_set: Arc<FeatureSet>,
876
877 reserved_account_keys: Arc<ReservedAccountKeys>,
879
880 pub drop_callback: RwLock<OptionalDropCallback>,
882
883 pub freeze_started: AtomicBool,
884
885 vote_only_bank: bool,
886
887 cost_tracker: RwLock<CostTracker>,
888
889 accounts_data_size_initial: u64,
891 accounts_data_size_delta_on_chain: AtomicI64,
893 accounts_data_size_delta_off_chain: AtomicI64,
895
896 skipped_rewrites: Mutex<HashMap<Pubkey, AccountHash>>,
899
900 epoch_reward_status: EpochRewardStatus,
901
902 transaction_processor: TransactionBatchProcessor<BankForks>,
903
904 check_program_modification_slot: bool,
905
906 collector_fee_details: RwLock<CollectorFeeDetails>,
908
909 compute_budget: Option<ComputeBudget>,
911
912 transaction_account_lock_limit: Option<usize>,
914
915 fee_structure: FeeStructure,
917
918 #[cfg(feature = "dev-context-only-utils")]
921 hash_overrides: Arc<Mutex<HashOverrides>>,
922
923 accounts_lt_hash: Mutex<AccountsLtHash>,
927
928 cache_for_accounts_lt_hash: DashMap<Pubkey, AccountsLtHashCacheValue, ahash::RandomState>,
936
937 stats_for_accounts_lt_hash: AccountsLtHashStats,
939
940 block_id: RwLock<Option<Hash>>,
944
945 bank_hash_stats: AtomicBankHashStats,
947}
948
949#[derive(Debug)]
950struct VoteReward {
951 vote_account: AccountSharedData,
952 commission: u8,
953 vote_rewards: u64,
954 vote_needs_store: bool,
955}
956
957type VoteRewards = DashMap<Pubkey, VoteReward>;
958
959#[derive(Debug, Default)]
960pub struct NewBankOptions {
961 pub vote_only_bank: bool,
962}
963
964#[cfg(feature = "dev-context-only-utils")]
965#[derive(Debug)]
966pub struct BankTestConfig {
967 pub accounts_db_config: AccountsDbConfig,
968}
969
970#[cfg(feature = "dev-context-only-utils")]
971impl Default for BankTestConfig {
972 fn default() -> Self {
973 Self {
974 accounts_db_config: ACCOUNTS_DB_CONFIG_FOR_TESTING,
975 }
976 }
977}
978
979#[derive(Debug)]
980struct PrevEpochInflationRewards {
981 validator_rewards: u64,
982 prev_epoch_duration_in_years: f64,
983 validator_rate: f64,
984 foundation_rate: f64,
985}
986
987#[derive(Debug, Default, PartialEq)]
988pub struct ProcessedTransactionCounts {
989 pub processed_transactions_count: u64,
990 pub processed_non_vote_transactions_count: u64,
991 pub processed_with_successful_result_count: u64,
992 pub signature_count: u64,
993}
994
995#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
998#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
999pub struct BankHashStats {
1000 pub num_updated_accounts: u64,
1001 pub num_removed_accounts: u64,
1002 pub num_lamports_stored: u64,
1003 pub total_data_len: u64,
1004 pub num_executable_accounts: u64,
1005}
1006
1007impl BankHashStats {
1008 pub fn update<T: ReadableAccount>(&mut self, account: &T) {
1009 if account.lamports() == 0 {
1010 self.num_removed_accounts += 1;
1011 } else {
1012 self.num_updated_accounts += 1;
1013 }
1014 self.total_data_len = self
1015 .total_data_len
1016 .wrapping_add(account.data().len() as u64);
1017 if account.executable() {
1018 self.num_executable_accounts += 1;
1019 }
1020 self.num_lamports_stored = self.num_lamports_stored.wrapping_add(account.lamports());
1021 }
1022 pub fn accumulate(&mut self, other: &BankHashStats) {
1023 self.num_updated_accounts += other.num_updated_accounts;
1024 self.num_removed_accounts += other.num_removed_accounts;
1025 self.total_data_len = self.total_data_len.wrapping_add(other.total_data_len);
1026 self.num_lamports_stored = self
1027 .num_lamports_stored
1028 .wrapping_add(other.num_lamports_stored);
1029 self.num_executable_accounts += other.num_executable_accounts;
1030 }
1031}
1032
1033#[derive(Debug, Default)]
1034pub struct AtomicBankHashStats {
1035 pub num_updated_accounts: AtomicU64,
1036 pub num_removed_accounts: AtomicU64,
1037 pub num_lamports_stored: AtomicU64,
1038 pub total_data_len: AtomicU64,
1039 pub num_executable_accounts: AtomicU64,
1040}
1041
1042impl AtomicBankHashStats {
1043 pub fn new(stat: &BankHashStats) -> Self {
1044 AtomicBankHashStats {
1045 num_updated_accounts: AtomicU64::new(stat.num_updated_accounts),
1046 num_removed_accounts: AtomicU64::new(stat.num_removed_accounts),
1047 num_lamports_stored: AtomicU64::new(stat.num_lamports_stored),
1048 total_data_len: AtomicU64::new(stat.total_data_len),
1049 num_executable_accounts: AtomicU64::new(stat.num_executable_accounts),
1050 }
1051 }
1052
1053 pub fn accumulate(&self, other: &BankHashStats) {
1054 self.num_updated_accounts
1055 .fetch_add(other.num_updated_accounts, Relaxed);
1056 self.num_removed_accounts
1057 .fetch_add(other.num_removed_accounts, Relaxed);
1058 self.total_data_len.fetch_add(other.total_data_len, Relaxed);
1059 self.num_lamports_stored
1060 .fetch_add(other.num_lamports_stored, Relaxed);
1061 self.num_executable_accounts
1062 .fetch_add(other.num_executable_accounts, Relaxed);
1063 }
1064
1065 pub fn load(&self) -> BankHashStats {
1066 BankHashStats {
1067 num_updated_accounts: self.num_updated_accounts.load(Relaxed),
1068 num_removed_accounts: self.num_removed_accounts.load(Relaxed),
1069 num_lamports_stored: self.num_lamports_stored.load(Relaxed),
1070 total_data_len: self.total_data_len.load(Relaxed),
1071 num_executable_accounts: self.num_executable_accounts.load(Relaxed),
1072 }
1073 }
1074}
1075
1076impl Bank {
1077 fn default_with_accounts(accounts: Accounts) -> Self {
1078 let mut bank = Self {
1079 skipped_rewrites: Mutex::default(),
1080 rc: BankRc::new(accounts),
1081 status_cache: Arc::<RwLock<BankStatusCache>>::default(),
1082 blockhash_queue: RwLock::<BlockhashQueue>::default(),
1083 ancestors: Ancestors::default(),
1084 hash: RwLock::<Hash>::default(),
1085 parent_hash: Hash::default(),
1086 parent_slot: Slot::default(),
1087 hard_forks: Arc::<RwLock<HardForks>>::default(),
1088 transaction_count: AtomicU64::default(),
1089 non_vote_transaction_count_since_restart: AtomicU64::default(),
1090 transaction_error_count: AtomicU64::default(),
1091 transaction_entries_count: AtomicU64::default(),
1092 transactions_per_entry_max: AtomicU64::default(),
1093 tick_height: AtomicU64::default(),
1094 signature_count: AtomicU64::default(),
1095 capitalization: AtomicU64::default(),
1096 max_tick_height: u64::default(),
1097 hashes_per_tick: Option::<u64>::default(),
1098 ticks_per_slot: u64::default(),
1099 ns_per_slot: u128::default(),
1100 genesis_creation_time: UnixTimestamp::default(),
1101 slots_per_year: f64::default(),
1102 slot: Slot::default(),
1103 bank_id: BankId::default(),
1104 epoch: Epoch::default(),
1105 block_height: u64::default(),
1106 collector_id: Pubkey::default(),
1107 collector_fees: AtomicU64::default(),
1108 fee_rate_governor: FeeRateGovernor::default(),
1109 collected_rent: AtomicU64::default(),
1110 rent_collector: RentCollector::default(),
1111 epoch_schedule: EpochSchedule::default(),
1112 inflation: Arc::<RwLock<Inflation>>::default(),
1113 stakes_cache: StakesCache::default(),
1114 epoch_stakes: HashMap::<Epoch, EpochStakes>::default(),
1115 is_delta: AtomicBool::default(),
1116 rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
1117 cluster_type: Option::<ClusterType>::default(),
1118 lazy_rent_collection: AtomicBool::default(),
1119 rewards_pool_pubkeys: Arc::<HashSet<Pubkey>>::default(),
1120 transaction_debug_keys: Option::<Arc<HashSet<Pubkey>>>::default(),
1121 transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
1122 ),
1123 transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
1124 feature_set: Arc::<FeatureSet>::default(),
1125 reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
1126 drop_callback: RwLock::new(OptionalDropCallback(None)),
1127 freeze_started: AtomicBool::default(),
1128 vote_only_bank: false,
1129 cost_tracker: RwLock::<CostTracker>::default(),
1130 accounts_data_size_initial: 0,
1131 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1132 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1133 epoch_reward_status: EpochRewardStatus::default(),
1134 transaction_processor: TransactionBatchProcessor::default(),
1135 check_program_modification_slot: false,
1136 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1137 compute_budget: None,
1138 transaction_account_lock_limit: None,
1139 fee_structure: FeeStructure::default(),
1140 #[cfg(feature = "dev-context-only-utils")]
1141 hash_overrides: Arc::new(Mutex::new(HashOverrides::default())),
1142 accounts_lt_hash: Mutex::new(AccountsLtHash(LtHash::identity())),
1143 cache_for_accounts_lt_hash: DashMap::default(),
1144 stats_for_accounts_lt_hash: AccountsLtHashStats::default(),
1145 block_id: RwLock::new(None),
1146 bank_hash_stats: AtomicBankHashStats::default(),
1147 };
1148
1149 bank.transaction_processor =
1150 TransactionBatchProcessor::new_uninitialized(bank.slot, bank.epoch);
1151
1152 let accounts_data_size_initial = bank.get_total_accounts_stats().unwrap().data_len as u64;
1153 bank.accounts_data_size_initial = accounts_data_size_initial;
1154
1155 bank
1156 }
1157
1158 #[allow(clippy::too_many_arguments)]
1159 pub fn new_with_paths(
1160 genesis_config: &GenesisConfig,
1161 runtime_config: Arc<RuntimeConfig>,
1162 paths: Vec<PathBuf>,
1163 debug_keys: Option<Arc<HashSet<Pubkey>>>,
1164 additional_builtins: Option<&[BuiltinPrototype]>,
1165 debug_do_not_add_builtins: bool,
1166 accounts_db_config: Option<AccountsDbConfig>,
1167 accounts_update_notifier: Option<AccountsUpdateNotifier>,
1168 #[allow(unused)] collector_id_for_tests: Option<Pubkey>,
1169 exit: Arc<AtomicBool>,
1170 #[allow(unused)] genesis_hash: Option<Hash>,
1171 #[allow(unused)] feature_set: Option<FeatureSet>,
1172 ) -> Self {
1173 let accounts_db =
1174 AccountsDb::new_with_config(paths, accounts_db_config, accounts_update_notifier, exit);
1175 let accounts = Accounts::new(Arc::new(accounts_db));
1176 let mut bank = Self::default_with_accounts(accounts);
1177 bank.ancestors = Ancestors::from(vec![bank.slot()]);
1178 bank.compute_budget = runtime_config.compute_budget;
1179 bank.transaction_account_lock_limit = runtime_config.transaction_account_lock_limit;
1180 bank.transaction_debug_keys = debug_keys;
1181 bank.cluster_type = Some(genesis_config.cluster_type);
1182
1183 #[cfg(feature = "dev-context-only-utils")]
1184 {
1185 bank.feature_set = Arc::new(feature_set.unwrap_or_default());
1186 }
1187
1188 #[cfg(not(feature = "dev-context-only-utils"))]
1189 bank.process_genesis_config(genesis_config);
1190 #[cfg(feature = "dev-context-only-utils")]
1191 bank.process_genesis_config(genesis_config, collector_id_for_tests, genesis_hash);
1192
1193 bank.finish_init(
1194 genesis_config,
1195 additional_builtins,
1196 debug_do_not_add_builtins,
1197 );
1198
1199 {
1202 let stakes = bank.stakes_cache.stakes().clone();
1203 let stakes = Arc::new(StakesEnum::from(stakes));
1204 for epoch in 0..=bank.get_leader_schedule_epoch(bank.slot) {
1205 bank.epoch_stakes
1206 .insert(epoch, EpochStakes::new(stakes.clone(), epoch));
1207 }
1208 bank.update_stake_history(None);
1209 }
1210 bank.update_clock(None);
1211 bank.update_rent();
1212 bank.update_epoch_schedule();
1213 bank.update_recent_blockhashes();
1214 bank.update_last_restart_slot();
1215 bank.transaction_processor
1216 .fill_missing_sysvar_cache_entries(&bank);
1217 bank
1218 }
1219
1220 pub fn new_from_parent(parent: Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self {
1222 Self::_new_from_parent(
1223 parent,
1224 collector_id,
1225 slot,
1226 null_tracer(),
1227 NewBankOptions::default(),
1228 )
1229 }
1230
1231 pub fn new_from_parent_with_options(
1232 parent: Arc<Bank>,
1233 collector_id: &Pubkey,
1234 slot: Slot,
1235 new_bank_options: NewBankOptions,
1236 ) -> Self {
1237 Self::_new_from_parent(parent, collector_id, slot, null_tracer(), new_bank_options)
1238 }
1239
1240 pub fn new_from_parent_with_tracer(
1241 parent: Arc<Bank>,
1242 collector_id: &Pubkey,
1243 slot: Slot,
1244 reward_calc_tracer: impl RewardCalcTracer,
1245 ) -> Self {
1246 Self::_new_from_parent(
1247 parent,
1248 collector_id,
1249 slot,
1250 Some(reward_calc_tracer),
1251 NewBankOptions::default(),
1252 )
1253 }
1254
1255 fn get_rent_collector_from(rent_collector: &RentCollector, epoch: Epoch) -> RentCollector {
1256 rent_collector.clone_with_epoch(epoch)
1257 }
1258
1259 fn _new_from_parent(
1260 parent: Arc<Bank>,
1261 collector_id: &Pubkey,
1262 slot: Slot,
1263 reward_calc_tracer: Option<impl RewardCalcTracer>,
1264 new_bank_options: NewBankOptions,
1265 ) -> Self {
1266 let mut time = Measure::start("bank::new_from_parent");
1267 let NewBankOptions { vote_only_bank } = new_bank_options;
1268
1269 parent.freeze();
1270 assert_ne!(slot, parent.slot());
1271
1272 let epoch_schedule = parent.epoch_schedule().clone();
1273 let epoch = epoch_schedule.get_epoch(slot);
1274
1275 let (rc, bank_rc_creation_time_us) = measure_us!({
1276 let accounts_db = Arc::clone(&parent.rc.accounts.accounts_db);
1277 BankRc {
1278 accounts: Arc::new(Accounts::new(accounts_db)),
1279 parent: RwLock::new(Some(Arc::clone(&parent))),
1280 bank_id_generator: Arc::clone(&parent.rc.bank_id_generator),
1281 }
1282 });
1283
1284 let (status_cache, status_cache_time_us) = measure_us!(Arc::clone(&parent.status_cache));
1285
1286 let (fee_rate_governor, fee_components_time_us) = measure_us!(
1287 FeeRateGovernor::new_derived(&parent.fee_rate_governor, parent.signature_count())
1288 );
1289
1290 let bank_id = rc.bank_id_generator.fetch_add(1, Relaxed) + 1;
1291 let (blockhash_queue, blockhash_queue_time_us) =
1292 measure_us!(RwLock::new(parent.blockhash_queue.read().unwrap().clone()));
1293
1294 let (stakes_cache, stakes_cache_time_us) =
1295 measure_us!(StakesCache::new(parent.stakes_cache.stakes().clone()));
1296
1297 let (epoch_stakes, epoch_stakes_time_us) = measure_us!(parent.epoch_stakes.clone());
1298
1299 let (transaction_processor, builtin_program_ids_time_us) = measure_us!(
1300 TransactionBatchProcessor::new_from(&parent.transaction_processor, slot, epoch)
1301 );
1302
1303 let (rewards_pool_pubkeys, rewards_pool_pubkeys_time_us) =
1304 measure_us!(parent.rewards_pool_pubkeys.clone());
1305
1306 let (transaction_debug_keys, transaction_debug_keys_time_us) =
1307 measure_us!(parent.transaction_debug_keys.clone());
1308
1309 let (transaction_log_collector_config, transaction_log_collector_config_time_us) =
1310 measure_us!(parent.transaction_log_collector_config.clone());
1311
1312 let (feature_set, feature_set_time_us) = measure_us!(parent.feature_set.clone());
1313
1314 let accounts_data_size_initial = parent.load_accounts_data_size();
1315 let mut new = Self {
1316 skipped_rewrites: Mutex::default(),
1317 rc,
1318 status_cache,
1319 slot,
1320 bank_id,
1321 epoch,
1322 blockhash_queue,
1323
1324 hashes_per_tick: parent.hashes_per_tick,
1326 ticks_per_slot: parent.ticks_per_slot,
1327 ns_per_slot: parent.ns_per_slot,
1328 genesis_creation_time: parent.genesis_creation_time,
1329 slots_per_year: parent.slots_per_year,
1330 epoch_schedule,
1331 collected_rent: AtomicU64::new(0),
1332 rent_collector: Self::get_rent_collector_from(&parent.rent_collector, epoch),
1333 max_tick_height: slot
1334 .checked_add(1)
1335 .expect("max tick height addition overflowed")
1336 .checked_mul(parent.ticks_per_slot)
1337 .expect("max tick height multiplication overflowed"),
1338 block_height: parent
1339 .block_height
1340 .checked_add(1)
1341 .expect("block height addition overflowed"),
1342 fee_rate_governor,
1343 capitalization: AtomicU64::new(parent.capitalization()),
1344 vote_only_bank,
1345 inflation: parent.inflation.clone(),
1346 transaction_count: AtomicU64::new(parent.transaction_count()),
1347 non_vote_transaction_count_since_restart: AtomicU64::new(
1348 parent.non_vote_transaction_count_since_restart(),
1349 ),
1350 transaction_error_count: AtomicU64::new(0),
1351 transaction_entries_count: AtomicU64::new(0),
1352 transactions_per_entry_max: AtomicU64::new(0),
1353 stakes_cache,
1355 epoch_stakes,
1356 parent_hash: parent.hash(),
1357 parent_slot: parent.slot(),
1358 collector_id: *collector_id,
1359 collector_fees: AtomicU64::new(0),
1360 ancestors: Ancestors::default(),
1361 hash: RwLock::new(Hash::default()),
1362 is_delta: AtomicBool::new(false),
1363 tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)),
1364 signature_count: AtomicU64::new(0),
1365 hard_forks: parent.hard_forks.clone(),
1366 rewards: RwLock::new(vec![]),
1367 cluster_type: parent.cluster_type,
1368 lazy_rent_collection: AtomicBool::new(parent.lazy_rent_collection.load(Relaxed)),
1369 rewards_pool_pubkeys,
1370 transaction_debug_keys,
1371 transaction_log_collector_config,
1372 transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
1373 feature_set: Arc::clone(&feature_set),
1374 reserved_account_keys: parent.reserved_account_keys.clone(),
1375 drop_callback: RwLock::new(OptionalDropCallback(
1376 parent
1377 .drop_callback
1378 .read()
1379 .unwrap()
1380 .0
1381 .as_ref()
1382 .map(|drop_callback| drop_callback.clone_box()),
1383 )),
1384 freeze_started: AtomicBool::new(false),
1385 cost_tracker: RwLock::new(parent.read_cost_tracker().unwrap().new_from_parent_limits()),
1386 accounts_data_size_initial,
1387 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1388 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1389 epoch_reward_status: parent.epoch_reward_status.clone(),
1390 transaction_processor,
1391 check_program_modification_slot: false,
1392 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1393 compute_budget: parent.compute_budget,
1394 transaction_account_lock_limit: parent.transaction_account_lock_limit,
1395 fee_structure: parent.fee_structure.clone(),
1396 #[cfg(feature = "dev-context-only-utils")]
1397 hash_overrides: parent.hash_overrides.clone(),
1398 accounts_lt_hash: Mutex::new(parent.accounts_lt_hash.lock().unwrap().clone()),
1399 cache_for_accounts_lt_hash: DashMap::default(),
1400 stats_for_accounts_lt_hash: AccountsLtHashStats::default(),
1401 block_id: RwLock::new(None),
1402 bank_hash_stats: AtomicBankHashStats::default(),
1403 };
1404
1405 let (_, ancestors_time_us) = measure_us!({
1406 let mut ancestors = Vec::with_capacity(1 + new.parents().len());
1407 ancestors.push(new.slot());
1408 new.parents().iter().for_each(|p| {
1409 ancestors.push(p.slot());
1410 });
1411 new.ancestors = Ancestors::from(ancestors);
1412 });
1413
1414 let (_, update_epoch_time_us) = measure_us!({
1416 if parent.epoch() < new.epoch() {
1417 new.process_new_epoch(
1418 parent.epoch(),
1419 parent.slot(),
1420 parent.block_height(),
1421 reward_calc_tracer,
1422 );
1423 } else {
1424 let leader_schedule_epoch = new.epoch_schedule().get_leader_schedule_epoch(slot);
1426 new.update_epoch_stakes(leader_schedule_epoch);
1427 }
1428 new.distribute_partitioned_epoch_rewards();
1429 });
1430
1431 let (_epoch, slot_index) = new.epoch_schedule.get_epoch_and_slot_index(new.slot);
1432 let slots_in_epoch = new.epoch_schedule.get_slots_in_epoch(new.epoch);
1433
1434 let (_, cache_preparation_time_us) = measure_us!(new
1435 .transaction_processor
1436 .prepare_program_cache_for_upcoming_feature_set(
1437 &new,
1438 &new.compute_active_feature_set(true).0,
1439 &new.compute_budget.unwrap_or_default(),
1440 slot_index,
1441 slots_in_epoch,
1442 ));
1443
1444 let (_, update_sysvars_time_us) = measure_us!({
1446 new.update_slot_hashes();
1447 new.update_stake_history(Some(parent.epoch()));
1448 new.update_clock(Some(parent.epoch()));
1449 new.update_last_restart_slot()
1450 });
1451
1452 let (_, fill_sysvar_cache_time_us) = measure_us!(new
1453 .transaction_processor
1454 .fill_missing_sysvar_cache_entries(&new));
1455
1456 let (num_accounts_modified_this_slot, populate_cache_for_accounts_lt_hash_us) = new
1457 .is_accounts_lt_hash_enabled()
1458 .then(|| {
1459 measure_us!({
1460 let accounts_modified_this_slot =
1468 new.rc.accounts.accounts_db.get_pubkeys_for_slot(slot);
1469 let num_accounts_modified_this_slot = accounts_modified_this_slot.len();
1470 for pubkey in accounts_modified_this_slot {
1471 new.cache_for_accounts_lt_hash
1472 .entry(pubkey)
1473 .or_insert(AccountsLtHashCacheValue::BankNew);
1474 }
1475 num_accounts_modified_this_slot
1476 })
1477 })
1478 .unzip();
1479
1480 time.stop();
1481 report_new_bank_metrics(
1482 slot,
1483 parent.slot(),
1484 new.block_height,
1485 num_accounts_modified_this_slot,
1486 NewBankTimings {
1487 bank_rc_creation_time_us,
1488 total_elapsed_time_us: time.as_us(),
1489 status_cache_time_us,
1490 fee_components_time_us,
1491 blockhash_queue_time_us,
1492 stakes_cache_time_us,
1493 epoch_stakes_time_us,
1494 builtin_program_ids_time_us,
1495 rewards_pool_pubkeys_time_us,
1496 executor_cache_time_us: 0,
1497 transaction_debug_keys_time_us,
1498 transaction_log_collector_config_time_us,
1499 feature_set_time_us,
1500 ancestors_time_us,
1501 update_epoch_time_us,
1502 cache_preparation_time_us,
1503 update_sysvars_time_us,
1504 fill_sysvar_cache_time_us,
1505 populate_cache_for_accounts_lt_hash_us,
1506 },
1507 );
1508
1509 report_loaded_programs_stats(
1510 &parent
1511 .transaction_processor
1512 .program_cache
1513 .read()
1514 .unwrap()
1515 .stats,
1516 parent.slot(),
1517 );
1518
1519 new.transaction_processor
1520 .program_cache
1521 .write()
1522 .unwrap()
1523 .stats
1524 .reset();
1525
1526 new
1527 }
1528
1529 pub fn set_fork_graph_in_program_cache(&self, fork_graph: Weak<RwLock<BankForks>>) {
1530 self.transaction_processor
1531 .program_cache
1532 .write()
1533 .unwrap()
1534 .set_fork_graph(fork_graph);
1535 }
1536
1537 pub fn prune_program_cache(&self, new_root_slot: Slot, new_root_epoch: Epoch) {
1538 self.transaction_processor
1539 .program_cache
1540 .write()
1541 .unwrap()
1542 .prune(new_root_slot, new_root_epoch);
1543 }
1544
1545 pub fn prune_program_cache_by_deployment_slot(&self, deployment_slot: Slot) {
1546 self.transaction_processor
1547 .program_cache
1548 .write()
1549 .unwrap()
1550 .prune_by_deployment_slot(deployment_slot);
1551 }
1552
1553 pub fn new_warmup_cooldown_rate_epoch(&self) -> Option<Epoch> {
1555 self.feature_set
1556 .new_warmup_cooldown_rate_epoch(&self.epoch_schedule)
1557 }
1558
1559 fn process_new_epoch(
1561 &mut self,
1562 parent_epoch: Epoch,
1563 parent_slot: Slot,
1564 parent_height: u64,
1565 reward_calc_tracer: Option<impl RewardCalcTracer>,
1566 ) {
1567 let epoch = self.epoch();
1568 let slot = self.slot();
1569 let (thread_pool, thread_pool_time_us) = measure_us!(ThreadPoolBuilder::new()
1570 .thread_name(|i| format!("solBnkNewEpch{i:02}"))
1571 .build()
1572 .expect("new rayon threadpool"));
1573
1574 let (_, apply_feature_activations_time_us) = measure_us!(thread_pool.install(|| {
1575 self.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, false)
1576 }));
1577
1578 let (_, activate_epoch_time_us) = measure_us!(self.stakes_cache.activate_epoch(
1582 epoch,
1583 &thread_pool,
1584 self.new_warmup_cooldown_rate_epoch()
1585 ));
1586
1587 let leader_schedule_epoch = self.epoch_schedule.get_leader_schedule_epoch(slot);
1589 let (_, update_epoch_stakes_time_us) =
1590 measure_us!(self.update_epoch_stakes(leader_schedule_epoch));
1591
1592 let mut rewards_metrics = RewardsMetrics::default();
1593 let (_, update_rewards_with_thread_pool_time_us) = measure_us!(self
1595 .begin_partitioned_rewards(
1596 reward_calc_tracer,
1597 &thread_pool,
1598 parent_epoch,
1599 parent_slot,
1600 parent_height,
1601 &mut rewards_metrics,
1602 ));
1603
1604 report_new_epoch_metrics(
1605 epoch,
1606 slot,
1607 parent_slot,
1608 NewEpochTimings {
1609 thread_pool_time_us,
1610 apply_feature_activations_time_us,
1611 activate_epoch_time_us,
1612 update_epoch_stakes_time_us,
1613 update_rewards_with_thread_pool_time_us,
1614 },
1615 rewards_metrics,
1616 );
1617 }
1618
1619 pub fn byte_limit_for_scans(&self) -> Option<usize> {
1620 self.rc
1621 .accounts
1622 .accounts_db
1623 .accounts_index
1624 .scan_results_limit_bytes
1625 }
1626
1627 pub fn proper_ancestors_set(&self) -> HashSet<Slot> {
1628 HashSet::from_iter(self.proper_ancestors())
1629 }
1630
1631 pub(crate) fn proper_ancestors(&self) -> impl Iterator<Item = Slot> + '_ {
1633 self.ancestors
1634 .keys()
1635 .into_iter()
1636 .filter(move |slot| *slot != self.slot)
1637 }
1638
1639 pub fn set_callback(&self, callback: Option<Box<dyn DropCallback + Send + Sync>>) {
1640 *self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
1641 }
1642
1643 pub fn vote_only_bank(&self) -> bool {
1644 self.vote_only_bank
1645 }
1646
1647 pub fn warp_from_parent(
1654 parent: Arc<Bank>,
1655 collector_id: &Pubkey,
1656 slot: Slot,
1657 data_source: CalcAccountsHashDataSource,
1658 ) -> Self {
1659 parent.freeze();
1660 parent
1661 .rc
1662 .accounts
1663 .accounts_db
1664 .epoch_accounts_hash_manager
1665 .set_in_flight(parent.slot());
1666 let accounts_hash = parent.update_accounts_hash(data_source, false, true);
1667 let epoch_accounts_hash = accounts_hash.into();
1668 parent
1669 .rc
1670 .accounts
1671 .accounts_db
1672 .epoch_accounts_hash_manager
1673 .set_valid(epoch_accounts_hash, parent.slot());
1674
1675 let parent_timestamp = parent.clock().unix_timestamp;
1676 let mut new = Bank::new_from_parent(parent, collector_id, slot);
1677 new.apply_feature_activations(ApplyFeatureActivationsCaller::WarpFromParent, false);
1678 new.update_epoch_stakes(new.epoch_schedule().get_epoch(slot));
1679 new.tick_height.store(new.max_tick_height(), Relaxed);
1680
1681 let mut clock = new.clock();
1682 clock.epoch_start_timestamp = parent_timestamp;
1683 clock.unix_timestamp = parent_timestamp;
1684 new.update_sysvar_account(&sysvar::clock::id(), |account| {
1685 create_account(
1686 &clock,
1687 new.inherit_specially_retained_account_fields(account),
1688 )
1689 });
1690 new.transaction_processor
1691 .fill_missing_sysvar_cache_entries(&new);
1692 new.freeze();
1693 new
1694 }
1695
1696 pub(crate) fn new_from_fields(
1698 bank_rc: BankRc,
1699 genesis_config: &GenesisConfig,
1700 runtime_config: Arc<RuntimeConfig>,
1701 fields: BankFieldsToDeserialize,
1702 debug_keys: Option<Arc<HashSet<Pubkey>>>,
1703 additional_builtins: Option<&[BuiltinPrototype]>,
1704 debug_do_not_add_builtins: bool,
1705 accounts_data_size_initial: u64,
1706 ) -> Self {
1707 let now = Instant::now();
1708 let ancestors = Ancestors::from(&fields.ancestors);
1709 let (stakes, stakes_time) = measure_time!(Stakes::new(&fields.stakes, |pubkey| {
1720 let (account, _slot) = bank_rc
1721 .accounts
1722 .load_with_fixed_root_do_not_populate_read_cache(&ancestors, pubkey)?;
1723 Some(account)
1724 })
1725 .expect(
1726 "Stakes cache is inconsistent with accounts-db. This can indicate \
1727 a corrupted snapshot or bugs in cached accounts or accounts-db.",
1728 ));
1729 info!("Loading Stakes took: {stakes_time}");
1730 let stakes_accounts_load_duration = now.elapsed();
1731 let mut bank = Self {
1732 skipped_rewrites: Mutex::default(),
1733 rc: bank_rc,
1734 status_cache: Arc::<RwLock<BankStatusCache>>::default(),
1735 blockhash_queue: RwLock::new(fields.blockhash_queue),
1736 ancestors,
1737 hash: RwLock::new(fields.hash),
1738 parent_hash: fields.parent_hash,
1739 parent_slot: fields.parent_slot,
1740 hard_forks: Arc::new(RwLock::new(fields.hard_forks)),
1741 transaction_count: AtomicU64::new(fields.transaction_count),
1742 non_vote_transaction_count_since_restart: AtomicU64::default(),
1743 transaction_error_count: AtomicU64::default(),
1744 transaction_entries_count: AtomicU64::default(),
1745 transactions_per_entry_max: AtomicU64::default(),
1746 tick_height: AtomicU64::new(fields.tick_height),
1747 signature_count: AtomicU64::new(fields.signature_count),
1748 capitalization: AtomicU64::new(fields.capitalization),
1749 max_tick_height: fields.max_tick_height,
1750 hashes_per_tick: fields.hashes_per_tick,
1751 ticks_per_slot: fields.ticks_per_slot,
1752 ns_per_slot: fields.ns_per_slot,
1753 genesis_creation_time: fields.genesis_creation_time,
1754 slots_per_year: fields.slots_per_year,
1755 slot: fields.slot,
1756 bank_id: 0,
1757 epoch: fields.epoch,
1758 block_height: fields.block_height,
1759 collector_id: fields.collector_id,
1760 collector_fees: AtomicU64::new(fields.collector_fees),
1761 fee_rate_governor: fields.fee_rate_governor,
1762 collected_rent: AtomicU64::new(fields.collected_rent),
1763 rent_collector: Self::get_rent_collector_from(&fields.rent_collector, fields.epoch),
1765 epoch_schedule: fields.epoch_schedule,
1766 inflation: Arc::new(RwLock::new(fields.inflation)),
1767 stakes_cache: StakesCache::new(stakes),
1768 epoch_stakes: fields.epoch_stakes,
1769 is_delta: AtomicBool::new(fields.is_delta),
1770 rewards: RwLock::new(vec![]),
1771 cluster_type: Some(genesis_config.cluster_type),
1772 lazy_rent_collection: AtomicBool::default(),
1773 rewards_pool_pubkeys: Arc::<HashSet<Pubkey>>::default(),
1774 transaction_debug_keys: debug_keys,
1775 transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
1776 ),
1777 transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
1778 feature_set: Arc::<FeatureSet>::default(),
1779 reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
1780 drop_callback: RwLock::new(OptionalDropCallback(None)),
1781 freeze_started: AtomicBool::new(fields.hash != Hash::default()),
1782 vote_only_bank: false,
1783 cost_tracker: RwLock::new(CostTracker::default()),
1784 accounts_data_size_initial,
1785 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1786 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1787 epoch_reward_status: EpochRewardStatus::default(),
1788 transaction_processor: TransactionBatchProcessor::default(),
1789 check_program_modification_slot: false,
1790 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1792 compute_budget: runtime_config.compute_budget,
1793 transaction_account_lock_limit: runtime_config.transaction_account_lock_limit,
1794 fee_structure: FeeStructure::default(),
1795 #[cfg(feature = "dev-context-only-utils")]
1796 hash_overrides: Arc::new(Mutex::new(HashOverrides::default())),
1797 accounts_lt_hash: Mutex::new(AccountsLtHash(LtHash([0xBAD1; LtHash::NUM_ELEMENTS]))),
1798 cache_for_accounts_lt_hash: DashMap::default(),
1799 stats_for_accounts_lt_hash: AccountsLtHashStats::default(),
1800 block_id: RwLock::new(None),
1801 bank_hash_stats: AtomicBankHashStats::new(&fields.bank_hash_stats),
1802 };
1803
1804 bank.transaction_processor =
1805 TransactionBatchProcessor::new_uninitialized(bank.slot, bank.epoch);
1806
1807 let thread_pool = ThreadPoolBuilder::new()
1808 .thread_name(|i| format!("solBnkNewFlds{i:02}"))
1809 .build()
1810 .expect("new rayon threadpool");
1811 bank.recalculate_partitioned_rewards(null_tracer(), &thread_pool);
1812
1813 bank.finish_init(
1814 genesis_config,
1815 additional_builtins,
1816 debug_do_not_add_builtins,
1817 );
1818 bank.transaction_processor
1819 .fill_missing_sysvar_cache_entries(&bank);
1820 bank.rebuild_skipped_rewrites();
1821
1822 let mut calculate_accounts_lt_hash_duration = None;
1823 if let Some(accounts_lt_hash) = fields.accounts_lt_hash {
1824 *bank.accounts_lt_hash.get_mut().unwrap() = accounts_lt_hash;
1825 } else {
1826 assert!(
1829 !bank
1830 .feature_set
1831 .is_active(&feature_set::accounts_lt_hash::id()),
1832 "snapshot must have an accounts lt hash if the feature is enabled",
1833 );
1834 if bank.is_accounts_lt_hash_enabled() {
1835 info!(
1836 "Calculating the accounts lt hash for slot {}...",
1837 bank.slot(),
1838 );
1839 let (ancestors, slot) = if bank.is_frozen() {
1840 (bank.ancestors.clone(), bank.slot())
1845 } else {
1846 let parent_ancestors = {
1851 let mut ancestors = bank.ancestors.clone();
1852 ancestors.remove(&bank.slot());
1853 ancestors
1854 };
1855 (parent_ancestors, bank.parent_slot)
1856 };
1857 let (accounts_lt_hash, duration) = meas_dur!({
1858 thread_pool.install(|| {
1859 bank.rc
1860 .accounts
1861 .accounts_db
1862 .calculate_accounts_lt_hash_at_startup_from_index(&ancestors, slot)
1863 })
1864 });
1865 calculate_accounts_lt_hash_duration = Some(duration);
1866 *bank.accounts_lt_hash.get_mut().unwrap() = accounts_lt_hash;
1867 info!(
1868 "Calculating the accounts lt hash for slot {}... \
1869 Done in {duration:?}, accounts_lt_hash checksum: {}",
1870 bank.slot(),
1871 bank.accounts_lt_hash.get_mut().unwrap().0.checksum(),
1872 );
1873 }
1874 }
1875
1876 assert_eq!(
1881 bank.genesis_creation_time, genesis_config.creation_time,
1882 "Bank snapshot genesis creation time does not match genesis.bin creation time. \
1883 The snapshot and genesis.bin might pertain to different clusters"
1884 );
1885 assert_eq!(bank.ticks_per_slot, genesis_config.ticks_per_slot);
1886 assert_eq!(
1887 bank.ns_per_slot,
1888 genesis_config.poh_config.target_tick_duration.as_nanos()
1889 * genesis_config.ticks_per_slot as u128
1890 );
1891 assert_eq!(bank.max_tick_height, (bank.slot + 1) * bank.ticks_per_slot);
1892 assert_eq!(
1893 bank.slots_per_year,
1894 years_as_slots(
1895 1.0,
1896 &genesis_config.poh_config.target_tick_duration,
1897 bank.ticks_per_slot,
1898 )
1899 );
1900 assert_eq!(bank.epoch_schedule, genesis_config.epoch_schedule);
1901 assert_eq!(bank.epoch, bank.epoch_schedule.get_epoch(bank.slot));
1902
1903 datapoint_info!(
1904 "bank-new-from-fields",
1905 (
1906 "accounts_data_len-from-snapshot",
1907 fields.accounts_data_len as i64,
1908 i64
1909 ),
1910 (
1911 "accounts_data_len-from-generate_index",
1912 accounts_data_size_initial as i64,
1913 i64
1914 ),
1915 (
1916 "stakes_accounts_load_duration_us",
1917 stakes_accounts_load_duration.as_micros(),
1918 i64
1919 ),
1920 (
1921 "calculate_accounts_lt_hash_us",
1922 calculate_accounts_lt_hash_duration.as_ref().map(Duration::as_micros),
1923 Option<i64>
1924 ),
1925 );
1926 bank
1927 }
1928
1929 pub(crate) fn get_fields_to_serialize(&self) -> BankFieldsToSerialize {
1931 let (epoch_stakes, versioned_epoch_stakes) = split_epoch_stakes(self.epoch_stakes.clone());
1932 BankFieldsToSerialize {
1933 blockhash_queue: self.blockhash_queue.read().unwrap().clone(),
1934 ancestors: AncestorsForSerialization::from(&self.ancestors),
1935 hash: *self.hash.read().unwrap(),
1936 parent_hash: self.parent_hash,
1937 parent_slot: self.parent_slot,
1938 hard_forks: self.hard_forks.read().unwrap().clone(),
1939 transaction_count: self.transaction_count.load(Relaxed),
1940 tick_height: self.tick_height.load(Relaxed),
1941 signature_count: self.signature_count.load(Relaxed),
1942 capitalization: self.capitalization.load(Relaxed),
1943 max_tick_height: self.max_tick_height,
1944 hashes_per_tick: self.hashes_per_tick,
1945 ticks_per_slot: self.ticks_per_slot,
1946 ns_per_slot: self.ns_per_slot,
1947 genesis_creation_time: self.genesis_creation_time,
1948 slots_per_year: self.slots_per_year,
1949 slot: self.slot,
1950 epoch: self.epoch,
1951 block_height: self.block_height,
1952 collector_id: self.collector_id,
1953 collector_fees: self.collector_fees.load(Relaxed),
1954 fee_rate_governor: self.fee_rate_governor.clone(),
1955 collected_rent: self.collected_rent.load(Relaxed),
1956 rent_collector: self.rent_collector.clone(),
1957 epoch_schedule: self.epoch_schedule.clone(),
1958 inflation: *self.inflation.read().unwrap(),
1959 stakes: StakesEnum::from(self.stakes_cache.stakes().clone()),
1960 epoch_stakes,
1961 is_delta: self.is_delta.load(Relaxed),
1962 accounts_data_len: self.load_accounts_data_size(),
1963 versioned_epoch_stakes,
1964 accounts_lt_hash: self
1965 .is_accounts_lt_hash_enabled()
1966 .then(|| self.accounts_lt_hash.lock().unwrap().clone()),
1967 }
1968 }
1969
1970 pub fn collector_id(&self) -> &Pubkey {
1971 &self.collector_id
1972 }
1973
1974 pub fn genesis_creation_time(&self) -> UnixTimestamp {
1975 self.genesis_creation_time
1976 }
1977
1978 pub fn slot(&self) -> Slot {
1979 self.slot
1980 }
1981
1982 pub fn bank_id(&self) -> BankId {
1983 self.bank_id
1984 }
1985
1986 pub fn epoch(&self) -> Epoch {
1987 self.epoch
1988 }
1989
1990 pub fn first_normal_epoch(&self) -> Epoch {
1991 self.epoch_schedule().first_normal_epoch
1992 }
1993
1994 pub fn freeze_lock(&self) -> RwLockReadGuard<Hash> {
1995 self.hash.read().unwrap()
1996 }
1997
1998 pub fn hash(&self) -> Hash {
1999 *self.hash.read().unwrap()
2000 }
2001
2002 pub fn is_frozen(&self) -> bool {
2003 *self.hash.read().unwrap() != Hash::default()
2004 }
2005
2006 pub fn freeze_started(&self) -> bool {
2007 self.freeze_started.load(Relaxed)
2008 }
2009
2010 pub fn status_cache_ancestors(&self) -> Vec<u64> {
2011 let mut roots = self.status_cache.read().unwrap().roots().clone();
2012 let min = roots.iter().min().cloned().unwrap_or(0);
2013 for ancestor in self.ancestors.keys() {
2014 if ancestor >= min {
2015 roots.insert(ancestor);
2016 }
2017 }
2018
2019 let mut ancestors: Vec<_> = roots.into_iter().collect();
2020 #[allow(clippy::stable_sort_primitive)]
2021 ancestors.sort();
2022 ancestors
2023 }
2024
2025 pub fn unix_timestamp_from_genesis(&self) -> i64 {
2027 self.genesis_creation_time.saturating_add(
2028 (self.slot as u128)
2029 .saturating_mul(self.ns_per_slot)
2030 .saturating_div(1_000_000_000) as i64,
2031 )
2032 }
2033
2034 fn update_sysvar_account<F>(&self, pubkey: &Pubkey, updater: F)
2035 where
2036 F: Fn(&Option<AccountSharedData>) -> AccountSharedData,
2037 {
2038 let old_account = self.get_account_with_fixed_root(pubkey);
2039 let mut new_account = updater(&old_account);
2040
2041 self.adjust_sysvar_balance_for_rent(&mut new_account);
2047 self.store_account_and_update_capitalization(pubkey, &new_account);
2048 }
2049
2050 fn inherit_specially_retained_account_fields(
2051 &self,
2052 old_account: &Option<AccountSharedData>,
2053 ) -> InheritableAccountFields {
2054 const RENT_UNADJUSTED_INITIAL_BALANCE: u64 = 1;
2055
2056 (
2057 old_account
2058 .as_ref()
2059 .map(|a| a.lamports())
2060 .unwrap_or(RENT_UNADJUSTED_INITIAL_BALANCE),
2061 old_account
2062 .as_ref()
2063 .map(|a| a.rent_epoch())
2064 .unwrap_or(INITIAL_RENT_EPOCH),
2065 )
2066 }
2067
2068 pub fn clock(&self) -> sysvar::clock::Clock {
2069 from_account(&self.get_account(&sysvar::clock::id()).unwrap_or_default())
2070 .unwrap_or_default()
2071 }
2072
2073 fn update_clock(&self, parent_epoch: Option<Epoch>) {
2074 let mut unix_timestamp = self.clock().unix_timestamp;
2075 let epoch_start_timestamp = {
2077 let epoch = if let Some(epoch) = parent_epoch {
2078 epoch
2079 } else {
2080 self.epoch()
2081 };
2082 let first_slot_in_epoch = self.epoch_schedule().get_first_slot_in_epoch(epoch);
2083 Some((first_slot_in_epoch, self.clock().epoch_start_timestamp))
2084 };
2085 let max_allowable_drift = MaxAllowableDrift {
2086 fast: MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST,
2087 slow: MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
2088 };
2089
2090 let ancestor_timestamp = self.clock().unix_timestamp;
2091 if let Some(timestamp_estimate) =
2092 self.get_timestamp_estimate(max_allowable_drift, epoch_start_timestamp)
2093 {
2094 unix_timestamp = timestamp_estimate;
2095 if timestamp_estimate < ancestor_timestamp {
2096 unix_timestamp = ancestor_timestamp;
2097 }
2098 }
2099 datapoint_info!(
2100 "bank-timestamp-correction",
2101 ("slot", self.slot(), i64),
2102 ("from_genesis", self.unix_timestamp_from_genesis(), i64),
2103 ("corrected", unix_timestamp, i64),
2104 ("ancestor_timestamp", ancestor_timestamp, i64),
2105 );
2106 let mut epoch_start_timestamp =
2107 if parent_epoch.is_some() && parent_epoch.unwrap() != self.epoch() {
2109 unix_timestamp
2110 } else {
2111 self.clock().epoch_start_timestamp
2112 };
2113 if self.slot == 0 {
2114 unix_timestamp = self.unix_timestamp_from_genesis();
2115 epoch_start_timestamp = self.unix_timestamp_from_genesis();
2116 }
2117 let clock = sysvar::clock::Clock {
2118 slot: self.slot,
2119 epoch_start_timestamp,
2120 epoch: self.epoch_schedule().get_epoch(self.slot),
2121 leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
2122 unix_timestamp,
2123 };
2124 self.update_sysvar_account(&sysvar::clock::id(), |account| {
2125 create_account(
2126 &clock,
2127 self.inherit_specially_retained_account_fields(account),
2128 )
2129 });
2130 }
2131
2132 pub fn update_last_restart_slot(&self) {
2133 let feature_flag = self
2134 .feature_set
2135 .is_active(&feature_set::last_restart_slot_sysvar::id());
2136
2137 if feature_flag {
2138 let current_last_restart_slot = self
2141 .get_account(&sysvar::last_restart_slot::id())
2142 .and_then(|account| {
2143 let lrs: Option<LastRestartSlot> = from_account(&account);
2144 lrs
2145 })
2146 .map(|account| account.last_restart_slot);
2147
2148 let last_restart_slot = {
2149 let slot = self.slot;
2150 let hard_forks_r = self.hard_forks.read().unwrap();
2151
2152 hard_forks_r
2155 .iter()
2156 .rev()
2157 .find(|(hard_fork, _)| *hard_fork <= slot)
2158 .map(|(slot, _)| *slot)
2159 .unwrap_or(0)
2160 };
2161
2162 if current_last_restart_slot != Some(last_restart_slot) {
2164 self.update_sysvar_account(&sysvar::last_restart_slot::id(), |account| {
2165 create_account(
2166 &LastRestartSlot { last_restart_slot },
2167 self.inherit_specially_retained_account_fields(account),
2168 )
2169 });
2170 }
2171 }
2172 }
2173
2174 pub fn set_sysvar_for_tests<T>(&self, sysvar: &T)
2175 where
2176 T: Sysvar + SysvarId,
2177 {
2178 self.update_sysvar_account(&T::id(), |account| {
2179 create_account(
2180 sysvar,
2181 self.inherit_specially_retained_account_fields(account),
2182 )
2183 });
2184 self.transaction_processor.reset_sysvar_cache();
2187 self.transaction_processor
2188 .fill_missing_sysvar_cache_entries(self);
2189 }
2190
2191 fn update_slot_history(&self) {
2192 self.update_sysvar_account(&sysvar::slot_history::id(), |account| {
2193 let mut slot_history = account
2194 .as_ref()
2195 .map(|account| from_account::<SlotHistory, _>(account).unwrap())
2196 .unwrap_or_default();
2197 slot_history.add(self.slot());
2198 create_account(
2199 &slot_history,
2200 self.inherit_specially_retained_account_fields(account),
2201 )
2202 });
2203 }
2204
2205 fn update_slot_hashes(&self) {
2206 self.update_sysvar_account(&sysvar::slot_hashes::id(), |account| {
2207 let mut slot_hashes = account
2208 .as_ref()
2209 .map(|account| from_account::<SlotHashes, _>(account).unwrap())
2210 .unwrap_or_default();
2211 slot_hashes.add(self.parent_slot, self.parent_hash);
2212 create_account(
2213 &slot_hashes,
2214 self.inherit_specially_retained_account_fields(account),
2215 )
2216 });
2217 }
2218
2219 pub fn get_slot_history(&self) -> SlotHistory {
2220 from_account(&self.get_account(&sysvar::slot_history::id()).unwrap()).unwrap()
2221 }
2222
2223 fn update_epoch_stakes(&mut self, leader_schedule_epoch: Epoch) {
2224 if !self.epoch_stakes.contains_key(&leader_schedule_epoch) {
2228 self.epoch_stakes.retain(|&epoch, _| {
2229 epoch >= leader_schedule_epoch.saturating_sub(MAX_LEADER_SCHEDULE_STAKES)
2230 });
2231 let stakes = self.stakes_cache.stakes().clone();
2232 let stakes = Arc::new(StakesEnum::from(stakes));
2233 let new_epoch_stakes = EpochStakes::new(stakes, leader_schedule_epoch);
2234 info!(
2235 "new epoch stakes, epoch: {}, total_stake: {}",
2236 leader_schedule_epoch,
2237 new_epoch_stakes.total_stake(),
2238 );
2239
2240 if log::log_enabled!(log::Level::Trace) {
2243 let vote_stakes: HashMap<_, _> = self
2244 .stakes_cache
2245 .stakes()
2246 .vote_accounts()
2247 .delegated_stakes()
2248 .map(|(pubkey, stake)| (*pubkey, stake))
2249 .collect();
2250 trace!("new epoch stakes, stakes: {vote_stakes:#?}");
2251 }
2252 self.epoch_stakes
2253 .insert(leader_schedule_epoch, new_epoch_stakes);
2254 }
2255 }
2256
2257 #[cfg(feature = "dev-context-only-utils")]
2258 pub fn set_epoch_stakes_for_test(&mut self, epoch: Epoch, stakes: EpochStakes) {
2259 self.epoch_stakes.insert(epoch, stakes);
2260 }
2261
2262 fn update_rent(&self) {
2263 self.update_sysvar_account(&sysvar::rent::id(), |account| {
2264 create_account(
2265 &self.rent_collector.rent,
2266 self.inherit_specially_retained_account_fields(account),
2267 )
2268 });
2269 }
2270
2271 fn update_epoch_schedule(&self) {
2272 self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
2273 create_account(
2274 self.epoch_schedule(),
2275 self.inherit_specially_retained_account_fields(account),
2276 )
2277 });
2278 }
2279
2280 fn update_stake_history(&self, epoch: Option<Epoch>) {
2281 if epoch == Some(self.epoch()) {
2282 return;
2283 }
2284 self.update_sysvar_account(&sysvar::stake_history::id(), |account| {
2286 create_account::<sysvar::stake_history::StakeHistory>(
2287 self.stakes_cache.stakes().history(),
2288 self.inherit_specially_retained_account_fields(account),
2289 )
2290 });
2291 }
2292
2293 pub fn epoch_duration_in_years(&self, prev_epoch: Epoch) -> f64 {
2294 self.epoch_schedule().get_slots_in_epoch(prev_epoch) as f64 / self.slots_per_year
2298 }
2299
2300 fn get_inflation_start_slot(&self) -> Slot {
2306 let mut slots = self
2307 .feature_set
2308 .full_inflation_features_enabled()
2309 .iter()
2310 .filter_map(|id| self.feature_set.activated_slot(id))
2311 .collect::<Vec<_>>();
2312 slots.sort_unstable();
2313 slots.first().cloned().unwrap_or_else(|| {
2314 self.feature_set
2315 .activated_slot(&feature_set::pico_inflation::id())
2316 .unwrap_or(0)
2317 })
2318 }
2319
2320 fn get_inflation_num_slots(&self) -> u64 {
2321 let inflation_activation_slot = self.get_inflation_start_slot();
2322 let inflation_start_slot = self.epoch_schedule().get_first_slot_in_epoch(
2324 self.epoch_schedule()
2325 .get_epoch(inflation_activation_slot)
2326 .saturating_sub(1),
2327 );
2328 self.epoch_schedule().get_first_slot_in_epoch(self.epoch()) - inflation_start_slot
2329 }
2330
2331 pub fn slot_in_year_for_inflation(&self) -> f64 {
2332 let num_slots = self.get_inflation_num_slots();
2333
2334 num_slots as f64 / self.slots_per_year
2336 }
2337
2338 fn calculate_previous_epoch_inflation_rewards(
2339 &self,
2340 prev_epoch_capitalization: u64,
2341 prev_epoch: Epoch,
2342 ) -> PrevEpochInflationRewards {
2343 let slot_in_year = self.slot_in_year_for_inflation();
2344 let (validator_rate, foundation_rate) = {
2345 let inflation = self.inflation.read().unwrap();
2346 (
2347 (*inflation).validator(slot_in_year),
2348 (*inflation).foundation(slot_in_year),
2349 )
2350 };
2351
2352 let prev_epoch_duration_in_years = self.epoch_duration_in_years(prev_epoch);
2353 let validator_rewards = (validator_rate
2354 * prev_epoch_capitalization as f64
2355 * prev_epoch_duration_in_years) as u64;
2356
2357 PrevEpochInflationRewards {
2358 validator_rewards,
2359 prev_epoch_duration_in_years,
2360 validator_rate,
2361 foundation_rate,
2362 }
2363 }
2364
2365 fn assert_validator_rewards_paid(&self, validator_rewards_paid: u64) {
2366 assert_eq!(
2367 validator_rewards_paid,
2368 u64::try_from(
2369 self.rewards
2370 .read()
2371 .unwrap()
2372 .par_iter()
2373 .map(|(_address, reward_info)| {
2374 match reward_info.reward_type {
2375 RewardType::Voting | RewardType::Staking => reward_info.lamports,
2376 _ => 0,
2377 }
2378 })
2379 .sum::<i64>()
2380 )
2381 .unwrap()
2382 );
2383 }
2384
2385 fn filter_stake_delegations<'a>(
2386 &self,
2387 stakes: &'a Stakes<StakeAccount<Delegation>>,
2388 ) -> Vec<(&'a Pubkey, &'a StakeAccount<Delegation>)> {
2389 if self
2390 .feature_set
2391 .is_active(&feature_set::stake_minimum_delegation_for_rewards::id())
2392 {
2393 let num_stake_delegations = stakes.stake_delegations().len();
2394 let min_stake_delegation =
2395 solana_stake_program::get_minimum_delegation(&self.feature_set)
2396 .max(LAMPORTS_PER_SOL);
2397
2398 let (stake_delegations, filter_time_us) = measure_us!(stakes
2399 .stake_delegations()
2400 .iter()
2401 .filter(|(_stake_pubkey, cached_stake_account)| {
2402 cached_stake_account.delegation().stake >= min_stake_delegation
2403 })
2404 .collect::<Vec<_>>());
2405
2406 datapoint_info!(
2407 "stake_account_filter_time",
2408 ("filter_time_us", filter_time_us, i64),
2409 ("num_stake_delegations_before", num_stake_delegations, i64),
2410 ("num_stake_delegations_after", stake_delegations.len(), i64)
2411 );
2412 stake_delegations
2413 } else {
2414 stakes.stake_delegations().iter().collect()
2415 }
2416 }
2417
2418 fn calc_vote_accounts_to_store(
2427 vote_account_rewards: DashMap<Pubkey, VoteReward>,
2428 ) -> VoteRewardsAccounts {
2429 let len = vote_account_rewards.len();
2430 let mut result = VoteRewardsAccounts {
2431 rewards: Vec::with_capacity(len),
2432 accounts_to_store: Vec::with_capacity(len),
2433 };
2434 vote_account_rewards.into_iter().for_each(
2435 |(
2436 vote_pubkey,
2437 VoteReward {
2438 mut vote_account,
2439 commission,
2440 vote_rewards,
2441 vote_needs_store,
2442 },
2443 )| {
2444 if let Err(err) = vote_account.checked_add_lamports(vote_rewards) {
2445 debug!("reward redemption failed for {}: {:?}", vote_pubkey, err);
2446 return;
2447 }
2448
2449 result.rewards.push((
2450 vote_pubkey,
2451 RewardInfo {
2452 reward_type: RewardType::Voting,
2453 lamports: vote_rewards as i64,
2454 post_balance: vote_account.lamports(),
2455 commission: Some(commission),
2456 },
2457 ));
2458 result
2459 .accounts_to_store
2460 .push(vote_needs_store.then_some(vote_account));
2461 },
2462 );
2463 result
2464 }
2465
2466 fn update_reward_history(
2467 &self,
2468 stake_rewards: StakeRewards,
2469 mut vote_rewards: Vec<(Pubkey, RewardInfo)>,
2470 ) {
2471 let additional_reserve = stake_rewards.len() + vote_rewards.len();
2472 let mut rewards = self.rewards.write().unwrap();
2473 rewards.reserve(additional_reserve);
2474 rewards.append(&mut vote_rewards);
2475 stake_rewards
2476 .into_iter()
2477 .filter(|x| x.get_stake_reward() > 0)
2478 .for_each(|x| rewards.push((x.stake_pubkey, x.stake_reward_info)));
2479 }
2480
2481 fn update_recent_blockhashes_locked(&self, locked_blockhash_queue: &BlockhashQueue) {
2482 #[allow(deprecated)]
2483 self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
2484 let recent_blockhash_iter = locked_blockhash_queue.get_recent_blockhashes();
2485 recent_blockhashes_account::create_account_with_data_and_fields(
2486 recent_blockhash_iter,
2487 self.inherit_specially_retained_account_fields(account),
2488 )
2489 });
2490 }
2491
2492 pub fn update_recent_blockhashes(&self) {
2493 let blockhash_queue = self.blockhash_queue.read().unwrap();
2494 self.update_recent_blockhashes_locked(&blockhash_queue);
2495 }
2496
2497 fn get_timestamp_estimate(
2498 &self,
2499 max_allowable_drift: MaxAllowableDrift,
2500 epoch_start_timestamp: Option<(Slot, UnixTimestamp)>,
2501 ) -> Option<UnixTimestamp> {
2502 let mut get_timestamp_estimate_time = Measure::start("get_timestamp_estimate");
2503 let slots_per_epoch = self.epoch_schedule().slots_per_epoch;
2504 let vote_accounts = self.vote_accounts();
2505 let recent_timestamps = vote_accounts.iter().filter_map(|(pubkey, (_, account))| {
2506 let vote_state = account.vote_state();
2507 let slot_delta = self.slot().checked_sub(vote_state.last_timestamp.slot)?;
2508 (slot_delta <= slots_per_epoch).then_some({
2509 (
2510 *pubkey,
2511 (
2512 vote_state.last_timestamp.slot,
2513 vote_state.last_timestamp.timestamp,
2514 ),
2515 )
2516 })
2517 });
2518 let slot_duration = Duration::from_nanos(self.ns_per_slot as u64);
2519 let epoch = self.epoch_schedule().get_epoch(self.slot());
2520 let stakes = self.epoch_vote_accounts(epoch)?;
2521 let stake_weighted_timestamp = calculate_stake_weighted_timestamp(
2522 recent_timestamps,
2523 stakes,
2524 self.slot(),
2525 slot_duration,
2526 epoch_start_timestamp,
2527 max_allowable_drift,
2528 self.feature_set
2529 .is_active(&feature_set::warp_timestamp_again::id()),
2530 );
2531 get_timestamp_estimate_time.stop();
2532 datapoint_info!(
2533 "bank-timestamp",
2534 (
2535 "get_timestamp_estimate_us",
2536 get_timestamp_estimate_time.as_us(),
2537 i64
2538 ),
2539 );
2540 stake_weighted_timestamp
2541 }
2542
2543 pub fn rehash(&self) {
2551 let get_delta_hash = || {
2552 (!self
2553 .feature_set
2554 .is_active(&feature_set::remove_accounts_delta_hash::id()))
2555 .then(|| {
2556 self.rc
2557 .accounts
2558 .accounts_db
2559 .get_accounts_delta_hash(self.slot())
2560 })
2561 .flatten()
2562 };
2563
2564 let mut hash = self.hash.write().unwrap();
2565 let curr_accounts_delta_hash = get_delta_hash();
2566 let new = self.hash_internal_state();
2567 if let Some(curr_accounts_delta_hash) = curr_accounts_delta_hash {
2568 let new_accounts_delta_hash = get_delta_hash().unwrap();
2569 assert_eq!(
2570 new_accounts_delta_hash, curr_accounts_delta_hash,
2571 "rehashing is not allowed to change the account state",
2572 );
2573 }
2574 if new != *hash {
2575 warn!("Updating bank hash to {new}");
2576 *hash = new;
2577 }
2578 }
2579
2580 pub fn freeze(&self) {
2581 let mut hash = self.hash.write().unwrap();
2593 if *hash == Hash::default() {
2594 self.collect_rent_eagerly();
2596 if self.feature_set.is_active(&reward_full_priority_fee::id()) {
2597 self.distribute_transaction_fee_details();
2598 } else {
2599 self.distribute_transaction_fees();
2600 }
2601 self.distribute_rent_fees();
2602 self.update_slot_history();
2603 self.run_incinerator();
2604
2605 self.freeze_started.store(true, Relaxed);
2607 if self.is_accounts_lt_hash_enabled() {
2608 self.update_accounts_lt_hash();
2611
2612 if self
2616 .rc
2617 .accounts
2618 .accounts_db
2619 .verify_experimental_accumulator_hash
2620 {
2621 let slot = self.slot();
2622 info!("Verifying the accounts lt hash for slot {slot}...");
2623 let (calculated_accounts_lt_hash, duration) = meas_dur!({
2624 self.rc
2625 .accounts
2626 .accounts_db
2627 .calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors, slot)
2628 });
2629 let actual_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap();
2630 assert_eq!(
2631 calculated_accounts_lt_hash,
2632 *actual_accounts_lt_hash,
2633 "Verifying the accounts lt hash for slot {slot} failed! calculated checksum: {}, actual checksum: {}",
2634 calculated_accounts_lt_hash.0.checksum(),
2635 actual_accounts_lt_hash.0.checksum(),
2636 );
2637 info!("Verifying the accounts lt hash for slot {slot}... Done successfully in {duration:?}");
2638 }
2639 }
2640 *hash = self.hash_internal_state();
2641 self.rc.accounts.accounts_db.mark_slot_frozen(self.slot());
2642 }
2643 }
2644
2645 #[cfg(feature = "dev-context-only-utils")]
2647 pub fn unfreeze_for_ledger_tool(&self) {
2648 self.freeze_started.store(false, Relaxed);
2649 }
2650
2651 pub fn epoch_schedule(&self) -> &EpochSchedule {
2652 &self.epoch_schedule
2653 }
2654
2655 pub fn squash(&self) -> SquashTiming {
2661 self.freeze();
2662
2663 let mut roots = vec![self.slot()];
2665 roots.append(&mut self.parents().iter().map(|p| p.slot()).collect());
2666
2667 let mut total_index_us = 0;
2668 let mut total_cache_us = 0;
2669 let mut total_store_us = 0;
2670
2671 let mut squash_accounts_time = Measure::start("squash_accounts_time");
2672 for slot in roots.iter().rev() {
2673 let add_root_timing = self.rc.accounts.add_root(*slot);
2675 total_index_us += add_root_timing.index_us;
2676 total_cache_us += add_root_timing.cache_us;
2677 total_store_us += add_root_timing.store_us;
2678 }
2679 squash_accounts_time.stop();
2680
2681 *self.rc.parent.write().unwrap() = None;
2682
2683 let mut squash_cache_time = Measure::start("squash_cache_time");
2684 roots
2685 .iter()
2686 .for_each(|slot| self.status_cache.write().unwrap().add_root(*slot));
2687 squash_cache_time.stop();
2688
2689 SquashTiming {
2690 squash_accounts_ms: squash_accounts_time.as_ms(),
2691 squash_accounts_index_ms: total_index_us / 1000,
2692 squash_accounts_cache_ms: total_cache_us / 1000,
2693 squash_accounts_store_ms: total_store_us / 1000,
2694
2695 squash_cache_ms: squash_cache_time.as_ms(),
2696 }
2697 }
2698
2699 pub fn parent(&self) -> Option<Arc<Bank>> {
2701 self.rc.parent.read().unwrap().clone()
2702 }
2703
2704 pub fn parent_slot(&self) -> Slot {
2705 self.parent_slot
2706 }
2707
2708 pub fn parent_hash(&self) -> Hash {
2709 self.parent_hash
2710 }
2711
2712 fn process_genesis_config(
2713 &mut self,
2714 genesis_config: &GenesisConfig,
2715 #[cfg(feature = "dev-context-only-utils")] collector_id_for_tests: Option<Pubkey>,
2716 #[cfg(feature = "dev-context-only-utils")] genesis_hash: Option<Hash>,
2717 ) {
2718 self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
2720
2721 for (pubkey, account) in genesis_config.accounts.iter() {
2722 assert!(
2723 self.get_account(pubkey).is_none(),
2724 "{pubkey} repeated in genesis config"
2725 );
2726 self.store_account(pubkey, &account.to_account_shared_data());
2727 self.capitalization.fetch_add(account.lamports(), Relaxed);
2728 self.accounts_data_size_initial += account.data().len() as u64;
2729 }
2730
2731 for (pubkey, account) in genesis_config.rewards_pools.iter() {
2732 assert!(
2733 self.get_account(pubkey).is_none(),
2734 "{pubkey} repeated in genesis config"
2735 );
2736 self.store_account(pubkey, &account.to_account_shared_data());
2737 self.accounts_data_size_initial += account.data().len() as u64;
2738 }
2739
2740 let collector_id = self.stakes_cache.stakes().highest_staked_node().copied();
2745 #[cfg(feature = "dev-context-only-utils")]
2746 let collector_id = collector_id.or(collector_id_for_tests);
2747 self.collector_id =
2748 collector_id.expect("genesis processing failed because no staked nodes exist");
2749
2750 #[cfg(not(feature = "dev-context-only-utils"))]
2751 let genesis_hash = genesis_config.hash();
2752 #[cfg(feature = "dev-context-only-utils")]
2753 let genesis_hash = genesis_hash.unwrap_or(genesis_config.hash());
2754
2755 self.blockhash_queue
2756 .write()
2757 .unwrap()
2758 .genesis_hash(&genesis_hash, self.fee_rate_governor.lamports_per_signature);
2759
2760 self.hashes_per_tick = genesis_config.hashes_per_tick();
2761 self.ticks_per_slot = genesis_config.ticks_per_slot();
2762 self.ns_per_slot = genesis_config.ns_per_slot();
2763 self.genesis_creation_time = genesis_config.creation_time;
2764 self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
2765 self.slots_per_year = genesis_config.slots_per_year();
2766
2767 self.epoch_schedule = genesis_config.epoch_schedule.clone();
2768
2769 self.inflation = Arc::new(RwLock::new(genesis_config.inflation));
2770
2771 self.rent_collector = RentCollector::new(
2772 self.epoch,
2773 self.epoch_schedule().clone(),
2774 self.slots_per_year,
2775 genesis_config.rent.clone(),
2776 );
2777
2778 for (name, program_id) in &genesis_config.native_instruction_processors {
2780 self.add_builtin_account(name, program_id);
2781 }
2782 }
2783
2784 fn burn_and_purge_account(&self, program_id: &Pubkey, mut account: AccountSharedData) {
2785 let old_data_size = account.data().len();
2786 self.capitalization.fetch_sub(account.lamports(), Relaxed);
2787 account.set_lamports(0);
2790 account.data_as_mut_slice().fill(0);
2791 self.store_account(program_id, &account);
2792 self.calculate_and_update_accounts_data_size_delta_off_chain(old_data_size, 0);
2793 }
2794
2795 pub fn add_precompiled_account(&self, program_id: &Pubkey) {
2797 self.add_precompiled_account_with_owner(program_id, native_loader::id())
2798 }
2799
2800 fn add_precompiled_account_with_owner(&self, program_id: &Pubkey, owner: Pubkey) {
2802 if let Some(account) = self.get_account_with_fixed_root(program_id) {
2803 if account.executable() {
2804 return;
2805 } else {
2806 self.burn_and_purge_account(program_id, account);
2808 }
2809 };
2810
2811 assert!(
2812 !self.freeze_started(),
2813 "Can't change frozen bank by adding not-existing new precompiled program ({program_id}). \
2814 Maybe, inconsistent program activation is detected on snapshot restore?"
2815 );
2816
2817 let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None);
2819
2820 let account = AccountSharedData::from(Account {
2821 lamports,
2822 owner,
2823 data: vec![],
2824 executable: true,
2825 rent_epoch,
2826 });
2827 self.store_account_and_update_capitalization(program_id, &account);
2828 }
2829
2830 pub fn set_rent_burn_percentage(&mut self, burn_percent: u8) {
2831 self.rent_collector.rent.burn_percent = burn_percent;
2832 }
2833
2834 pub fn set_hashes_per_tick(&mut self, hashes_per_tick: Option<u64>) {
2835 self.hashes_per_tick = hashes_per_tick;
2836 }
2837
2838 pub fn last_blockhash(&self) -> Hash {
2840 self.blockhash_queue.read().unwrap().last_hash()
2841 }
2842
2843 pub fn last_blockhash_and_lamports_per_signature(&self) -> (Hash, u64) {
2844 let blockhash_queue = self.blockhash_queue.read().unwrap();
2845 let last_hash = blockhash_queue.last_hash();
2846 let last_lamports_per_signature = blockhash_queue
2847 .get_lamports_per_signature(&last_hash)
2848 .unwrap(); (last_hash, last_lamports_per_signature)
2850 }
2851
2852 pub fn is_blockhash_valid(&self, hash: &Hash) -> bool {
2853 let blockhash_queue = self.blockhash_queue.read().unwrap();
2854 blockhash_queue.is_hash_valid_for_age(hash, MAX_PROCESSING_AGE)
2855 }
2856
2857 pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
2858 self.rent_collector.rent.minimum_balance(data_len).max(1)
2859 }
2860
2861 pub fn get_lamports_per_signature(&self) -> u64 {
2862 self.fee_rate_governor.lamports_per_signature
2863 }
2864
2865 pub fn get_lamports_per_signature_for_blockhash(&self, hash: &Hash) -> Option<u64> {
2866 let blockhash_queue = self.blockhash_queue.read().unwrap();
2867 blockhash_queue.get_lamports_per_signature(hash)
2868 }
2869
2870 pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option<u64> {
2871 let lamports_per_signature = {
2872 let blockhash_queue = self.blockhash_queue.read().unwrap();
2873 blockhash_queue.get_lamports_per_signature(message.recent_blockhash())
2874 }
2875 .or_else(|| {
2876 self.load_message_nonce_account(message).map(
2877 |(_nonce_address, _nonce_account, nonce_data)| {
2878 nonce_data.get_lamports_per_signature()
2879 },
2880 )
2881 })?;
2882 Some(self.get_fee_for_message_with_lamports_per_signature(message, lamports_per_signature))
2883 }
2884
2885 pub fn get_startup_verification_complete(&self) -> &Arc<AtomicBool> {
2887 &self
2888 .rc
2889 .accounts
2890 .accounts_db
2891 .verify_accounts_hash_in_bg
2892 .verified
2893 }
2894
2895 pub fn is_startup_verification_complete(&self) -> bool {
2899 self.has_initial_accounts_hash_verification_completed()
2900 }
2901
2902 pub fn set_startup_verification_complete(&self) {
2905 self.set_initial_accounts_hash_verification_completed();
2906 }
2907
2908 pub fn get_fee_for_message_with_lamports_per_signature(
2909 &self,
2910 message: &impl SVMMessage,
2911 lamports_per_signature: u64,
2912 ) -> u64 {
2913 let fee_budget_limits = FeeBudgetLimits::from(
2914 process_compute_budget_instructions(
2915 message.program_instructions_iter(),
2916 &self.feature_set,
2917 )
2918 .unwrap_or_default(),
2919 );
2920 solana_fee::calculate_fee(
2921 message,
2922 lamports_per_signature == 0,
2923 self.fee_structure().lamports_per_signature,
2924 fee_budget_limits.prioritization_fee,
2925 FeeFeatures::from(self.feature_set.as_ref()),
2926 )
2927 }
2928
2929 pub fn get_blockhash_last_valid_block_height(&self, blockhash: &Hash) -> Option<Slot> {
2930 let blockhash_queue = self.blockhash_queue.read().unwrap();
2931 blockhash_queue
2934 .get_hash_age(blockhash)
2935 .map(|age| self.block_height + MAX_PROCESSING_AGE as u64 - age)
2936 }
2937
2938 pub fn confirmed_last_blockhash(&self) -> Hash {
2939 const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
2940
2941 let parents = self.parents();
2942 if parents.is_empty() {
2943 self.last_blockhash()
2944 } else {
2945 let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
2946 parents[index].last_blockhash()
2947 }
2948 }
2949
2950 pub fn clear_signatures(&self) {
2952 self.status_cache.write().unwrap().clear();
2953 }
2954
2955 pub fn clear_slot_signatures(&self, slot: Slot) {
2956 self.status_cache.write().unwrap().clear_slot_entries(slot);
2957 }
2958
2959 fn update_transaction_statuses(
2960 &self,
2961 sanitized_txs: &[impl TransactionWithMeta],
2962 processing_results: &[TransactionProcessingResult],
2963 ) {
2964 let mut status_cache = self.status_cache.write().unwrap();
2965 assert_eq!(sanitized_txs.len(), processing_results.len());
2966 for (tx, processing_result) in sanitized_txs.iter().zip(processing_results) {
2967 if let Ok(processed_tx) = &processing_result {
2968 status_cache.insert(
2971 tx.recent_blockhash(),
2972 tx.message_hash(),
2973 self.slot(),
2974 processed_tx.status(),
2975 );
2976 status_cache.insert(
2980 tx.recent_blockhash(),
2981 tx.signature(),
2982 self.slot(),
2983 processed_tx.status(),
2984 );
2985 }
2986 }
2987 }
2988
2989 fn register_recent_blockhash(&self, blockhash: &Hash, scheduler: &InstalledSchedulerRwLock) {
2993 BankWithScheduler::wait_for_paused_scheduler(self, scheduler);
2996
2997 let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3001
3002 #[cfg(feature = "dev-context-only-utils")]
3003 let blockhash_override = self
3004 .hash_overrides
3005 .lock()
3006 .unwrap()
3007 .get_blockhash_override(self.slot())
3008 .copied()
3009 .inspect(|blockhash_override| {
3010 if blockhash_override != blockhash {
3011 info!(
3012 "bank: slot: {}: overrode blockhash: {} with {}",
3013 self.slot(),
3014 blockhash,
3015 blockhash_override
3016 );
3017 }
3018 });
3019 #[cfg(feature = "dev-context-only-utils")]
3020 let blockhash = blockhash_override.as_ref().unwrap_or(blockhash);
3021
3022 w_blockhash_queue.register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3023 self.update_recent_blockhashes_locked(&w_blockhash_queue);
3024 }
3025
3026 pub fn register_unique_recent_blockhash_for_test(&self) {
3029 self.register_recent_blockhash(
3030 &Hash::new_unique(),
3031 &BankWithScheduler::no_scheduler_available(),
3032 )
3033 }
3034
3035 #[cfg(feature = "dev-context-only-utils")]
3036 pub fn register_recent_blockhash_for_test(
3037 &self,
3038 blockhash: &Hash,
3039 lamports_per_signature: Option<u64>,
3040 ) {
3041 let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3045 if let Some(lamports_per_signature) = lamports_per_signature {
3046 w_blockhash_queue.register_hash(blockhash, lamports_per_signature);
3047 } else {
3048 w_blockhash_queue
3049 .register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3050 }
3051 }
3052
3053 pub fn register_tick(&self, hash: &Hash, scheduler: &InstalledSchedulerRwLock) {
3060 assert!(
3061 !self.freeze_started(),
3062 "register_tick() working on a bank that is already frozen or is undergoing freezing!"
3063 );
3064
3065 if self.is_block_boundary(self.tick_height.load(Relaxed) + 1) {
3066 self.register_recent_blockhash(hash, scheduler);
3067 }
3068
3069 self.tick_height.fetch_add(1, Relaxed);
3075 }
3076
3077 #[cfg(feature = "dev-context-only-utils")]
3078 pub fn register_tick_for_test(&self, hash: &Hash) {
3079 self.register_tick(hash, &BankWithScheduler::no_scheduler_available())
3080 }
3081
3082 #[cfg(feature = "dev-context-only-utils")]
3083 pub fn register_default_tick_for_test(&self) {
3084 self.register_tick_for_test(&Hash::default())
3085 }
3086
3087 #[cfg(feature = "dev-context-only-utils")]
3088 pub fn register_unique_tick(&self) {
3089 self.register_tick_for_test(&Hash::new_unique())
3090 }
3091
3092 pub fn is_complete(&self) -> bool {
3093 self.tick_height() == self.max_tick_height()
3094 }
3095
3096 pub fn is_block_boundary(&self, tick_height: u64) -> bool {
3097 tick_height == self.max_tick_height
3098 }
3099
3100 pub fn get_transaction_account_lock_limit(&self) -> usize {
3102 if let Some(transaction_account_lock_limit) = self.transaction_account_lock_limit {
3103 transaction_account_lock_limit
3104 } else if self
3105 .feature_set
3106 .is_active(&feature_set::increase_tx_account_lock_limit::id())
3107 {
3108 MAX_TX_ACCOUNT_LOCKS
3109 } else {
3110 64
3111 }
3112 }
3113
3114 pub fn prepare_entry_batch(
3117 &self,
3118 txs: Vec<VersionedTransaction>,
3119 ) -> Result<TransactionBatch<RuntimeTransaction<SanitizedTransaction>>> {
3120 let sanitized_txs = txs
3121 .into_iter()
3122 .map(|tx| {
3123 RuntimeTransaction::try_create(
3124 tx,
3125 MessageHash::Compute,
3126 None,
3127 self,
3128 self.get_reserved_account_keys(),
3129 )
3130 })
3131 .collect::<Result<Vec<_>>>()?;
3132 let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3133 let lock_results = self
3134 .rc
3135 .accounts
3136 .lock_accounts(sanitized_txs.iter(), tx_account_lock_limit);
3137 Ok(TransactionBatch::new(
3138 lock_results,
3139 self,
3140 OwnedOrBorrowed::Owned(sanitized_txs),
3141 ))
3142 }
3143
3144 pub fn try_lock_accounts(&self, txs: &[impl SVMMessage]) -> Vec<Result<()>> {
3146 let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3147 self.rc
3148 .accounts
3149 .lock_accounts(txs.iter(), tx_account_lock_limit)
3150 }
3151
3152 pub fn prepare_sanitized_batch<'a, 'b, Tx: SVMMessage>(
3154 &'a self,
3155 txs: &'b [Tx],
3156 ) -> TransactionBatch<'a, 'b, Tx> {
3157 TransactionBatch::new(
3158 self.try_lock_accounts(txs),
3159 self,
3160 OwnedOrBorrowed::Borrowed(txs),
3161 )
3162 }
3163
3164 pub fn prepare_sanitized_batch_with_results<'a, 'b, Tx: SVMMessage>(
3167 &'a self,
3168 transactions: &'b [Tx],
3169 transaction_results: impl Iterator<Item = Result<()>>,
3170 ) -> TransactionBatch<'a, 'b, Tx> {
3171 let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3173 let lock_results = self.rc.accounts.lock_accounts_with_results(
3174 transactions.iter(),
3175 transaction_results,
3176 tx_account_lock_limit,
3177 );
3178 TransactionBatch::new(lock_results, self, OwnedOrBorrowed::Borrowed(transactions))
3179 }
3180
3181 pub fn prepare_unlocked_batch_from_single_tx<'a, Tx: SVMMessage>(
3183 &'a self,
3184 transaction: &'a Tx,
3185 ) -> TransactionBatch<'a, 'a, Tx> {
3186 let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3187 let lock_result = validate_account_locks(transaction.account_keys(), tx_account_lock_limit);
3188 let mut batch = TransactionBatch::new(
3189 vec![lock_result],
3190 self,
3191 OwnedOrBorrowed::Borrowed(slice::from_ref(transaction)),
3192 );
3193 batch.set_needs_unlock(false);
3194 batch
3195 }
3196
3197 pub fn simulate_transaction(
3199 &self,
3200 transaction: &impl TransactionWithMeta,
3201 enable_cpi_recording: bool,
3202 ) -> TransactionSimulationResult {
3203 assert!(self.is_frozen(), "simulation bank must be frozen");
3204
3205 self.simulate_transaction_unchecked(transaction, enable_cpi_recording)
3206 }
3207
3208 pub fn simulate_transaction_unchecked(
3211 &self,
3212 transaction: &impl TransactionWithMeta,
3213 enable_cpi_recording: bool,
3214 ) -> TransactionSimulationResult {
3215 let account_keys = transaction.account_keys();
3216 let number_of_accounts = account_keys.len();
3217 let account_overrides = self.get_account_overrides_for_simulation(&account_keys);
3218 let batch = self.prepare_unlocked_batch_from_single_tx(transaction);
3219 let mut timings = ExecuteTimings::default();
3220
3221 let LoadAndExecuteTransactionsOutput {
3222 mut processing_results,
3223 ..
3224 } = self.load_and_execute_transactions(
3225 &batch,
3226 MAX_PROCESSING_AGE - MAX_TRANSACTION_FORWARDING_DELAY,
3230 &mut timings,
3231 &mut TransactionErrorMetrics::default(),
3232 TransactionProcessingConfig {
3233 account_overrides: Some(&account_overrides),
3234 check_program_modification_slot: self.check_program_modification_slot,
3235 compute_budget: self.compute_budget(),
3236 log_messages_bytes_limit: None,
3237 limit_to_load_programs: true,
3238 recording_config: ExecutionRecordingConfig {
3239 enable_cpi_recording,
3240 enable_log_recording: true,
3241 enable_return_data_recording: true,
3242 },
3243 transaction_account_lock_limit: Some(self.get_transaction_account_lock_limit()),
3244 },
3245 );
3246
3247 let units_consumed =
3248 timings
3249 .details
3250 .per_program_timings
3251 .iter()
3252 .fold(0, |acc: u64, (_, program_timing)| {
3253 (std::num::Saturating(acc)
3254 + program_timing.accumulated_units
3255 + program_timing.total_errored_units)
3256 .0
3257 });
3258
3259 debug!("simulate_transaction: {:?}", timings);
3260
3261 let processing_result = processing_results
3262 .pop()
3263 .unwrap_or(Err(TransactionError::InvalidProgramForExecution));
3264 let (post_simulation_accounts, result, logs, return_data, inner_instructions) =
3265 match processing_result {
3266 Ok(processed_tx) => match processed_tx {
3267 ProcessedTransaction::Executed(executed_tx) => {
3268 let details = executed_tx.execution_details;
3269 let post_simulation_accounts = executed_tx
3270 .loaded_transaction
3271 .accounts
3272 .into_iter()
3273 .take(number_of_accounts)
3274 .collect::<Vec<_>>();
3275 (
3276 post_simulation_accounts,
3277 details.status,
3278 details.log_messages,
3279 details.return_data,
3280 details.inner_instructions,
3281 )
3282 }
3283 ProcessedTransaction::FeesOnly(fees_only_tx) => {
3284 (vec![], Err(fees_only_tx.load_error), None, None, None)
3285 }
3286 },
3287 Err(error) => (vec![], Err(error), None, None, None),
3288 };
3289 let logs = logs.unwrap_or_default();
3290
3291 TransactionSimulationResult {
3292 result,
3293 logs,
3294 post_simulation_accounts,
3295 units_consumed,
3296 return_data,
3297 inner_instructions,
3298 }
3299 }
3300
3301 fn get_account_overrides_for_simulation(&self, account_keys: &AccountKeys) -> AccountOverrides {
3302 let mut account_overrides = AccountOverrides::default();
3303 let slot_history_id = sysvar::slot_history::id();
3304 if account_keys.iter().any(|pubkey| *pubkey == slot_history_id) {
3305 let current_account = self.get_account_with_fixed_root(&slot_history_id);
3306 let slot_history = current_account
3307 .as_ref()
3308 .map(|account| from_account::<SlotHistory, _>(account).unwrap())
3309 .unwrap_or_default();
3310 if slot_history.check(self.slot()) == Check::Found {
3311 let ancestors = Ancestors::from(self.proper_ancestors().collect::<Vec<_>>());
3312 if let Some((account, _)) =
3313 self.load_slow_with_fixed_root(&ancestors, &slot_history_id)
3314 {
3315 account_overrides.set_slot_history(Some(account));
3316 }
3317 }
3318 }
3319 account_overrides
3320 }
3321
3322 pub fn unlock_accounts<'a, Tx: SVMMessage + 'a>(
3323 &self,
3324 txs_and_results: impl Iterator<Item = (&'a Tx, &'a Result<()>)> + Clone,
3325 ) {
3326 self.rc.accounts.unlock_accounts(txs_and_results)
3327 }
3328
3329 pub fn remove_unrooted_slots(&self, slots: &[(Slot, BankId)]) {
3330 self.rc.accounts.accounts_db.remove_unrooted_slots(slots)
3331 }
3332
3333 pub fn get_hash_age(&self, hash: &Hash) -> Option<u64> {
3334 self.blockhash_queue.read().unwrap().get_hash_age(hash)
3335 }
3336
3337 pub fn is_hash_valid_for_age(&self, hash: &Hash, max_age: usize) -> bool {
3338 self.blockhash_queue
3339 .read()
3340 .unwrap()
3341 .is_hash_valid_for_age(hash, max_age)
3342 }
3343
3344 pub fn collect_balances(
3345 &self,
3346 batch: &TransactionBatch<impl SVMMessage>,
3347 ) -> TransactionBalances {
3348 let mut balances: TransactionBalances = vec![];
3349 for transaction in batch.sanitized_transactions() {
3350 let mut transaction_balances: Vec<u64> = vec![];
3351 for account_key in transaction.account_keys().iter() {
3352 transaction_balances.push(self.get_balance(account_key));
3353 }
3354 balances.push(transaction_balances);
3355 }
3356 balances
3357 }
3358
3359 pub fn load_and_execute_transactions(
3360 &self,
3361 batch: &TransactionBatch<impl TransactionWithMeta>,
3362 max_age: usize,
3363 timings: &mut ExecuteTimings,
3364 error_counters: &mut TransactionErrorMetrics,
3365 processing_config: TransactionProcessingConfig,
3366 ) -> LoadAndExecuteTransactionsOutput {
3367 let sanitized_txs = batch.sanitized_transactions();
3368
3369 let (check_results, check_us) = measure_us!(self.check_transactions(
3370 sanitized_txs,
3371 batch.lock_results(),
3372 max_age,
3373 error_counters,
3374 ));
3375 timings.saturating_add_in_place(ExecuteTimingType::CheckUs, check_us);
3376
3377 let (blockhash, blockhash_lamports_per_signature) =
3378 self.last_blockhash_and_lamports_per_signature();
3379 let rent_collector_with_metrics =
3380 RentCollectorWithMetrics::new(self.rent_collector.clone());
3381 let processing_environment = TransactionProcessingEnvironment {
3382 blockhash,
3383 blockhash_lamports_per_signature,
3384 epoch_total_stake: self.get_current_epoch_total_stake(),
3385 feature_set: Arc::clone(&self.feature_set),
3386 fee_lamports_per_signature: self.fee_structure.lamports_per_signature,
3387 rent_collector: Some(&rent_collector_with_metrics),
3388 };
3389
3390 let sanitized_output = self
3391 .transaction_processor
3392 .load_and_execute_sanitized_transactions(
3393 self,
3394 sanitized_txs,
3395 check_results,
3396 &processing_environment,
3397 &processing_config,
3398 );
3399
3400 error_counters.accumulate(&sanitized_output.error_metrics);
3402
3403 timings.accumulate(&sanitized_output.execute_timings);
3405
3406 let ((), collect_logs_us) =
3407 measure_us!(self.collect_logs(sanitized_txs, &sanitized_output.processing_results));
3408 timings.saturating_add_in_place(ExecuteTimingType::CollectLogsUs, collect_logs_us);
3409
3410 let mut processed_counts = ProcessedTransactionCounts::default();
3411 let err_count = &mut error_counters.total;
3412
3413 for (processing_result, tx) in sanitized_output
3414 .processing_results
3415 .iter()
3416 .zip(sanitized_txs)
3417 {
3418 if let Some(debug_keys) = &self.transaction_debug_keys {
3419 for key in tx.account_keys().iter() {
3420 if debug_keys.contains(key) {
3421 let result = processing_result.flattened_result();
3422 info!("slot: {} result: {:?} tx: {:?}", self.slot, result, tx);
3423 break;
3424 }
3425 }
3426 }
3427
3428 if processing_result.was_processed() {
3429 processed_counts.signature_count +=
3433 tx.signature_details().num_transaction_signatures();
3434 processed_counts.processed_transactions_count += 1;
3435
3436 if !tx.is_simple_vote_transaction() {
3437 processed_counts.processed_non_vote_transactions_count += 1;
3438 }
3439 }
3440
3441 match processing_result.flattened_result() {
3442 Ok(()) => {
3443 processed_counts.processed_with_successful_result_count += 1;
3444 }
3445 Err(err) => {
3446 if err_count.0 == 0 {
3447 debug!("tx error: {:?} {:?}", err, tx);
3448 }
3449 *err_count += 1;
3450 }
3451 }
3452 }
3453
3454 LoadAndExecuteTransactionsOutput {
3455 processing_results: sanitized_output.processing_results,
3456 processed_counts,
3457 }
3458 }
3459
3460 fn collect_logs(
3461 &self,
3462 transactions: &[impl TransactionWithMeta],
3463 processing_results: &[TransactionProcessingResult],
3464 ) {
3465 let transaction_log_collector_config =
3466 self.transaction_log_collector_config.read().unwrap();
3467 if transaction_log_collector_config.filter == TransactionLogCollectorFilter::None {
3468 return;
3469 }
3470
3471 let collected_logs: Vec<_> = processing_results
3472 .iter()
3473 .zip(transactions)
3474 .filter_map(|(processing_result, transaction)| {
3475 let processed_tx = processing_result.processed_transaction()?;
3477 let execution_details = processed_tx.execution_details()?;
3479 Self::collect_transaction_logs(
3480 &transaction_log_collector_config,
3481 transaction,
3482 execution_details,
3483 )
3484 })
3485 .collect();
3486
3487 if !collected_logs.is_empty() {
3488 let mut transaction_log_collector = self.transaction_log_collector.write().unwrap();
3489 for (log, filtered_mentioned_addresses) in collected_logs {
3490 let transaction_log_index = transaction_log_collector.logs.len();
3491 transaction_log_collector.logs.push(log);
3492 for key in filtered_mentioned_addresses.into_iter() {
3493 transaction_log_collector
3494 .mentioned_address_map
3495 .entry(key)
3496 .or_default()
3497 .push(transaction_log_index);
3498 }
3499 }
3500 }
3501 }
3502
3503 fn collect_transaction_logs(
3504 transaction_log_collector_config: &TransactionLogCollectorConfig,
3505 transaction: &impl TransactionWithMeta,
3506 execution_details: &TransactionExecutionDetails,
3507 ) -> Option<(TransactionLogInfo, Vec<Pubkey>)> {
3508 let log_messages = execution_details.log_messages.as_ref()?;
3510
3511 let mut filtered_mentioned_addresses = Vec::new();
3512 if !transaction_log_collector_config
3513 .mentioned_addresses
3514 .is_empty()
3515 {
3516 for key in transaction.account_keys().iter() {
3517 if transaction_log_collector_config
3518 .mentioned_addresses
3519 .contains(key)
3520 {
3521 filtered_mentioned_addresses.push(*key);
3522 }
3523 }
3524 }
3525
3526 let is_vote = transaction.is_simple_vote_transaction();
3527 let store = match transaction_log_collector_config.filter {
3528 TransactionLogCollectorFilter::All => {
3529 !is_vote || !filtered_mentioned_addresses.is_empty()
3530 }
3531 TransactionLogCollectorFilter::AllWithVotes => true,
3532 TransactionLogCollectorFilter::None => false,
3533 TransactionLogCollectorFilter::OnlyMentionedAddresses => {
3534 !filtered_mentioned_addresses.is_empty()
3535 }
3536 };
3537
3538 if store {
3539 Some((
3540 TransactionLogInfo {
3541 signature: *transaction.signature(),
3542 result: execution_details.status.clone(),
3543 is_vote,
3544 log_messages: log_messages.clone(),
3545 },
3546 filtered_mentioned_addresses,
3547 ))
3548 } else {
3549 None
3550 }
3551 }
3552
3553 pub fn load_accounts_data_size(&self) -> u64 {
3555 self.accounts_data_size_initial
3556 .saturating_add_signed(self.load_accounts_data_size_delta())
3557 }
3558
3559 pub fn load_accounts_data_size_delta(&self) -> i64 {
3561 let delta_on_chain = self.load_accounts_data_size_delta_on_chain();
3562 let delta_off_chain = self.load_accounts_data_size_delta_off_chain();
3563 delta_on_chain.saturating_add(delta_off_chain)
3564 }
3565
3566 pub fn load_accounts_data_size_delta_on_chain(&self) -> i64 {
3569 self.accounts_data_size_delta_on_chain.load(Acquire)
3570 }
3571
3572 pub fn load_accounts_data_size_delta_off_chain(&self) -> i64 {
3575 self.accounts_data_size_delta_off_chain.load(Acquire)
3576 }
3577
3578 fn update_accounts_data_size_delta_on_chain(&self, amount: i64) {
3581 if amount == 0 {
3582 return;
3583 }
3584
3585 self.accounts_data_size_delta_on_chain
3586 .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_on_chain| {
3587 Some(accounts_data_size_delta_on_chain.saturating_add(amount))
3588 })
3589 .unwrap();
3591 }
3592
3593 fn update_accounts_data_size_delta_off_chain(&self, amount: i64) {
3596 if amount == 0 {
3597 return;
3598 }
3599
3600 self.accounts_data_size_delta_off_chain
3601 .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_off_chain| {
3602 Some(accounts_data_size_delta_off_chain.saturating_add(amount))
3603 })
3604 .unwrap();
3606 }
3607
3608 fn calculate_and_update_accounts_data_size_delta_off_chain(
3610 &self,
3611 old_data_size: usize,
3612 new_data_size: usize,
3613 ) {
3614 let data_size_delta = calculate_data_size_delta(old_data_size, new_data_size);
3615 self.update_accounts_data_size_delta_off_chain(data_size_delta);
3616 }
3617
3618 fn filter_program_errors_and_collect_fee(
3619 &self,
3620 processing_results: &[TransactionProcessingResult],
3621 ) {
3622 let mut fees = 0;
3623
3624 processing_results.iter().for_each(|processing_result| {
3625 if let Ok(processed_tx) = processing_result {
3626 fees += processed_tx.fee_details().total_fee();
3627 }
3628 });
3629
3630 self.collector_fees.fetch_add(fees, Relaxed);
3631 }
3632
3633 fn filter_program_errors_and_collect_fee_details(
3635 &self,
3636 processing_results: &[TransactionProcessingResult],
3637 ) {
3638 let mut accumulated_fee_details = FeeDetails::default();
3639
3640 processing_results.iter().for_each(|processing_result| {
3641 if let Ok(processed_tx) = processing_result {
3642 accumulated_fee_details.accumulate(&processed_tx.fee_details());
3643 }
3644 });
3645
3646 self.collector_fee_details
3647 .write()
3648 .unwrap()
3649 .accumulate(&accumulated_fee_details);
3650 }
3651
3652 fn update_bank_hash_stats<'a>(&self, accounts: &impl StorableAccounts<'a>) {
3653 let mut stats = BankHashStats::default();
3654 (0..accounts.len()).for_each(|i| {
3655 accounts.account(i, |account| {
3656 stats.update(&account);
3657 })
3658 });
3659 self.bank_hash_stats.accumulate(&stats);
3660 }
3661
3662 pub fn commit_transactions(
3663 &self,
3664 sanitized_txs: &[impl TransactionWithMeta],
3665 processing_results: Vec<TransactionProcessingResult>,
3666 processed_counts: &ProcessedTransactionCounts,
3667 timings: &mut ExecuteTimings,
3668 ) -> Vec<TransactionCommitResult> {
3669 assert!(
3670 !self.freeze_started(),
3671 "commit_transactions() working on a bank that is already frozen or is undergoing freezing!"
3672 );
3673
3674 let ProcessedTransactionCounts {
3675 processed_transactions_count,
3676 processed_non_vote_transactions_count,
3677 processed_with_successful_result_count,
3678 signature_count,
3679 } = *processed_counts;
3680
3681 self.increment_transaction_count(processed_transactions_count);
3682 self.increment_non_vote_transaction_count_since_restart(
3683 processed_non_vote_transactions_count,
3684 );
3685 self.increment_signature_count(signature_count);
3686
3687 let processed_with_failure_result_count =
3688 processed_transactions_count.saturating_sub(processed_with_successful_result_count);
3689 self.transaction_error_count
3690 .fetch_add(processed_with_failure_result_count, Relaxed);
3691
3692 if processed_transactions_count > 0 {
3693 self.is_delta.store(true, Relaxed);
3694 self.transaction_entries_count.fetch_add(1, Relaxed);
3695 self.transactions_per_entry_max
3696 .fetch_max(processed_transactions_count, Relaxed);
3697 }
3698
3699 let ((), store_accounts_us) = measure_us!({
3700 let maybe_transaction_refs = self
3704 .accounts()
3705 .accounts_db
3706 .has_accounts_update_notifier()
3707 .then(|| {
3708 sanitized_txs
3709 .iter()
3710 .map(|tx| tx.as_sanitized_transaction())
3711 .collect::<Vec<_>>()
3712 });
3713
3714 let (accounts_to_store, transactions) = collect_accounts_to_store(
3715 sanitized_txs,
3716 &maybe_transaction_refs,
3717 &processing_results,
3718 );
3719
3720 let to_store = (self.slot(), accounts_to_store.as_slice());
3721 self.update_bank_hash_stats(&to_store);
3722 self.rc
3723 .accounts
3724 .store_cached(to_store, transactions.as_deref());
3725 });
3726
3727 self.collect_rent(&processing_results);
3728
3729 let ((), update_stakes_cache_us) =
3732 measure_us!(self.update_stakes_cache(sanitized_txs, &processing_results));
3733
3734 let ((), update_executors_us) = measure_us!({
3735 let mut cache = None;
3736 for processing_result in &processing_results {
3737 if let Some(ProcessedTransaction::Executed(executed_tx)) =
3738 processing_result.processed_transaction()
3739 {
3740 let programs_modified_by_tx = &executed_tx.programs_modified_by_tx;
3741 if executed_tx.was_successful() && !programs_modified_by_tx.is_empty() {
3742 cache
3743 .get_or_insert_with(|| {
3744 self.transaction_processor.program_cache.write().unwrap()
3745 })
3746 .merge(programs_modified_by_tx);
3747 }
3748 }
3749 }
3750 });
3751
3752 let accounts_data_len_delta = processing_results
3753 .iter()
3754 .filter_map(|processing_result| processing_result.processed_transaction())
3755 .filter_map(|processed_tx| processed_tx.execution_details())
3756 .filter_map(|details| {
3757 details
3758 .status
3759 .is_ok()
3760 .then_some(details.accounts_data_len_delta)
3761 })
3762 .sum();
3763 self.update_accounts_data_size_delta_on_chain(accounts_data_len_delta);
3764
3765 let ((), update_transaction_statuses_us) =
3766 measure_us!(self.update_transaction_statuses(sanitized_txs, &processing_results));
3767
3768 if self.feature_set.is_active(&reward_full_priority_fee::id()) {
3769 self.filter_program_errors_and_collect_fee_details(&processing_results)
3770 } else {
3771 self.filter_program_errors_and_collect_fee(&processing_results)
3772 };
3773
3774 timings.saturating_add_in_place(ExecuteTimingType::StoreUs, store_accounts_us);
3775 timings.saturating_add_in_place(
3776 ExecuteTimingType::UpdateStakesCacheUs,
3777 update_stakes_cache_us,
3778 );
3779 timings.saturating_add_in_place(ExecuteTimingType::UpdateExecutorsUs, update_executors_us);
3780 timings.saturating_add_in_place(
3781 ExecuteTimingType::UpdateTransactionStatuses,
3782 update_transaction_statuses_us,
3783 );
3784
3785 Self::create_commit_results(processing_results)
3786 }
3787
3788 fn create_commit_results(
3789 processing_results: Vec<TransactionProcessingResult>,
3790 ) -> Vec<TransactionCommitResult> {
3791 processing_results
3792 .into_iter()
3793 .map(|processing_result| {
3794 let processing_result = processing_result?;
3795 let executed_units = processing_result.executed_units();
3796 let loaded_accounts_data_size = processing_result.loaded_accounts_data_size();
3797
3798 match processing_result {
3799 ProcessedTransaction::Executed(executed_tx) => {
3800 let execution_details = executed_tx.execution_details;
3801 let LoadedTransaction {
3802 rent_debits,
3803 accounts: loaded_accounts,
3804 fee_details,
3805 ..
3806 } = executed_tx.loaded_transaction;
3807
3808 let rent_debits = if execution_details.was_successful() {
3810 rent_debits
3811 } else {
3812 RentDebits::default()
3813 };
3814
3815 Ok(CommittedTransaction {
3816 status: execution_details.status,
3817 log_messages: execution_details.log_messages,
3818 inner_instructions: execution_details.inner_instructions,
3819 return_data: execution_details.return_data,
3820 executed_units,
3821 fee_details,
3822 rent_debits,
3823 loaded_account_stats: TransactionLoadedAccountsStats {
3824 loaded_accounts_count: loaded_accounts.len(),
3825 loaded_accounts_data_size,
3826 },
3827 })
3828 }
3829 ProcessedTransaction::FeesOnly(fees_only_tx) => Ok(CommittedTransaction {
3830 status: Err(fees_only_tx.load_error),
3831 log_messages: None,
3832 inner_instructions: None,
3833 return_data: None,
3834 executed_units,
3835 rent_debits: RentDebits::default(),
3836 fee_details: fees_only_tx.fee_details,
3837 loaded_account_stats: TransactionLoadedAccountsStats {
3838 loaded_accounts_count: fees_only_tx.rollback_accounts.count(),
3839 loaded_accounts_data_size,
3840 },
3841 }),
3842 }
3843 })
3844 .collect()
3845 }
3846
3847 fn collect_rent(&self, processing_results: &[TransactionProcessingResult]) {
3848 let collected_rent = processing_results
3849 .iter()
3850 .filter_map(|processing_result| processing_result.processed_transaction())
3851 .filter_map(|processed_tx| processed_tx.executed_transaction())
3852 .filter(|executed_tx| executed_tx.was_successful())
3853 .map(|executed_tx| executed_tx.loaded_transaction.rent)
3854 .sum();
3855 self.collected_rent.fetch_add(collected_rent, Relaxed);
3856 }
3857
3858 fn run_incinerator(&self) {
3859 if let Some((account, _)) =
3860 self.get_account_modified_since_parent_with_fixed_root(&incinerator::id())
3861 {
3862 self.capitalization.fetch_sub(account.lamports(), Relaxed);
3863 self.store_account(&incinerator::id(), &AccountSharedData::default());
3864 }
3865 }
3866
3867 pub(crate) fn get_stake_accounts(&self, minimized_account_set: &DashSet<Pubkey>) {
3869 self.stakes_cache
3870 .stakes()
3871 .stake_delegations()
3872 .iter()
3873 .for_each(|(pubkey, _)| {
3874 minimized_account_set.insert(*pubkey);
3875 });
3876
3877 self.stakes_cache
3878 .stakes()
3879 .staked_nodes()
3880 .par_iter()
3881 .for_each(|(pubkey, _)| {
3882 minimized_account_set.insert(*pubkey);
3883 });
3884 }
3885
3886 fn rebuild_skipped_rewrites(&self) {
3897 if self.bank_hash_skips_rent_rewrites() {
3900 return;
3901 }
3902
3903 let (skipped_rewrites, measure_skipped_rewrites) =
3904 measure_time!(self.calculate_skipped_rewrites());
3905 info!(
3906 "Rebuilding skipped rewrites of {} accounts{measure_skipped_rewrites}",
3907 skipped_rewrites.len()
3908 );
3909
3910 *self.skipped_rewrites.lock().unwrap() = skipped_rewrites;
3911 }
3912
3913 fn calculate_skipped_rewrites(&self) -> HashMap<Pubkey, AccountHash> {
3932 self.get_accounts_for_skipped_rewrites()
3935 .map(|(pubkey, account_hash, _account)| (pubkey, account_hash))
3936 .collect()
3937 }
3938
3939 fn get_accounts_for_skipped_rewrites(
3943 &self,
3944 ) -> impl Iterator<Item = (Pubkey, AccountHash, AccountSharedData)> + '_ {
3945 self.rent_collection_partitions()
3946 .into_iter()
3947 .map(accounts_partition::pubkey_range_from_partition)
3948 .flat_map(|pubkey_range| {
3949 self.rc
3950 .accounts
3951 .load_to_collect_rent_eagerly(&self.ancestors, pubkey_range)
3952 })
3953 .map(|(pubkey, account, _slot)| {
3954 let account_hash = AccountsDb::hash_account(&account, &pubkey);
3955 (pubkey, account_hash, account)
3956 })
3957 }
3958
3959 pub(crate) fn get_accounts_for_bank_hash_details(&self) -> Vec<PubkeyHashAccount> {
3962 let accounts_db = &self.rc.accounts.accounts_db;
3963
3964 let mut accounts_written_this_slot =
3965 accounts_db.get_pubkey_hash_account_for_slot(self.slot());
3966
3967 if !self.bank_hash_skips_rent_rewrites()
3970 && accounts_db.test_skip_rewrites_but_include_in_bank_hash
3971 {
3972 let pubkeys_written_this_slot: HashSet<_> = accounts_written_this_slot
3973 .iter()
3974 .map(|pubkey_hash_account| pubkey_hash_account.pubkey)
3975 .collect();
3976
3977 let rent_collection_accounts = self.get_accounts_for_skipped_rewrites();
3978 for (pubkey, hash, account) in rent_collection_accounts {
3979 if !pubkeys_written_this_slot.contains(&pubkey) {
3980 accounts_written_this_slot.push(PubkeyHashAccount {
3981 pubkey,
3982 hash,
3983 account,
3984 });
3985 }
3986 }
3987 }
3988
3989 accounts_written_this_slot.sort_unstable_by_key(|account| account.pubkey);
3992 accounts_written_this_slot
3993 }
3994
3995 fn collect_rent_eagerly(&self) {
3996 if self.lazy_rent_collection.load(Relaxed) {
3997 return;
3998 }
3999
4000 let mut measure = Measure::start("collect_rent_eagerly-ms");
4001 let partitions = self.rent_collection_partitions();
4002 let count = partitions.len();
4003 let rent_metrics = RentMetrics::default();
4004 let mut parallel = count > 1;
4006 if parallel {
4007 let ranges = partitions
4008 .iter()
4009 .map(|partition| {
4010 (
4011 *partition,
4012 accounts_partition::pubkey_range_from_partition(*partition),
4013 )
4014 })
4015 .collect::<Vec<_>>();
4016 'outer: for i in 0..ranges.len() {
4021 for j in 0..ranges.len() {
4022 if i == j {
4023 continue;
4024 }
4025
4026 let i = &ranges[i].1;
4027 let j = &ranges[j].1;
4028 if i.contains(j.start()) || i.contains(j.end()) {
4030 parallel = false;
4031 break 'outer;
4032 }
4033 }
4034 }
4035
4036 if parallel {
4037 let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
4038 thread_pool.install(|| {
4039 ranges.into_par_iter().for_each(|range| {
4040 self.collect_rent_in_range(range.0, range.1, &rent_metrics)
4041 });
4042 });
4043 }
4044 }
4045 if !parallel {
4046 partitions
4048 .into_iter()
4049 .for_each(|partition| self.collect_rent_in_partition(partition, &rent_metrics));
4050 }
4051 measure.stop();
4052 datapoint_info!(
4053 "collect_rent_eagerly",
4054 ("accounts", rent_metrics.count.load(Relaxed), i64),
4055 ("partitions", count, i64),
4056 ("total_time_us", measure.as_us(), i64),
4057 (
4058 "hold_range_us",
4059 rent_metrics.hold_range_us.load(Relaxed),
4060 i64
4061 ),
4062 ("load_us", rent_metrics.load_us.load(Relaxed), i64),
4063 ("collect_us", rent_metrics.collect_us.load(Relaxed), i64),
4064 ("hash_us", rent_metrics.hash_us.load(Relaxed), i64),
4065 ("store_us", rent_metrics.store_us.load(Relaxed), i64),
4066 );
4067 }
4068
4069 fn rent_collection_partitions(&self) -> Vec<Partition> {
4070 if !self.use_fixed_collection_cycle() {
4071 self.variable_cycle_partitions()
4078 } else {
4079 self.fixed_cycle_partitions()
4086 }
4087 }
4088
4089 fn bank_hash_skips_rent_rewrites(&self) -> bool {
4094 self.feature_set
4095 .is_active(&feature_set::skip_rent_rewrites::id())
4096 }
4097
4098 fn should_collect_rent(&self) -> bool {
4100 !self
4101 .feature_set
4102 .is_active(&feature_set::disable_rent_fees_collection::id())
4103 }
4104
4105 fn collect_rent_from_accounts(
4115 &self,
4116 mut accounts: Vec<(Pubkey, AccountSharedData, Slot)>,
4117 rent_paying_pubkeys: Option<&HashSet<Pubkey>>,
4118 partition_index: PartitionIndex,
4119 ) -> CollectRentFromAccountsInfo {
4120 let mut rent_debits = RentDebits::default();
4121 let mut total_rent_collected_info = CollectedInfo::default();
4122 let mut accounts_to_store =
4123 Vec::<(&Pubkey, &AccountSharedData)>::with_capacity(accounts.len());
4124 let mut time_collecting_rent_us = 0;
4125 let mut time_storing_accounts_us = 0;
4126 let can_skip_rewrites = self.bank_hash_skips_rent_rewrites();
4127 let test_skip_rewrites_but_include_in_bank_hash = self
4128 .rc
4129 .accounts
4130 .accounts_db
4131 .test_skip_rewrites_but_include_in_bank_hash;
4132 let mut skipped_rewrites = Vec::default();
4133 for (pubkey, account, _loaded_slot) in accounts.iter_mut() {
4134 let rent_epoch_pre = account.rent_epoch();
4135 let (rent_collected_info, collect_rent_us) = measure_us!(collect_rent_from_account(
4136 &self.feature_set,
4137 &self.rent_collector,
4138 pubkey,
4139 account
4140 ));
4141 time_collecting_rent_us += collect_rent_us;
4142 let rent_epoch_post = account.rent_epoch();
4143
4144 let rent_epoch_changed = rent_epoch_post != rent_epoch_pre;
4146 let account_changed = rent_collected_info.rent_amount != 0 || rent_epoch_changed;
4147
4148 let always_store_accounts =
4150 !can_skip_rewrites && !test_skip_rewrites_but_include_in_bank_hash;
4151
4152 if account_changed || always_store_accounts {
4158 if rent_collected_info.rent_amount > 0 {
4159 if let Some(rent_paying_pubkeys) = rent_paying_pubkeys {
4160 if !rent_paying_pubkeys.contains(pubkey) {
4161 let partition_from_pubkey = accounts_partition::partition_from_pubkey(
4162 pubkey,
4163 self.epoch_schedule.slots_per_epoch,
4164 );
4165 datapoint_warn!(
4167 "bank-unexpected_rent_paying_pubkey",
4168 ("slot", self.slot(), i64),
4169 ("pubkey", pubkey.to_string(), String),
4170 ("partition_index", partition_index, i64),
4171 ("partition_from_pubkey", partition_from_pubkey, i64)
4172 );
4173 warn!(
4174 "Collecting rent from unexpected pubkey: {}, slot: {}, parent_slot: {:?}, \
4175 partition_index: {}, partition_from_pubkey: {}",
4176 pubkey,
4177 self.slot(),
4178 self.parent().map(|bank| bank.slot()),
4179 partition_index,
4180 partition_from_pubkey,
4181 );
4182 }
4183 }
4184 } else {
4185 debug_assert_eq!(rent_collected_info.rent_amount, 0);
4186 if rent_epoch_changed {
4187 datapoint_info!(
4188 "bank-rent_collection_updated_only_rent_epoch",
4189 ("slot", self.slot(), i64),
4190 ("pubkey", pubkey.to_string(), String),
4191 ("rent_epoch_pre", rent_epoch_pre, i64),
4192 ("rent_epoch_post", rent_epoch_post, i64),
4193 );
4194 }
4195 }
4196 total_rent_collected_info += rent_collected_info;
4197 accounts_to_store.push((pubkey, account));
4198 } else if !account_changed
4199 && !can_skip_rewrites
4200 && test_skip_rewrites_but_include_in_bank_hash
4201 {
4202 let hash = AccountsDb::hash_account(account, pubkey);
4207 skipped_rewrites.push((*pubkey, hash));
4208 }
4209 rent_debits.insert(pubkey, rent_collected_info.rent_amount, account.lamports());
4210 }
4211
4212 if !accounts_to_store.is_empty() {
4213 let (_, store_accounts_us) =
4216 measure_us!(self.store_accounts((self.slot(), &accounts_to_store[..])));
4217 time_storing_accounts_us += store_accounts_us;
4218 }
4219
4220 CollectRentFromAccountsInfo {
4221 skipped_rewrites,
4222 rent_collected_info: total_rent_collected_info,
4223 rent_rewards: rent_debits.into_unordered_rewards_iter().collect(),
4224 time_collecting_rent_us,
4225 time_storing_accounts_us,
4226 num_accounts: accounts.len(),
4227 }
4228 }
4229
4230 fn collect_rent_in_partition(&self, partition: Partition, metrics: &RentMetrics) {
4232 let subrange_full = accounts_partition::pubkey_range_from_partition(partition);
4233 self.collect_rent_in_range(partition, subrange_full, metrics)
4234 }
4235
4236 fn get_rent_paying_pubkeys(&self, partition: &Partition) -> Option<HashSet<Pubkey>> {
4238 self.rc
4239 .accounts
4240 .accounts_db
4241 .accounts_index
4242 .rent_paying_accounts_by_partition
4243 .get()
4244 .and_then(|rent_paying_accounts| {
4245 rent_paying_accounts.is_initialized().then(|| {
4246 accounts_partition::get_partition_end_indexes(partition)
4247 .into_iter()
4248 .flat_map(|end_index| {
4249 rent_paying_accounts.get_pubkeys_in_partition_index(end_index)
4250 })
4251 .cloned()
4252 .collect::<HashSet<_>>()
4253 })
4254 })
4255 }
4256
4257 fn collect_rent_in_range(
4262 &self,
4263 partition: Partition,
4264 subrange_full: RangeInclusive<Pubkey>,
4265 metrics: &RentMetrics,
4266 ) {
4267 let mut hold_range = Measure::start("hold_range");
4268 let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
4269 thread_pool.install(|| {
4270 self.rc
4271 .accounts
4272 .hold_range_in_memory(&subrange_full, true, thread_pool);
4273 hold_range.stop();
4274 metrics.hold_range_us.fetch_add(hold_range.as_us(), Relaxed);
4275
4276 let rent_paying_pubkeys_ = self.get_rent_paying_pubkeys(&partition);
4277 let rent_paying_pubkeys = rent_paying_pubkeys_.as_ref();
4278
4279 let num_threads = solana_accounts_db::accounts_db::quarter_thread_count() as u64;
4283 let sz = std::mem::size_of::<u64>();
4284 let start_prefix = accounts_partition::prefix_from_pubkey(subrange_full.start());
4285 let end_prefix_inclusive = accounts_partition::prefix_from_pubkey(subrange_full.end());
4286 let range = end_prefix_inclusive - start_prefix;
4287 let increment = range / num_threads;
4288 let mut results = (0..num_threads)
4289 .into_par_iter()
4290 .map(|chunk| {
4291 let offset = |chunk| start_prefix + chunk * increment;
4292 let start = offset(chunk);
4293 let last = chunk == num_threads - 1;
4294 let merge_prefix = |prefix: u64, mut bound: Pubkey| {
4295 bound.as_mut()[0..sz].copy_from_slice(&prefix.to_be_bytes());
4296 bound
4297 };
4298 let start = merge_prefix(start, *subrange_full.start());
4299 let (accounts, measure_load_accounts) = measure_time!(if last {
4300 let end = *subrange_full.end();
4301 let subrange = start..=end; self.rc
4303 .accounts
4304 .load_to_collect_rent_eagerly(&self.ancestors, subrange)
4305 } else {
4306 let end = merge_prefix(offset(chunk + 1), *subrange_full.start());
4307 let subrange = start..end; self.rc
4309 .accounts
4310 .load_to_collect_rent_eagerly(&self.ancestors, subrange)
4311 });
4312 CollectRentInPartitionInfo::new(
4313 self.collect_rent_from_accounts(accounts, rent_paying_pubkeys, partition.1),
4314 Duration::from_nanos(measure_load_accounts.as_ns()),
4315 )
4316 })
4317 .reduce(
4318 CollectRentInPartitionInfo::default,
4319 CollectRentInPartitionInfo::reduce,
4320 );
4321
4322 self.skipped_rewrites
4323 .lock()
4324 .unwrap()
4325 .extend(results.skipped_rewrites);
4326
4327 self.rc
4331 .accounts
4332 .hold_range_in_memory(&subrange_full, false, thread_pool);
4333
4334 self.collected_rent
4335 .fetch_add(results.rent_collected, Relaxed);
4336 self.update_accounts_data_size_delta_off_chain(
4337 -(results.accounts_data_size_reclaimed as i64),
4338 );
4339 self.rewards
4340 .write()
4341 .unwrap()
4342 .append(&mut results.rent_rewards);
4343
4344 metrics
4345 .load_us
4346 .fetch_add(results.time_loading_accounts_us, Relaxed);
4347 metrics
4348 .collect_us
4349 .fetch_add(results.time_collecting_rent_us, Relaxed);
4350 metrics
4351 .store_us
4352 .fetch_add(results.time_storing_accounts_us, Relaxed);
4353 metrics.count.fetch_add(results.num_accounts, Relaxed);
4354 });
4355 }
4356
4357 pub(crate) fn fixed_cycle_partitions_between_slots(
4358 &self,
4359 starting_slot: Slot,
4360 ending_slot: Slot,
4361 ) -> Vec<Partition> {
4362 let slot_count_in_two_day = self.slot_count_in_two_day();
4363 accounts_partition::get_partitions(ending_slot, starting_slot, slot_count_in_two_day)
4364 }
4365
4366 fn fixed_cycle_partitions(&self) -> Vec<Partition> {
4367 self.fixed_cycle_partitions_between_slots(self.parent_slot(), self.slot())
4368 }
4369
4370 pub(crate) fn variable_cycle_partitions_between_slots(
4371 &self,
4372 starting_slot: Slot,
4373 ending_slot: Slot,
4374 ) -> Vec<Partition> {
4375 let (starting_epoch, mut starting_slot_index) =
4376 self.get_epoch_and_slot_index(starting_slot);
4377 let (ending_epoch, ending_slot_index) = self.get_epoch_and_slot_index(ending_slot);
4378
4379 let mut partitions = vec![];
4380 if starting_epoch < ending_epoch {
4381 let slot_skipped = (ending_slot - starting_slot) > 1;
4382 if slot_skipped {
4383 let parent_last_slot_index = self.get_slots_in_epoch(starting_epoch) - 1;
4387
4388 partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
4390 starting_slot_index,
4391 parent_last_slot_index,
4392 starting_epoch,
4393 ));
4394
4395 if ending_slot_index > 0 {
4396 partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
4398 0,
4399 0,
4400 ending_epoch,
4401 ));
4402 }
4403 }
4404 starting_slot_index = 0;
4405 }
4406
4407 partitions.push(self.partition_from_normal_slot_indexes(
4408 starting_slot_index,
4409 ending_slot_index,
4410 ending_epoch,
4411 ));
4412
4413 partitions
4414 }
4415
4416 fn variable_cycle_partitions(&self) -> Vec<Partition> {
4417 self.variable_cycle_partitions_between_slots(self.parent_slot(), self.slot())
4418 }
4419
4420 fn do_partition_from_slot_indexes(
4421 &self,
4422 start_slot_index: SlotIndex,
4423 end_slot_index: SlotIndex,
4424 epoch: Epoch,
4425 generated_for_gapped_epochs: bool,
4426 ) -> Partition {
4427 let slot_count_per_epoch = self.get_slots_in_epoch(epoch);
4428
4429 let cycle_params = if !self.use_multi_epoch_collection_cycle(epoch) {
4430 accounts_partition::rent_single_epoch_collection_cycle_params(
4432 epoch,
4433 slot_count_per_epoch,
4434 )
4435 } else {
4436 accounts_partition::rent_multi_epoch_collection_cycle_params(
4437 epoch,
4438 slot_count_per_epoch,
4439 self.first_normal_epoch(),
4440 self.slot_count_in_two_day() / slot_count_per_epoch,
4441 )
4442 };
4443 accounts_partition::get_partition_from_slot_indexes(
4444 cycle_params,
4445 start_slot_index,
4446 end_slot_index,
4447 generated_for_gapped_epochs,
4448 )
4449 }
4450
4451 fn partition_from_normal_slot_indexes(
4452 &self,
4453 start_slot_index: SlotIndex,
4454 end_slot_index: SlotIndex,
4455 epoch: Epoch,
4456 ) -> Partition {
4457 self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, false)
4458 }
4459
4460 fn partition_from_slot_indexes_with_gapped_epochs(
4461 &self,
4462 start_slot_index: SlotIndex,
4463 end_slot_index: SlotIndex,
4464 epoch: Epoch,
4465 ) -> Partition {
4466 self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, true)
4467 }
4468
4469 fn use_multi_epoch_collection_cycle(&self, epoch: Epoch) -> bool {
4475 #[cfg(not(test))]
4477 if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
4478 {
4479 return false;
4480 }
4481
4482 epoch >= self.first_normal_epoch()
4483 && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
4484 }
4485
4486 pub(crate) fn use_fixed_collection_cycle(&self) -> bool {
4487 #[cfg(not(test))]
4489 if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
4490 {
4491 return false;
4492 }
4493
4494 self.cluster_type() != ClusterType::MainnetBeta
4495 && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
4496 }
4497
4498 fn slot_count_in_two_day(&self) -> SlotCount {
4499 Self::slot_count_in_two_day_helper(self.ticks_per_slot)
4500 }
4501
4502 pub fn slot_count_in_two_day_helper(ticks_per_slot: SlotCount) -> SlotCount {
4506 2 * DEFAULT_TICKS_PER_SECOND * SECONDS_PER_DAY / ticks_per_slot
4507 }
4508
4509 fn slot_count_per_normal_epoch(&self) -> SlotCount {
4510 self.get_slots_in_epoch(self.first_normal_epoch())
4511 }
4512
4513 pub fn cluster_type(&self) -> ClusterType {
4514 self.cluster_type.unwrap()
4517 }
4518
4519 #[must_use]
4521 pub fn load_execute_and_commit_transactions(
4522 &self,
4523 batch: &TransactionBatch<impl TransactionWithMeta>,
4524 max_age: usize,
4525 collect_balances: bool,
4526 recording_config: ExecutionRecordingConfig,
4527 timings: &mut ExecuteTimings,
4528 log_messages_bytes_limit: Option<usize>,
4529 ) -> (Vec<TransactionCommitResult>, TransactionBalancesSet) {
4530 self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4531 batch,
4532 max_age,
4533 collect_balances,
4534 recording_config,
4535 timings,
4536 log_messages_bytes_limit,
4537 None::<fn(&mut _, &_) -> _>,
4538 )
4539 .unwrap()
4540 }
4541
4542 pub fn load_execute_and_commit_transactions_with_pre_commit_callback<'a>(
4543 &'a self,
4544 batch: &TransactionBatch<impl TransactionWithMeta>,
4545 max_age: usize,
4546 collect_balances: bool,
4547 recording_config: ExecutionRecordingConfig,
4548 timings: &mut ExecuteTimings,
4549 log_messages_bytes_limit: Option<usize>,
4550 pre_commit_callback: impl FnOnce(
4551 &mut ExecuteTimings,
4552 &[TransactionProcessingResult],
4553 ) -> PreCommitResult<'a>,
4554 ) -> Result<(Vec<TransactionCommitResult>, TransactionBalancesSet)> {
4555 self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4556 batch,
4557 max_age,
4558 collect_balances,
4559 recording_config,
4560 timings,
4561 log_messages_bytes_limit,
4562 Some(pre_commit_callback),
4563 )
4564 }
4565
4566 fn do_load_execute_and_commit_transactions_with_pre_commit_callback<'a>(
4567 &'a self,
4568 batch: &TransactionBatch<impl TransactionWithMeta>,
4569 max_age: usize,
4570 collect_balances: bool,
4571 recording_config: ExecutionRecordingConfig,
4572 timings: &mut ExecuteTimings,
4573 log_messages_bytes_limit: Option<usize>,
4574 pre_commit_callback: Option<
4575 impl FnOnce(&mut ExecuteTimings, &[TransactionProcessingResult]) -> PreCommitResult<'a>,
4576 >,
4577 ) -> Result<(Vec<TransactionCommitResult>, TransactionBalancesSet)> {
4578 let pre_balances = if collect_balances {
4579 self.collect_balances(batch)
4580 } else {
4581 vec![]
4582 };
4583
4584 let LoadAndExecuteTransactionsOutput {
4585 processing_results,
4586 processed_counts,
4587 } = self.load_and_execute_transactions(
4588 batch,
4589 max_age,
4590 timings,
4591 &mut TransactionErrorMetrics::default(),
4592 TransactionProcessingConfig {
4593 account_overrides: None,
4594 check_program_modification_slot: self.check_program_modification_slot,
4595 compute_budget: self.compute_budget(),
4596 log_messages_bytes_limit,
4597 limit_to_load_programs: false,
4598 recording_config,
4599 transaction_account_lock_limit: Some(self.get_transaction_account_lock_limit()),
4600 },
4601 );
4602
4603 let freeze_lock = if let Some(pre_commit_callback) = pre_commit_callback {
4608 pre_commit_callback(timings, &processing_results)?
4609 } else {
4610 None
4611 };
4612 let commit_results = self.commit_transactions(
4613 batch.sanitized_transactions(),
4614 processing_results,
4615 &processed_counts,
4616 timings,
4617 );
4618 drop(freeze_lock);
4619 let post_balances = if collect_balances {
4620 self.collect_balances(batch)
4621 } else {
4622 vec![]
4623 };
4624 Ok((
4625 commit_results,
4626 TransactionBalancesSet::new(pre_balances, post_balances),
4627 ))
4628 }
4629
4630 pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
4633 self.try_process_transactions(std::iter::once(tx))?[0].clone()?;
4634 tx.signatures
4635 .first()
4636 .map_or(Ok(()), |sig| self.get_signature_status(sig).unwrap())
4637 }
4638
4639 pub fn process_transaction_with_metadata(
4642 &self,
4643 tx: impl Into<VersionedTransaction>,
4644 ) -> Result<CommittedTransaction> {
4645 let txs = vec![tx.into()];
4646 let batch = self.prepare_entry_batch(txs)?;
4647
4648 let (mut commit_results, ..) = self.load_execute_and_commit_transactions(
4649 &batch,
4650 MAX_PROCESSING_AGE,
4651 false, ExecutionRecordingConfig {
4653 enable_cpi_recording: false,
4654 enable_log_recording: true,
4655 enable_return_data_recording: true,
4656 },
4657 &mut ExecuteTimings::default(),
4658 Some(1000 * 1000),
4659 );
4660
4661 commit_results.remove(0)
4662 }
4663
4664 pub fn try_process_transactions<'a>(
4667 &self,
4668 txs: impl Iterator<Item = &'a Transaction>,
4669 ) -> Result<Vec<Result<()>>> {
4670 let txs = txs
4671 .map(|tx| VersionedTransaction::from(tx.clone()))
4672 .collect();
4673 self.try_process_entry_transactions(txs)
4674 }
4675
4676 pub fn try_process_entry_transactions(
4679 &self,
4680 txs: Vec<VersionedTransaction>,
4681 ) -> Result<Vec<Result<()>>> {
4682 let batch = self.prepare_entry_batch(txs)?;
4683 Ok(self.process_transaction_batch(&batch))
4684 }
4685
4686 #[must_use]
4687 fn process_transaction_batch(
4688 &self,
4689 batch: &TransactionBatch<impl TransactionWithMeta>,
4690 ) -> Vec<Result<()>> {
4691 self.load_execute_and_commit_transactions(
4692 batch,
4693 MAX_PROCESSING_AGE,
4694 false,
4695 ExecutionRecordingConfig::new_single_setting(false),
4696 &mut ExecuteTimings::default(),
4697 None,
4698 )
4699 .0
4700 .into_iter()
4701 .map(|commit_result| commit_result.map(|_| ()))
4702 .collect()
4703 }
4704
4705 pub fn transfer(&self, n: u64, keypair: &Keypair, to: &Pubkey) -> Result<Signature> {
4708 let blockhash = self.last_blockhash();
4709 let tx = system_transaction::transfer(keypair, to, n, blockhash);
4710 let signature = tx.signatures[0];
4711 self.process_transaction(&tx).map(|_| signature)
4712 }
4713
4714 pub fn read_balance(account: &AccountSharedData) -> u64 {
4715 account.lamports()
4716 }
4717 pub fn get_balance(&self, pubkey: &Pubkey) -> u64 {
4720 self.get_account(pubkey)
4721 .map(|x| Self::read_balance(&x))
4722 .unwrap_or(0)
4723 }
4724
4725 pub fn parents(&self) -> Vec<Arc<Bank>> {
4727 let mut parents = vec![];
4728 let mut bank = self.parent();
4729 while let Some(parent) = bank {
4730 parents.push(parent.clone());
4731 bank = parent.parent();
4732 }
4733 parents
4734 }
4735
4736 pub fn parents_inclusive(self: Arc<Self>) -> Vec<Arc<Bank>> {
4738 let mut parents = self.parents();
4739 parents.insert(0, self);
4740 parents
4741 }
4742
4743 pub fn store_account(&self, pubkey: &Pubkey, account: &AccountSharedData) {
4746 self.store_accounts((self.slot(), &[(pubkey, account)][..]))
4747 }
4748
4749 pub fn store_accounts<'a>(&self, accounts: impl StorableAccounts<'a>) {
4750 assert!(!self.freeze_started());
4751 let mut m = Measure::start("stakes_cache.check_and_store");
4752 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
4753
4754 (0..accounts.len()).for_each(|i| {
4755 accounts.account(i, |account| {
4756 self.stakes_cache.check_and_store(
4757 account.pubkey(),
4758 &account,
4759 new_warmup_cooldown_rate_epoch,
4760 )
4761 })
4762 });
4763 self.update_bank_hash_stats(&accounts);
4764 self.rc.accounts.store_accounts_cached(accounts);
4765 m.stop();
4766 self.rc
4767 .accounts
4768 .accounts_db
4769 .stats
4770 .stakes_cache_check_and_store_us
4771 .fetch_add(m.as_us(), Relaxed);
4772 }
4773
4774 pub fn force_flush_accounts_cache(&self) {
4775 self.rc
4776 .accounts
4777 .accounts_db
4778 .flush_accounts_cache(true, Some(self.slot()))
4779 }
4780
4781 pub fn flush_accounts_cache_if_needed(&self) {
4782 self.rc
4783 .accounts
4784 .accounts_db
4785 .flush_accounts_cache(false, Some(self.slot()))
4786 }
4787
4788 fn store_account_and_update_capitalization(
4791 &self,
4792 pubkey: &Pubkey,
4793 new_account: &AccountSharedData,
4794 ) {
4795 let old_account_data_size =
4796 if let Some(old_account) = self.get_account_with_fixed_root_no_cache(pubkey) {
4797 match new_account.lamports().cmp(&old_account.lamports()) {
4798 std::cmp::Ordering::Greater => {
4799 let increased = new_account.lamports() - old_account.lamports();
4800 trace!(
4801 "store_account_and_update_capitalization: increased: {} {}",
4802 pubkey,
4803 increased
4804 );
4805 self.capitalization.fetch_add(increased, Relaxed);
4806 }
4807 std::cmp::Ordering::Less => {
4808 let decreased = old_account.lamports() - new_account.lamports();
4809 trace!(
4810 "store_account_and_update_capitalization: decreased: {} {}",
4811 pubkey,
4812 decreased
4813 );
4814 self.capitalization.fetch_sub(decreased, Relaxed);
4815 }
4816 std::cmp::Ordering::Equal => {}
4817 }
4818 old_account.data().len()
4819 } else {
4820 trace!(
4821 "store_account_and_update_capitalization: created: {} {}",
4822 pubkey,
4823 new_account.lamports()
4824 );
4825 self.capitalization
4826 .fetch_add(new_account.lamports(), Relaxed);
4827 0
4828 };
4829
4830 self.store_account(pubkey, new_account);
4831 self.calculate_and_update_accounts_data_size_delta_off_chain(
4832 old_account_data_size,
4833 new_account.data().len(),
4834 );
4835 }
4836
4837 pub fn accounts(&self) -> Arc<Accounts> {
4838 self.rc.accounts.clone()
4839 }
4840
4841 fn finish_init(
4842 &mut self,
4843 genesis_config: &GenesisConfig,
4844 additional_builtins: Option<&[BuiltinPrototype]>,
4845 debug_do_not_add_builtins: bool,
4846 ) {
4847 self.rewards_pool_pubkeys =
4848 Arc::new(genesis_config.rewards_pools.keys().cloned().collect());
4849
4850 self.apply_feature_activations(
4851 ApplyFeatureActivationsCaller::FinishInit,
4852 debug_do_not_add_builtins,
4853 );
4854
4855 if self
4860 .feature_set
4861 .is_active(&feature_set::raise_block_limits_to_50m::id())
4862 {
4863 let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits();
4864 self.write_cost_tracker().unwrap().set_limits(
4865 account_cost_limit,
4866 block_cost_limit,
4867 vote_cost_limit,
4868 );
4869 }
4870
4871 if !debug_do_not_add_builtins {
4872 for builtin in BUILTINS
4873 .iter()
4874 .chain(additional_builtins.unwrap_or(&[]).iter())
4875 {
4876 let builtin_is_bpf = |program_id: &Pubkey| {
4882 self.get_account(program_id)
4883 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
4884 .unwrap_or(false)
4885 };
4886 if builtin.enable_feature_id.is_none() && !builtin_is_bpf(&builtin.program_id) {
4887 self.transaction_processor.add_builtin(
4888 self,
4889 builtin.program_id,
4890 builtin.name,
4891 ProgramCacheEntry::new_builtin(0, builtin.name.len(), builtin.entrypoint),
4892 );
4893 }
4894 }
4895 for precompile in get_precompiles() {
4896 if precompile.feature.is_none() {
4897 self.add_precompile(&precompile.program_id);
4898 }
4899 }
4900 }
4901
4902 self.transaction_processor
4903 .configure_program_runtime_environments(
4904 Some(Arc::new(
4905 create_program_runtime_environment_v1(
4906 &self.feature_set,
4907 &self.compute_budget().unwrap_or_default(),
4908 false, false, )
4911 .unwrap(),
4912 )),
4913 Some(Arc::new(create_program_runtime_environment_v2(
4914 &self.compute_budget().unwrap_or_default(),
4915 false, ))),
4917 );
4918 }
4919
4920 pub fn set_inflation(&self, inflation: Inflation) {
4921 *self.inflation.write().unwrap() = inflation;
4922 }
4923
4924 pub fn hard_forks(&self) -> HardForks {
4926 self.hard_forks.read().unwrap().clone()
4927 }
4928
4929 pub fn register_hard_fork(&self, new_hard_fork_slot: Slot) {
4930 let bank_slot = self.slot();
4931
4932 let lock = self.freeze_lock();
4933 let bank_frozen = *lock != Hash::default();
4934 if new_hard_fork_slot < bank_slot {
4935 warn!(
4936 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is older \
4937 than the bank at slot {bank_slot} that attempted to register it."
4938 );
4939 } else if (new_hard_fork_slot == bank_slot) && bank_frozen {
4940 warn!(
4941 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is the same \
4942 slot as the bank at slot {bank_slot} that attempted to register it, but that \
4943 bank is already frozen."
4944 );
4945 } else {
4946 self.hard_forks
4947 .write()
4948 .unwrap()
4949 .register(new_hard_fork_slot);
4950 }
4951 }
4952
4953 pub fn get_account_with_fixed_root_no_cache(
4954 &self,
4955 pubkey: &Pubkey,
4956 ) -> Option<AccountSharedData> {
4957 self.load_account_with(pubkey, |_| false)
4958 .map(|(acc, _slot)| acc)
4959 }
4960
4961 fn load_account_with(
4962 &self,
4963 pubkey: &Pubkey,
4964 callback: impl for<'local> Fn(&'local AccountSharedData) -> bool,
4965 ) -> Option<(AccountSharedData, Slot)> {
4966 self.rc
4967 .accounts
4968 .accounts_db
4969 .load_account_with(&self.ancestors, pubkey, callback)
4970 }
4971
4972 pub fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
4976 self.get_account_modified_slot(pubkey)
4977 .map(|(acc, _slot)| acc)
4978 }
4979
4980 pub fn get_account_with_fixed_root(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
4987 self.get_account_modified_slot_with_fixed_root(pubkey)
4988 .map(|(acc, _slot)| acc)
4989 }
4990
4991 pub fn get_account_modified_slot_with_fixed_root(
4993 &self,
4994 pubkey: &Pubkey,
4995 ) -> Option<(AccountSharedData, Slot)> {
4996 self.load_slow_with_fixed_root(&self.ancestors, pubkey)
4997 }
4998
4999 pub fn get_account_modified_slot(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
5000 self.load_slow(&self.ancestors, pubkey)
5001 }
5002
5003 fn load_slow(
5004 &self,
5005 ancestors: &Ancestors,
5006 pubkey: &Pubkey,
5007 ) -> Option<(AccountSharedData, Slot)> {
5008 self.rc.accounts.load_without_fixed_root(ancestors, pubkey)
5012 }
5013
5014 fn load_slow_with_fixed_root(
5015 &self,
5016 ancestors: &Ancestors,
5017 pubkey: &Pubkey,
5018 ) -> Option<(AccountSharedData, Slot)> {
5019 self.rc.accounts.load_with_fixed_root(ancestors, pubkey)
5020 }
5021
5022 pub fn get_program_accounts(
5023 &self,
5024 program_id: &Pubkey,
5025 config: &ScanConfig,
5026 ) -> ScanResult<Vec<TransactionAccount>> {
5027 self.rc
5028 .accounts
5029 .load_by_program(&self.ancestors, self.bank_id, program_id, config)
5030 }
5031
5032 pub fn get_filtered_program_accounts<F: Fn(&AccountSharedData) -> bool>(
5033 &self,
5034 program_id: &Pubkey,
5035 filter: F,
5036 config: &ScanConfig,
5037 ) -> ScanResult<Vec<TransactionAccount>> {
5038 self.rc.accounts.load_by_program_with_filter(
5039 &self.ancestors,
5040 self.bank_id,
5041 program_id,
5042 filter,
5043 config,
5044 )
5045 }
5046
5047 pub fn get_filtered_indexed_accounts<F: Fn(&AccountSharedData) -> bool>(
5048 &self,
5049 index_key: &IndexKey,
5050 filter: F,
5051 config: &ScanConfig,
5052 byte_limit_for_scan: Option<usize>,
5053 ) -> ScanResult<Vec<TransactionAccount>> {
5054 self.rc.accounts.load_by_index_key_with_filter(
5055 &self.ancestors,
5056 self.bank_id,
5057 index_key,
5058 filter,
5059 config,
5060 byte_limit_for_scan,
5061 )
5062 }
5063
5064 pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
5065 self.rc.accounts.account_indexes_include_key(key)
5066 }
5067
5068 pub fn get_all_accounts(&self, sort_results: bool) -> ScanResult<Vec<PubkeyAccountSlot>> {
5070 self.rc
5071 .accounts
5072 .load_all(&self.ancestors, self.bank_id, sort_results)
5073 }
5074
5075 pub fn scan_all_accounts<F>(&self, scan_func: F, sort_results: bool) -> ScanResult<()>
5077 where
5078 F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>),
5079 {
5080 self.rc
5081 .accounts
5082 .scan_all(&self.ancestors, self.bank_id, scan_func, sort_results)
5083 }
5084
5085 pub fn get_program_accounts_modified_since_parent(
5086 &self,
5087 program_id: &Pubkey,
5088 ) -> Vec<TransactionAccount> {
5089 self.rc
5090 .accounts
5091 .load_by_program_slot(self.slot(), Some(program_id))
5092 }
5093
5094 pub fn get_transaction_logs(
5095 &self,
5096 address: Option<&Pubkey>,
5097 ) -> Option<Vec<TransactionLogInfo>> {
5098 self.transaction_log_collector
5099 .read()
5100 .unwrap()
5101 .get_logs_for_address(address)
5102 }
5103
5104 pub fn get_all_accounts_modified_since_parent(&self) -> Vec<TransactionAccount> {
5106 self.rc.accounts.load_by_program_slot(self.slot(), None)
5107 }
5108
5109 fn get_account_modified_since_parent_with_fixed_root(
5111 &self,
5112 pubkey: &Pubkey,
5113 ) -> Option<(AccountSharedData, Slot)> {
5114 let just_self: Ancestors = Ancestors::from(vec![self.slot()]);
5115 if let Some((account, slot)) = self.load_slow_with_fixed_root(&just_self, pubkey) {
5116 if slot == self.slot() {
5117 return Some((account, slot));
5118 }
5119 }
5120 None
5121 }
5122
5123 pub fn get_largest_accounts(
5124 &self,
5125 num: usize,
5126 filter_by_address: &HashSet<Pubkey>,
5127 filter: AccountAddressFilter,
5128 sort_results: bool,
5129 ) -> ScanResult<Vec<(Pubkey, u64)>> {
5130 self.rc.accounts.load_largest_accounts(
5131 &self.ancestors,
5132 self.bank_id,
5133 num,
5134 filter_by_address,
5135 filter,
5136 sort_results,
5137 )
5138 }
5139
5140 pub fn transaction_count(&self) -> u64 {
5142 self.transaction_count.load(Relaxed)
5143 }
5144
5145 pub fn non_vote_transaction_count_since_restart(&self) -> u64 {
5150 self.non_vote_transaction_count_since_restart.load(Relaxed)
5151 }
5152
5153 pub fn executed_transaction_count(&self) -> u64 {
5155 self.transaction_count()
5156 .saturating_sub(self.parent().map_or(0, |parent| parent.transaction_count()))
5157 }
5158
5159 pub fn transaction_error_count(&self) -> u64 {
5160 self.transaction_error_count.load(Relaxed)
5161 }
5162
5163 pub fn transaction_entries_count(&self) -> u64 {
5164 self.transaction_entries_count.load(Relaxed)
5165 }
5166
5167 pub fn transactions_per_entry_max(&self) -> u64 {
5168 self.transactions_per_entry_max.load(Relaxed)
5169 }
5170
5171 fn increment_transaction_count(&self, tx_count: u64) {
5172 self.transaction_count.fetch_add(tx_count, Relaxed);
5173 }
5174
5175 fn increment_non_vote_transaction_count_since_restart(&self, tx_count: u64) {
5176 self.non_vote_transaction_count_since_restart
5177 .fetch_add(tx_count, Relaxed);
5178 }
5179
5180 pub fn signature_count(&self) -> u64 {
5181 self.signature_count.load(Relaxed)
5182 }
5183
5184 fn increment_signature_count(&self, signature_count: u64) {
5185 self.signature_count.fetch_add(signature_count, Relaxed);
5186 }
5187
5188 pub fn get_signature_status_processed_since_parent(
5189 &self,
5190 signature: &Signature,
5191 ) -> Option<Result<()>> {
5192 if let Some((slot, status)) = self.get_signature_status_slot(signature) {
5193 if slot <= self.slot() {
5194 return Some(status);
5195 }
5196 }
5197 None
5198 }
5199
5200 pub fn get_signature_status_with_blockhash(
5201 &self,
5202 signature: &Signature,
5203 blockhash: &Hash,
5204 ) -> Option<Result<()>> {
5205 let rcache = self.status_cache.read().unwrap();
5206 rcache
5207 .get_status(signature, blockhash, &self.ancestors)
5208 .map(|v| v.1)
5209 }
5210
5211 pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
5212 let rcache = self.status_cache.read().unwrap();
5213 rcache.get_status_any_blockhash(signature, &self.ancestors)
5214 }
5215
5216 pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
5217 self.get_signature_status_slot(signature).map(|v| v.1)
5218 }
5219
5220 pub fn has_signature(&self, signature: &Signature) -> bool {
5221 self.get_signature_status_slot(signature).is_some()
5222 }
5223
5224 fn hash_internal_state(&self) -> Hash {
5227 let measure_total = Measure::start("");
5228 let slot = self.slot();
5229
5230 let delta_hash_info = (!self
5231 .feature_set
5232 .is_active(&feature_set::remove_accounts_delta_hash::id()))
5233 .then(|| {
5234 measure_us!({
5235 self.rc
5236 .accounts
5237 .accounts_db
5238 .calculate_accounts_delta_hash_internal(
5239 slot,
5240 None,
5241 self.skipped_rewrites.lock().unwrap().clone(),
5242 )
5243 })
5244 });
5245
5246 let mut hash = if let Some((accounts_delta_hash, _measure)) = delta_hash_info.as_ref() {
5247 hashv(&[
5248 self.parent_hash.as_ref(),
5249 accounts_delta_hash.0.as_ref(),
5250 &self.signature_count().to_le_bytes(),
5251 self.last_blockhash().as_ref(),
5252 ])
5253 } else {
5254 hashv(&[
5255 self.parent_hash.as_ref(),
5256 &self.signature_count().to_le_bytes(),
5257 self.last_blockhash().as_ref(),
5258 ])
5259 };
5260
5261 let accounts_hash_info = if self
5262 .feature_set
5263 .is_active(&feature_set::accounts_lt_hash::id())
5264 {
5265 let accounts_lt_hash = &*self.accounts_lt_hash.lock().unwrap();
5266 let lt_hash_bytes = bytemuck::must_cast_slice(&accounts_lt_hash.0 .0);
5267 hash = hashv(&[hash.as_ref(), lt_hash_bytes]);
5268 let checksum = accounts_lt_hash.0.checksum();
5269 Some(format!(", accounts_lt_hash checksum: {checksum}"))
5270 } else {
5271 let epoch_accounts_hash = self.wait_get_epoch_accounts_hash();
5272 epoch_accounts_hash.map(|epoch_accounts_hash| {
5273 hash = hashv(&[hash.as_ref(), epoch_accounts_hash.as_ref().as_ref()]);
5274 format!(", epoch_accounts_hash: {:?}", epoch_accounts_hash.as_ref())
5275 })
5276 };
5277
5278 let buf = self
5279 .hard_forks
5280 .read()
5281 .unwrap()
5282 .get_hash_data(slot, self.parent_slot());
5283 if let Some(buf) = buf {
5284 let hard_forked_hash = extend_and_hash(&hash, &buf);
5285 warn!("hard fork at slot {slot} by hashing {buf:?}: {hash} => {hard_forked_hash}");
5286 hash = hard_forked_hash;
5287 }
5288
5289 #[cfg(feature = "dev-context-only-utils")]
5290 let hash_override = self
5291 .hash_overrides
5292 .lock()
5293 .unwrap()
5294 .get_bank_hash_override(slot)
5295 .copied()
5296 .inspect(|&hash_override| {
5297 if hash_override != hash {
5298 info!(
5299 "bank: slot: {}: overrode bank hash: {} with {}",
5300 self.slot(),
5301 hash,
5302 hash_override
5303 );
5304 }
5305 });
5306 #[cfg(feature = "dev-context-only-utils")]
5310 let hash = hash_override.unwrap_or(std::hint::black_box(hash));
5311
5312 let bank_hash_stats = self.bank_hash_stats.load();
5313
5314 let total_us = measure_total.end_as_us();
5315
5316 let (accounts_delta_hash_us, accounts_delta_hash_log) = delta_hash_info
5317 .map(|(hash, us)| (us, format!(" accounts_delta: {}", hash.0)))
5318 .unzip();
5319 datapoint_info!(
5320 "bank-hash_internal_state",
5321 ("slot", slot, i64),
5322 ("total_us", total_us, i64),
5323 ("accounts_delta_hash_us", accounts_delta_hash_us, Option<i64>),
5324 );
5325 info!(
5326 "bank frozen: {slot} hash: {hash}{} signature_count: {} last_blockhash: {} capitalization: {}{}, stats: {bank_hash_stats:?}",
5327 accounts_delta_hash_log.unwrap_or_default(),
5328 self.signature_count(),
5329 self.last_blockhash(),
5330 self.capitalization(),
5331 accounts_hash_info.unwrap_or_default(),
5332 );
5333 hash
5334 }
5335
5336 pub fn collector_fees(&self) -> u64 {
5337 self.collector_fees.load(Relaxed)
5338 }
5339
5340 fn should_include_epoch_accounts_hash(&self) -> bool {
5343 if !epoch_accounts_hash_utils::is_enabled_this_epoch(self) {
5344 return false;
5345 }
5346
5347 let stop_slot = epoch_accounts_hash_utils::calculation_stop(self);
5348 self.parent_slot() < stop_slot && self.slot() >= stop_slot
5349 }
5350
5351 fn wait_get_epoch_accounts_hash(&self) -> Option<EpochAccountsHash> {
5354 if !self.should_include_epoch_accounts_hash() {
5355 return None;
5356 }
5357
5358 let (epoch_accounts_hash, waiting_time_us) = measure_us!(self
5359 .rc
5360 .accounts
5361 .accounts_db
5362 .epoch_accounts_hash_manager
5363 .wait_get_epoch_accounts_hash());
5364
5365 datapoint_info!(
5366 "bank-wait_get_epoch_accounts_hash",
5367 ("slot", self.slot(), i64),
5368 ("waiting-time-us", waiting_time_us, i64),
5369 );
5370 Some(epoch_accounts_hash)
5371 }
5372
5373 pub fn run_final_hash_calc(&self, on_halt_store_hash_raw_data_for_debug: bool) {
5376 self.force_flush_accounts_cache();
5377 _ = self.verify_accounts_hash(
5379 None,
5380 VerifyAccountsHashConfig {
5381 test_hash_calculation: false,
5382 ignore_mismatch: true,
5383 require_rooted_bank: false,
5384 run_in_background: false,
5385 store_hash_raw_data_for_debug: on_halt_store_hash_raw_data_for_debug,
5386 },
5387 None,
5388 );
5389 }
5390
5391 #[must_use]
5395 fn verify_accounts_hash(
5396 &self,
5397 base: Option<(Slot, u64)>,
5398 mut config: VerifyAccountsHashConfig,
5399 duplicates_lt_hash: Option<Box<DuplicatesLtHash>>,
5400 ) -> bool {
5401 #[derive(Debug, Eq, PartialEq)]
5402 enum VerifyKind {
5403 Merkle,
5404 Lattice,
5405 }
5406
5407 let accounts = &self.rc.accounts;
5408 accounts
5411 .accounts_db
5412 .verify_accounts_hash_in_bg
5413 .join_background_thread();
5414
5415 let slot = self.slot();
5416
5417 let verify_kind = match (
5418 duplicates_lt_hash.is_some(),
5419 self.rc
5420 .accounts
5421 .accounts_db
5422 .is_experimental_accumulator_hash_enabled(),
5423 ) {
5424 (true, _) => VerifyKind::Lattice,
5425 (false, false) => VerifyKind::Merkle,
5426 (false, true) => {
5427 config.run_in_background = false;
5431 VerifyKind::Lattice
5432 }
5433 };
5434
5435 if config.require_rooted_bank && !accounts.accounts_db.accounts_index.is_alive_root(slot) {
5436 if let Some(parent) = self.parent() {
5437 info!(
5438 "slot {slot} is not a root, so verify accounts hash on parent bank at slot {}",
5439 parent.slot(),
5440 );
5441 if verify_kind == VerifyKind::Lattice {
5442 config.run_in_background = false;
5446 }
5447 return parent.verify_accounts_hash(base, config, None);
5448 } else {
5449 panic!("cannot verify accounts hash because slot {slot} is not a root");
5452 }
5453 }
5454
5455 let snapshot_storages = self.rc.accounts.accounts_db.get_storages(RangeFull);
5459 let capitalization = self.capitalization();
5460 let verify_config = VerifyAccountsHashAndLamportsConfig {
5461 ancestors: &self.ancestors,
5462 epoch_schedule: self.epoch_schedule(),
5463 rent_collector: self.rent_collector(),
5464 test_hash_calculation: config.test_hash_calculation,
5465 ignore_mismatch: config.ignore_mismatch,
5466 store_detailed_debug_info: config.store_hash_raw_data_for_debug,
5467 use_bg_thread_pool: config.run_in_background,
5468 };
5469
5470 info!(
5471 "Verifying accounts, in background? {}, verify kind: {verify_kind:?}",
5472 config.run_in_background,
5473 );
5474 if config.run_in_background {
5475 let accounts = Arc::clone(accounts);
5476 let accounts_ = Arc::clone(&accounts);
5477 let ancestors = self.ancestors.clone();
5478 let epoch_schedule = self.epoch_schedule().clone();
5479 let rent_collector = self.rent_collector().clone();
5480 let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5481 accounts.accounts_db.verify_accounts_hash_in_bg.start(|| {
5482 Builder::new()
5483 .name("solBgHashVerify".into())
5484 .spawn(move || {
5485 info!("Initial background accounts hash verification has started");
5486 let start = Instant::now();
5487 let mut lattice_verify_time = None;
5488 let mut merkle_verify_time = None;
5489 let is_ok = match verify_kind {
5490 VerifyKind::Lattice => {
5491 let accounts_db = &accounts_.accounts_db;
5493 let (calculated_accounts_lt_hash, duration) =
5494 meas_dur!(accounts_db.thread_pool_hash.install(|| {
5495 accounts_db
5496 .calculate_accounts_lt_hash_at_startup_from_storages(
5497 snapshot_storages.0.as_slice(),
5498 &duplicates_lt_hash.unwrap(),
5499 )
5500 }));
5501 let is_ok =
5502 calculated_accounts_lt_hash == expected_accounts_lt_hash;
5503 if !is_ok {
5504 let expected = expected_accounts_lt_hash.0.checksum();
5505 let calculated = calculated_accounts_lt_hash.0.checksum();
5506 error!(
5507 "Verifying accounts failed: accounts lattice hashes do not \
5508 match, expected: {expected}, calculated: {calculated}",
5509 );
5510 }
5511 lattice_verify_time = Some(duration);
5512 is_ok
5513 }
5514 VerifyKind::Merkle => {
5515 let snapshot_storages_and_slots = (
5517 snapshot_storages.0.as_slice(),
5518 snapshot_storages.1.as_slice(),
5519 );
5520 let (is_ok, duration) = meas_dur!(accounts_
5521 .verify_accounts_hash_and_lamports(
5522 snapshot_storages_and_slots,
5523 slot,
5524 capitalization,
5525 base,
5526 VerifyAccountsHashAndLamportsConfig {
5527 ancestors: &ancestors,
5528 epoch_schedule: &epoch_schedule,
5529 rent_collector: &rent_collector,
5530 ..verify_config
5531 },
5532 ));
5533 merkle_verify_time = Some(duration);
5534 is_ok
5535 }
5536 };
5537 accounts_
5538 .accounts_db
5539 .verify_accounts_hash_in_bg
5540 .background_finished();
5541 let total_time = start.elapsed();
5542 datapoint_info!(
5543 "startup_verify_accounts",
5544 ("total_us", total_time.as_micros(), i64),
5545 (
5546 "verify_accounts_lt_hash_us",
5547 lattice_verify_time.as_ref().map(Duration::as_micros),
5548 Option<i64>
5549 ),
5550 ("verify_accounts_hash_us",
5551 merkle_verify_time.as_ref().map(Duration::as_micros),
5552 Option<i64>
5553 ),
5554 );
5555 info!("Initial background accounts hash verification has stopped");
5556 is_ok
5557 })
5558 .unwrap()
5559 });
5560 true } else {
5562 match verify_kind {
5563 VerifyKind::Lattice => {
5564 let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5565 let calculated_accounts_lt_hash = if let Some(duplicates_lt_hash) =
5566 duplicates_lt_hash
5567 {
5568 accounts
5569 .accounts_db
5570 .calculate_accounts_lt_hash_at_startup_from_storages(
5571 snapshot_storages.0.as_slice(),
5572 &duplicates_lt_hash,
5573 )
5574 } else {
5575 accounts
5576 .accounts_db
5577 .calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors, slot)
5578 };
5579 let is_ok = calculated_accounts_lt_hash == expected_accounts_lt_hash;
5580 if !is_ok {
5581 let expected = expected_accounts_lt_hash.0.checksum();
5582 let calculated = calculated_accounts_lt_hash.0.checksum();
5583 error!(
5584 "Verifying accounts failed: accounts lattice hashes do not \
5585 match, expected: {expected}, calculated: {calculated}",
5586 );
5587 }
5588 is_ok
5589 }
5590 VerifyKind::Merkle => {
5591 let snapshot_storages_and_slots = (
5592 snapshot_storages.0.as_slice(),
5593 snapshot_storages.1.as_slice(),
5594 );
5595 let is_ok = accounts.verify_accounts_hash_and_lamports(
5596 snapshot_storages_and_slots,
5597 slot,
5598 capitalization,
5599 base,
5600 verify_config,
5601 );
5602 self.set_initial_accounts_hash_verification_completed();
5603 is_ok
5604 }
5605 }
5606 }
5607 }
5608
5609 pub fn set_initial_accounts_hash_verification_completed(&self) {
5613 self.rc
5614 .accounts
5615 .accounts_db
5616 .verify_accounts_hash_in_bg
5617 .verification_complete();
5618 }
5619
5620 pub fn has_initial_accounts_hash_verification_completed(&self) -> bool {
5624 self.rc
5625 .accounts
5626 .accounts_db
5627 .verify_accounts_hash_in_bg
5628 .check_complete()
5629 }
5630
5631 pub fn get_snapshot_storages(&self, base_slot: Option<Slot>) -> Vec<Arc<AccountStorageEntry>> {
5635 let start_slot = base_slot.map_or(0, |slot| slot.saturating_add(1));
5637 let requested_slots = start_slot..=self.slot();
5639
5640 self.rc.accounts.accounts_db.get_storages(requested_slots).0
5641 }
5642
5643 #[must_use]
5644 fn verify_hash(&self) -> bool {
5645 assert!(self.is_frozen());
5646 let calculated_hash = self.hash_internal_state();
5647 let expected_hash = self.hash();
5648
5649 if calculated_hash == expected_hash {
5650 true
5651 } else {
5652 warn!(
5653 "verify failed: slot: {}, {} (calculated) != {} (expected)",
5654 self.slot(),
5655 calculated_hash,
5656 expected_hash
5657 );
5658 false
5659 }
5660 }
5661
5662 pub fn verify_transaction(
5663 &self,
5664 tx: VersionedTransaction,
5665 verification_mode: TransactionVerificationMode,
5666 ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5667 let sanitized_tx = {
5668 let size =
5669 bincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?;
5670 if size > PACKET_DATA_SIZE as u64 {
5671 return Err(TransactionError::SanitizeFailure);
5672 }
5673 let message_hash = if verification_mode == TransactionVerificationMode::FullVerification
5674 {
5675 tx.verify_and_hash_message()?
5676 } else {
5677 tx.message.hash()
5678 };
5679
5680 RuntimeTransaction::try_create(
5681 tx,
5682 MessageHash::Precomputed(message_hash),
5683 None,
5684 self,
5685 self.get_reserved_account_keys(),
5686 )
5687 }?;
5688
5689 let move_precompile_verification_to_svm = self
5690 .feature_set
5691 .is_active(&feature_set::move_precompile_verification_to_svm::id());
5692 if !move_precompile_verification_to_svm && {
5693 verification_mode == TransactionVerificationMode::HashAndVerifyPrecompiles
5694 || verification_mode == TransactionVerificationMode::FullVerification
5695 } {
5696 verify_precompiles(&sanitized_tx, &self.feature_set)?;
5697 }
5698
5699 Ok(sanitized_tx)
5700 }
5701
5702 pub fn fully_verify_transaction(
5703 &self,
5704 tx: VersionedTransaction,
5705 ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5706 self.verify_transaction(tx, TransactionVerificationMode::FullVerification)
5707 }
5708
5709 pub fn check_reserved_keys(&self, tx: &impl SVMMessage) -> Result<()> {
5713 let reserved_keys = self.get_reserved_account_keys();
5716 for (index, key) in tx.account_keys().iter().enumerate() {
5717 if tx.is_writable(index) && reserved_keys.contains(key) {
5718 return Err(TransactionError::ResanitizationNeeded);
5719 }
5720 }
5721
5722 Ok(())
5723 }
5724
5725 fn calculate_capitalization(&self, debug_verify: bool) -> u64 {
5727 let is_startup = true;
5728 self.rc
5729 .accounts
5730 .accounts_db
5731 .verify_accounts_hash_in_bg
5732 .join_background_thread();
5733 self.rc
5734 .accounts
5735 .accounts_db
5736 .update_accounts_hash_with_verify_from(
5737 CalcAccountsHashDataSource::IndexForTests,
5739 debug_verify,
5740 self.slot(),
5741 &self.ancestors,
5742 None,
5743 self.epoch_schedule(),
5744 &self.rent_collector,
5745 is_startup,
5746 )
5747 .1
5748 }
5749
5750 pub fn calculate_and_verify_capitalization(&self, debug_verify: bool) -> bool {
5752 let calculated = self.calculate_capitalization(debug_verify);
5753 let expected = self.capitalization();
5754 if calculated == expected {
5755 true
5756 } else {
5757 warn!(
5758 "Capitalization mismatch: calculated: {} != expected: {}",
5759 calculated, expected
5760 );
5761 false
5762 }
5763 }
5764
5765 pub fn set_capitalization(&self) -> u64 {
5768 let old = self.capitalization();
5769 let debug_verify = false;
5773 self.capitalization
5774 .store(self.calculate_capitalization(debug_verify), Relaxed);
5775 old
5776 }
5777
5778 pub fn get_accounts_hash(&self) -> Option<AccountsHash> {
5783 self.rc
5784 .accounts
5785 .accounts_db
5786 .get_accounts_hash(self.slot())
5787 .map(|(accounts_hash, _)| accounts_hash)
5788 }
5789
5790 pub fn get_incremental_accounts_hash(&self) -> Option<IncrementalAccountsHash> {
5795 self.rc
5796 .accounts
5797 .accounts_db
5798 .get_incremental_accounts_hash(self.slot())
5799 .map(|(incremental_accounts_hash, _)| incremental_accounts_hash)
5800 }
5801
5802 pub fn get_snapshot_hash(&self) -> SnapshotHash {
5812 if self.is_snapshots_lt_hash_enabled() {
5813 self.get_lattice_snapshot_hash()
5814 } else {
5815 self.get_merkle_snapshot_hash()
5816 }
5817 }
5818
5819 pub fn get_merkle_snapshot_hash(&self) -> SnapshotHash {
5829 let accounts_hash = self.get_accounts_hash();
5830 let incremental_accounts_hash = self.get_incremental_accounts_hash();
5831 let accounts_hash_kind = match (accounts_hash, incremental_accounts_hash) {
5832 (Some(_), Some(_)) => panic!("Both full and incremental accounts hashes are present for slot {}; it is ambiguous which one to use for the snapshot hash!", self.slot()),
5833 (Some(accounts_hash), None) => accounts_hash.into(),
5834 (None, Some(incremental_accounts_hash)) => incremental_accounts_hash.into(),
5835 (None, None) => panic!("accounts hash is required to get snapshot hash"),
5836 };
5837 let epoch_accounts_hash = self.get_epoch_accounts_hash_to_serialize();
5838 SnapshotHash::new(
5839 &MerkleOrLatticeAccountsHash::Merkle(accounts_hash_kind),
5840 epoch_accounts_hash.as_ref(),
5841 None,
5842 )
5843 }
5844
5845 pub fn get_lattice_snapshot_hash(&self) -> SnapshotHash {
5849 SnapshotHash::new(
5850 &MerkleOrLatticeAccountsHash::Lattice,
5851 None,
5852 Some(self.accounts_lt_hash.lock().unwrap().0.checksum()),
5853 )
5854 }
5855
5856 pub fn load_account_into_read_cache(&self, key: &Pubkey) {
5857 self.rc
5858 .accounts
5859 .accounts_db
5860 .load_account_into_read_cache(&self.ancestors, key);
5861 }
5862
5863 pub fn update_accounts_hash(
5864 &self,
5865 data_source: CalcAccountsHashDataSource,
5866 mut debug_verify: bool,
5867 is_startup: bool,
5868 ) -> AccountsHash {
5869 let (accounts_hash, total_lamports) = self
5870 .rc
5871 .accounts
5872 .accounts_db
5873 .update_accounts_hash_with_verify_from(
5874 data_source,
5875 debug_verify,
5876 self.slot(),
5877 &self.ancestors,
5878 Some(self.capitalization()),
5879 self.epoch_schedule(),
5880 &self.rent_collector,
5881 is_startup,
5882 );
5883 if total_lamports != self.capitalization() {
5884 datapoint_info!(
5885 "capitalization_mismatch",
5886 ("slot", self.slot(), i64),
5887 ("calculated_lamports", total_lamports, i64),
5888 ("capitalization", self.capitalization(), i64),
5889 );
5890
5891 if !debug_verify {
5892 debug_verify = true;
5895 self.rc
5896 .accounts
5897 .accounts_db
5898 .update_accounts_hash_with_verify_from(
5899 data_source,
5900 debug_verify,
5901 self.slot(),
5902 &self.ancestors,
5903 Some(self.capitalization()),
5904 self.epoch_schedule(),
5905 &self.rent_collector,
5906 is_startup,
5907 );
5908 }
5909
5910 panic!(
5911 "capitalization_mismatch. slot: {}, calculated_lamports: {}, capitalization: {}",
5912 self.slot(),
5913 total_lamports,
5914 self.capitalization()
5915 );
5916 }
5917 accounts_hash
5918 }
5919
5920 pub fn update_incremental_accounts_hash(&self, base_slot: Slot) -> IncrementalAccountsHash {
5922 let config = CalcAccountsHashConfig {
5923 use_bg_thread_pool: true,
5924 ancestors: None, epoch_schedule: &self.epoch_schedule,
5926 rent_collector: &self.rent_collector,
5927 store_detailed_debug_info_on_failure: false,
5928 };
5929 let storages = self.get_snapshot_storages(Some(base_slot));
5930 let sorted_storages = SortedStorages::new(&storages);
5931 self.rc
5932 .accounts
5933 .accounts_db
5934 .update_incremental_accounts_hash(
5935 &config,
5936 &sorted_storages,
5937 self.slot(),
5938 HashStats::default(),
5939 )
5940 .0
5941 }
5942
5943 pub fn verify_snapshot_bank(
5946 &self,
5947 test_hash_calculation: bool,
5948 skip_shrink: bool,
5949 force_clean: bool,
5950 latest_full_snapshot_slot: Slot,
5951 base: Option<(Slot, u64)>,
5952 duplicates_lt_hash: Option<Box<DuplicatesLtHash>>,
5953 ) -> bool {
5954 let (verified_accounts, verify_accounts_time_us) = measure_us!({
5962 let should_verify_accounts = !self.rc.accounts.accounts_db.skip_initial_hash_calc;
5963 if should_verify_accounts {
5964 info!("Verifying accounts...");
5965 let verified = self.verify_accounts_hash(
5966 base,
5967 VerifyAccountsHashConfig {
5968 test_hash_calculation,
5969 ignore_mismatch: false,
5970 require_rooted_bank: false,
5971 run_in_background: true,
5972 store_hash_raw_data_for_debug: false,
5973 },
5974 duplicates_lt_hash,
5975 );
5976 info!("Verifying accounts... In background.");
5977 verified
5978 } else {
5979 info!("Verifying accounts... Skipped.");
5980 self.rc
5981 .accounts
5982 .accounts_db
5983 .verify_accounts_hash_in_bg
5984 .verification_complete();
5985 true
5986 }
5987 });
5988
5989 let (_, clean_time_us) = measure_us!({
5990 let should_clean = force_clean || (!skip_shrink && self.slot() > 0);
5991 if should_clean {
5992 info!("Cleaning...");
5993 self.rc.accounts.accounts_db.clean_accounts(
5998 Some(latest_full_snapshot_slot),
5999 true,
6000 self.epoch_schedule(),
6001 self.clean_accounts_old_storages_policy(),
6002 );
6003 info!("Cleaning... Done.");
6004 } else {
6005 info!("Cleaning... Skipped.");
6006 }
6007 });
6008
6009 let (_, shrink_time_us) = measure_us!({
6010 let should_shrink = !skip_shrink && self.slot() > 0;
6011 if should_shrink {
6012 info!("Shrinking...");
6013 self.rc.accounts.accounts_db.shrink_all_slots(
6014 true,
6015 self.epoch_schedule(),
6016 Some(self.slot()),
6018 );
6019 info!("Shrinking... Done.");
6020 } else {
6021 info!("Shrinking... Skipped.");
6022 }
6023 });
6024
6025 info!("Verifying bank...");
6026 let (verified_bank, verify_bank_time_us) = measure_us!(self.verify_hash());
6027 info!("Verifying bank... Done.");
6028
6029 datapoint_info!(
6030 "verify_snapshot_bank",
6031 ("clean_us", clean_time_us, i64),
6032 ("shrink_us", shrink_time_us, i64),
6033 ("verify_accounts_us", verify_accounts_time_us, i64),
6034 ("verify_bank_us", verify_bank_time_us, i64),
6035 );
6036
6037 verified_accounts && verified_bank
6038 }
6039
6040 pub fn hashes_per_tick(&self) -> &Option<u64> {
6042 &self.hashes_per_tick
6043 }
6044
6045 pub fn ticks_per_slot(&self) -> u64 {
6047 self.ticks_per_slot
6048 }
6049
6050 pub fn slots_per_year(&self) -> f64 {
6052 self.slots_per_year
6053 }
6054
6055 pub fn tick_height(&self) -> u64 {
6057 self.tick_height.load(Relaxed)
6058 }
6059
6060 pub fn inflation(&self) -> Inflation {
6062 *self.inflation.read().unwrap()
6063 }
6064
6065 pub fn rent_collector(&self) -> &RentCollector {
6067 &self.rent_collector
6068 }
6069
6070 pub fn capitalization(&self) -> u64 {
6072 self.capitalization.load(Relaxed)
6073 }
6074
6075 pub fn max_tick_height(&self) -> u64 {
6077 self.max_tick_height
6078 }
6079
6080 pub fn block_height(&self) -> u64 {
6082 self.block_height
6083 }
6084
6085 pub fn get_slots_in_epoch(&self, epoch: Epoch) -> u64 {
6087 self.epoch_schedule().get_slots_in_epoch(epoch)
6088 }
6089
6090 pub fn get_leader_schedule_epoch(&self, slot: Slot) -> Epoch {
6093 self.epoch_schedule().get_leader_schedule_epoch(slot)
6094 }
6095
6096 fn update_stakes_cache(
6098 &self,
6099 txs: &[impl SVMMessage],
6100 processing_results: &[TransactionProcessingResult],
6101 ) {
6102 debug_assert_eq!(txs.len(), processing_results.len());
6103 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
6104 txs.iter()
6105 .zip(processing_results)
6106 .filter_map(|(tx, processing_result)| {
6107 processing_result
6108 .processed_transaction()
6109 .map(|processed_tx| (tx, processed_tx))
6110 })
6111 .filter_map(|(tx, processed_tx)| {
6112 processed_tx
6113 .executed_transaction()
6114 .map(|executed_tx| (tx, executed_tx))
6115 })
6116 .filter(|(_, executed_tx)| executed_tx.was_successful())
6117 .flat_map(|(tx, executed_tx)| {
6118 let num_account_keys = tx.account_keys().len();
6119 let loaded_tx = &executed_tx.loaded_transaction;
6120 loaded_tx.accounts.iter().take(num_account_keys)
6121 })
6122 .for_each(|(pubkey, account)| {
6123 self.stakes_cache
6126 .check_and_store(pubkey, account, new_warmup_cooldown_rate_epoch);
6127 });
6128 }
6129
6130 pub fn vote_accounts(&self) -> Arc<VoteAccountsHashMap> {
6133 let stakes = self.stakes_cache.stakes();
6134 Arc::from(stakes.vote_accounts())
6135 }
6136
6137 pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<VoteAccount> {
6139 let stakes = self.stakes_cache.stakes();
6140 let vote_account = stakes.vote_accounts().get(vote_account)?;
6141 Some(vote_account.clone())
6142 }
6143
6144 pub fn current_epoch_stakes(&self) -> &EpochStakes {
6146 self.epoch_stakes
6149 .get(&self.epoch.saturating_add(1))
6150 .expect("Current epoch stakes must exist")
6151 }
6152
6153 pub fn epoch_stakes(&self, epoch: Epoch) -> Option<&EpochStakes> {
6155 self.epoch_stakes.get(&epoch)
6156 }
6157
6158 pub fn epoch_stakes_map(&self) -> &HashMap<Epoch, EpochStakes> {
6159 &self.epoch_stakes
6160 }
6161
6162 pub fn current_epoch_staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
6164 self.current_epoch_stakes().stakes().staked_nodes()
6165 }
6166
6167 pub fn epoch_staked_nodes(&self, epoch: Epoch) -> Option<Arc<HashMap<Pubkey, u64>>> {
6168 Some(self.epoch_stakes.get(&epoch)?.stakes().staked_nodes())
6169 }
6170
6171 pub fn epoch_total_stake(&self, epoch: Epoch) -> Option<u64> {
6173 self.epoch_stakes
6174 .get(&epoch)
6175 .map(|epoch_stakes| epoch_stakes.total_stake())
6176 }
6177
6178 pub fn get_current_epoch_total_stake(&self) -> u64 {
6180 self.current_epoch_stakes().total_stake()
6181 }
6182
6183 pub fn epoch_vote_accounts(&self, epoch: Epoch) -> Option<&VoteAccountsHashMap> {
6186 let epoch_stakes = self.epoch_stakes.get(&epoch)?.stakes();
6187 Some(epoch_stakes.vote_accounts().as_ref())
6188 }
6189
6190 pub fn get_current_epoch_vote_accounts(&self) -> &VoteAccountsHashMap {
6193 self.current_epoch_stakes()
6194 .stakes()
6195 .vote_accounts()
6196 .as_ref()
6197 }
6198
6199 pub fn epoch_authorized_voter(&self, vote_account: &Pubkey) -> Option<&Pubkey> {
6202 self.epoch_stakes
6203 .get(&self.epoch)
6204 .expect("Epoch stakes for bank's own epoch must exist")
6205 .epoch_authorized_voters()
6206 .get(vote_account)
6207 }
6208
6209 pub fn epoch_vote_accounts_for_node_id(&self, node_id: &Pubkey) -> Option<&NodeVoteAccounts> {
6212 self.epoch_stakes
6213 .get(&self.epoch)
6214 .expect("Epoch stakes for bank's own epoch must exist")
6215 .node_id_to_vote_accounts()
6216 .get(node_id)
6217 }
6218
6219 pub fn epoch_node_id_to_stake(&self, epoch: Epoch, node_id: &Pubkey) -> Option<u64> {
6222 self.epoch_stakes(epoch)
6223 .and_then(|epoch_stakes| epoch_stakes.node_id_to_stake(node_id))
6224 }
6225
6226 pub fn total_epoch_stake(&self) -> u64 {
6228 self.epoch_stakes
6229 .get(&self.epoch)
6230 .expect("Epoch stakes for bank's own epoch must exist")
6231 .total_stake()
6232 }
6233
6234 pub fn epoch_vote_account_stake(&self, vote_account: &Pubkey) -> u64 {
6236 *self
6237 .epoch_vote_accounts(self.epoch())
6238 .expect("Bank epoch vote accounts must contain entry for the bank's own epoch")
6239 .get(vote_account)
6240 .map(|(stake, _)| stake)
6241 .unwrap_or(&0)
6242 }
6243
6244 pub fn get_epoch_and_slot_index(&self, slot: Slot) -> (Epoch, SlotIndex) {
6250 self.epoch_schedule().get_epoch_and_slot_index(slot)
6251 }
6252
6253 pub fn get_epoch_info(&self) -> EpochInfo {
6254 let absolute_slot = self.slot();
6255 let block_height = self.block_height();
6256 let (epoch, slot_index) = self.get_epoch_and_slot_index(absolute_slot);
6257 let slots_in_epoch = self.get_slots_in_epoch(epoch);
6258 let transaction_count = Some(self.transaction_count());
6259 EpochInfo {
6260 epoch,
6261 slot_index,
6262 slots_in_epoch,
6263 absolute_slot,
6264 block_height,
6265 transaction_count,
6266 }
6267 }
6268
6269 pub fn is_empty(&self) -> bool {
6270 !self.is_delta.load(Relaxed)
6271 }
6272
6273 pub fn add_mockup_builtin(
6274 &mut self,
6275 program_id: Pubkey,
6276 builtin_function: BuiltinFunctionWithContext,
6277 ) {
6278 self.transaction_processor.add_builtin(
6279 self,
6280 program_id,
6281 "mockup",
6282 ProgramCacheEntry::new_builtin(self.slot, 0, builtin_function),
6283 );
6284 }
6285
6286 pub fn add_precompile(&mut self, program_id: &Pubkey) {
6287 debug!("Adding precompiled program {}", program_id);
6288 self.add_precompiled_account(program_id);
6289 debug!("Added precompiled program {:?}", program_id);
6290 }
6291
6292 pub(crate) fn clean_accounts(&self) {
6297 let highest_slot_to_clean = self.slot().saturating_sub(1);
6304
6305 self.rc.accounts.accounts_db.clean_accounts(
6306 Some(highest_slot_to_clean),
6307 false,
6308 self.epoch_schedule(),
6309 self.clean_accounts_old_storages_policy(),
6310 );
6311 }
6312
6313 pub fn print_accounts_stats(&self) {
6314 self.rc.accounts.accounts_db.print_accounts_stats("");
6315 }
6316
6317 pub fn shrink_candidate_slots(&self) -> usize {
6318 self.rc
6319 .accounts
6320 .accounts_db
6321 .shrink_candidate_slots(self.epoch_schedule())
6322 }
6323
6324 pub(crate) fn shrink_ancient_slots(&self) {
6325 if self.are_ancient_storages_enabled() {
6329 self.rc
6330 .accounts
6331 .accounts_db
6332 .shrink_ancient_slots(self.epoch_schedule())
6333 }
6334 }
6335
6336 pub fn are_ancient_storages_enabled(&self) -> bool {
6338 let can_skip_rewrites = self.bank_hash_skips_rent_rewrites();
6339 let test_skip_rewrites_but_include_in_bank_hash = self
6340 .rc
6341 .accounts
6342 .accounts_db
6343 .test_skip_rewrites_but_include_in_bank_hash;
6344 can_skip_rewrites || test_skip_rewrites_but_include_in_bank_hash
6345 }
6346
6347 fn clean_accounts_old_storages_policy(&self) -> OldStoragesPolicy {
6349 if self.are_ancient_storages_enabled() {
6350 OldStoragesPolicy::Leave
6351 } else {
6352 OldStoragesPolicy::Clean
6353 }
6354 }
6355
6356 pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<CostTracker>> {
6357 self.cost_tracker.read()
6358 }
6359
6360 pub fn write_cost_tracker(&self) -> LockResult<RwLockWriteGuard<CostTracker>> {
6361 self.cost_tracker.write()
6362 }
6363
6364 pub fn should_bank_still_be_processing_txs(
6367 bank_creation_time: &Instant,
6368 max_tx_ingestion_nanos: u128,
6369 ) -> bool {
6370 bank_creation_time.elapsed().as_nanos() <= max_tx_ingestion_nanos
6372 }
6373
6374 pub fn deactivate_feature(&mut self, id: &Pubkey) {
6375 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6376 feature_set.active.remove(id);
6377 feature_set.inactive.insert(*id);
6378 self.feature_set = Arc::new(feature_set);
6379 }
6380
6381 pub fn activate_feature(&mut self, id: &Pubkey) {
6382 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6383 feature_set.inactive.remove(id);
6384 feature_set.active.insert(*id, 0);
6385 self.feature_set = Arc::new(feature_set);
6386 }
6387
6388 pub fn fill_bank_with_ticks_for_tests(&self) {
6389 self.do_fill_bank_with_ticks_for_tests(&BankWithScheduler::no_scheduler_available())
6390 }
6391
6392 pub(crate) fn do_fill_bank_with_ticks_for_tests(&self, scheduler: &InstalledSchedulerRwLock) {
6393 if self.tick_height.load(Relaxed) < self.max_tick_height {
6394 let last_blockhash = self.last_blockhash();
6395 while self.last_blockhash() == last_blockhash {
6396 self.register_tick(&Hash::new_unique(), scheduler)
6397 }
6398 } else {
6399 warn!("Bank already reached max tick height, cannot fill it with more ticks");
6400 }
6401 }
6402
6403 pub fn get_reserved_account_keys(&self) -> &HashSet<Pubkey> {
6406 &self.reserved_account_keys.active
6407 }
6408
6409 fn apply_feature_activations(
6412 &mut self,
6413 caller: ApplyFeatureActivationsCaller,
6414 debug_do_not_add_builtins: bool,
6415 ) {
6416 use ApplyFeatureActivationsCaller as Caller;
6417 let allow_new_activations = match caller {
6418 Caller::FinishInit => false,
6419 Caller::NewFromParent => true,
6420 Caller::WarpFromParent => false,
6421 };
6422 let (feature_set, new_feature_activations) =
6423 self.compute_active_feature_set(allow_new_activations);
6424 self.feature_set = Arc::new(feature_set);
6425
6426 for feature_id in new_feature_activations.iter() {
6428 if let Some(mut account) = self.get_account_with_fixed_root(feature_id) {
6429 if let Some(mut feature) = feature::from_account(&account) {
6430 feature.activated_at = Some(self.slot());
6431 if feature::to_account(&feature, &mut account).is_some() {
6432 self.store_account(feature_id, &account);
6433 }
6434 info!("Feature {} activated at slot {}", feature_id, self.slot());
6435 }
6436 }
6437 }
6438
6439 self.reserved_account_keys = {
6441 let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
6442 reserved_keys.update_active_set(&self.feature_set);
6443 Arc::new(reserved_keys)
6444 };
6445
6446 if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
6447 *self.inflation.write().unwrap() = Inflation::pico();
6448 self.fee_rate_governor.burn_percent = 50; self.rent_collector.rent.burn_percent = 50; }
6451
6452 if !new_feature_activations.is_disjoint(&self.feature_set.full_inflation_features_enabled())
6453 {
6454 *self.inflation.write().unwrap() = Inflation::full();
6455 self.fee_rate_governor.burn_percent = 50; self.rent_collector.rent.burn_percent = 50; }
6458
6459 if !debug_do_not_add_builtins {
6460 self.apply_builtin_program_feature_transitions(
6461 allow_new_activations,
6462 &new_feature_activations,
6463 );
6464 }
6465
6466 if new_feature_activations.contains(&feature_set::update_hashes_per_tick::id()) {
6467 self.apply_updated_hashes_per_tick(DEFAULT_HASHES_PER_TICK);
6468 }
6469
6470 if new_feature_activations.contains(&feature_set::update_hashes_per_tick2::id()) {
6471 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK2);
6472 }
6473
6474 if new_feature_activations.contains(&feature_set::update_hashes_per_tick3::id()) {
6475 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK3);
6476 }
6477
6478 if new_feature_activations.contains(&feature_set::update_hashes_per_tick4::id()) {
6479 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK4);
6480 }
6481
6482 if new_feature_activations.contains(&feature_set::update_hashes_per_tick5::id()) {
6483 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK5);
6484 }
6485
6486 if new_feature_activations.contains(&feature_set::update_hashes_per_tick6::id()) {
6487 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK6);
6488 }
6489
6490 if new_feature_activations.contains(&feature_set::accounts_lt_hash::id()) {
6491 if self
6495 .rc
6496 .accounts
6497 .accounts_db
6498 .is_experimental_accumulator_hash_enabled()
6499 {
6500 } else {
6503 let parent_slot = self.parent_slot;
6504 info!(
6505 "Calculating the accounts lt hash for slot {parent_slot} \
6506 as part of feature activation; this may take some time...",
6507 );
6508 let parent_ancestors = {
6513 let mut ancestors = self.ancestors.clone();
6514 ancestors.remove(&self.slot());
6515 ancestors
6516 };
6517 let (parent_accounts_lt_hash, duration) = meas_dur!({
6518 self.rc
6519 .accounts
6520 .accounts_db
6521 .calculate_accounts_lt_hash_at_startup_from_index(
6522 &parent_ancestors,
6523 parent_slot,
6524 )
6525 });
6526 *self.accounts_lt_hash.get_mut().unwrap() = parent_accounts_lt_hash;
6527 info!(
6528 "Calculating the accounts lt hash for slot {parent_slot} \
6529 completed in {duration:?}, accounts_lt_hash checksum: {}",
6530 self.accounts_lt_hash.get_mut().unwrap().0.checksum(),
6531 );
6532 }
6533 }
6534
6535 if new_feature_activations.contains(&feature_set::raise_block_limits_to_50m::id()) {
6536 let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits();
6537 self.write_cost_tracker().unwrap().set_limits(
6538 account_cost_limit,
6539 block_cost_limit,
6540 vote_cost_limit,
6541 );
6542 }
6543 }
6544
6545 fn apply_updated_hashes_per_tick(&mut self, hashes_per_tick: u64) {
6546 info!(
6547 "Activating update_hashes_per_tick {} at slot {}",
6548 hashes_per_tick,
6549 self.slot(),
6550 );
6551 self.hashes_per_tick = Some(hashes_per_tick);
6552 }
6553
6554 fn adjust_sysvar_balance_for_rent(&self, account: &mut AccountSharedData) {
6555 account.set_lamports(
6556 self.get_minimum_balance_for_rent_exemption(account.data().len())
6557 .max(account.lamports()),
6558 );
6559 }
6560
6561 fn compute_active_feature_set(&self, include_pending: bool) -> (FeatureSet, AHashSet<Pubkey>) {
6564 let mut active = self.feature_set.active.clone();
6565 let mut inactive = AHashSet::new();
6566 let mut pending = AHashSet::new();
6567 let slot = self.slot();
6568
6569 for feature_id in &self.feature_set.inactive {
6570 let mut activated = None;
6571 if let Some(account) = self.get_account_with_fixed_root(feature_id) {
6572 if let Some(feature) = feature::from_account(&account) {
6573 match feature.activated_at {
6574 None if include_pending => {
6575 pending.insert(*feature_id);
6577 activated = Some(slot);
6578 }
6579 Some(activation_slot) if slot >= activation_slot => {
6580 activated = Some(activation_slot);
6582 }
6583 _ => {}
6584 }
6585 }
6586 }
6587 if let Some(slot) = activated {
6588 active.insert(*feature_id, slot);
6589 } else {
6590 inactive.insert(*feature_id);
6591 }
6592 }
6593
6594 (FeatureSet { active, inactive }, pending)
6595 }
6596
6597 fn apply_builtin_program_feature_transitions(
6598 &mut self,
6599 only_apply_transitions_for_new_features: bool,
6600 new_feature_activations: &AHashSet<Pubkey>,
6601 ) {
6602 for builtin in BUILTINS.iter() {
6603 let mut builtin_is_bpf = false;
6620 if let Some(core_bpf_migration_config) = &builtin.core_bpf_migration_config {
6621 if new_feature_activations.contains(&core_bpf_migration_config.feature_id) {
6626 if let Err(e) = self
6627 .migrate_builtin_to_core_bpf(&builtin.program_id, core_bpf_migration_config)
6628 {
6629 warn!(
6630 "Failed to migrate builtin {} to Core BPF: {}",
6631 builtin.name, e
6632 );
6633 } else {
6634 builtin_is_bpf = true;
6635 }
6636 } else {
6637 builtin_is_bpf = self
6640 .get_account(&builtin.program_id)
6641 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
6642 .unwrap_or(false);
6643 }
6644 };
6645
6646 if let Some(feature_id) = builtin.enable_feature_id {
6647 let should_enable_builtin_on_feature_transition = !builtin_is_bpf
6648 && if only_apply_transitions_for_new_features {
6649 new_feature_activations.contains(&feature_id)
6650 } else {
6651 self.feature_set.is_active(&feature_id)
6652 };
6653
6654 if should_enable_builtin_on_feature_transition {
6655 self.transaction_processor.add_builtin(
6656 self,
6657 builtin.program_id,
6658 builtin.name,
6659 ProgramCacheEntry::new_builtin(
6660 self.feature_set.activated_slot(&feature_id).unwrap_or(0),
6661 builtin.name.len(),
6662 builtin.entrypoint,
6663 ),
6664 );
6665 }
6666 }
6667 }
6668
6669 for stateless_builtin in STATELESS_BUILTINS.iter() {
6673 if let Some(core_bpf_migration_config) = &stateless_builtin.core_bpf_migration_config {
6674 if new_feature_activations.contains(&core_bpf_migration_config.feature_id) {
6675 if let Err(e) = self.migrate_builtin_to_core_bpf(
6676 &stateless_builtin.program_id,
6677 core_bpf_migration_config,
6678 ) {
6679 warn!(
6680 "Failed to migrate stateless builtin {} to Core BPF: {}",
6681 stateless_builtin.name, e
6682 );
6683 }
6684 }
6685 }
6686 }
6687
6688 for precompile in get_precompiles() {
6689 let should_add_precompile = precompile
6690 .feature
6691 .as_ref()
6692 .map(|feature_id| self.feature_set.is_active(feature_id))
6693 .unwrap_or(false);
6694 if should_add_precompile {
6695 self.add_precompile(&precompile.program_id);
6696 }
6697 }
6698 }
6699
6700 #[allow(dead_code)]
6702 fn replace_program_account(
6703 &mut self,
6704 old_address: &Pubkey,
6705 new_address: &Pubkey,
6706 datapoint_name: &'static str,
6707 ) {
6708 if let Some(old_account) = self.get_account_with_fixed_root(old_address) {
6709 if let Some(new_account) = self.get_account_with_fixed_root(new_address) {
6710 datapoint_info!(datapoint_name, ("slot", self.slot, i64));
6711
6712 self.capitalization
6714 .fetch_sub(old_account.lamports(), Relaxed);
6715
6716 self.store_account(old_address, &new_account);
6718
6719 self.store_account(new_address, &AccountSharedData::default());
6721
6722 self.transaction_processor
6724 .program_cache
6725 .write()
6726 .unwrap()
6727 .remove_programs([*old_address].into_iter());
6728
6729 self.calculate_and_update_accounts_data_size_delta_off_chain(
6730 old_account.data().len(),
6731 new_account.data().len(),
6732 );
6733 }
6734 }
6735 }
6736
6737 pub fn get_total_accounts_stats(&self) -> ScanResult<TotalAccountsStats> {
6739 let accounts = self.get_all_accounts(false)?;
6740 Ok(self.calculate_total_accounts_stats(
6741 accounts
6742 .iter()
6743 .map(|(pubkey, account, _slot)| (pubkey, account)),
6744 ))
6745 }
6746
6747 pub fn calculate_total_accounts_stats<'a>(
6749 &self,
6750 accounts: impl Iterator<Item = (&'a Pubkey, &'a AccountSharedData)>,
6751 ) -> TotalAccountsStats {
6752 let rent_collector = self.rent_collector();
6753 let mut total_accounts_stats = TotalAccountsStats::default();
6754 accounts.for_each(|(pubkey, account)| {
6755 total_accounts_stats.accumulate_account(pubkey, account, rent_collector);
6756 });
6757
6758 total_accounts_stats
6759 }
6760
6761 pub fn get_epoch_accounts_hash_to_serialize(&self) -> Option<EpochAccountsHash> {
6767 let should_get_epoch_accounts_hash = epoch_accounts_hash_utils::is_enabled_this_epoch(self)
6768 && epoch_accounts_hash_utils::is_in_calculation_window(self);
6769 if !should_get_epoch_accounts_hash {
6770 return None;
6771 }
6772
6773 let (epoch_accounts_hash, waiting_time_us) = measure_us!(self
6774 .rc
6775 .accounts
6776 .accounts_db
6777 .epoch_accounts_hash_manager
6778 .wait_get_epoch_accounts_hash());
6779
6780 datapoint_info!(
6781 "bank-get_epoch_accounts_hash_to_serialize",
6782 ("slot", self.slot(), i64),
6783 ("waiting-time-us", waiting_time_us, i64),
6784 );
6785 Some(epoch_accounts_hash)
6786 }
6787
6788 pub fn epoch_accounts_hash(&self) -> Option<EpochAccountsHash> {
6790 self.rc
6791 .accounts
6792 .accounts_db
6793 .epoch_accounts_hash_manager
6794 .try_get_epoch_accounts_hash()
6795 }
6796
6797 pub fn is_in_slot_hashes_history(&self, slot: &Slot) -> bool {
6798 if slot < &self.slot {
6799 if let Ok(slot_hashes) = self.transaction_processor.sysvar_cache().get_slot_hashes() {
6800 return slot_hashes.get(slot).is_some();
6801 }
6802 }
6803 false
6804 }
6805
6806 pub fn check_program_modification_slot(&self) -> bool {
6807 self.check_program_modification_slot
6808 }
6809
6810 pub fn set_check_program_modification_slot(&mut self, check: bool) {
6811 self.check_program_modification_slot = check;
6812 }
6813
6814 pub fn fee_structure(&self) -> &FeeStructure {
6815 &self.fee_structure
6816 }
6817
6818 pub fn block_id(&self) -> Option<Hash> {
6819 *self.block_id.read().unwrap()
6820 }
6821
6822 pub fn set_block_id(&self, block_id: Option<Hash>) {
6823 *self.block_id.write().unwrap() = block_id;
6824 }
6825
6826 pub fn compute_budget(&self) -> Option<ComputeBudget> {
6827 self.compute_budget
6828 }
6829
6830 pub fn add_builtin(&self, program_id: Pubkey, name: &str, builtin: ProgramCacheEntry) {
6831 self.transaction_processor
6832 .add_builtin(self, program_id, name, builtin)
6833 }
6834
6835 pub fn get_bank_hash_stats(&self) -> BankHashStats {
6836 self.bank_hash_stats.load()
6837 }
6838}
6839
6840impl TransactionProcessingCallback for Bank {
6841 fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
6842 self.rc
6843 .accounts
6844 .accounts_db
6845 .account_matches_owners(&self.ancestors, account, owners)
6846 .ok()
6847 }
6848
6849 fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6850 self.rc
6851 .accounts
6852 .accounts_db
6853 .load_with_fixed_root(&self.ancestors, pubkey)
6854 .map(|(acc, _)| acc)
6855 }
6856
6857 fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
6860 let existing_genuine_program =
6861 self.get_account_with_fixed_root(program_id)
6862 .and_then(|account| {
6863 if native_loader::check_id(account.owner()) {
6867 Some(account)
6868 } else {
6869 self.burn_and_purge_account(program_id, account);
6871 None
6872 }
6873 });
6874
6875 if existing_genuine_program.is_some() {
6877 return;
6879 }
6880
6881 assert!(
6882 !self.freeze_started(),
6883 "Can't change frozen bank by adding not-existing new builtin program ({name}, {program_id}). \
6884 Maybe, inconsistent program activation is detected on snapshot restore?"
6885 );
6886
6887 let account = native_loader::create_loadable_account_with_fields(
6889 name,
6890 self.inherit_specially_retained_account_fields(&existing_genuine_program),
6891 );
6892 self.store_account_and_update_capitalization(program_id, &account);
6893 }
6894
6895 fn inspect_account(&self, address: &Pubkey, account_state: AccountState, is_writable: bool) {
6896 if self.is_accounts_lt_hash_enabled() {
6897 self.inspect_account_for_accounts_lt_hash(address, &account_state, is_writable);
6898 }
6899 }
6900
6901 fn get_current_epoch_vote_account_stake(&self, vote_address: &Pubkey) -> u64 {
6902 self.get_current_epoch_vote_accounts()
6903 .get(vote_address)
6904 .map(|(stake, _)| (*stake))
6905 .unwrap_or(0)
6906 }
6907
6908 fn calculate_fee(
6909 &self,
6910 message: &impl SVMMessage,
6911 lamports_per_signature: u64,
6912 prioritization_fee: u64,
6913 feature_set: &FeatureSet,
6914 ) -> FeeDetails {
6915 solana_fee::calculate_fee_details(
6916 message,
6917 false, lamports_per_signature,
6919 prioritization_fee,
6920 FeeFeatures::from(feature_set),
6921 )
6922 }
6923}
6924
6925#[cfg(feature = "dev-context-only-utils")]
6926impl Bank {
6927 pub fn wrap_with_bank_forks_for_tests(self) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6928 let bank_forks = BankForks::new_rw_arc(self);
6929 let bank = bank_forks.read().unwrap().root_bank();
6930 (bank, bank_forks)
6931 }
6932
6933 pub fn default_for_tests() -> Self {
6934 let accounts_db = AccountsDb::default_for_tests();
6935 let accounts = Accounts::new(Arc::new(accounts_db));
6936 Self::default_with_accounts(accounts)
6937 }
6938
6939 pub fn new_with_bank_forks_for_tests(
6940 genesis_config: &GenesisConfig,
6941 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6942 let bank = Self::new_for_tests(genesis_config);
6943 bank.wrap_with_bank_forks_for_tests()
6944 }
6945
6946 pub fn new_for_tests(genesis_config: &GenesisConfig) -> Self {
6947 Self::new_with_config_for_tests(genesis_config, BankTestConfig::default())
6948 }
6949
6950 pub fn new_with_mockup_builtin_for_tests(
6951 genesis_config: &GenesisConfig,
6952 program_id: Pubkey,
6953 builtin_function: BuiltinFunctionWithContext,
6954 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6955 let mut bank = Self::new_for_tests(genesis_config);
6956 bank.add_mockup_builtin(program_id, builtin_function);
6957 bank.wrap_with_bank_forks_for_tests()
6958 }
6959
6960 pub fn new_no_wallclock_throttle_for_tests(
6961 genesis_config: &GenesisConfig,
6962 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6963 let mut bank = Self::new_for_tests(genesis_config);
6964
6965 bank.ns_per_slot = u128::MAX;
6966 bank.wrap_with_bank_forks_for_tests()
6967 }
6968
6969 pub fn new_with_config_for_tests(
6970 genesis_config: &GenesisConfig,
6971 test_config: BankTestConfig,
6972 ) -> Self {
6973 Self::new_with_paths_for_tests(
6974 genesis_config,
6975 Arc::new(RuntimeConfig::default()),
6976 test_config,
6977 Vec::new(),
6978 )
6979 }
6980
6981 pub fn new_with_paths_for_tests(
6982 genesis_config: &GenesisConfig,
6983 runtime_config: Arc<RuntimeConfig>,
6984 test_config: BankTestConfig,
6985 paths: Vec<PathBuf>,
6986 ) -> Self {
6987 Self::new_with_paths(
6988 genesis_config,
6989 runtime_config,
6990 paths,
6991 None,
6992 None,
6993 false,
6994 Some(test_config.accounts_db_config),
6995 None,
6996 Some(Pubkey::new_unique()),
6997 Arc::default(),
6998 None,
6999 None,
7000 )
7001 }
7002
7003 pub fn new_for_benches(genesis_config: &GenesisConfig) -> Self {
7004 Self::new_with_paths_for_benches(genesis_config, Vec::new())
7005 }
7006
7007 pub fn new_with_paths_for_benches(genesis_config: &GenesisConfig, paths: Vec<PathBuf>) -> Self {
7010 Self::new_with_paths(
7011 genesis_config,
7012 Arc::<RuntimeConfig>::default(),
7013 paths,
7014 None,
7015 None,
7016 false,
7017 Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
7018 None,
7019 Some(Pubkey::new_unique()),
7020 Arc::default(),
7021 None,
7022 None,
7023 )
7024 }
7025
7026 #[cfg(feature = "dev-context-only-utils")]
7028 pub fn prepare_batch_for_tests(
7029 &self,
7030 txs: Vec<Transaction>,
7031 ) -> TransactionBatch<RuntimeTransaction<SanitizedTransaction>> {
7032 let transaction_account_lock_limit = self.get_transaction_account_lock_limit();
7033 let sanitized_txs = txs
7034 .into_iter()
7035 .map(RuntimeTransaction::from_transaction_for_tests)
7036 .collect::<Vec<_>>();
7037 let lock_results = self
7038 .rc
7039 .accounts
7040 .lock_accounts(sanitized_txs.iter(), transaction_account_lock_limit);
7041 TransactionBatch::new(lock_results, self, OwnedOrBorrowed::Owned(sanitized_txs))
7042 }
7043
7044 pub fn set_accounts_data_size_initial_for_tests(&mut self, amount: u64) {
7047 self.accounts_data_size_initial = amount;
7048 }
7049
7050 pub fn update_accounts_data_size_delta_off_chain_for_tests(&self, amount: i64) {
7053 self.update_accounts_data_size_delta_off_chain(amount)
7054 }
7055
7056 #[cfg(test)]
7057 fn restore_old_behavior_for_fragile_tests(&self) {
7058 self.lazy_rent_collection.store(true, Relaxed);
7059 }
7060
7061 #[must_use]
7067 pub fn process_transactions<'a>(
7068 &self,
7069 txs: impl Iterator<Item = &'a Transaction>,
7070 ) -> Vec<Result<()>> {
7071 self.try_process_transactions(txs).unwrap()
7072 }
7073
7074 #[must_use]
7080 pub fn process_entry_transactions(&self, txs: Vec<VersionedTransaction>) -> Vec<Result<()>> {
7081 self.try_process_entry_transactions(txs).unwrap()
7082 }
7083
7084 #[cfg(test)]
7085 pub fn flush_accounts_cache_slot_for_tests(&self) {
7086 self.rc
7087 .accounts
7088 .accounts_db
7089 .flush_accounts_cache_slot_for_tests(self.slot())
7090 }
7091
7092 pub fn wait_for_initial_accounts_hash_verification_completed_for_tests(&self) {
7095 self.rc
7096 .accounts
7097 .accounts_db
7098 .verify_accounts_hash_in_bg
7099 .join_background_thread()
7100 }
7101
7102 pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
7103 self.transaction_processor.get_sysvar_cache_for_tests()
7104 }
7105
7106 pub fn update_accounts_hash_for_tests(&self) -> AccountsHash {
7107 self.update_accounts_hash(CalcAccountsHashDataSource::IndexForTests, false, false)
7108 }
7109
7110 pub fn new_program_cache_for_tx_batch_for_slot(&self, slot: Slot) -> ProgramCacheForTxBatch {
7111 ProgramCacheForTxBatch::new_from_cache(
7112 slot,
7113 self.epoch_schedule.get_epoch(slot),
7114 &self.transaction_processor.program_cache.read().unwrap(),
7115 )
7116 }
7117
7118 pub fn get_transaction_processor(&self) -> &TransactionBatchProcessor<BankForks> {
7119 &self.transaction_processor
7120 }
7121
7122 pub fn set_fee_structure(&mut self, fee_structure: &FeeStructure) {
7123 self.fee_structure = fee_structure.clone();
7124 }
7125
7126 pub fn load_program(
7127 &self,
7128 pubkey: &Pubkey,
7129 reload: bool,
7130 effective_epoch: Epoch,
7131 ) -> Option<Arc<ProgramCacheEntry>> {
7132 let environments = self
7133 .transaction_processor
7134 .get_environments_for_epoch(effective_epoch)?;
7135 load_program_with_pubkey(
7136 self,
7137 &environments,
7138 pubkey,
7139 self.slot(),
7140 &mut ExecuteTimings::default(), reload,
7142 )
7143 }
7144
7145 pub fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
7146 match self.get_account_with_fixed_root(pubkey) {
7147 Some(mut account) => {
7148 let min_balance = match get_system_account_kind(&account) {
7149 Some(SystemAccountKind::Nonce) => self
7150 .rent_collector
7151 .rent
7152 .minimum_balance(nonce::State::size()),
7153 _ => 0,
7154 };
7155
7156 lamports
7157 .checked_add(min_balance)
7158 .filter(|required_balance| *required_balance <= account.lamports())
7159 .ok_or(TransactionError::InsufficientFundsForFee)?;
7160 account
7161 .checked_sub_lamports(lamports)
7162 .map_err(|_| TransactionError::InsufficientFundsForFee)?;
7163 self.store_account(pubkey, &account);
7164
7165 Ok(())
7166 }
7167 None => Err(TransactionError::AccountNotFound),
7168 }
7169 }
7170
7171 pub fn set_hash_overrides(&self, hash_overrides: HashOverrides) {
7172 *self.hash_overrides.lock().unwrap() = hash_overrides;
7173 }
7174}
7175
7176fn calculate_data_size_delta(old_data_size: usize, new_data_size: usize) -> i64 {
7179 assert!(old_data_size <= i64::MAX as usize);
7180 assert!(new_data_size <= i64::MAX as usize);
7181 let old_data_size = old_data_size as i64;
7182 let new_data_size = new_data_size as i64;
7183
7184 new_data_size.saturating_sub(old_data_size)
7185}
7186
7187#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7190enum ApplyFeatureActivationsCaller {
7191 FinishInit,
7192 NewFromParent,
7193 WarpFromParent,
7194}
7195
7196#[derive(Debug, Default)]
7202struct CollectRentFromAccountsInfo {
7203 skipped_rewrites: Vec<(Pubkey, AccountHash)>,
7204 rent_collected_info: CollectedInfo,
7205 rent_rewards: Vec<(Pubkey, RewardInfo)>,
7206 time_collecting_rent_us: u64,
7207 time_storing_accounts_us: u64,
7208 num_accounts: usize,
7209}
7210
7211#[derive(Debug, Default)]
7214struct CollectRentInPartitionInfo {
7215 skipped_rewrites: Vec<(Pubkey, AccountHash)>,
7216 rent_collected: u64,
7217 accounts_data_size_reclaimed: u64,
7218 rent_rewards: Vec<(Pubkey, RewardInfo)>,
7219 time_loading_accounts_us: u64,
7220 time_collecting_rent_us: u64,
7221 time_storing_accounts_us: u64,
7222 num_accounts: usize,
7223}
7224
7225impl CollectRentInPartitionInfo {
7226 #[must_use]
7229 fn new(info: CollectRentFromAccountsInfo, time_loading_accounts: Duration) -> Self {
7230 Self {
7231 skipped_rewrites: info.skipped_rewrites,
7232 rent_collected: info.rent_collected_info.rent_amount,
7233 accounts_data_size_reclaimed: info.rent_collected_info.account_data_len_reclaimed,
7234 rent_rewards: info.rent_rewards,
7235 time_loading_accounts_us: time_loading_accounts.as_micros() as u64,
7236 time_collecting_rent_us: info.time_collecting_rent_us,
7237 time_storing_accounts_us: info.time_storing_accounts_us,
7238 num_accounts: info.num_accounts,
7239 }
7240 }
7241
7242 #[must_use]
7247 fn reduce(lhs: Self, rhs: Self) -> Self {
7248 Self {
7249 skipped_rewrites: [lhs.skipped_rewrites, rhs.skipped_rewrites].concat(),
7250 rent_collected: lhs.rent_collected.saturating_add(rhs.rent_collected),
7251 accounts_data_size_reclaimed: lhs
7252 .accounts_data_size_reclaimed
7253 .saturating_add(rhs.accounts_data_size_reclaimed),
7254 rent_rewards: [lhs.rent_rewards, rhs.rent_rewards].concat(),
7255 time_loading_accounts_us: lhs
7256 .time_loading_accounts_us
7257 .saturating_add(rhs.time_loading_accounts_us),
7258 time_collecting_rent_us: lhs
7259 .time_collecting_rent_us
7260 .saturating_add(rhs.time_collecting_rent_us),
7261 time_storing_accounts_us: lhs
7262 .time_storing_accounts_us
7263 .saturating_add(rhs.time_storing_accounts_us),
7264 num_accounts: lhs.num_accounts.saturating_add(rhs.num_accounts),
7265 }
7266 }
7267}
7268
7269#[derive(Debug, Default, Copy, Clone, Serialize)]
7271pub struct TotalAccountsStats {
7272 pub num_accounts: usize,
7274 pub data_len: usize,
7276
7277 pub num_executable_accounts: usize,
7279 pub executable_data_len: usize,
7281
7282 pub num_rent_exempt_accounts: usize,
7284 pub num_rent_paying_accounts: usize,
7286 pub num_rent_paying_accounts_without_data: usize,
7288 pub lamports_in_rent_paying_accounts: u64,
7290}
7291
7292impl TotalAccountsStats {
7293 pub fn accumulate_account(
7294 &mut self,
7295 address: &Pubkey,
7296 account: &AccountSharedData,
7297 rent_collector: &RentCollector,
7298 ) {
7299 let data_len = account.data().len();
7300 self.num_accounts += 1;
7301 self.data_len += data_len;
7302
7303 if account.executable() {
7304 self.num_executable_accounts += 1;
7305 self.executable_data_len += data_len;
7306 }
7307
7308 if !rent_collector.should_collect_rent(address, account.executable())
7309 || rent_collector
7310 .get_rent_due(
7311 account.lamports(),
7312 account.data().len(),
7313 account.rent_epoch(),
7314 )
7315 .is_exempt()
7316 {
7317 self.num_rent_exempt_accounts += 1;
7318 } else {
7319 self.num_rent_paying_accounts += 1;
7320 self.lamports_in_rent_paying_accounts += account.lamports();
7321 if data_len == 0 {
7322 self.num_rent_paying_accounts_without_data += 1;
7323 }
7324 }
7325 }
7326}
7327
7328impl Drop for Bank {
7329 fn drop(&mut self) {
7330 if let Some(drop_callback) = self.drop_callback.read().unwrap().0.as_ref() {
7331 drop_callback.callback(self);
7332 } else {
7333 self.rc
7335 .accounts
7336 .accounts_db
7337 .purge_slot(self.slot(), self.bank_id(), false);
7338 }
7339 }
7340}
7341
7342pub mod test_utils {
7344 use {
7345 super::Bank,
7346 crate::installed_scheduler_pool::BankWithScheduler,
7347 solana_sdk::{
7348 account::{ReadableAccount, WritableAccount},
7349 hash::hashv,
7350 lamports::LamportsError,
7351 pubkey::Pubkey,
7352 },
7353 solana_vote_program::vote_state::{self, BlockTimestamp, VoteStateVersions},
7354 std::sync::Arc,
7355 };
7356 pub fn goto_end_of_slot(bank: Arc<Bank>) {
7357 goto_end_of_slot_with_scheduler(&BankWithScheduler::new_without_scheduler(bank))
7358 }
7359
7360 pub fn goto_end_of_slot_with_scheduler(bank: &BankWithScheduler) {
7361 let mut tick_hash = bank.last_blockhash();
7362 loop {
7363 tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
7364 bank.register_tick(&tick_hash);
7365 if tick_hash == bank.last_blockhash() {
7366 bank.freeze();
7367 return;
7368 }
7369 }
7370 }
7371
7372 pub fn update_vote_account_timestamp(
7373 timestamp: BlockTimestamp,
7374 bank: &Bank,
7375 vote_pubkey: &Pubkey,
7376 ) {
7377 let mut vote_account = bank.get_account(vote_pubkey).unwrap_or_default();
7378 let mut vote_state = vote_state::from(&vote_account).unwrap_or_default();
7379 vote_state.last_timestamp = timestamp;
7380 let versioned = VoteStateVersions::new_current(vote_state);
7381 vote_state::to(&versioned, &mut vote_account).unwrap();
7382 bank.store_account(vote_pubkey, &vote_account);
7383 }
7384
7385 pub fn deposit(
7386 bank: &Bank,
7387 pubkey: &Pubkey,
7388 lamports: u64,
7389 ) -> std::result::Result<u64, LamportsError> {
7390 let mut account = bank
7393 .get_account_with_fixed_root_no_cache(pubkey)
7394 .unwrap_or_default();
7395 account.checked_add_lamports(lamports)?;
7396 bank.store_account(pubkey, &account);
7397 Ok(account.lamports())
7398 }
7399}