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 !self
4873 .feature_set
4874 .is_active(&feature_set::remove_accounts_delta_hash::id())
4875 {
4876 self.rc.accounts.accounts_db.start_background_hasher();
4877 }
4878
4879 if !debug_do_not_add_builtins {
4880 for builtin in BUILTINS
4881 .iter()
4882 .chain(additional_builtins.unwrap_or(&[]).iter())
4883 {
4884 let builtin_is_bpf = |program_id: &Pubkey| {
4890 self.get_account(program_id)
4891 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
4892 .unwrap_or(false)
4893 };
4894 if builtin.enable_feature_id.is_none() && !builtin_is_bpf(&builtin.program_id) {
4895 self.transaction_processor.add_builtin(
4896 self,
4897 builtin.program_id,
4898 builtin.name,
4899 ProgramCacheEntry::new_builtin(0, builtin.name.len(), builtin.entrypoint),
4900 );
4901 }
4902 }
4903 for precompile in get_precompiles() {
4904 if precompile.feature.is_none() {
4905 self.add_precompile(&precompile.program_id);
4906 }
4907 }
4908 }
4909
4910 self.transaction_processor
4911 .configure_program_runtime_environments(
4912 Some(Arc::new(
4913 create_program_runtime_environment_v1(
4914 &self.feature_set,
4915 &self.compute_budget().unwrap_or_default(),
4916 false, false, )
4919 .unwrap(),
4920 )),
4921 Some(Arc::new(create_program_runtime_environment_v2(
4922 &self.compute_budget().unwrap_or_default(),
4923 false, ))),
4925 );
4926 }
4927
4928 pub fn set_inflation(&self, inflation: Inflation) {
4929 *self.inflation.write().unwrap() = inflation;
4930 }
4931
4932 pub fn hard_forks(&self) -> HardForks {
4934 self.hard_forks.read().unwrap().clone()
4935 }
4936
4937 pub fn register_hard_fork(&self, new_hard_fork_slot: Slot) {
4938 let bank_slot = self.slot();
4939
4940 let lock = self.freeze_lock();
4941 let bank_frozen = *lock != Hash::default();
4942 if new_hard_fork_slot < bank_slot {
4943 warn!(
4944 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is older \
4945 than the bank at slot {bank_slot} that attempted to register it."
4946 );
4947 } else if (new_hard_fork_slot == bank_slot) && bank_frozen {
4948 warn!(
4949 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is the same \
4950 slot as the bank at slot {bank_slot} that attempted to register it, but that \
4951 bank is already frozen."
4952 );
4953 } else {
4954 self.hard_forks
4955 .write()
4956 .unwrap()
4957 .register(new_hard_fork_slot);
4958 }
4959 }
4960
4961 pub fn get_account_with_fixed_root_no_cache(
4962 &self,
4963 pubkey: &Pubkey,
4964 ) -> Option<AccountSharedData> {
4965 self.load_account_with(pubkey, |_| false)
4966 .map(|(acc, _slot)| acc)
4967 }
4968
4969 fn load_account_with(
4970 &self,
4971 pubkey: &Pubkey,
4972 callback: impl for<'local> Fn(&'local AccountSharedData) -> bool,
4973 ) -> Option<(AccountSharedData, Slot)> {
4974 self.rc
4975 .accounts
4976 .accounts_db
4977 .load_account_with(&self.ancestors, pubkey, callback)
4978 }
4979
4980 pub fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
4984 self.get_account_modified_slot(pubkey)
4985 .map(|(acc, _slot)| acc)
4986 }
4987
4988 pub fn get_account_with_fixed_root(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
4995 self.get_account_modified_slot_with_fixed_root(pubkey)
4996 .map(|(acc, _slot)| acc)
4997 }
4998
4999 pub fn get_account_modified_slot_with_fixed_root(
5001 &self,
5002 pubkey: &Pubkey,
5003 ) -> Option<(AccountSharedData, Slot)> {
5004 self.load_slow_with_fixed_root(&self.ancestors, pubkey)
5005 }
5006
5007 pub fn get_account_modified_slot(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
5008 self.load_slow(&self.ancestors, pubkey)
5009 }
5010
5011 fn load_slow(
5012 &self,
5013 ancestors: &Ancestors,
5014 pubkey: &Pubkey,
5015 ) -> Option<(AccountSharedData, Slot)> {
5016 self.rc.accounts.load_without_fixed_root(ancestors, pubkey)
5020 }
5021
5022 fn load_slow_with_fixed_root(
5023 &self,
5024 ancestors: &Ancestors,
5025 pubkey: &Pubkey,
5026 ) -> Option<(AccountSharedData, Slot)> {
5027 self.rc.accounts.load_with_fixed_root(ancestors, pubkey)
5028 }
5029
5030 pub fn get_program_accounts(
5031 &self,
5032 program_id: &Pubkey,
5033 config: &ScanConfig,
5034 ) -> ScanResult<Vec<TransactionAccount>> {
5035 self.rc
5036 .accounts
5037 .load_by_program(&self.ancestors, self.bank_id, program_id, config)
5038 }
5039
5040 pub fn get_filtered_program_accounts<F: Fn(&AccountSharedData) -> bool>(
5041 &self,
5042 program_id: &Pubkey,
5043 filter: F,
5044 config: &ScanConfig,
5045 ) -> ScanResult<Vec<TransactionAccount>> {
5046 self.rc.accounts.load_by_program_with_filter(
5047 &self.ancestors,
5048 self.bank_id,
5049 program_id,
5050 filter,
5051 config,
5052 )
5053 }
5054
5055 pub fn get_filtered_indexed_accounts<F: Fn(&AccountSharedData) -> bool>(
5056 &self,
5057 index_key: &IndexKey,
5058 filter: F,
5059 config: &ScanConfig,
5060 byte_limit_for_scan: Option<usize>,
5061 ) -> ScanResult<Vec<TransactionAccount>> {
5062 self.rc.accounts.load_by_index_key_with_filter(
5063 &self.ancestors,
5064 self.bank_id,
5065 index_key,
5066 filter,
5067 config,
5068 byte_limit_for_scan,
5069 )
5070 }
5071
5072 pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
5073 self.rc.accounts.account_indexes_include_key(key)
5074 }
5075
5076 pub fn get_all_accounts(&self, sort_results: bool) -> ScanResult<Vec<PubkeyAccountSlot>> {
5078 self.rc
5079 .accounts
5080 .load_all(&self.ancestors, self.bank_id, sort_results)
5081 }
5082
5083 pub fn scan_all_accounts<F>(&self, scan_func: F, sort_results: bool) -> ScanResult<()>
5085 where
5086 F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>),
5087 {
5088 self.rc
5089 .accounts
5090 .scan_all(&self.ancestors, self.bank_id, scan_func, sort_results)
5091 }
5092
5093 pub fn get_program_accounts_modified_since_parent(
5094 &self,
5095 program_id: &Pubkey,
5096 ) -> Vec<TransactionAccount> {
5097 self.rc
5098 .accounts
5099 .load_by_program_slot(self.slot(), Some(program_id))
5100 }
5101
5102 pub fn get_transaction_logs(
5103 &self,
5104 address: Option<&Pubkey>,
5105 ) -> Option<Vec<TransactionLogInfo>> {
5106 self.transaction_log_collector
5107 .read()
5108 .unwrap()
5109 .get_logs_for_address(address)
5110 }
5111
5112 pub fn get_all_accounts_modified_since_parent(&self) -> Vec<TransactionAccount> {
5114 self.rc.accounts.load_by_program_slot(self.slot(), None)
5115 }
5116
5117 fn get_account_modified_since_parent_with_fixed_root(
5119 &self,
5120 pubkey: &Pubkey,
5121 ) -> Option<(AccountSharedData, Slot)> {
5122 let just_self: Ancestors = Ancestors::from(vec![self.slot()]);
5123 if let Some((account, slot)) = self.load_slow_with_fixed_root(&just_self, pubkey) {
5124 if slot == self.slot() {
5125 return Some((account, slot));
5126 }
5127 }
5128 None
5129 }
5130
5131 pub fn get_largest_accounts(
5132 &self,
5133 num: usize,
5134 filter_by_address: &HashSet<Pubkey>,
5135 filter: AccountAddressFilter,
5136 sort_results: bool,
5137 ) -> ScanResult<Vec<(Pubkey, u64)>> {
5138 self.rc.accounts.load_largest_accounts(
5139 &self.ancestors,
5140 self.bank_id,
5141 num,
5142 filter_by_address,
5143 filter,
5144 sort_results,
5145 )
5146 }
5147
5148 pub fn transaction_count(&self) -> u64 {
5150 self.transaction_count.load(Relaxed)
5151 }
5152
5153 pub fn non_vote_transaction_count_since_restart(&self) -> u64 {
5158 self.non_vote_transaction_count_since_restart.load(Relaxed)
5159 }
5160
5161 pub fn executed_transaction_count(&self) -> u64 {
5163 self.transaction_count()
5164 .saturating_sub(self.parent().map_or(0, |parent| parent.transaction_count()))
5165 }
5166
5167 pub fn transaction_error_count(&self) -> u64 {
5168 self.transaction_error_count.load(Relaxed)
5169 }
5170
5171 pub fn transaction_entries_count(&self) -> u64 {
5172 self.transaction_entries_count.load(Relaxed)
5173 }
5174
5175 pub fn transactions_per_entry_max(&self) -> u64 {
5176 self.transactions_per_entry_max.load(Relaxed)
5177 }
5178
5179 fn increment_transaction_count(&self, tx_count: u64) {
5180 self.transaction_count.fetch_add(tx_count, Relaxed);
5181 }
5182
5183 fn increment_non_vote_transaction_count_since_restart(&self, tx_count: u64) {
5184 self.non_vote_transaction_count_since_restart
5185 .fetch_add(tx_count, Relaxed);
5186 }
5187
5188 pub fn signature_count(&self) -> u64 {
5189 self.signature_count.load(Relaxed)
5190 }
5191
5192 fn increment_signature_count(&self, signature_count: u64) {
5193 self.signature_count.fetch_add(signature_count, Relaxed);
5194 }
5195
5196 pub fn get_signature_status_processed_since_parent(
5197 &self,
5198 signature: &Signature,
5199 ) -> Option<Result<()>> {
5200 if let Some((slot, status)) = self.get_signature_status_slot(signature) {
5201 if slot <= self.slot() {
5202 return Some(status);
5203 }
5204 }
5205 None
5206 }
5207
5208 pub fn get_signature_status_with_blockhash(
5209 &self,
5210 signature: &Signature,
5211 blockhash: &Hash,
5212 ) -> Option<Result<()>> {
5213 let rcache = self.status_cache.read().unwrap();
5214 rcache
5215 .get_status(signature, blockhash, &self.ancestors)
5216 .map(|v| v.1)
5217 }
5218
5219 pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
5220 let rcache = self.status_cache.read().unwrap();
5221 rcache.get_status_any_blockhash(signature, &self.ancestors)
5222 }
5223
5224 pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
5225 self.get_signature_status_slot(signature).map(|v| v.1)
5226 }
5227
5228 pub fn has_signature(&self, signature: &Signature) -> bool {
5229 self.get_signature_status_slot(signature).is_some()
5230 }
5231
5232 fn hash_internal_state(&self) -> Hash {
5235 let measure_total = Measure::start("");
5236 let slot = self.slot();
5237
5238 let delta_hash_info = (!self
5239 .feature_set
5240 .is_active(&feature_set::remove_accounts_delta_hash::id()))
5241 .then(|| {
5242 measure_us!({
5243 self.rc
5244 .accounts
5245 .accounts_db
5246 .calculate_accounts_delta_hash_internal(
5247 slot,
5248 None,
5249 self.skipped_rewrites.lock().unwrap().clone(),
5250 )
5251 })
5252 });
5253
5254 let mut hash = if let Some((accounts_delta_hash, _measure)) = delta_hash_info.as_ref() {
5255 hashv(&[
5256 self.parent_hash.as_ref(),
5257 accounts_delta_hash.0.as_ref(),
5258 &self.signature_count().to_le_bytes(),
5259 self.last_blockhash().as_ref(),
5260 ])
5261 } else {
5262 hashv(&[
5263 self.parent_hash.as_ref(),
5264 &self.signature_count().to_le_bytes(),
5265 self.last_blockhash().as_ref(),
5266 ])
5267 };
5268
5269 let accounts_hash_info = if self
5270 .feature_set
5271 .is_active(&feature_set::accounts_lt_hash::id())
5272 {
5273 let accounts_lt_hash = &*self.accounts_lt_hash.lock().unwrap();
5274 let lt_hash_bytes = bytemuck::must_cast_slice(&accounts_lt_hash.0 .0);
5275 hash = hashv(&[hash.as_ref(), lt_hash_bytes]);
5276 let checksum = accounts_lt_hash.0.checksum();
5277 Some(format!(", accounts_lt_hash checksum: {checksum}"))
5278 } else {
5279 let epoch_accounts_hash = self.wait_get_epoch_accounts_hash();
5280 epoch_accounts_hash.map(|epoch_accounts_hash| {
5281 hash = hashv(&[hash.as_ref(), epoch_accounts_hash.as_ref().as_ref()]);
5282 format!(", epoch_accounts_hash: {:?}", epoch_accounts_hash.as_ref())
5283 })
5284 };
5285
5286 let buf = self
5287 .hard_forks
5288 .read()
5289 .unwrap()
5290 .get_hash_data(slot, self.parent_slot());
5291 if let Some(buf) = buf {
5292 let hard_forked_hash = extend_and_hash(&hash, &buf);
5293 warn!("hard fork at slot {slot} by hashing {buf:?}: {hash} => {hard_forked_hash}");
5294 hash = hard_forked_hash;
5295 }
5296
5297 #[cfg(feature = "dev-context-only-utils")]
5298 let hash_override = self
5299 .hash_overrides
5300 .lock()
5301 .unwrap()
5302 .get_bank_hash_override(slot)
5303 .copied()
5304 .inspect(|&hash_override| {
5305 if hash_override != hash {
5306 info!(
5307 "bank: slot: {}: overrode bank hash: {} with {}",
5308 self.slot(),
5309 hash,
5310 hash_override
5311 );
5312 }
5313 });
5314 #[cfg(feature = "dev-context-only-utils")]
5318 let hash = hash_override.unwrap_or(std::hint::black_box(hash));
5319
5320 let bank_hash_stats = self.bank_hash_stats.load();
5321
5322 let total_us = measure_total.end_as_us();
5323
5324 let (accounts_delta_hash_us, accounts_delta_hash_log) = delta_hash_info
5325 .map(|(hash, us)| (us, format!(" accounts_delta: {}", hash.0)))
5326 .unzip();
5327 datapoint_info!(
5328 "bank-hash_internal_state",
5329 ("slot", slot, i64),
5330 ("total_us", total_us, i64),
5331 ("accounts_delta_hash_us", accounts_delta_hash_us, Option<i64>),
5332 );
5333 info!(
5334 "bank frozen: {slot} hash: {hash}{} signature_count: {} last_blockhash: {} capitalization: {}{}, stats: {bank_hash_stats:?}",
5335 accounts_delta_hash_log.unwrap_or_default(),
5336 self.signature_count(),
5337 self.last_blockhash(),
5338 self.capitalization(),
5339 accounts_hash_info.unwrap_or_default(),
5340 );
5341 hash
5342 }
5343
5344 pub fn collector_fees(&self) -> u64 {
5345 self.collector_fees.load(Relaxed)
5346 }
5347
5348 fn should_include_epoch_accounts_hash(&self) -> bool {
5351 if !epoch_accounts_hash_utils::is_enabled_this_epoch(self) {
5352 return false;
5353 }
5354
5355 let stop_slot = epoch_accounts_hash_utils::calculation_stop(self);
5356 self.parent_slot() < stop_slot && self.slot() >= stop_slot
5357 }
5358
5359 fn wait_get_epoch_accounts_hash(&self) -> Option<EpochAccountsHash> {
5362 if !self.should_include_epoch_accounts_hash() {
5363 return None;
5364 }
5365
5366 let (epoch_accounts_hash, waiting_time_us) = measure_us!(self
5367 .rc
5368 .accounts
5369 .accounts_db
5370 .epoch_accounts_hash_manager
5371 .wait_get_epoch_accounts_hash());
5372
5373 datapoint_info!(
5374 "bank-wait_get_epoch_accounts_hash",
5375 ("slot", self.slot(), i64),
5376 ("waiting-time-us", waiting_time_us, i64),
5377 );
5378 Some(epoch_accounts_hash)
5379 }
5380
5381 pub fn run_final_hash_calc(&self, on_halt_store_hash_raw_data_for_debug: bool) {
5384 self.force_flush_accounts_cache();
5385 _ = self.verify_accounts_hash(
5387 None,
5388 VerifyAccountsHashConfig {
5389 test_hash_calculation: false,
5390 ignore_mismatch: true,
5391 require_rooted_bank: false,
5392 run_in_background: false,
5393 store_hash_raw_data_for_debug: on_halt_store_hash_raw_data_for_debug,
5394 },
5395 None,
5396 );
5397 }
5398
5399 #[must_use]
5403 fn verify_accounts_hash(
5404 &self,
5405 base: Option<(Slot, u64)>,
5406 mut config: VerifyAccountsHashConfig,
5407 duplicates_lt_hash: Option<Box<DuplicatesLtHash>>,
5408 ) -> bool {
5409 #[derive(Debug, Eq, PartialEq)]
5410 enum VerifyKind {
5411 Merkle,
5412 Lattice,
5413 }
5414
5415 let accounts = &self.rc.accounts;
5416 accounts
5419 .accounts_db
5420 .verify_accounts_hash_in_bg
5421 .join_background_thread();
5422
5423 let slot = self.slot();
5424
5425 let verify_kind = match (
5426 duplicates_lt_hash.is_some(),
5427 self.rc
5428 .accounts
5429 .accounts_db
5430 .is_experimental_accumulator_hash_enabled(),
5431 ) {
5432 (true, _) => VerifyKind::Lattice,
5433 (false, false) => VerifyKind::Merkle,
5434 (false, true) => {
5435 config.run_in_background = false;
5439 VerifyKind::Lattice
5440 }
5441 };
5442
5443 if config.require_rooted_bank && !accounts.accounts_db.accounts_index.is_alive_root(slot) {
5444 if let Some(parent) = self.parent() {
5445 info!(
5446 "slot {slot} is not a root, so verify accounts hash on parent bank at slot {}",
5447 parent.slot(),
5448 );
5449 if verify_kind == VerifyKind::Lattice {
5450 config.run_in_background = false;
5454 }
5455 return parent.verify_accounts_hash(base, config, None);
5456 } else {
5457 panic!("cannot verify accounts hash because slot {slot} is not a root");
5460 }
5461 }
5462
5463 let snapshot_storages = self.rc.accounts.accounts_db.get_storages(RangeFull);
5467 let capitalization = self.capitalization();
5468 let verify_config = VerifyAccountsHashAndLamportsConfig {
5469 ancestors: &self.ancestors,
5470 epoch_schedule: self.epoch_schedule(),
5471 rent_collector: self.rent_collector(),
5472 test_hash_calculation: config.test_hash_calculation,
5473 ignore_mismatch: config.ignore_mismatch,
5474 store_detailed_debug_info: config.store_hash_raw_data_for_debug,
5475 use_bg_thread_pool: config.run_in_background,
5476 };
5477
5478 info!(
5479 "Verifying accounts, in background? {}, verify kind: {verify_kind:?}",
5480 config.run_in_background,
5481 );
5482 if config.run_in_background {
5483 let accounts = Arc::clone(accounts);
5484 let accounts_ = Arc::clone(&accounts);
5485 let ancestors = self.ancestors.clone();
5486 let epoch_schedule = self.epoch_schedule().clone();
5487 let rent_collector = self.rent_collector().clone();
5488 let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5489 accounts.accounts_db.verify_accounts_hash_in_bg.start(|| {
5490 Builder::new()
5491 .name("solBgHashVerify".into())
5492 .spawn(move || {
5493 info!("Initial background accounts hash verification has started");
5494 let start = Instant::now();
5495 let mut lattice_verify_time = None;
5496 let mut merkle_verify_time = None;
5497 let is_ok = match verify_kind {
5498 VerifyKind::Lattice => {
5499 let accounts_db = &accounts_.accounts_db;
5501 let (calculated_accounts_lt_hash, duration) =
5502 meas_dur!(accounts_db.thread_pool_hash.install(|| {
5503 accounts_db
5504 .calculate_accounts_lt_hash_at_startup_from_storages(
5505 snapshot_storages.0.as_slice(),
5506 &duplicates_lt_hash.unwrap(),
5507 )
5508 }));
5509 let is_ok =
5510 calculated_accounts_lt_hash == expected_accounts_lt_hash;
5511 if !is_ok {
5512 let expected = expected_accounts_lt_hash.0.checksum();
5513 let calculated = calculated_accounts_lt_hash.0.checksum();
5514 error!(
5515 "Verifying accounts failed: accounts lattice hashes do not \
5516 match, expected: {expected}, calculated: {calculated}",
5517 );
5518 }
5519 lattice_verify_time = Some(duration);
5520 is_ok
5521 }
5522 VerifyKind::Merkle => {
5523 let snapshot_storages_and_slots = (
5525 snapshot_storages.0.as_slice(),
5526 snapshot_storages.1.as_slice(),
5527 );
5528 let (is_ok, duration) = meas_dur!(accounts_
5529 .verify_accounts_hash_and_lamports(
5530 snapshot_storages_and_slots,
5531 slot,
5532 capitalization,
5533 base,
5534 VerifyAccountsHashAndLamportsConfig {
5535 ancestors: &ancestors,
5536 epoch_schedule: &epoch_schedule,
5537 rent_collector: &rent_collector,
5538 ..verify_config
5539 },
5540 ));
5541 merkle_verify_time = Some(duration);
5542 is_ok
5543 }
5544 };
5545 accounts_
5546 .accounts_db
5547 .verify_accounts_hash_in_bg
5548 .background_finished();
5549 let total_time = start.elapsed();
5550 datapoint_info!(
5551 "startup_verify_accounts",
5552 ("total_us", total_time.as_micros(), i64),
5553 (
5554 "verify_accounts_lt_hash_us",
5555 lattice_verify_time.as_ref().map(Duration::as_micros),
5556 Option<i64>
5557 ),
5558 ("verify_accounts_hash_us",
5559 merkle_verify_time.as_ref().map(Duration::as_micros),
5560 Option<i64>
5561 ),
5562 );
5563 info!("Initial background accounts hash verification has stopped");
5564 is_ok
5565 })
5566 .unwrap()
5567 });
5568 true } else {
5570 match verify_kind {
5571 VerifyKind::Lattice => {
5572 let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5573 let calculated_accounts_lt_hash = if let Some(duplicates_lt_hash) =
5574 duplicates_lt_hash
5575 {
5576 accounts
5577 .accounts_db
5578 .calculate_accounts_lt_hash_at_startup_from_storages(
5579 snapshot_storages.0.as_slice(),
5580 &duplicates_lt_hash,
5581 )
5582 } else {
5583 accounts
5584 .accounts_db
5585 .calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors, slot)
5586 };
5587 let is_ok = calculated_accounts_lt_hash == expected_accounts_lt_hash;
5588 if !is_ok {
5589 let expected = expected_accounts_lt_hash.0.checksum();
5590 let calculated = calculated_accounts_lt_hash.0.checksum();
5591 error!(
5592 "Verifying accounts failed: accounts lattice hashes do not \
5593 match, expected: {expected}, calculated: {calculated}",
5594 );
5595 }
5596 is_ok
5597 }
5598 VerifyKind::Merkle => {
5599 let snapshot_storages_and_slots = (
5600 snapshot_storages.0.as_slice(),
5601 snapshot_storages.1.as_slice(),
5602 );
5603 let is_ok = accounts.verify_accounts_hash_and_lamports(
5604 snapshot_storages_and_slots,
5605 slot,
5606 capitalization,
5607 base,
5608 verify_config,
5609 );
5610 self.set_initial_accounts_hash_verification_completed();
5611 is_ok
5612 }
5613 }
5614 }
5615 }
5616
5617 pub fn set_initial_accounts_hash_verification_completed(&self) {
5621 self.rc
5622 .accounts
5623 .accounts_db
5624 .verify_accounts_hash_in_bg
5625 .verification_complete();
5626 }
5627
5628 pub fn has_initial_accounts_hash_verification_completed(&self) -> bool {
5632 self.rc
5633 .accounts
5634 .accounts_db
5635 .verify_accounts_hash_in_bg
5636 .check_complete()
5637 }
5638
5639 pub fn get_snapshot_storages(&self, base_slot: Option<Slot>) -> Vec<Arc<AccountStorageEntry>> {
5643 let start_slot = base_slot.map_or(0, |slot| slot.saturating_add(1));
5645 let requested_slots = start_slot..=self.slot();
5647
5648 self.rc.accounts.accounts_db.get_storages(requested_slots).0
5649 }
5650
5651 #[must_use]
5652 fn verify_hash(&self) -> bool {
5653 assert!(self.is_frozen());
5654 let calculated_hash = self.hash_internal_state();
5655 let expected_hash = self.hash();
5656
5657 if calculated_hash == expected_hash {
5658 true
5659 } else {
5660 warn!(
5661 "verify failed: slot: {}, {} (calculated) != {} (expected)",
5662 self.slot(),
5663 calculated_hash,
5664 expected_hash
5665 );
5666 false
5667 }
5668 }
5669
5670 pub fn verify_transaction(
5671 &self,
5672 tx: VersionedTransaction,
5673 verification_mode: TransactionVerificationMode,
5674 ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5675 let sanitized_tx = {
5676 let size =
5677 bincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?;
5678 if size > PACKET_DATA_SIZE as u64 {
5679 return Err(TransactionError::SanitizeFailure);
5680 }
5681 let message_hash = if verification_mode == TransactionVerificationMode::FullVerification
5682 {
5683 tx.verify_and_hash_message()?
5684 } else {
5685 tx.message.hash()
5686 };
5687
5688 RuntimeTransaction::try_create(
5689 tx,
5690 MessageHash::Precomputed(message_hash),
5691 None,
5692 self,
5693 self.get_reserved_account_keys(),
5694 )
5695 }?;
5696
5697 let move_precompile_verification_to_svm = self
5698 .feature_set
5699 .is_active(&feature_set::move_precompile_verification_to_svm::id());
5700 if !move_precompile_verification_to_svm && {
5701 verification_mode == TransactionVerificationMode::HashAndVerifyPrecompiles
5702 || verification_mode == TransactionVerificationMode::FullVerification
5703 } {
5704 verify_precompiles(&sanitized_tx, &self.feature_set)?;
5705 }
5706
5707 Ok(sanitized_tx)
5708 }
5709
5710 pub fn fully_verify_transaction(
5711 &self,
5712 tx: VersionedTransaction,
5713 ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5714 self.verify_transaction(tx, TransactionVerificationMode::FullVerification)
5715 }
5716
5717 pub fn check_reserved_keys(&self, tx: &impl SVMMessage) -> Result<()> {
5721 let reserved_keys = self.get_reserved_account_keys();
5724 for (index, key) in tx.account_keys().iter().enumerate() {
5725 if tx.is_writable(index) && reserved_keys.contains(key) {
5726 return Err(TransactionError::ResanitizationNeeded);
5727 }
5728 }
5729
5730 Ok(())
5731 }
5732
5733 fn calculate_capitalization(&self, debug_verify: bool) -> u64 {
5735 let is_startup = true;
5736 self.rc
5737 .accounts
5738 .accounts_db
5739 .verify_accounts_hash_in_bg
5740 .join_background_thread();
5741 self.rc
5742 .accounts
5743 .accounts_db
5744 .update_accounts_hash_with_verify_from(
5745 CalcAccountsHashDataSource::IndexForTests,
5747 debug_verify,
5748 self.slot(),
5749 &self.ancestors,
5750 None,
5751 self.epoch_schedule(),
5752 &self.rent_collector,
5753 is_startup,
5754 )
5755 .1
5756 }
5757
5758 pub fn calculate_and_verify_capitalization(&self, debug_verify: bool) -> bool {
5760 let calculated = self.calculate_capitalization(debug_verify);
5761 let expected = self.capitalization();
5762 if calculated == expected {
5763 true
5764 } else {
5765 warn!(
5766 "Capitalization mismatch: calculated: {} != expected: {}",
5767 calculated, expected
5768 );
5769 false
5770 }
5771 }
5772
5773 pub fn set_capitalization(&self) -> u64 {
5776 let old = self.capitalization();
5777 let debug_verify = false;
5781 self.capitalization
5782 .store(self.calculate_capitalization(debug_verify), Relaxed);
5783 old
5784 }
5785
5786 pub fn get_accounts_hash(&self) -> Option<AccountsHash> {
5791 self.rc
5792 .accounts
5793 .accounts_db
5794 .get_accounts_hash(self.slot())
5795 .map(|(accounts_hash, _)| accounts_hash)
5796 }
5797
5798 pub fn get_incremental_accounts_hash(&self) -> Option<IncrementalAccountsHash> {
5803 self.rc
5804 .accounts
5805 .accounts_db
5806 .get_incremental_accounts_hash(self.slot())
5807 .map(|(incremental_accounts_hash, _)| incremental_accounts_hash)
5808 }
5809
5810 pub fn get_snapshot_hash(&self) -> SnapshotHash {
5820 if self.is_snapshots_lt_hash_enabled() {
5821 self.get_lattice_snapshot_hash()
5822 } else {
5823 self.get_merkle_snapshot_hash()
5824 }
5825 }
5826
5827 pub fn get_merkle_snapshot_hash(&self) -> SnapshotHash {
5837 let accounts_hash = self.get_accounts_hash();
5838 let incremental_accounts_hash = self.get_incremental_accounts_hash();
5839 let accounts_hash_kind = match (accounts_hash, incremental_accounts_hash) {
5840 (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()),
5841 (Some(accounts_hash), None) => accounts_hash.into(),
5842 (None, Some(incremental_accounts_hash)) => incremental_accounts_hash.into(),
5843 (None, None) => panic!("accounts hash is required to get snapshot hash"),
5844 };
5845 let epoch_accounts_hash = self.get_epoch_accounts_hash_to_serialize();
5846 SnapshotHash::new(
5847 &MerkleOrLatticeAccountsHash::Merkle(accounts_hash_kind),
5848 epoch_accounts_hash.as_ref(),
5849 None,
5850 )
5851 }
5852
5853 pub fn get_lattice_snapshot_hash(&self) -> SnapshotHash {
5857 SnapshotHash::new(
5858 &MerkleOrLatticeAccountsHash::Lattice,
5859 None,
5860 Some(self.accounts_lt_hash.lock().unwrap().0.checksum()),
5861 )
5862 }
5863
5864 pub fn load_account_into_read_cache(&self, key: &Pubkey) {
5865 self.rc
5866 .accounts
5867 .accounts_db
5868 .load_account_into_read_cache(&self.ancestors, key);
5869 }
5870
5871 pub fn update_accounts_hash(
5872 &self,
5873 data_source: CalcAccountsHashDataSource,
5874 mut debug_verify: bool,
5875 is_startup: bool,
5876 ) -> AccountsHash {
5877 let (accounts_hash, total_lamports) = self
5878 .rc
5879 .accounts
5880 .accounts_db
5881 .update_accounts_hash_with_verify_from(
5882 data_source,
5883 debug_verify,
5884 self.slot(),
5885 &self.ancestors,
5886 Some(self.capitalization()),
5887 self.epoch_schedule(),
5888 &self.rent_collector,
5889 is_startup,
5890 );
5891 if total_lamports != self.capitalization() {
5892 datapoint_info!(
5893 "capitalization_mismatch",
5894 ("slot", self.slot(), i64),
5895 ("calculated_lamports", total_lamports, i64),
5896 ("capitalization", self.capitalization(), i64),
5897 );
5898
5899 if !debug_verify {
5900 debug_verify = true;
5903 self.rc
5904 .accounts
5905 .accounts_db
5906 .update_accounts_hash_with_verify_from(
5907 data_source,
5908 debug_verify,
5909 self.slot(),
5910 &self.ancestors,
5911 Some(self.capitalization()),
5912 self.epoch_schedule(),
5913 &self.rent_collector,
5914 is_startup,
5915 );
5916 }
5917
5918 panic!(
5919 "capitalization_mismatch. slot: {}, calculated_lamports: {}, capitalization: {}",
5920 self.slot(),
5921 total_lamports,
5922 self.capitalization()
5923 );
5924 }
5925 accounts_hash
5926 }
5927
5928 pub fn update_incremental_accounts_hash(&self, base_slot: Slot) -> IncrementalAccountsHash {
5930 let config = CalcAccountsHashConfig {
5931 use_bg_thread_pool: true,
5932 ancestors: None, epoch_schedule: &self.epoch_schedule,
5934 rent_collector: &self.rent_collector,
5935 store_detailed_debug_info_on_failure: false,
5936 };
5937 let storages = self.get_snapshot_storages(Some(base_slot));
5938 let sorted_storages = SortedStorages::new(&storages);
5939 self.rc
5940 .accounts
5941 .accounts_db
5942 .update_incremental_accounts_hash(
5943 &config,
5944 &sorted_storages,
5945 self.slot(),
5946 HashStats::default(),
5947 )
5948 .0
5949 }
5950
5951 pub fn verify_snapshot_bank(
5954 &self,
5955 test_hash_calculation: bool,
5956 skip_shrink: bool,
5957 force_clean: bool,
5958 latest_full_snapshot_slot: Slot,
5959 base: Option<(Slot, u64)>,
5960 duplicates_lt_hash: Option<Box<DuplicatesLtHash>>,
5961 ) -> bool {
5962 let (verified_accounts, verify_accounts_time_us) = measure_us!({
5970 let should_verify_accounts = !self.rc.accounts.accounts_db.skip_initial_hash_calc;
5971 if should_verify_accounts {
5972 info!("Verifying accounts...");
5973 let verified = self.verify_accounts_hash(
5974 base,
5975 VerifyAccountsHashConfig {
5976 test_hash_calculation,
5977 ignore_mismatch: false,
5978 require_rooted_bank: false,
5979 run_in_background: true,
5980 store_hash_raw_data_for_debug: false,
5981 },
5982 duplicates_lt_hash,
5983 );
5984 info!("Verifying accounts... In background.");
5985 verified
5986 } else {
5987 info!("Verifying accounts... Skipped.");
5988 self.rc
5989 .accounts
5990 .accounts_db
5991 .verify_accounts_hash_in_bg
5992 .verification_complete();
5993 true
5994 }
5995 });
5996
5997 let (_, clean_time_us) = measure_us!({
5998 let should_clean = force_clean || (!skip_shrink && self.slot() > 0);
5999 if should_clean {
6000 info!("Cleaning...");
6001 self.rc.accounts.accounts_db.clean_accounts(
6006 Some(latest_full_snapshot_slot),
6007 true,
6008 self.epoch_schedule(),
6009 self.clean_accounts_old_storages_policy(),
6010 );
6011 info!("Cleaning... Done.");
6012 } else {
6013 info!("Cleaning... Skipped.");
6014 }
6015 });
6016
6017 let (_, shrink_time_us) = measure_us!({
6018 let should_shrink = !skip_shrink && self.slot() > 0;
6019 if should_shrink {
6020 info!("Shrinking...");
6021 self.rc.accounts.accounts_db.shrink_all_slots(
6022 true,
6023 self.epoch_schedule(),
6024 Some(self.slot()),
6026 );
6027 info!("Shrinking... Done.");
6028 } else {
6029 info!("Shrinking... Skipped.");
6030 }
6031 });
6032
6033 info!("Verifying bank...");
6034 let (verified_bank, verify_bank_time_us) = measure_us!(self.verify_hash());
6035 info!("Verifying bank... Done.");
6036
6037 datapoint_info!(
6038 "verify_snapshot_bank",
6039 ("clean_us", clean_time_us, i64),
6040 ("shrink_us", shrink_time_us, i64),
6041 ("verify_accounts_us", verify_accounts_time_us, i64),
6042 ("verify_bank_us", verify_bank_time_us, i64),
6043 );
6044
6045 verified_accounts && verified_bank
6046 }
6047
6048 pub fn hashes_per_tick(&self) -> &Option<u64> {
6050 &self.hashes_per_tick
6051 }
6052
6053 pub fn ticks_per_slot(&self) -> u64 {
6055 self.ticks_per_slot
6056 }
6057
6058 pub fn slots_per_year(&self) -> f64 {
6060 self.slots_per_year
6061 }
6062
6063 pub fn tick_height(&self) -> u64 {
6065 self.tick_height.load(Relaxed)
6066 }
6067
6068 pub fn inflation(&self) -> Inflation {
6070 *self.inflation.read().unwrap()
6071 }
6072
6073 pub fn rent_collector(&self) -> &RentCollector {
6075 &self.rent_collector
6076 }
6077
6078 pub fn capitalization(&self) -> u64 {
6080 self.capitalization.load(Relaxed)
6081 }
6082
6083 pub fn max_tick_height(&self) -> u64 {
6085 self.max_tick_height
6086 }
6087
6088 pub fn block_height(&self) -> u64 {
6090 self.block_height
6091 }
6092
6093 pub fn get_slots_in_epoch(&self, epoch: Epoch) -> u64 {
6095 self.epoch_schedule().get_slots_in_epoch(epoch)
6096 }
6097
6098 pub fn get_leader_schedule_epoch(&self, slot: Slot) -> Epoch {
6101 self.epoch_schedule().get_leader_schedule_epoch(slot)
6102 }
6103
6104 fn update_stakes_cache(
6106 &self,
6107 txs: &[impl SVMMessage],
6108 processing_results: &[TransactionProcessingResult],
6109 ) {
6110 debug_assert_eq!(txs.len(), processing_results.len());
6111 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
6112 txs.iter()
6113 .zip(processing_results)
6114 .filter_map(|(tx, processing_result)| {
6115 processing_result
6116 .processed_transaction()
6117 .map(|processed_tx| (tx, processed_tx))
6118 })
6119 .filter_map(|(tx, processed_tx)| {
6120 processed_tx
6121 .executed_transaction()
6122 .map(|executed_tx| (tx, executed_tx))
6123 })
6124 .filter(|(_, executed_tx)| executed_tx.was_successful())
6125 .flat_map(|(tx, executed_tx)| {
6126 let num_account_keys = tx.account_keys().len();
6127 let loaded_tx = &executed_tx.loaded_transaction;
6128 loaded_tx.accounts.iter().take(num_account_keys)
6129 })
6130 .for_each(|(pubkey, account)| {
6131 self.stakes_cache
6134 .check_and_store(pubkey, account, new_warmup_cooldown_rate_epoch);
6135 });
6136 }
6137
6138 pub fn vote_accounts(&self) -> Arc<VoteAccountsHashMap> {
6141 let stakes = self.stakes_cache.stakes();
6142 Arc::from(stakes.vote_accounts())
6143 }
6144
6145 pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<VoteAccount> {
6147 let stakes = self.stakes_cache.stakes();
6148 let vote_account = stakes.vote_accounts().get(vote_account)?;
6149 Some(vote_account.clone())
6150 }
6151
6152 pub fn current_epoch_stakes(&self) -> &EpochStakes {
6154 self.epoch_stakes
6157 .get(&self.epoch.saturating_add(1))
6158 .expect("Current epoch stakes must exist")
6159 }
6160
6161 pub fn epoch_stakes(&self, epoch: Epoch) -> Option<&EpochStakes> {
6163 self.epoch_stakes.get(&epoch)
6164 }
6165
6166 pub fn epoch_stakes_map(&self) -> &HashMap<Epoch, EpochStakes> {
6167 &self.epoch_stakes
6168 }
6169
6170 pub fn current_epoch_staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
6172 self.current_epoch_stakes().stakes().staked_nodes()
6173 }
6174
6175 pub fn epoch_staked_nodes(&self, epoch: Epoch) -> Option<Arc<HashMap<Pubkey, u64>>> {
6176 Some(self.epoch_stakes.get(&epoch)?.stakes().staked_nodes())
6177 }
6178
6179 pub fn epoch_total_stake(&self, epoch: Epoch) -> Option<u64> {
6181 self.epoch_stakes
6182 .get(&epoch)
6183 .map(|epoch_stakes| epoch_stakes.total_stake())
6184 }
6185
6186 pub fn get_current_epoch_total_stake(&self) -> u64 {
6188 self.current_epoch_stakes().total_stake()
6189 }
6190
6191 pub fn epoch_vote_accounts(&self, epoch: Epoch) -> Option<&VoteAccountsHashMap> {
6194 let epoch_stakes = self.epoch_stakes.get(&epoch)?.stakes();
6195 Some(epoch_stakes.vote_accounts().as_ref())
6196 }
6197
6198 pub fn get_current_epoch_vote_accounts(&self) -> &VoteAccountsHashMap {
6201 self.current_epoch_stakes()
6202 .stakes()
6203 .vote_accounts()
6204 .as_ref()
6205 }
6206
6207 pub fn epoch_authorized_voter(&self, vote_account: &Pubkey) -> Option<&Pubkey> {
6210 self.epoch_stakes
6211 .get(&self.epoch)
6212 .expect("Epoch stakes for bank's own epoch must exist")
6213 .epoch_authorized_voters()
6214 .get(vote_account)
6215 }
6216
6217 pub fn epoch_vote_accounts_for_node_id(&self, node_id: &Pubkey) -> Option<&NodeVoteAccounts> {
6220 self.epoch_stakes
6221 .get(&self.epoch)
6222 .expect("Epoch stakes for bank's own epoch must exist")
6223 .node_id_to_vote_accounts()
6224 .get(node_id)
6225 }
6226
6227 pub fn epoch_node_id_to_stake(&self, epoch: Epoch, node_id: &Pubkey) -> Option<u64> {
6230 self.epoch_stakes(epoch)
6231 .and_then(|epoch_stakes| epoch_stakes.node_id_to_stake(node_id))
6232 }
6233
6234 pub fn total_epoch_stake(&self) -> u64 {
6236 self.epoch_stakes
6237 .get(&self.epoch)
6238 .expect("Epoch stakes for bank's own epoch must exist")
6239 .total_stake()
6240 }
6241
6242 pub fn epoch_vote_account_stake(&self, vote_account: &Pubkey) -> u64 {
6244 *self
6245 .epoch_vote_accounts(self.epoch())
6246 .expect("Bank epoch vote accounts must contain entry for the bank's own epoch")
6247 .get(vote_account)
6248 .map(|(stake, _)| stake)
6249 .unwrap_or(&0)
6250 }
6251
6252 pub fn get_epoch_and_slot_index(&self, slot: Slot) -> (Epoch, SlotIndex) {
6258 self.epoch_schedule().get_epoch_and_slot_index(slot)
6259 }
6260
6261 pub fn get_epoch_info(&self) -> EpochInfo {
6262 let absolute_slot = self.slot();
6263 let block_height = self.block_height();
6264 let (epoch, slot_index) = self.get_epoch_and_slot_index(absolute_slot);
6265 let slots_in_epoch = self.get_slots_in_epoch(epoch);
6266 let transaction_count = Some(self.transaction_count());
6267 EpochInfo {
6268 epoch,
6269 slot_index,
6270 slots_in_epoch,
6271 absolute_slot,
6272 block_height,
6273 transaction_count,
6274 }
6275 }
6276
6277 pub fn is_empty(&self) -> bool {
6278 !self.is_delta.load(Relaxed)
6279 }
6280
6281 pub fn add_mockup_builtin(
6282 &mut self,
6283 program_id: Pubkey,
6284 builtin_function: BuiltinFunctionWithContext,
6285 ) {
6286 self.transaction_processor.add_builtin(
6287 self,
6288 program_id,
6289 "mockup",
6290 ProgramCacheEntry::new_builtin(self.slot, 0, builtin_function),
6291 );
6292 }
6293
6294 pub fn add_precompile(&mut self, program_id: &Pubkey) {
6295 debug!("Adding precompiled program {}", program_id);
6296 self.add_precompiled_account(program_id);
6297 debug!("Added precompiled program {:?}", program_id);
6298 }
6299
6300 pub(crate) fn clean_accounts(&self) {
6305 let highest_slot_to_clean = self.slot().saturating_sub(1);
6312
6313 self.rc.accounts.accounts_db.clean_accounts(
6314 Some(highest_slot_to_clean),
6315 false,
6316 self.epoch_schedule(),
6317 self.clean_accounts_old_storages_policy(),
6318 );
6319 }
6320
6321 pub fn print_accounts_stats(&self) {
6322 self.rc.accounts.accounts_db.print_accounts_stats("");
6323 }
6324
6325 pub fn shrink_candidate_slots(&self) -> usize {
6326 self.rc
6327 .accounts
6328 .accounts_db
6329 .shrink_candidate_slots(self.epoch_schedule())
6330 }
6331
6332 pub(crate) fn shrink_ancient_slots(&self) {
6333 if self.are_ancient_storages_enabled() {
6337 self.rc
6338 .accounts
6339 .accounts_db
6340 .shrink_ancient_slots(self.epoch_schedule())
6341 }
6342 }
6343
6344 pub fn are_ancient_storages_enabled(&self) -> bool {
6346 let can_skip_rewrites = self.bank_hash_skips_rent_rewrites();
6347 let test_skip_rewrites_but_include_in_bank_hash = self
6348 .rc
6349 .accounts
6350 .accounts_db
6351 .test_skip_rewrites_but_include_in_bank_hash;
6352 can_skip_rewrites || test_skip_rewrites_but_include_in_bank_hash
6353 }
6354
6355 fn clean_accounts_old_storages_policy(&self) -> OldStoragesPolicy {
6357 if self.are_ancient_storages_enabled() {
6358 OldStoragesPolicy::Leave
6359 } else {
6360 OldStoragesPolicy::Clean
6361 }
6362 }
6363
6364 pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<CostTracker>> {
6365 self.cost_tracker.read()
6366 }
6367
6368 pub fn write_cost_tracker(&self) -> LockResult<RwLockWriteGuard<CostTracker>> {
6369 self.cost_tracker.write()
6370 }
6371
6372 pub fn should_bank_still_be_processing_txs(
6375 bank_creation_time: &Instant,
6376 max_tx_ingestion_nanos: u128,
6377 ) -> bool {
6378 bank_creation_time.elapsed().as_nanos() <= max_tx_ingestion_nanos
6380 }
6381
6382 pub fn deactivate_feature(&mut self, id: &Pubkey) {
6383 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6384 feature_set.active.remove(id);
6385 feature_set.inactive.insert(*id);
6386 self.feature_set = Arc::new(feature_set);
6387 }
6388
6389 pub fn activate_feature(&mut self, id: &Pubkey) {
6390 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6391 feature_set.inactive.remove(id);
6392 feature_set.active.insert(*id, 0);
6393 self.feature_set = Arc::new(feature_set);
6394 }
6395
6396 pub fn fill_bank_with_ticks_for_tests(&self) {
6397 self.do_fill_bank_with_ticks_for_tests(&BankWithScheduler::no_scheduler_available())
6398 }
6399
6400 pub(crate) fn do_fill_bank_with_ticks_for_tests(&self, scheduler: &InstalledSchedulerRwLock) {
6401 if self.tick_height.load(Relaxed) < self.max_tick_height {
6402 let last_blockhash = self.last_blockhash();
6403 while self.last_blockhash() == last_blockhash {
6404 self.register_tick(&Hash::new_unique(), scheduler)
6405 }
6406 } else {
6407 warn!("Bank already reached max tick height, cannot fill it with more ticks");
6408 }
6409 }
6410
6411 pub fn get_reserved_account_keys(&self) -> &HashSet<Pubkey> {
6414 &self.reserved_account_keys.active
6415 }
6416
6417 fn apply_feature_activations(
6420 &mut self,
6421 caller: ApplyFeatureActivationsCaller,
6422 debug_do_not_add_builtins: bool,
6423 ) {
6424 use ApplyFeatureActivationsCaller as Caller;
6425 let allow_new_activations = match caller {
6426 Caller::FinishInit => false,
6427 Caller::NewFromParent => true,
6428 Caller::WarpFromParent => false,
6429 };
6430 let (feature_set, new_feature_activations) =
6431 self.compute_active_feature_set(allow_new_activations);
6432 self.feature_set = Arc::new(feature_set);
6433
6434 for feature_id in new_feature_activations.iter() {
6436 if let Some(mut account) = self.get_account_with_fixed_root(feature_id) {
6437 if let Some(mut feature) = feature::from_account(&account) {
6438 feature.activated_at = Some(self.slot());
6439 if feature::to_account(&feature, &mut account).is_some() {
6440 self.store_account(feature_id, &account);
6441 }
6442 info!("Feature {} activated at slot {}", feature_id, self.slot());
6443 }
6444 }
6445 }
6446
6447 self.reserved_account_keys = {
6449 let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
6450 reserved_keys.update_active_set(&self.feature_set);
6451 Arc::new(reserved_keys)
6452 };
6453
6454 if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
6455 *self.inflation.write().unwrap() = Inflation::pico();
6456 self.fee_rate_governor.burn_percent = 50; self.rent_collector.rent.burn_percent = 50; }
6459
6460 if !new_feature_activations.is_disjoint(&self.feature_set.full_inflation_features_enabled())
6461 {
6462 *self.inflation.write().unwrap() = Inflation::full();
6463 self.fee_rate_governor.burn_percent = 50; self.rent_collector.rent.burn_percent = 50; }
6466
6467 if !debug_do_not_add_builtins {
6468 self.apply_builtin_program_feature_transitions(
6469 allow_new_activations,
6470 &new_feature_activations,
6471 );
6472 }
6473
6474 if new_feature_activations.contains(&feature_set::update_hashes_per_tick::id()) {
6475 self.apply_updated_hashes_per_tick(DEFAULT_HASHES_PER_TICK);
6476 }
6477
6478 if new_feature_activations.contains(&feature_set::update_hashes_per_tick2::id()) {
6479 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK2);
6480 }
6481
6482 if new_feature_activations.contains(&feature_set::update_hashes_per_tick3::id()) {
6483 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK3);
6484 }
6485
6486 if new_feature_activations.contains(&feature_set::update_hashes_per_tick4::id()) {
6487 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK4);
6488 }
6489
6490 if new_feature_activations.contains(&feature_set::update_hashes_per_tick5::id()) {
6491 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK5);
6492 }
6493
6494 if new_feature_activations.contains(&feature_set::update_hashes_per_tick6::id()) {
6495 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK6);
6496 }
6497
6498 if new_feature_activations.contains(&feature_set::accounts_lt_hash::id()) {
6499 if self
6503 .rc
6504 .accounts
6505 .accounts_db
6506 .is_experimental_accumulator_hash_enabled()
6507 {
6508 } else {
6511 let parent_slot = self.parent_slot;
6512 info!(
6513 "Calculating the accounts lt hash for slot {parent_slot} \
6514 as part of feature activation; this may take some time...",
6515 );
6516 let parent_ancestors = {
6521 let mut ancestors = self.ancestors.clone();
6522 ancestors.remove(&self.slot());
6523 ancestors
6524 };
6525 let (parent_accounts_lt_hash, duration) = meas_dur!({
6526 self.rc
6527 .accounts
6528 .accounts_db
6529 .calculate_accounts_lt_hash_at_startup_from_index(
6530 &parent_ancestors,
6531 parent_slot,
6532 )
6533 });
6534 *self.accounts_lt_hash.get_mut().unwrap() = parent_accounts_lt_hash;
6535 info!(
6536 "Calculating the accounts lt hash for slot {parent_slot} \
6537 completed in {duration:?}, accounts_lt_hash checksum: {}",
6538 self.accounts_lt_hash.get_mut().unwrap().0.checksum(),
6539 );
6540 }
6541 }
6542
6543 if new_feature_activations.contains(&feature_set::raise_block_limits_to_50m::id()) {
6544 let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits();
6545 self.write_cost_tracker().unwrap().set_limits(
6546 account_cost_limit,
6547 block_cost_limit,
6548 vote_cost_limit,
6549 );
6550 }
6551
6552 if new_feature_activations.contains(&feature_set::remove_accounts_delta_hash::id()) {
6553 self.rc.accounts.accounts_db.stop_background_hasher();
6556 }
6557 }
6558
6559 fn apply_updated_hashes_per_tick(&mut self, hashes_per_tick: u64) {
6560 info!(
6561 "Activating update_hashes_per_tick {} at slot {}",
6562 hashes_per_tick,
6563 self.slot(),
6564 );
6565 self.hashes_per_tick = Some(hashes_per_tick);
6566 }
6567
6568 fn adjust_sysvar_balance_for_rent(&self, account: &mut AccountSharedData) {
6569 account.set_lamports(
6570 self.get_minimum_balance_for_rent_exemption(account.data().len())
6571 .max(account.lamports()),
6572 );
6573 }
6574
6575 fn compute_active_feature_set(&self, include_pending: bool) -> (FeatureSet, AHashSet<Pubkey>) {
6578 let mut active = self.feature_set.active.clone();
6579 let mut inactive = AHashSet::new();
6580 let mut pending = AHashSet::new();
6581 let slot = self.slot();
6582
6583 for feature_id in &self.feature_set.inactive {
6584 let mut activated = None;
6585 if let Some(account) = self.get_account_with_fixed_root(feature_id) {
6586 if let Some(feature) = feature::from_account(&account) {
6587 match feature.activated_at {
6588 None if include_pending => {
6589 pending.insert(*feature_id);
6591 activated = Some(slot);
6592 }
6593 Some(activation_slot) if slot >= activation_slot => {
6594 activated = Some(activation_slot);
6596 }
6597 _ => {}
6598 }
6599 }
6600 }
6601 if let Some(slot) = activated {
6602 active.insert(*feature_id, slot);
6603 } else {
6604 inactive.insert(*feature_id);
6605 }
6606 }
6607
6608 (FeatureSet { active, inactive }, pending)
6609 }
6610
6611 fn apply_builtin_program_feature_transitions(
6612 &mut self,
6613 only_apply_transitions_for_new_features: bool,
6614 new_feature_activations: &AHashSet<Pubkey>,
6615 ) {
6616 for builtin in BUILTINS.iter() {
6617 let mut builtin_is_bpf = false;
6634 if let Some(core_bpf_migration_config) = &builtin.core_bpf_migration_config {
6635 if new_feature_activations.contains(&core_bpf_migration_config.feature_id) {
6640 if let Err(e) = self
6641 .migrate_builtin_to_core_bpf(&builtin.program_id, core_bpf_migration_config)
6642 {
6643 warn!(
6644 "Failed to migrate builtin {} to Core BPF: {}",
6645 builtin.name, e
6646 );
6647 } else {
6648 builtin_is_bpf = true;
6649 }
6650 } else {
6651 builtin_is_bpf = self
6654 .get_account(&builtin.program_id)
6655 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
6656 .unwrap_or(false);
6657 }
6658 };
6659
6660 if let Some(feature_id) = builtin.enable_feature_id {
6661 let should_enable_builtin_on_feature_transition = !builtin_is_bpf
6662 && if only_apply_transitions_for_new_features {
6663 new_feature_activations.contains(&feature_id)
6664 } else {
6665 self.feature_set.is_active(&feature_id)
6666 };
6667
6668 if should_enable_builtin_on_feature_transition {
6669 self.transaction_processor.add_builtin(
6670 self,
6671 builtin.program_id,
6672 builtin.name,
6673 ProgramCacheEntry::new_builtin(
6674 self.feature_set.activated_slot(&feature_id).unwrap_or(0),
6675 builtin.name.len(),
6676 builtin.entrypoint,
6677 ),
6678 );
6679 }
6680 }
6681 }
6682
6683 for stateless_builtin in STATELESS_BUILTINS.iter() {
6687 if let Some(core_bpf_migration_config) = &stateless_builtin.core_bpf_migration_config {
6688 if new_feature_activations.contains(&core_bpf_migration_config.feature_id) {
6689 if let Err(e) = self.migrate_builtin_to_core_bpf(
6690 &stateless_builtin.program_id,
6691 core_bpf_migration_config,
6692 ) {
6693 warn!(
6694 "Failed to migrate stateless builtin {} to Core BPF: {}",
6695 stateless_builtin.name, e
6696 );
6697 }
6698 }
6699 }
6700 }
6701
6702 for precompile in get_precompiles() {
6703 let should_add_precompile = precompile
6704 .feature
6705 .as_ref()
6706 .map(|feature_id| self.feature_set.is_active(feature_id))
6707 .unwrap_or(false);
6708 if should_add_precompile {
6709 self.add_precompile(&precompile.program_id);
6710 }
6711 }
6712 }
6713
6714 #[allow(dead_code)]
6716 fn replace_program_account(
6717 &mut self,
6718 old_address: &Pubkey,
6719 new_address: &Pubkey,
6720 datapoint_name: &'static str,
6721 ) {
6722 if let Some(old_account) = self.get_account_with_fixed_root(old_address) {
6723 if let Some(new_account) = self.get_account_with_fixed_root(new_address) {
6724 datapoint_info!(datapoint_name, ("slot", self.slot, i64));
6725
6726 self.capitalization
6728 .fetch_sub(old_account.lamports(), Relaxed);
6729
6730 self.store_account(old_address, &new_account);
6732
6733 self.store_account(new_address, &AccountSharedData::default());
6735
6736 self.transaction_processor
6738 .program_cache
6739 .write()
6740 .unwrap()
6741 .remove_programs([*old_address].into_iter());
6742
6743 self.calculate_and_update_accounts_data_size_delta_off_chain(
6744 old_account.data().len(),
6745 new_account.data().len(),
6746 );
6747 }
6748 }
6749 }
6750
6751 pub fn get_total_accounts_stats(&self) -> ScanResult<TotalAccountsStats> {
6753 let accounts = self.get_all_accounts(false)?;
6754 Ok(self.calculate_total_accounts_stats(
6755 accounts
6756 .iter()
6757 .map(|(pubkey, account, _slot)| (pubkey, account)),
6758 ))
6759 }
6760
6761 pub fn calculate_total_accounts_stats<'a>(
6763 &self,
6764 accounts: impl Iterator<Item = (&'a Pubkey, &'a AccountSharedData)>,
6765 ) -> TotalAccountsStats {
6766 let rent_collector = self.rent_collector();
6767 let mut total_accounts_stats = TotalAccountsStats::default();
6768 accounts.for_each(|(pubkey, account)| {
6769 total_accounts_stats.accumulate_account(pubkey, account, rent_collector);
6770 });
6771
6772 total_accounts_stats
6773 }
6774
6775 pub fn get_epoch_accounts_hash_to_serialize(&self) -> Option<EpochAccountsHash> {
6781 let should_get_epoch_accounts_hash = epoch_accounts_hash_utils::is_enabled_this_epoch(self)
6782 && epoch_accounts_hash_utils::is_in_calculation_window(self);
6783 if !should_get_epoch_accounts_hash {
6784 return None;
6785 }
6786
6787 let (epoch_accounts_hash, waiting_time_us) = measure_us!(self
6788 .rc
6789 .accounts
6790 .accounts_db
6791 .epoch_accounts_hash_manager
6792 .wait_get_epoch_accounts_hash());
6793
6794 datapoint_info!(
6795 "bank-get_epoch_accounts_hash_to_serialize",
6796 ("slot", self.slot(), i64),
6797 ("waiting-time-us", waiting_time_us, i64),
6798 );
6799 Some(epoch_accounts_hash)
6800 }
6801
6802 pub fn epoch_accounts_hash(&self) -> Option<EpochAccountsHash> {
6804 self.rc
6805 .accounts
6806 .accounts_db
6807 .epoch_accounts_hash_manager
6808 .try_get_epoch_accounts_hash()
6809 }
6810
6811 pub fn is_in_slot_hashes_history(&self, slot: &Slot) -> bool {
6812 if slot < &self.slot {
6813 if let Ok(slot_hashes) = self.transaction_processor.sysvar_cache().get_slot_hashes() {
6814 return slot_hashes.get(slot).is_some();
6815 }
6816 }
6817 false
6818 }
6819
6820 pub fn check_program_modification_slot(&self) -> bool {
6821 self.check_program_modification_slot
6822 }
6823
6824 pub fn set_check_program_modification_slot(&mut self, check: bool) {
6825 self.check_program_modification_slot = check;
6826 }
6827
6828 pub fn fee_structure(&self) -> &FeeStructure {
6829 &self.fee_structure
6830 }
6831
6832 pub fn block_id(&self) -> Option<Hash> {
6833 *self.block_id.read().unwrap()
6834 }
6835
6836 pub fn set_block_id(&self, block_id: Option<Hash>) {
6837 *self.block_id.write().unwrap() = block_id;
6838 }
6839
6840 pub fn compute_budget(&self) -> Option<ComputeBudget> {
6841 self.compute_budget
6842 }
6843
6844 pub fn add_builtin(&self, program_id: Pubkey, name: &str, builtin: ProgramCacheEntry) {
6845 self.transaction_processor
6846 .add_builtin(self, program_id, name, builtin)
6847 }
6848
6849 pub fn get_bank_hash_stats(&self) -> BankHashStats {
6850 self.bank_hash_stats.load()
6851 }
6852}
6853
6854impl TransactionProcessingCallback for Bank {
6855 fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
6856 self.rc
6857 .accounts
6858 .accounts_db
6859 .account_matches_owners(&self.ancestors, account, owners)
6860 .ok()
6861 }
6862
6863 fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6864 self.rc
6865 .accounts
6866 .accounts_db
6867 .load_with_fixed_root(&self.ancestors, pubkey)
6868 .map(|(acc, _)| acc)
6869 }
6870
6871 fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
6874 let existing_genuine_program =
6875 self.get_account_with_fixed_root(program_id)
6876 .and_then(|account| {
6877 if native_loader::check_id(account.owner()) {
6881 Some(account)
6882 } else {
6883 self.burn_and_purge_account(program_id, account);
6885 None
6886 }
6887 });
6888
6889 if existing_genuine_program.is_some() {
6891 return;
6893 }
6894
6895 assert!(
6896 !self.freeze_started(),
6897 "Can't change frozen bank by adding not-existing new builtin program ({name}, {program_id}). \
6898 Maybe, inconsistent program activation is detected on snapshot restore?"
6899 );
6900
6901 let account = native_loader::create_loadable_account_with_fields(
6903 name,
6904 self.inherit_specially_retained_account_fields(&existing_genuine_program),
6905 );
6906 self.store_account_and_update_capitalization(program_id, &account);
6907 }
6908
6909 fn inspect_account(&self, address: &Pubkey, account_state: AccountState, is_writable: bool) {
6910 if self.is_accounts_lt_hash_enabled() {
6911 self.inspect_account_for_accounts_lt_hash(address, &account_state, is_writable);
6912 }
6913 }
6914
6915 fn get_current_epoch_vote_account_stake(&self, vote_address: &Pubkey) -> u64 {
6916 self.get_current_epoch_vote_accounts()
6917 .get(vote_address)
6918 .map(|(stake, _)| (*stake))
6919 .unwrap_or(0)
6920 }
6921
6922 fn calculate_fee(
6923 &self,
6924 message: &impl SVMMessage,
6925 lamports_per_signature: u64,
6926 prioritization_fee: u64,
6927 feature_set: &FeatureSet,
6928 ) -> FeeDetails {
6929 solana_fee::calculate_fee_details(
6930 message,
6931 false, lamports_per_signature,
6933 prioritization_fee,
6934 FeeFeatures::from(feature_set),
6935 )
6936 }
6937}
6938
6939#[cfg(feature = "dev-context-only-utils")]
6940impl Bank {
6941 pub fn wrap_with_bank_forks_for_tests(self) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6942 let bank_forks = BankForks::new_rw_arc(self);
6943 let bank = bank_forks.read().unwrap().root_bank();
6944 (bank, bank_forks)
6945 }
6946
6947 pub fn default_for_tests() -> Self {
6948 let accounts_db = AccountsDb::default_for_tests();
6949 let accounts = Accounts::new(Arc::new(accounts_db));
6950 Self::default_with_accounts(accounts)
6951 }
6952
6953 pub fn new_with_bank_forks_for_tests(
6954 genesis_config: &GenesisConfig,
6955 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6956 let bank = Self::new_for_tests(genesis_config);
6957 bank.wrap_with_bank_forks_for_tests()
6958 }
6959
6960 pub fn new_for_tests(genesis_config: &GenesisConfig) -> Self {
6961 Self::new_with_config_for_tests(genesis_config, BankTestConfig::default())
6962 }
6963
6964 pub fn new_with_mockup_builtin_for_tests(
6965 genesis_config: &GenesisConfig,
6966 program_id: Pubkey,
6967 builtin_function: BuiltinFunctionWithContext,
6968 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6969 let mut bank = Self::new_for_tests(genesis_config);
6970 bank.add_mockup_builtin(program_id, builtin_function);
6971 bank.wrap_with_bank_forks_for_tests()
6972 }
6973
6974 pub fn new_no_wallclock_throttle_for_tests(
6975 genesis_config: &GenesisConfig,
6976 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6977 let mut bank = Self::new_for_tests(genesis_config);
6978
6979 bank.ns_per_slot = u128::MAX;
6980 bank.wrap_with_bank_forks_for_tests()
6981 }
6982
6983 pub fn new_with_config_for_tests(
6984 genesis_config: &GenesisConfig,
6985 test_config: BankTestConfig,
6986 ) -> Self {
6987 Self::new_with_paths_for_tests(
6988 genesis_config,
6989 Arc::new(RuntimeConfig::default()),
6990 test_config,
6991 Vec::new(),
6992 )
6993 }
6994
6995 pub fn new_with_paths_for_tests(
6996 genesis_config: &GenesisConfig,
6997 runtime_config: Arc<RuntimeConfig>,
6998 test_config: BankTestConfig,
6999 paths: Vec<PathBuf>,
7000 ) -> Self {
7001 Self::new_with_paths(
7002 genesis_config,
7003 runtime_config,
7004 paths,
7005 None,
7006 None,
7007 false,
7008 Some(test_config.accounts_db_config),
7009 None,
7010 Some(Pubkey::new_unique()),
7011 Arc::default(),
7012 None,
7013 None,
7014 )
7015 }
7016
7017 pub fn new_for_benches(genesis_config: &GenesisConfig) -> Self {
7018 Self::new_with_paths_for_benches(genesis_config, Vec::new())
7019 }
7020
7021 pub fn new_with_paths_for_benches(genesis_config: &GenesisConfig, paths: Vec<PathBuf>) -> Self {
7024 Self::new_with_paths(
7025 genesis_config,
7026 Arc::<RuntimeConfig>::default(),
7027 paths,
7028 None,
7029 None,
7030 false,
7031 Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
7032 None,
7033 Some(Pubkey::new_unique()),
7034 Arc::default(),
7035 None,
7036 None,
7037 )
7038 }
7039
7040 #[cfg(feature = "dev-context-only-utils")]
7042 pub fn prepare_batch_for_tests(
7043 &self,
7044 txs: Vec<Transaction>,
7045 ) -> TransactionBatch<RuntimeTransaction<SanitizedTransaction>> {
7046 let transaction_account_lock_limit = self.get_transaction_account_lock_limit();
7047 let sanitized_txs = txs
7048 .into_iter()
7049 .map(RuntimeTransaction::from_transaction_for_tests)
7050 .collect::<Vec<_>>();
7051 let lock_results = self
7052 .rc
7053 .accounts
7054 .lock_accounts(sanitized_txs.iter(), transaction_account_lock_limit);
7055 TransactionBatch::new(lock_results, self, OwnedOrBorrowed::Owned(sanitized_txs))
7056 }
7057
7058 pub fn set_accounts_data_size_initial_for_tests(&mut self, amount: u64) {
7061 self.accounts_data_size_initial = amount;
7062 }
7063
7064 pub fn update_accounts_data_size_delta_off_chain_for_tests(&self, amount: i64) {
7067 self.update_accounts_data_size_delta_off_chain(amount)
7068 }
7069
7070 #[cfg(test)]
7071 fn restore_old_behavior_for_fragile_tests(&self) {
7072 self.lazy_rent_collection.store(true, Relaxed);
7073 }
7074
7075 #[must_use]
7081 pub fn process_transactions<'a>(
7082 &self,
7083 txs: impl Iterator<Item = &'a Transaction>,
7084 ) -> Vec<Result<()>> {
7085 self.try_process_transactions(txs).unwrap()
7086 }
7087
7088 #[must_use]
7094 pub fn process_entry_transactions(&self, txs: Vec<VersionedTransaction>) -> Vec<Result<()>> {
7095 self.try_process_entry_transactions(txs).unwrap()
7096 }
7097
7098 #[cfg(test)]
7099 pub fn flush_accounts_cache_slot_for_tests(&self) {
7100 self.rc
7101 .accounts
7102 .accounts_db
7103 .flush_accounts_cache_slot_for_tests(self.slot())
7104 }
7105
7106 pub fn wait_for_initial_accounts_hash_verification_completed_for_tests(&self) {
7109 self.rc
7110 .accounts
7111 .accounts_db
7112 .verify_accounts_hash_in_bg
7113 .join_background_thread()
7114 }
7115
7116 pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
7117 self.transaction_processor.get_sysvar_cache_for_tests()
7118 }
7119
7120 pub fn update_accounts_hash_for_tests(&self) -> AccountsHash {
7121 self.update_accounts_hash(CalcAccountsHashDataSource::IndexForTests, false, false)
7122 }
7123
7124 pub fn new_program_cache_for_tx_batch_for_slot(&self, slot: Slot) -> ProgramCacheForTxBatch {
7125 ProgramCacheForTxBatch::new_from_cache(
7126 slot,
7127 self.epoch_schedule.get_epoch(slot),
7128 &self.transaction_processor.program_cache.read().unwrap(),
7129 )
7130 }
7131
7132 pub fn get_transaction_processor(&self) -> &TransactionBatchProcessor<BankForks> {
7133 &self.transaction_processor
7134 }
7135
7136 pub fn set_fee_structure(&mut self, fee_structure: &FeeStructure) {
7137 self.fee_structure = fee_structure.clone();
7138 }
7139
7140 pub fn load_program(
7141 &self,
7142 pubkey: &Pubkey,
7143 reload: bool,
7144 effective_epoch: Epoch,
7145 ) -> Option<Arc<ProgramCacheEntry>> {
7146 let environments = self
7147 .transaction_processor
7148 .get_environments_for_epoch(effective_epoch)?;
7149 load_program_with_pubkey(
7150 self,
7151 &environments,
7152 pubkey,
7153 self.slot(),
7154 &mut ExecuteTimings::default(), reload,
7156 )
7157 }
7158
7159 pub fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
7160 match self.get_account_with_fixed_root(pubkey) {
7161 Some(mut account) => {
7162 let min_balance = match get_system_account_kind(&account) {
7163 Some(SystemAccountKind::Nonce) => self
7164 .rent_collector
7165 .rent
7166 .minimum_balance(nonce::State::size()),
7167 _ => 0,
7168 };
7169
7170 lamports
7171 .checked_add(min_balance)
7172 .filter(|required_balance| *required_balance <= account.lamports())
7173 .ok_or(TransactionError::InsufficientFundsForFee)?;
7174 account
7175 .checked_sub_lamports(lamports)
7176 .map_err(|_| TransactionError::InsufficientFundsForFee)?;
7177 self.store_account(pubkey, &account);
7178
7179 Ok(())
7180 }
7181 None => Err(TransactionError::AccountNotFound),
7182 }
7183 }
7184
7185 pub fn set_hash_overrides(&self, hash_overrides: HashOverrides) {
7186 *self.hash_overrides.lock().unwrap() = hash_overrides;
7187 }
7188}
7189
7190fn calculate_data_size_delta(old_data_size: usize, new_data_size: usize) -> i64 {
7193 assert!(old_data_size <= i64::MAX as usize);
7194 assert!(new_data_size <= i64::MAX as usize);
7195 let old_data_size = old_data_size as i64;
7196 let new_data_size = new_data_size as i64;
7197
7198 new_data_size.saturating_sub(old_data_size)
7199}
7200
7201#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7204enum ApplyFeatureActivationsCaller {
7205 FinishInit,
7206 NewFromParent,
7207 WarpFromParent,
7208}
7209
7210#[derive(Debug, Default)]
7216struct CollectRentFromAccountsInfo {
7217 skipped_rewrites: Vec<(Pubkey, AccountHash)>,
7218 rent_collected_info: CollectedInfo,
7219 rent_rewards: Vec<(Pubkey, RewardInfo)>,
7220 time_collecting_rent_us: u64,
7221 time_storing_accounts_us: u64,
7222 num_accounts: usize,
7223}
7224
7225#[derive(Debug, Default)]
7228struct CollectRentInPartitionInfo {
7229 skipped_rewrites: Vec<(Pubkey, AccountHash)>,
7230 rent_collected: u64,
7231 accounts_data_size_reclaimed: u64,
7232 rent_rewards: Vec<(Pubkey, RewardInfo)>,
7233 time_loading_accounts_us: u64,
7234 time_collecting_rent_us: u64,
7235 time_storing_accounts_us: u64,
7236 num_accounts: usize,
7237}
7238
7239impl CollectRentInPartitionInfo {
7240 #[must_use]
7243 fn new(info: CollectRentFromAccountsInfo, time_loading_accounts: Duration) -> Self {
7244 Self {
7245 skipped_rewrites: info.skipped_rewrites,
7246 rent_collected: info.rent_collected_info.rent_amount,
7247 accounts_data_size_reclaimed: info.rent_collected_info.account_data_len_reclaimed,
7248 rent_rewards: info.rent_rewards,
7249 time_loading_accounts_us: time_loading_accounts.as_micros() as u64,
7250 time_collecting_rent_us: info.time_collecting_rent_us,
7251 time_storing_accounts_us: info.time_storing_accounts_us,
7252 num_accounts: info.num_accounts,
7253 }
7254 }
7255
7256 #[must_use]
7261 fn reduce(lhs: Self, rhs: Self) -> Self {
7262 Self {
7263 skipped_rewrites: [lhs.skipped_rewrites, rhs.skipped_rewrites].concat(),
7264 rent_collected: lhs.rent_collected.saturating_add(rhs.rent_collected),
7265 accounts_data_size_reclaimed: lhs
7266 .accounts_data_size_reclaimed
7267 .saturating_add(rhs.accounts_data_size_reclaimed),
7268 rent_rewards: [lhs.rent_rewards, rhs.rent_rewards].concat(),
7269 time_loading_accounts_us: lhs
7270 .time_loading_accounts_us
7271 .saturating_add(rhs.time_loading_accounts_us),
7272 time_collecting_rent_us: lhs
7273 .time_collecting_rent_us
7274 .saturating_add(rhs.time_collecting_rent_us),
7275 time_storing_accounts_us: lhs
7276 .time_storing_accounts_us
7277 .saturating_add(rhs.time_storing_accounts_us),
7278 num_accounts: lhs.num_accounts.saturating_add(rhs.num_accounts),
7279 }
7280 }
7281}
7282
7283#[derive(Debug, Default, Copy, Clone, Serialize)]
7285pub struct TotalAccountsStats {
7286 pub num_accounts: usize,
7288 pub data_len: usize,
7290
7291 pub num_executable_accounts: usize,
7293 pub executable_data_len: usize,
7295
7296 pub num_rent_exempt_accounts: usize,
7298 pub num_rent_paying_accounts: usize,
7300 pub num_rent_paying_accounts_without_data: usize,
7302 pub lamports_in_rent_paying_accounts: u64,
7304}
7305
7306impl TotalAccountsStats {
7307 pub fn accumulate_account(
7308 &mut self,
7309 address: &Pubkey,
7310 account: &AccountSharedData,
7311 rent_collector: &RentCollector,
7312 ) {
7313 let data_len = account.data().len();
7314 self.num_accounts += 1;
7315 self.data_len += data_len;
7316
7317 if account.executable() {
7318 self.num_executable_accounts += 1;
7319 self.executable_data_len += data_len;
7320 }
7321
7322 if !rent_collector.should_collect_rent(address, account.executable())
7323 || rent_collector
7324 .get_rent_due(
7325 account.lamports(),
7326 account.data().len(),
7327 account.rent_epoch(),
7328 )
7329 .is_exempt()
7330 {
7331 self.num_rent_exempt_accounts += 1;
7332 } else {
7333 self.num_rent_paying_accounts += 1;
7334 self.lamports_in_rent_paying_accounts += account.lamports();
7335 if data_len == 0 {
7336 self.num_rent_paying_accounts_without_data += 1;
7337 }
7338 }
7339 }
7340}
7341
7342impl Drop for Bank {
7343 fn drop(&mut self) {
7344 if let Some(drop_callback) = self.drop_callback.read().unwrap().0.as_ref() {
7345 drop_callback.callback(self);
7346 } else {
7347 self.rc
7349 .accounts
7350 .accounts_db
7351 .purge_slot(self.slot(), self.bank_id(), false);
7352 }
7353 }
7354}
7355
7356pub mod test_utils {
7358 use {
7359 super::Bank,
7360 crate::installed_scheduler_pool::BankWithScheduler,
7361 solana_sdk::{
7362 account::{ReadableAccount, WritableAccount},
7363 hash::hashv,
7364 lamports::LamportsError,
7365 pubkey::Pubkey,
7366 },
7367 solana_vote_program::vote_state::{self, BlockTimestamp, VoteStateVersions},
7368 std::sync::Arc,
7369 };
7370 pub fn goto_end_of_slot(bank: Arc<Bank>) {
7371 goto_end_of_slot_with_scheduler(&BankWithScheduler::new_without_scheduler(bank))
7372 }
7373
7374 pub fn goto_end_of_slot_with_scheduler(bank: &BankWithScheduler) {
7375 let mut tick_hash = bank.last_blockhash();
7376 loop {
7377 tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
7378 bank.register_tick(&tick_hash);
7379 if tick_hash == bank.last_blockhash() {
7380 bank.freeze();
7381 return;
7382 }
7383 }
7384 }
7385
7386 pub fn update_vote_account_timestamp(
7387 timestamp: BlockTimestamp,
7388 bank: &Bank,
7389 vote_pubkey: &Pubkey,
7390 ) {
7391 let mut vote_account = bank.get_account(vote_pubkey).unwrap_or_default();
7392 let mut vote_state = vote_state::from(&vote_account).unwrap_or_default();
7393 vote_state.last_timestamp = timestamp;
7394 let versioned = VoteStateVersions::new_current(vote_state);
7395 vote_state::to(&versioned, &mut vote_account).unwrap();
7396 bank.store_account(vote_pubkey, &vote_account);
7397 }
7398
7399 pub fn deposit(
7400 bank: &Bank,
7401 pubkey: &Pubkey,
7402 lamports: u64,
7403 ) -> std::result::Result<u64, LamportsError> {
7404 let mut account = bank
7407 .get_account_with_fixed_root_no_cache(pubkey)
7408 .unwrap_or_default();
7409 account.checked_add_lamports(lamports)?;
7410 bank.store_account(pubkey, &account);
7411 Ok(account.lamports())
7412 }
7413}