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 agave_feature_set::{self as feature_set, reward_full_priority_fee, FeatureSet},
62 agave_precompiles::get_precompiles,
63 agave_reserved_account_keys::ReservedAccountKeys,
64 ahash::AHashSet,
65 dashmap::{DashMap, DashSet},
66 log::*,
67 rayon::{
68 iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator},
69 ThreadPoolBuilder,
70 },
71 serde::Serialize,
72 solana_accounts_db::{
73 account_locks::validate_account_locks,
74 accounts::{AccountAddressFilter, Accounts, PubkeyAccountSlot},
75 accounts_db::{
76 AccountStorageEntry, AccountsDb, AccountsDbConfig, CalcAccountsHashDataSource,
77 DuplicatesLtHash, OldStoragesPolicy, PubkeyHashAccount,
78 VerifyAccountsHashAndLamportsConfig,
79 },
80 accounts_hash::{
81 AccountHash, AccountsHash, AccountsLtHash, CalcAccountsHashConfig, HashStats,
82 IncrementalAccountsHash, MerkleOrLatticeAccountsHash,
83 },
84 accounts_index::{IndexKey, ScanConfig, ScanResult},
85 accounts_partition::{self, Partition, PartitionIndex},
86 accounts_update_notifier_interface::AccountsUpdateNotifier,
87 ancestors::{Ancestors, AncestorsForSerialization},
88 blockhash_queue::BlockhashQueue,
89 epoch_accounts_hash::EpochAccountsHash,
90 sorted_storages::SortedStorages,
91 storable_accounts::StorableAccounts,
92 },
93 solana_bpf_loader_program::syscalls::{
94 create_program_runtime_environment_v1, create_program_runtime_environment_v2,
95 },
96 solana_builtins::{prototype::BuiltinPrototype, BUILTINS, STATELESS_BUILTINS},
97 solana_compute_budget::compute_budget::ComputeBudget,
98 solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions,
99 solana_cost_model::{block_cost_limits::simd_0207_block_limits, cost_tracker::CostTracker},
100 solana_fee::FeeFeatures,
101 solana_lattice_hash::lt_hash::LtHash,
102 solana_measure::{meas_dur, measure::Measure, measure_time, measure_us},
103 solana_program_runtime::{
104 invoke_context::BuiltinFunctionWithContext, loaded_programs::ProgramCacheEntry,
105 },
106 solana_runtime_transaction::{
107 runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta,
108 },
109 solana_sdk::{
110 account::{
111 create_account_shared_data_with_fields as create_account, from_account, Account,
112 AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
113 },
114 bpf_loader_upgradeable,
115 clock::{
116 BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_HASHES_PER_TICK,
117 DEFAULT_TICKS_PER_SECOND, INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE,
118 MAX_TRANSACTION_FORWARDING_DELAY, SECONDS_PER_DAY, UPDATED_HASHES_PER_TICK2,
119 UPDATED_HASHES_PER_TICK3, UPDATED_HASHES_PER_TICK4, UPDATED_HASHES_PER_TICK5,
120 UPDATED_HASHES_PER_TICK6,
121 },
122 epoch_info::EpochInfo,
123 epoch_schedule::EpochSchedule,
124 feature,
125 fee::{FeeBudgetLimits, FeeDetails, FeeStructure},
126 fee_calculator::FeeRateGovernor,
127 genesis_config::{ClusterType, GenesisConfig},
128 hard_forks::HardForks,
129 hash::{extend_and_hash, hashv, Hash},
130 incinerator,
131 inflation::Inflation,
132 inner_instruction::InnerInstructions,
133 message::{AccountKeys, SanitizedMessage},
134 native_loader,
135 native_token::LAMPORTS_PER_SOL,
136 packet::PACKET_DATA_SIZE,
137 pubkey::Pubkey,
138 rent_collector::{CollectedInfo, RentCollector},
139 rent_debits::RentDebits,
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 },
153 solana_stake_program::points::InflationPointCalculationEvent,
154 solana_svm::{
155 account_loader::{collect_rent_from_account, LoadedTransaction},
156 account_overrides::AccountOverrides,
157 transaction_commit_result::{CommittedTransaction, TransactionCommitResult},
158 transaction_error_metrics::TransactionErrorMetrics,
159 transaction_execution_result::{
160 TransactionExecutionDetails, TransactionLoadedAccountsStats,
161 },
162 transaction_processing_callback::{AccountState, TransactionProcessingCallback},
163 transaction_processing_result::{
164 ProcessedTransaction, TransactionProcessingResult,
165 TransactionProcessingResultExtensions,
166 },
167 transaction_processor::{
168 ExecutionRecordingConfig, TransactionBatchProcessor, TransactionLogMessages,
169 TransactionProcessingConfig, TransactionProcessingEnvironment,
170 },
171 },
172 solana_svm_transaction::svm_message::SVMMessage,
173 solana_timings::{ExecuteTimingType, ExecuteTimings},
174 solana_transaction_context::{TransactionAccount, TransactionReturnData},
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 if self
4001 .feature_set
4002 .is_active(&feature_set::disable_partitioned_rent_collection::id())
4003 {
4004 return;
4005 }
4006
4007 let mut measure = Measure::start("collect_rent_eagerly-ms");
4008 let partitions = self.rent_collection_partitions();
4009 let count = partitions.len();
4010 let rent_metrics = RentMetrics::default();
4011 let mut parallel = count > 1;
4013 if parallel {
4014 let ranges = partitions
4015 .iter()
4016 .map(|partition| {
4017 (
4018 *partition,
4019 accounts_partition::pubkey_range_from_partition(*partition),
4020 )
4021 })
4022 .collect::<Vec<_>>();
4023 'outer: for i in 0..ranges.len() {
4028 for j in 0..ranges.len() {
4029 if i == j {
4030 continue;
4031 }
4032
4033 let i = &ranges[i].1;
4034 let j = &ranges[j].1;
4035 if i.contains(j.start()) || i.contains(j.end()) {
4037 parallel = false;
4038 break 'outer;
4039 }
4040 }
4041 }
4042
4043 if parallel {
4044 let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
4045 thread_pool.install(|| {
4046 ranges.into_par_iter().for_each(|range| {
4047 self.collect_rent_in_range(range.0, range.1, &rent_metrics)
4048 });
4049 });
4050 }
4051 }
4052 if !parallel {
4053 partitions
4055 .into_iter()
4056 .for_each(|partition| self.collect_rent_in_partition(partition, &rent_metrics));
4057 }
4058 measure.stop();
4059 datapoint_info!(
4060 "collect_rent_eagerly",
4061 ("accounts", rent_metrics.count.load(Relaxed), i64),
4062 ("partitions", count, i64),
4063 ("total_time_us", measure.as_us(), i64),
4064 (
4065 "hold_range_us",
4066 rent_metrics.hold_range_us.load(Relaxed),
4067 i64
4068 ),
4069 ("load_us", rent_metrics.load_us.load(Relaxed), i64),
4070 ("collect_us", rent_metrics.collect_us.load(Relaxed), i64),
4071 ("hash_us", rent_metrics.hash_us.load(Relaxed), i64),
4072 ("store_us", rent_metrics.store_us.load(Relaxed), i64),
4073 );
4074 }
4075
4076 fn rent_collection_partitions(&self) -> Vec<Partition> {
4077 if !self.use_fixed_collection_cycle() {
4078 self.variable_cycle_partitions()
4085 } else {
4086 self.fixed_cycle_partitions()
4093 }
4094 }
4095
4096 fn bank_hash_skips_rent_rewrites(&self) -> bool {
4101 self.feature_set
4102 .is_active(&feature_set::skip_rent_rewrites::id())
4103 }
4104
4105 fn should_collect_rent(&self) -> bool {
4107 !self
4108 .feature_set
4109 .is_active(&feature_set::disable_rent_fees_collection::id())
4110 }
4111
4112 fn collect_rent_from_accounts(
4122 &self,
4123 mut accounts: Vec<(Pubkey, AccountSharedData, Slot)>,
4124 rent_paying_pubkeys: Option<&HashSet<Pubkey>>,
4125 partition_index: PartitionIndex,
4126 ) -> CollectRentFromAccountsInfo {
4127 let mut rent_debits = RentDebits::default();
4128 let mut total_rent_collected_info = CollectedInfo::default();
4129 let mut accounts_to_store =
4130 Vec::<(&Pubkey, &AccountSharedData)>::with_capacity(accounts.len());
4131 let mut time_collecting_rent_us = 0;
4132 let mut time_storing_accounts_us = 0;
4133 let can_skip_rewrites = self.bank_hash_skips_rent_rewrites();
4134 let test_skip_rewrites_but_include_in_bank_hash = self
4135 .rc
4136 .accounts
4137 .accounts_db
4138 .test_skip_rewrites_but_include_in_bank_hash;
4139 let mut skipped_rewrites = Vec::default();
4140 for (pubkey, account, _loaded_slot) in accounts.iter_mut() {
4141 let rent_epoch_pre = account.rent_epoch();
4142 let (rent_collected_info, collect_rent_us) = measure_us!(collect_rent_from_account(
4143 &self.feature_set,
4144 &self.rent_collector,
4145 pubkey,
4146 account
4147 ));
4148 time_collecting_rent_us += collect_rent_us;
4149 let rent_epoch_post = account.rent_epoch();
4150
4151 let rent_epoch_changed = rent_epoch_post != rent_epoch_pre;
4153 let account_changed = rent_collected_info.rent_amount != 0 || rent_epoch_changed;
4154
4155 let always_store_accounts =
4157 !can_skip_rewrites && !test_skip_rewrites_but_include_in_bank_hash;
4158
4159 if account_changed || always_store_accounts {
4165 if rent_collected_info.rent_amount > 0 {
4166 if let Some(rent_paying_pubkeys) = rent_paying_pubkeys {
4167 if !rent_paying_pubkeys.contains(pubkey) {
4168 let partition_from_pubkey = accounts_partition::partition_from_pubkey(
4169 pubkey,
4170 self.epoch_schedule.slots_per_epoch,
4171 );
4172 datapoint_warn!(
4174 "bank-unexpected_rent_paying_pubkey",
4175 ("slot", self.slot(), i64),
4176 ("pubkey", pubkey.to_string(), String),
4177 ("partition_index", partition_index, i64),
4178 ("partition_from_pubkey", partition_from_pubkey, i64)
4179 );
4180 warn!(
4181 "Collecting rent from unexpected pubkey: {}, slot: {}, parent_slot: {:?}, \
4182 partition_index: {}, partition_from_pubkey: {}",
4183 pubkey,
4184 self.slot(),
4185 self.parent().map(|bank| bank.slot()),
4186 partition_index,
4187 partition_from_pubkey,
4188 );
4189 }
4190 }
4191 } else {
4192 debug_assert_eq!(rent_collected_info.rent_amount, 0);
4193 if rent_epoch_changed {
4194 datapoint_info!(
4195 "bank-rent_collection_updated_only_rent_epoch",
4196 ("slot", self.slot(), i64),
4197 ("pubkey", pubkey.to_string(), String),
4198 ("rent_epoch_pre", rent_epoch_pre, i64),
4199 ("rent_epoch_post", rent_epoch_post, i64),
4200 );
4201 }
4202 }
4203 total_rent_collected_info += rent_collected_info;
4204 accounts_to_store.push((pubkey, account));
4205 } else if !account_changed
4206 && !can_skip_rewrites
4207 && test_skip_rewrites_but_include_in_bank_hash
4208 {
4209 let hash = AccountsDb::hash_account(account, pubkey);
4214 skipped_rewrites.push((*pubkey, hash));
4215 }
4216 rent_debits.insert(pubkey, rent_collected_info.rent_amount, account.lamports());
4217 }
4218
4219 if !accounts_to_store.is_empty() {
4220 let (_, store_accounts_us) =
4223 measure_us!(self.store_accounts((self.slot(), &accounts_to_store[..])));
4224 time_storing_accounts_us += store_accounts_us;
4225 }
4226
4227 CollectRentFromAccountsInfo {
4228 skipped_rewrites,
4229 rent_collected_info: total_rent_collected_info,
4230 rent_rewards: rent_debits.into_unordered_rewards_iter().collect(),
4231 time_collecting_rent_us,
4232 time_storing_accounts_us,
4233 num_accounts: accounts.len(),
4234 }
4235 }
4236
4237 fn collect_rent_in_partition(&self, partition: Partition, metrics: &RentMetrics) {
4239 let subrange_full = accounts_partition::pubkey_range_from_partition(partition);
4240 self.collect_rent_in_range(partition, subrange_full, metrics)
4241 }
4242
4243 fn get_rent_paying_pubkeys(&self, partition: &Partition) -> Option<HashSet<Pubkey>> {
4245 self.rc
4246 .accounts
4247 .accounts_db
4248 .accounts_index
4249 .rent_paying_accounts_by_partition
4250 .get()
4251 .and_then(|rent_paying_accounts| {
4252 rent_paying_accounts.is_initialized().then(|| {
4253 accounts_partition::get_partition_end_indexes(partition)
4254 .into_iter()
4255 .flat_map(|end_index| {
4256 rent_paying_accounts.get_pubkeys_in_partition_index(end_index)
4257 })
4258 .cloned()
4259 .collect::<HashSet<_>>()
4260 })
4261 })
4262 }
4263
4264 fn collect_rent_in_range(
4269 &self,
4270 partition: Partition,
4271 subrange_full: RangeInclusive<Pubkey>,
4272 metrics: &RentMetrics,
4273 ) {
4274 let mut hold_range = Measure::start("hold_range");
4275 let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
4276 thread_pool.install(|| {
4277 self.rc
4278 .accounts
4279 .hold_range_in_memory(&subrange_full, true, thread_pool);
4280 hold_range.stop();
4281 metrics.hold_range_us.fetch_add(hold_range.as_us(), Relaxed);
4282
4283 let rent_paying_pubkeys_ = self.get_rent_paying_pubkeys(&partition);
4284 let rent_paying_pubkeys = rent_paying_pubkeys_.as_ref();
4285
4286 let num_threads = solana_accounts_db::accounts_db::quarter_thread_count() as u64;
4290 let sz = std::mem::size_of::<u64>();
4291 let start_prefix = accounts_partition::prefix_from_pubkey(subrange_full.start());
4292 let end_prefix_inclusive = accounts_partition::prefix_from_pubkey(subrange_full.end());
4293 let range = end_prefix_inclusive - start_prefix;
4294 let increment = range / num_threads;
4295 let mut results = (0..num_threads)
4296 .into_par_iter()
4297 .map(|chunk| {
4298 let offset = |chunk| start_prefix + chunk * increment;
4299 let start = offset(chunk);
4300 let last = chunk == num_threads - 1;
4301 let merge_prefix = |prefix: u64, mut bound: Pubkey| {
4302 bound.as_mut()[0..sz].copy_from_slice(&prefix.to_be_bytes());
4303 bound
4304 };
4305 let start = merge_prefix(start, *subrange_full.start());
4306 let (accounts, measure_load_accounts) = measure_time!(if last {
4307 let end = *subrange_full.end();
4308 let subrange = start..=end; self.rc
4310 .accounts
4311 .load_to_collect_rent_eagerly(&self.ancestors, subrange)
4312 } else {
4313 let end = merge_prefix(offset(chunk + 1), *subrange_full.start());
4314 let subrange = start..end; self.rc
4316 .accounts
4317 .load_to_collect_rent_eagerly(&self.ancestors, subrange)
4318 });
4319 CollectRentInPartitionInfo::new(
4320 self.collect_rent_from_accounts(accounts, rent_paying_pubkeys, partition.1),
4321 Duration::from_nanos(measure_load_accounts.as_ns()),
4322 )
4323 })
4324 .reduce(
4325 CollectRentInPartitionInfo::default,
4326 CollectRentInPartitionInfo::reduce,
4327 );
4328
4329 self.skipped_rewrites
4330 .lock()
4331 .unwrap()
4332 .extend(results.skipped_rewrites);
4333
4334 self.rc
4338 .accounts
4339 .hold_range_in_memory(&subrange_full, false, thread_pool);
4340
4341 self.collected_rent
4342 .fetch_add(results.rent_collected, Relaxed);
4343 self.update_accounts_data_size_delta_off_chain(
4344 -(results.accounts_data_size_reclaimed as i64),
4345 );
4346 self.rewards
4347 .write()
4348 .unwrap()
4349 .append(&mut results.rent_rewards);
4350
4351 metrics
4352 .load_us
4353 .fetch_add(results.time_loading_accounts_us, Relaxed);
4354 metrics
4355 .collect_us
4356 .fetch_add(results.time_collecting_rent_us, Relaxed);
4357 metrics
4358 .store_us
4359 .fetch_add(results.time_storing_accounts_us, Relaxed);
4360 metrics.count.fetch_add(results.num_accounts, Relaxed);
4361 });
4362 }
4363
4364 pub(crate) fn fixed_cycle_partitions_between_slots(
4365 &self,
4366 starting_slot: Slot,
4367 ending_slot: Slot,
4368 ) -> Vec<Partition> {
4369 let slot_count_in_two_day = self.slot_count_in_two_day();
4370 accounts_partition::get_partitions(ending_slot, starting_slot, slot_count_in_two_day)
4371 }
4372
4373 fn fixed_cycle_partitions(&self) -> Vec<Partition> {
4374 self.fixed_cycle_partitions_between_slots(self.parent_slot(), self.slot())
4375 }
4376
4377 pub(crate) fn variable_cycle_partitions_between_slots(
4378 &self,
4379 starting_slot: Slot,
4380 ending_slot: Slot,
4381 ) -> Vec<Partition> {
4382 let (starting_epoch, mut starting_slot_index) =
4383 self.get_epoch_and_slot_index(starting_slot);
4384 let (ending_epoch, ending_slot_index) = self.get_epoch_and_slot_index(ending_slot);
4385
4386 let mut partitions = vec![];
4387 if starting_epoch < ending_epoch {
4388 let slot_skipped = (ending_slot - starting_slot) > 1;
4389 if slot_skipped {
4390 let parent_last_slot_index = self.get_slots_in_epoch(starting_epoch) - 1;
4394
4395 partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
4397 starting_slot_index,
4398 parent_last_slot_index,
4399 starting_epoch,
4400 ));
4401
4402 if ending_slot_index > 0 {
4403 partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
4405 0,
4406 0,
4407 ending_epoch,
4408 ));
4409 }
4410 }
4411 starting_slot_index = 0;
4412 }
4413
4414 partitions.push(self.partition_from_normal_slot_indexes(
4415 starting_slot_index,
4416 ending_slot_index,
4417 ending_epoch,
4418 ));
4419
4420 partitions
4421 }
4422
4423 fn variable_cycle_partitions(&self) -> Vec<Partition> {
4424 self.variable_cycle_partitions_between_slots(self.parent_slot(), self.slot())
4425 }
4426
4427 fn do_partition_from_slot_indexes(
4428 &self,
4429 start_slot_index: SlotIndex,
4430 end_slot_index: SlotIndex,
4431 epoch: Epoch,
4432 generated_for_gapped_epochs: bool,
4433 ) -> Partition {
4434 let slot_count_per_epoch = self.get_slots_in_epoch(epoch);
4435
4436 let cycle_params = if !self.use_multi_epoch_collection_cycle(epoch) {
4437 accounts_partition::rent_single_epoch_collection_cycle_params(
4439 epoch,
4440 slot_count_per_epoch,
4441 )
4442 } else {
4443 accounts_partition::rent_multi_epoch_collection_cycle_params(
4444 epoch,
4445 slot_count_per_epoch,
4446 self.first_normal_epoch(),
4447 self.slot_count_in_two_day() / slot_count_per_epoch,
4448 )
4449 };
4450 accounts_partition::get_partition_from_slot_indexes(
4451 cycle_params,
4452 start_slot_index,
4453 end_slot_index,
4454 generated_for_gapped_epochs,
4455 )
4456 }
4457
4458 fn partition_from_normal_slot_indexes(
4459 &self,
4460 start_slot_index: SlotIndex,
4461 end_slot_index: SlotIndex,
4462 epoch: Epoch,
4463 ) -> Partition {
4464 self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, false)
4465 }
4466
4467 fn partition_from_slot_indexes_with_gapped_epochs(
4468 &self,
4469 start_slot_index: SlotIndex,
4470 end_slot_index: SlotIndex,
4471 epoch: Epoch,
4472 ) -> Partition {
4473 self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, true)
4474 }
4475
4476 fn use_multi_epoch_collection_cycle(&self, epoch: Epoch) -> bool {
4482 #[cfg(not(test))]
4484 if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
4485 {
4486 return false;
4487 }
4488
4489 epoch >= self.first_normal_epoch()
4490 && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
4491 }
4492
4493 pub(crate) fn use_fixed_collection_cycle(&self) -> bool {
4494 #[cfg(not(test))]
4496 if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
4497 {
4498 return false;
4499 }
4500
4501 self.cluster_type() != ClusterType::MainnetBeta
4502 && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
4503 }
4504
4505 fn slot_count_in_two_day(&self) -> SlotCount {
4506 Self::slot_count_in_two_day_helper(self.ticks_per_slot)
4507 }
4508
4509 pub fn slot_count_in_two_day_helper(ticks_per_slot: SlotCount) -> SlotCount {
4513 2 * DEFAULT_TICKS_PER_SECOND * SECONDS_PER_DAY / ticks_per_slot
4514 }
4515
4516 fn slot_count_per_normal_epoch(&self) -> SlotCount {
4517 self.get_slots_in_epoch(self.first_normal_epoch())
4518 }
4519
4520 pub fn cluster_type(&self) -> ClusterType {
4521 self.cluster_type.unwrap()
4524 }
4525
4526 #[must_use]
4528 pub fn load_execute_and_commit_transactions(
4529 &self,
4530 batch: &TransactionBatch<impl TransactionWithMeta>,
4531 max_age: usize,
4532 collect_balances: bool,
4533 recording_config: ExecutionRecordingConfig,
4534 timings: &mut ExecuteTimings,
4535 log_messages_bytes_limit: Option<usize>,
4536 ) -> (Vec<TransactionCommitResult>, TransactionBalancesSet) {
4537 self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4538 batch,
4539 max_age,
4540 collect_balances,
4541 recording_config,
4542 timings,
4543 log_messages_bytes_limit,
4544 None::<fn(&mut _, &_) -> _>,
4545 )
4546 .unwrap()
4547 }
4548
4549 pub fn load_execute_and_commit_transactions_with_pre_commit_callback<'a>(
4550 &'a self,
4551 batch: &TransactionBatch<impl TransactionWithMeta>,
4552 max_age: usize,
4553 collect_balances: bool,
4554 recording_config: ExecutionRecordingConfig,
4555 timings: &mut ExecuteTimings,
4556 log_messages_bytes_limit: Option<usize>,
4557 pre_commit_callback: impl FnOnce(
4558 &mut ExecuteTimings,
4559 &[TransactionProcessingResult],
4560 ) -> PreCommitResult<'a>,
4561 ) -> Result<(Vec<TransactionCommitResult>, TransactionBalancesSet)> {
4562 self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4563 batch,
4564 max_age,
4565 collect_balances,
4566 recording_config,
4567 timings,
4568 log_messages_bytes_limit,
4569 Some(pre_commit_callback),
4570 )
4571 }
4572
4573 fn do_load_execute_and_commit_transactions_with_pre_commit_callback<'a>(
4574 &'a self,
4575 batch: &TransactionBatch<impl TransactionWithMeta>,
4576 max_age: usize,
4577 collect_balances: bool,
4578 recording_config: ExecutionRecordingConfig,
4579 timings: &mut ExecuteTimings,
4580 log_messages_bytes_limit: Option<usize>,
4581 pre_commit_callback: Option<
4582 impl FnOnce(&mut ExecuteTimings, &[TransactionProcessingResult]) -> PreCommitResult<'a>,
4583 >,
4584 ) -> Result<(Vec<TransactionCommitResult>, TransactionBalancesSet)> {
4585 let pre_balances = if collect_balances {
4586 self.collect_balances(batch)
4587 } else {
4588 vec![]
4589 };
4590
4591 let LoadAndExecuteTransactionsOutput {
4592 processing_results,
4593 processed_counts,
4594 } = self.load_and_execute_transactions(
4595 batch,
4596 max_age,
4597 timings,
4598 &mut TransactionErrorMetrics::default(),
4599 TransactionProcessingConfig {
4600 account_overrides: None,
4601 check_program_modification_slot: self.check_program_modification_slot,
4602 compute_budget: self.compute_budget(),
4603 log_messages_bytes_limit,
4604 limit_to_load_programs: false,
4605 recording_config,
4606 transaction_account_lock_limit: Some(self.get_transaction_account_lock_limit()),
4607 },
4608 );
4609
4610 let freeze_lock = if let Some(pre_commit_callback) = pre_commit_callback {
4615 pre_commit_callback(timings, &processing_results)?
4616 } else {
4617 None
4618 };
4619 let commit_results = self.commit_transactions(
4620 batch.sanitized_transactions(),
4621 processing_results,
4622 &processed_counts,
4623 timings,
4624 );
4625 drop(freeze_lock);
4626 let post_balances = if collect_balances {
4627 self.collect_balances(batch)
4628 } else {
4629 vec![]
4630 };
4631 Ok((
4632 commit_results,
4633 TransactionBalancesSet::new(pre_balances, post_balances),
4634 ))
4635 }
4636
4637 pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
4640 self.try_process_transactions(std::iter::once(tx))?[0].clone()?;
4641 tx.signatures
4642 .first()
4643 .map_or(Ok(()), |sig| self.get_signature_status(sig).unwrap())
4644 }
4645
4646 pub fn process_transaction_with_metadata(
4649 &self,
4650 tx: impl Into<VersionedTransaction>,
4651 ) -> Result<CommittedTransaction> {
4652 let txs = vec![tx.into()];
4653 let batch = self.prepare_entry_batch(txs)?;
4654
4655 let (mut commit_results, ..) = self.load_execute_and_commit_transactions(
4656 &batch,
4657 MAX_PROCESSING_AGE,
4658 false, ExecutionRecordingConfig {
4660 enable_cpi_recording: false,
4661 enable_log_recording: true,
4662 enable_return_data_recording: true,
4663 },
4664 &mut ExecuteTimings::default(),
4665 Some(1000 * 1000),
4666 );
4667
4668 commit_results.remove(0)
4669 }
4670
4671 pub fn try_process_transactions<'a>(
4674 &self,
4675 txs: impl Iterator<Item = &'a Transaction>,
4676 ) -> Result<Vec<Result<()>>> {
4677 let txs = txs
4678 .map(|tx| VersionedTransaction::from(tx.clone()))
4679 .collect();
4680 self.try_process_entry_transactions(txs)
4681 }
4682
4683 pub fn try_process_entry_transactions(
4686 &self,
4687 txs: Vec<VersionedTransaction>,
4688 ) -> Result<Vec<Result<()>>> {
4689 let batch = self.prepare_entry_batch(txs)?;
4690 Ok(self.process_transaction_batch(&batch))
4691 }
4692
4693 #[must_use]
4694 fn process_transaction_batch(
4695 &self,
4696 batch: &TransactionBatch<impl TransactionWithMeta>,
4697 ) -> Vec<Result<()>> {
4698 self.load_execute_and_commit_transactions(
4699 batch,
4700 MAX_PROCESSING_AGE,
4701 false,
4702 ExecutionRecordingConfig::new_single_setting(false),
4703 &mut ExecuteTimings::default(),
4704 None,
4705 )
4706 .0
4707 .into_iter()
4708 .map(|commit_result| commit_result.map(|_| ()))
4709 .collect()
4710 }
4711
4712 pub fn transfer(&self, n: u64, keypair: &Keypair, to: &Pubkey) -> Result<Signature> {
4715 let blockhash = self.last_blockhash();
4716 let tx = system_transaction::transfer(keypair, to, n, blockhash);
4717 let signature = tx.signatures[0];
4718 self.process_transaction(&tx).map(|_| signature)
4719 }
4720
4721 pub fn read_balance(account: &AccountSharedData) -> u64 {
4722 account.lamports()
4723 }
4724 pub fn get_balance(&self, pubkey: &Pubkey) -> u64 {
4727 self.get_account(pubkey)
4728 .map(|x| Self::read_balance(&x))
4729 .unwrap_or(0)
4730 }
4731
4732 pub fn parents(&self) -> Vec<Arc<Bank>> {
4734 let mut parents = vec![];
4735 let mut bank = self.parent();
4736 while let Some(parent) = bank {
4737 parents.push(parent.clone());
4738 bank = parent.parent();
4739 }
4740 parents
4741 }
4742
4743 pub fn parents_inclusive(self: Arc<Self>) -> Vec<Arc<Bank>> {
4745 let mut parents = self.parents();
4746 parents.insert(0, self);
4747 parents
4748 }
4749
4750 pub fn store_account(&self, pubkey: &Pubkey, account: &AccountSharedData) {
4753 self.store_accounts((self.slot(), &[(pubkey, account)][..]))
4754 }
4755
4756 pub fn store_accounts<'a>(&self, accounts: impl StorableAccounts<'a>) {
4757 assert!(!self.freeze_started());
4758 let mut m = Measure::start("stakes_cache.check_and_store");
4759 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
4760
4761 (0..accounts.len()).for_each(|i| {
4762 accounts.account(i, |account| {
4763 self.stakes_cache.check_and_store(
4764 account.pubkey(),
4765 &account,
4766 new_warmup_cooldown_rate_epoch,
4767 )
4768 })
4769 });
4770 self.update_bank_hash_stats(&accounts);
4771 self.rc.accounts.store_accounts_cached(accounts);
4772 m.stop();
4773 self.rc
4774 .accounts
4775 .accounts_db
4776 .stats
4777 .stakes_cache_check_and_store_us
4778 .fetch_add(m.as_us(), Relaxed);
4779 }
4780
4781 pub fn force_flush_accounts_cache(&self) {
4782 self.rc
4783 .accounts
4784 .accounts_db
4785 .flush_accounts_cache(true, Some(self.slot()))
4786 }
4787
4788 pub fn flush_accounts_cache_if_needed(&self) {
4789 self.rc
4790 .accounts
4791 .accounts_db
4792 .flush_accounts_cache(false, Some(self.slot()))
4793 }
4794
4795 fn store_account_and_update_capitalization(
4798 &self,
4799 pubkey: &Pubkey,
4800 new_account: &AccountSharedData,
4801 ) {
4802 let old_account_data_size =
4803 if let Some(old_account) = self.get_account_with_fixed_root_no_cache(pubkey) {
4804 match new_account.lamports().cmp(&old_account.lamports()) {
4805 std::cmp::Ordering::Greater => {
4806 let increased = new_account.lamports() - old_account.lamports();
4807 trace!(
4808 "store_account_and_update_capitalization: increased: {} {}",
4809 pubkey,
4810 increased
4811 );
4812 self.capitalization.fetch_add(increased, Relaxed);
4813 }
4814 std::cmp::Ordering::Less => {
4815 let decreased = old_account.lamports() - new_account.lamports();
4816 trace!(
4817 "store_account_and_update_capitalization: decreased: {} {}",
4818 pubkey,
4819 decreased
4820 );
4821 self.capitalization.fetch_sub(decreased, Relaxed);
4822 }
4823 std::cmp::Ordering::Equal => {}
4824 }
4825 old_account.data().len()
4826 } else {
4827 trace!(
4828 "store_account_and_update_capitalization: created: {} {}",
4829 pubkey,
4830 new_account.lamports()
4831 );
4832 self.capitalization
4833 .fetch_add(new_account.lamports(), Relaxed);
4834 0
4835 };
4836
4837 self.store_account(pubkey, new_account);
4838 self.calculate_and_update_accounts_data_size_delta_off_chain(
4839 old_account_data_size,
4840 new_account.data().len(),
4841 );
4842 }
4843
4844 pub fn accounts(&self) -> Arc<Accounts> {
4845 self.rc.accounts.clone()
4846 }
4847
4848 fn finish_init(
4849 &mut self,
4850 genesis_config: &GenesisConfig,
4851 additional_builtins: Option<&[BuiltinPrototype]>,
4852 debug_do_not_add_builtins: bool,
4853 ) {
4854 self.rewards_pool_pubkeys =
4855 Arc::new(genesis_config.rewards_pools.keys().cloned().collect());
4856
4857 self.apply_feature_activations(
4858 ApplyFeatureActivationsCaller::FinishInit,
4859 debug_do_not_add_builtins,
4860 );
4861
4862 if self
4867 .feature_set
4868 .is_active(&feature_set::raise_block_limits_to_50m::id())
4869 {
4870 let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits();
4871 self.write_cost_tracker().unwrap().set_limits(
4872 account_cost_limit,
4873 block_cost_limit,
4874 vote_cost_limit,
4875 );
4876 }
4877
4878 if !self
4880 .feature_set
4881 .is_active(&feature_set::remove_accounts_delta_hash::id())
4882 {
4883 self.rc.accounts.accounts_db.start_background_hasher();
4884 }
4885
4886 if !debug_do_not_add_builtins {
4887 for builtin in BUILTINS
4888 .iter()
4889 .chain(additional_builtins.unwrap_or(&[]).iter())
4890 {
4891 let builtin_is_bpf = |program_id: &Pubkey| {
4897 self.get_account(program_id)
4898 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
4899 .unwrap_or(false)
4900 };
4901 if builtin.enable_feature_id.is_none() && !builtin_is_bpf(&builtin.program_id) {
4902 self.transaction_processor.add_builtin(
4903 self,
4904 builtin.program_id,
4905 builtin.name,
4906 ProgramCacheEntry::new_builtin(0, builtin.name.len(), builtin.entrypoint),
4907 );
4908 }
4909 }
4910 for precompile in get_precompiles() {
4911 if precompile.feature.is_none() {
4912 self.add_precompile(&precompile.program_id);
4913 }
4914 }
4915 }
4916
4917 self.transaction_processor
4918 .configure_program_runtime_environments(
4919 Some(Arc::new(
4920 create_program_runtime_environment_v1(
4921 &self.feature_set,
4922 &self.compute_budget().unwrap_or_default(),
4923 false, false, )
4926 .unwrap(),
4927 )),
4928 Some(Arc::new(create_program_runtime_environment_v2(
4929 &self.compute_budget().unwrap_or_default(),
4930 false, ))),
4932 );
4933 }
4934
4935 pub fn set_inflation(&self, inflation: Inflation) {
4936 *self.inflation.write().unwrap() = inflation;
4937 }
4938
4939 pub fn hard_forks(&self) -> HardForks {
4941 self.hard_forks.read().unwrap().clone()
4942 }
4943
4944 pub fn register_hard_fork(&self, new_hard_fork_slot: Slot) {
4945 let bank_slot = self.slot();
4946
4947 let lock = self.freeze_lock();
4948 let bank_frozen = *lock != Hash::default();
4949 if new_hard_fork_slot < bank_slot {
4950 warn!(
4951 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is older \
4952 than the bank at slot {bank_slot} that attempted to register it."
4953 );
4954 } else if (new_hard_fork_slot == bank_slot) && bank_frozen {
4955 warn!(
4956 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is the same \
4957 slot as the bank at slot {bank_slot} that attempted to register it, but that \
4958 bank is already frozen."
4959 );
4960 } else {
4961 self.hard_forks
4962 .write()
4963 .unwrap()
4964 .register(new_hard_fork_slot);
4965 }
4966 }
4967
4968 pub fn get_account_with_fixed_root_no_cache(
4969 &self,
4970 pubkey: &Pubkey,
4971 ) -> Option<AccountSharedData> {
4972 self.load_account_with(pubkey, |_| false)
4973 .map(|(acc, _slot)| acc)
4974 }
4975
4976 fn load_account_with(
4977 &self,
4978 pubkey: &Pubkey,
4979 callback: impl for<'local> Fn(&'local AccountSharedData) -> bool,
4980 ) -> Option<(AccountSharedData, Slot)> {
4981 self.rc
4982 .accounts
4983 .accounts_db
4984 .load_account_with(&self.ancestors, pubkey, callback)
4985 }
4986
4987 pub fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
4991 self.get_account_modified_slot(pubkey)
4992 .map(|(acc, _slot)| acc)
4993 }
4994
4995 pub fn get_account_with_fixed_root(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
5002 self.get_account_modified_slot_with_fixed_root(pubkey)
5003 .map(|(acc, _slot)| acc)
5004 }
5005
5006 pub fn get_account_modified_slot_with_fixed_root(
5008 &self,
5009 pubkey: &Pubkey,
5010 ) -> Option<(AccountSharedData, Slot)> {
5011 self.load_slow_with_fixed_root(&self.ancestors, pubkey)
5012 }
5013
5014 pub fn get_account_modified_slot(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
5015 self.load_slow(&self.ancestors, pubkey)
5016 }
5017
5018 fn load_slow(
5019 &self,
5020 ancestors: &Ancestors,
5021 pubkey: &Pubkey,
5022 ) -> Option<(AccountSharedData, Slot)> {
5023 self.rc.accounts.load_without_fixed_root(ancestors, pubkey)
5027 }
5028
5029 fn load_slow_with_fixed_root(
5030 &self,
5031 ancestors: &Ancestors,
5032 pubkey: &Pubkey,
5033 ) -> Option<(AccountSharedData, Slot)> {
5034 self.rc.accounts.load_with_fixed_root(ancestors, pubkey)
5035 }
5036
5037 pub fn get_program_accounts(
5038 &self,
5039 program_id: &Pubkey,
5040 config: &ScanConfig,
5041 ) -> ScanResult<Vec<TransactionAccount>> {
5042 self.rc
5043 .accounts
5044 .load_by_program(&self.ancestors, self.bank_id, program_id, config)
5045 }
5046
5047 pub fn get_filtered_program_accounts<F: Fn(&AccountSharedData) -> bool>(
5048 &self,
5049 program_id: &Pubkey,
5050 filter: F,
5051 config: &ScanConfig,
5052 ) -> ScanResult<Vec<TransactionAccount>> {
5053 self.rc.accounts.load_by_program_with_filter(
5054 &self.ancestors,
5055 self.bank_id,
5056 program_id,
5057 filter,
5058 config,
5059 )
5060 }
5061
5062 pub fn get_filtered_indexed_accounts<F: Fn(&AccountSharedData) -> bool>(
5063 &self,
5064 index_key: &IndexKey,
5065 filter: F,
5066 config: &ScanConfig,
5067 byte_limit_for_scan: Option<usize>,
5068 ) -> ScanResult<Vec<TransactionAccount>> {
5069 self.rc.accounts.load_by_index_key_with_filter(
5070 &self.ancestors,
5071 self.bank_id,
5072 index_key,
5073 filter,
5074 config,
5075 byte_limit_for_scan,
5076 )
5077 }
5078
5079 pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
5080 self.rc.accounts.account_indexes_include_key(key)
5081 }
5082
5083 pub fn get_all_accounts(&self, sort_results: bool) -> ScanResult<Vec<PubkeyAccountSlot>> {
5085 self.rc
5086 .accounts
5087 .load_all(&self.ancestors, self.bank_id, sort_results)
5088 }
5089
5090 pub fn scan_all_accounts<F>(&self, scan_func: F, sort_results: bool) -> ScanResult<()>
5092 where
5093 F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>),
5094 {
5095 self.rc
5096 .accounts
5097 .scan_all(&self.ancestors, self.bank_id, scan_func, sort_results)
5098 }
5099
5100 pub fn get_program_accounts_modified_since_parent(
5101 &self,
5102 program_id: &Pubkey,
5103 ) -> Vec<TransactionAccount> {
5104 self.rc
5105 .accounts
5106 .load_by_program_slot(self.slot(), Some(program_id))
5107 }
5108
5109 pub fn get_transaction_logs(
5110 &self,
5111 address: Option<&Pubkey>,
5112 ) -> Option<Vec<TransactionLogInfo>> {
5113 self.transaction_log_collector
5114 .read()
5115 .unwrap()
5116 .get_logs_for_address(address)
5117 }
5118
5119 pub fn get_all_accounts_modified_since_parent(&self) -> Vec<TransactionAccount> {
5121 self.rc.accounts.load_by_program_slot(self.slot(), None)
5122 }
5123
5124 fn get_account_modified_since_parent_with_fixed_root(
5126 &self,
5127 pubkey: &Pubkey,
5128 ) -> Option<(AccountSharedData, Slot)> {
5129 let just_self: Ancestors = Ancestors::from(vec![self.slot()]);
5130 if let Some((account, slot)) = self.load_slow_with_fixed_root(&just_self, pubkey) {
5131 if slot == self.slot() {
5132 return Some((account, slot));
5133 }
5134 }
5135 None
5136 }
5137
5138 pub fn get_largest_accounts(
5139 &self,
5140 num: usize,
5141 filter_by_address: &HashSet<Pubkey>,
5142 filter: AccountAddressFilter,
5143 sort_results: bool,
5144 ) -> ScanResult<Vec<(Pubkey, u64)>> {
5145 self.rc.accounts.load_largest_accounts(
5146 &self.ancestors,
5147 self.bank_id,
5148 num,
5149 filter_by_address,
5150 filter,
5151 sort_results,
5152 )
5153 }
5154
5155 pub fn transaction_count(&self) -> u64 {
5157 self.transaction_count.load(Relaxed)
5158 }
5159
5160 pub fn non_vote_transaction_count_since_restart(&self) -> u64 {
5165 self.non_vote_transaction_count_since_restart.load(Relaxed)
5166 }
5167
5168 pub fn executed_transaction_count(&self) -> u64 {
5170 self.transaction_count()
5171 .saturating_sub(self.parent().map_or(0, |parent| parent.transaction_count()))
5172 }
5173
5174 pub fn transaction_error_count(&self) -> u64 {
5175 self.transaction_error_count.load(Relaxed)
5176 }
5177
5178 pub fn transaction_entries_count(&self) -> u64 {
5179 self.transaction_entries_count.load(Relaxed)
5180 }
5181
5182 pub fn transactions_per_entry_max(&self) -> u64 {
5183 self.transactions_per_entry_max.load(Relaxed)
5184 }
5185
5186 fn increment_transaction_count(&self, tx_count: u64) {
5187 self.transaction_count.fetch_add(tx_count, Relaxed);
5188 }
5189
5190 fn increment_non_vote_transaction_count_since_restart(&self, tx_count: u64) {
5191 self.non_vote_transaction_count_since_restart
5192 .fetch_add(tx_count, Relaxed);
5193 }
5194
5195 pub fn signature_count(&self) -> u64 {
5196 self.signature_count.load(Relaxed)
5197 }
5198
5199 fn increment_signature_count(&self, signature_count: u64) {
5200 self.signature_count.fetch_add(signature_count, Relaxed);
5201 }
5202
5203 pub fn get_signature_status_processed_since_parent(
5204 &self,
5205 signature: &Signature,
5206 ) -> Option<Result<()>> {
5207 if let Some((slot, status)) = self.get_signature_status_slot(signature) {
5208 if slot <= self.slot() {
5209 return Some(status);
5210 }
5211 }
5212 None
5213 }
5214
5215 pub fn get_signature_status_with_blockhash(
5216 &self,
5217 signature: &Signature,
5218 blockhash: &Hash,
5219 ) -> Option<Result<()>> {
5220 let rcache = self.status_cache.read().unwrap();
5221 rcache
5222 .get_status(signature, blockhash, &self.ancestors)
5223 .map(|v| v.1)
5224 }
5225
5226 pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
5227 let rcache = self.status_cache.read().unwrap();
5228 rcache.get_status_any_blockhash(signature, &self.ancestors)
5229 }
5230
5231 pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
5232 self.get_signature_status_slot(signature).map(|v| v.1)
5233 }
5234
5235 pub fn has_signature(&self, signature: &Signature) -> bool {
5236 self.get_signature_status_slot(signature).is_some()
5237 }
5238
5239 fn hash_internal_state(&self) -> Hash {
5242 let measure_total = Measure::start("");
5243 let slot = self.slot();
5244
5245 let delta_hash_info = (!self
5246 .feature_set
5247 .is_active(&feature_set::remove_accounts_delta_hash::id()))
5248 .then(|| {
5249 measure_us!({
5250 self.rc
5251 .accounts
5252 .accounts_db
5253 .calculate_accounts_delta_hash_internal(
5254 slot,
5255 None,
5256 self.skipped_rewrites.lock().unwrap().clone(),
5257 )
5258 })
5259 });
5260
5261 let mut hash = if let Some((accounts_delta_hash, _measure)) = delta_hash_info.as_ref() {
5262 hashv(&[
5263 self.parent_hash.as_ref(),
5264 accounts_delta_hash.0.as_ref(),
5265 &self.signature_count().to_le_bytes(),
5266 self.last_blockhash().as_ref(),
5267 ])
5268 } else {
5269 hashv(&[
5270 self.parent_hash.as_ref(),
5271 &self.signature_count().to_le_bytes(),
5272 self.last_blockhash().as_ref(),
5273 ])
5274 };
5275
5276 let accounts_hash_info = if self
5277 .feature_set
5278 .is_active(&feature_set::accounts_lt_hash::id())
5279 {
5280 let accounts_lt_hash = &*self.accounts_lt_hash.lock().unwrap();
5281 let lt_hash_bytes = bytemuck::must_cast_slice(&accounts_lt_hash.0 .0);
5282 hash = hashv(&[hash.as_ref(), lt_hash_bytes]);
5283 let checksum = accounts_lt_hash.0.checksum();
5284 Some(format!(", accounts_lt_hash checksum: {checksum}"))
5285 } else {
5286 let epoch_accounts_hash = self.wait_get_epoch_accounts_hash();
5287 epoch_accounts_hash.map(|epoch_accounts_hash| {
5288 hash = hashv(&[hash.as_ref(), epoch_accounts_hash.as_ref().as_ref()]);
5289 format!(", epoch_accounts_hash: {:?}", epoch_accounts_hash.as_ref())
5290 })
5291 };
5292
5293 let buf = self
5294 .hard_forks
5295 .read()
5296 .unwrap()
5297 .get_hash_data(slot, self.parent_slot());
5298 if let Some(buf) = buf {
5299 let hard_forked_hash = extend_and_hash(&hash, &buf);
5300 warn!("hard fork at slot {slot} by hashing {buf:?}: {hash} => {hard_forked_hash}");
5301 hash = hard_forked_hash;
5302 }
5303
5304 #[cfg(feature = "dev-context-only-utils")]
5305 let hash_override = self
5306 .hash_overrides
5307 .lock()
5308 .unwrap()
5309 .get_bank_hash_override(slot)
5310 .copied()
5311 .inspect(|&hash_override| {
5312 if hash_override != hash {
5313 info!(
5314 "bank: slot: {}: overrode bank hash: {} with {}",
5315 self.slot(),
5316 hash,
5317 hash_override
5318 );
5319 }
5320 });
5321 #[cfg(feature = "dev-context-only-utils")]
5325 let hash = hash_override.unwrap_or(std::hint::black_box(hash));
5326
5327 let bank_hash_stats = self.bank_hash_stats.load();
5328
5329 let total_us = measure_total.end_as_us();
5330
5331 let (accounts_delta_hash_us, accounts_delta_hash_log) = delta_hash_info
5332 .map(|(hash, us)| (us, format!(" accounts_delta: {}", hash.0)))
5333 .unzip();
5334 datapoint_info!(
5335 "bank-hash_internal_state",
5336 ("slot", slot, i64),
5337 ("total_us", total_us, i64),
5338 ("accounts_delta_hash_us", accounts_delta_hash_us, Option<i64>),
5339 );
5340 info!(
5341 "bank frozen: {slot} hash: {hash}{} signature_count: {} last_blockhash: {} capitalization: {}{}, stats: {bank_hash_stats:?}",
5342 accounts_delta_hash_log.unwrap_or_default(),
5343 self.signature_count(),
5344 self.last_blockhash(),
5345 self.capitalization(),
5346 accounts_hash_info.unwrap_or_default(),
5347 );
5348 hash
5349 }
5350
5351 pub fn collector_fees(&self) -> u64 {
5352 self.collector_fees.load(Relaxed)
5353 }
5354
5355 fn should_include_epoch_accounts_hash(&self) -> bool {
5358 if !epoch_accounts_hash_utils::is_enabled_this_epoch(self) {
5359 return false;
5360 }
5361
5362 let stop_slot = epoch_accounts_hash_utils::calculation_stop(self);
5363 self.parent_slot() < stop_slot && self.slot() >= stop_slot
5364 }
5365
5366 fn wait_get_epoch_accounts_hash(&self) -> Option<EpochAccountsHash> {
5369 if !self.should_include_epoch_accounts_hash() {
5370 return None;
5371 }
5372
5373 let (epoch_accounts_hash, waiting_time_us) = measure_us!(self
5374 .rc
5375 .accounts
5376 .accounts_db
5377 .epoch_accounts_hash_manager
5378 .wait_get_epoch_accounts_hash());
5379
5380 datapoint_info!(
5381 "bank-wait_get_epoch_accounts_hash",
5382 ("slot", self.slot(), i64),
5383 ("waiting-time-us", waiting_time_us, i64),
5384 );
5385 Some(epoch_accounts_hash)
5386 }
5387
5388 pub fn run_final_hash_calc(&self, on_halt_store_hash_raw_data_for_debug: bool) {
5391 self.force_flush_accounts_cache();
5392 _ = self.verify_accounts_hash(
5394 None,
5395 VerifyAccountsHashConfig {
5396 test_hash_calculation: false,
5397 ignore_mismatch: true,
5398 require_rooted_bank: false,
5399 run_in_background: false,
5400 store_hash_raw_data_for_debug: on_halt_store_hash_raw_data_for_debug,
5401 },
5402 None,
5403 );
5404 }
5405
5406 #[must_use]
5410 fn verify_accounts_hash(
5411 &self,
5412 base: Option<(Slot, u64)>,
5413 mut config: VerifyAccountsHashConfig,
5414 duplicates_lt_hash: Option<Box<DuplicatesLtHash>>,
5415 ) -> bool {
5416 #[derive(Debug, Eq, PartialEq)]
5417 enum VerifyKind {
5418 Merkle,
5419 Lattice,
5420 }
5421
5422 let accounts = &self.rc.accounts;
5423 accounts
5426 .accounts_db
5427 .verify_accounts_hash_in_bg
5428 .join_background_thread();
5429
5430 let slot = self.slot();
5431
5432 let verify_kind = match (
5433 duplicates_lt_hash.is_some(),
5434 self.rc
5435 .accounts
5436 .accounts_db
5437 .is_experimental_accumulator_hash_enabled(),
5438 ) {
5439 (true, _) => VerifyKind::Lattice,
5440 (false, false) => VerifyKind::Merkle,
5441 (false, true) => {
5442 config.run_in_background = false;
5446 VerifyKind::Lattice
5447 }
5448 };
5449
5450 if config.require_rooted_bank && !accounts.accounts_db.accounts_index.is_alive_root(slot) {
5451 if let Some(parent) = self.parent() {
5452 info!(
5453 "slot {slot} is not a root, so verify accounts hash on parent bank at slot {}",
5454 parent.slot(),
5455 );
5456 if verify_kind == VerifyKind::Lattice {
5457 config.run_in_background = false;
5461 }
5462 return parent.verify_accounts_hash(base, config, None);
5463 } else {
5464 panic!("cannot verify accounts hash because slot {slot} is not a root");
5467 }
5468 }
5469
5470 let snapshot_storages = self.rc.accounts.accounts_db.get_storages(RangeFull);
5474 let capitalization = self.capitalization();
5475 let verify_config = VerifyAccountsHashAndLamportsConfig {
5476 ancestors: &self.ancestors,
5477 epoch_schedule: self.epoch_schedule(),
5478 rent_collector: self.rent_collector(),
5479 test_hash_calculation: config.test_hash_calculation,
5480 ignore_mismatch: config.ignore_mismatch,
5481 store_detailed_debug_info: config.store_hash_raw_data_for_debug,
5482 use_bg_thread_pool: config.run_in_background,
5483 };
5484
5485 info!(
5486 "Verifying accounts, in background? {}, verify kind: {verify_kind:?}",
5487 config.run_in_background,
5488 );
5489 if config.run_in_background {
5490 let accounts = Arc::clone(accounts);
5491 let accounts_ = Arc::clone(&accounts);
5492 let ancestors = self.ancestors.clone();
5493 let epoch_schedule = self.epoch_schedule().clone();
5494 let rent_collector = self.rent_collector().clone();
5495 let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5496 accounts.accounts_db.verify_accounts_hash_in_bg.start(|| {
5497 Builder::new()
5498 .name("solBgHashVerify".into())
5499 .spawn(move || {
5500 info!("Initial background accounts hash verification has started");
5501 let start = Instant::now();
5502 let mut lattice_verify_time = None;
5503 let mut merkle_verify_time = None;
5504 let is_ok = match verify_kind {
5505 VerifyKind::Lattice => {
5506 let accounts_db = &accounts_.accounts_db;
5508 let (calculated_accounts_lt_hash, duration) =
5509 meas_dur!(accounts_db.thread_pool_hash.install(|| {
5510 accounts_db
5511 .calculate_accounts_lt_hash_at_startup_from_storages(
5512 snapshot_storages.0.as_slice(),
5513 &duplicates_lt_hash.unwrap(),
5514 )
5515 }));
5516 let is_ok =
5517 calculated_accounts_lt_hash == expected_accounts_lt_hash;
5518 if !is_ok {
5519 let expected = expected_accounts_lt_hash.0.checksum();
5520 let calculated = calculated_accounts_lt_hash.0.checksum();
5521 error!(
5522 "Verifying accounts failed: accounts lattice hashes do not \
5523 match, expected: {expected}, calculated: {calculated}",
5524 );
5525 }
5526 lattice_verify_time = Some(duration);
5527 is_ok
5528 }
5529 VerifyKind::Merkle => {
5530 let snapshot_storages_and_slots = (
5532 snapshot_storages.0.as_slice(),
5533 snapshot_storages.1.as_slice(),
5534 );
5535 let (is_ok, duration) = meas_dur!(accounts_
5536 .verify_accounts_hash_and_lamports(
5537 snapshot_storages_and_slots,
5538 slot,
5539 capitalization,
5540 base,
5541 VerifyAccountsHashAndLamportsConfig {
5542 ancestors: &ancestors,
5543 epoch_schedule: &epoch_schedule,
5544 rent_collector: &rent_collector,
5545 ..verify_config
5546 },
5547 ));
5548 merkle_verify_time = Some(duration);
5549 is_ok
5550 }
5551 };
5552 accounts_
5553 .accounts_db
5554 .verify_accounts_hash_in_bg
5555 .background_finished();
5556 let total_time = start.elapsed();
5557 datapoint_info!(
5558 "startup_verify_accounts",
5559 ("total_us", total_time.as_micros(), i64),
5560 (
5561 "verify_accounts_lt_hash_us",
5562 lattice_verify_time.as_ref().map(Duration::as_micros),
5563 Option<i64>
5564 ),
5565 ("verify_accounts_hash_us",
5566 merkle_verify_time.as_ref().map(Duration::as_micros),
5567 Option<i64>
5568 ),
5569 );
5570 info!("Initial background accounts hash verification has stopped");
5571 is_ok
5572 })
5573 .unwrap()
5574 });
5575 true } else {
5577 match verify_kind {
5578 VerifyKind::Lattice => {
5579 let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5580 let calculated_accounts_lt_hash = if let Some(duplicates_lt_hash) =
5581 duplicates_lt_hash
5582 {
5583 accounts
5584 .accounts_db
5585 .calculate_accounts_lt_hash_at_startup_from_storages(
5586 snapshot_storages.0.as_slice(),
5587 &duplicates_lt_hash,
5588 )
5589 } else {
5590 accounts
5591 .accounts_db
5592 .calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors, slot)
5593 };
5594 let is_ok = calculated_accounts_lt_hash == expected_accounts_lt_hash;
5595 if !is_ok {
5596 let expected = expected_accounts_lt_hash.0.checksum();
5597 let calculated = calculated_accounts_lt_hash.0.checksum();
5598 error!(
5599 "Verifying accounts failed: accounts lattice hashes do not \
5600 match, expected: {expected}, calculated: {calculated}",
5601 );
5602 }
5603 is_ok
5604 }
5605 VerifyKind::Merkle => {
5606 let snapshot_storages_and_slots = (
5607 snapshot_storages.0.as_slice(),
5608 snapshot_storages.1.as_slice(),
5609 );
5610 let is_ok = accounts.verify_accounts_hash_and_lamports(
5611 snapshot_storages_and_slots,
5612 slot,
5613 capitalization,
5614 base,
5615 verify_config,
5616 );
5617 self.set_initial_accounts_hash_verification_completed();
5618 is_ok
5619 }
5620 }
5621 }
5622 }
5623
5624 pub fn set_initial_accounts_hash_verification_completed(&self) {
5628 self.rc
5629 .accounts
5630 .accounts_db
5631 .verify_accounts_hash_in_bg
5632 .verification_complete();
5633 }
5634
5635 pub fn has_initial_accounts_hash_verification_completed(&self) -> bool {
5639 self.rc
5640 .accounts
5641 .accounts_db
5642 .verify_accounts_hash_in_bg
5643 .check_complete()
5644 }
5645
5646 pub fn get_snapshot_storages(&self, base_slot: Option<Slot>) -> Vec<Arc<AccountStorageEntry>> {
5650 let start_slot = base_slot.map_or(0, |slot| slot.saturating_add(1));
5652 let requested_slots = start_slot..=self.slot();
5654
5655 self.rc.accounts.accounts_db.get_storages(requested_slots).0
5656 }
5657
5658 #[must_use]
5659 fn verify_hash(&self) -> bool {
5660 assert!(self.is_frozen());
5661 let calculated_hash = self.hash_internal_state();
5662 let expected_hash = self.hash();
5663
5664 if calculated_hash == expected_hash {
5665 true
5666 } else {
5667 warn!(
5668 "verify failed: slot: {}, {} (calculated) != {} (expected)",
5669 self.slot(),
5670 calculated_hash,
5671 expected_hash
5672 );
5673 false
5674 }
5675 }
5676
5677 pub fn verify_transaction(
5678 &self,
5679 tx: VersionedTransaction,
5680 verification_mode: TransactionVerificationMode,
5681 ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5682 let sanitized_tx = {
5683 let size =
5684 bincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?;
5685 if size > PACKET_DATA_SIZE as u64 {
5686 return Err(TransactionError::SanitizeFailure);
5687 }
5688 let message_hash = if verification_mode == TransactionVerificationMode::FullVerification
5689 {
5690 tx.verify_and_hash_message()?
5691 } else {
5692 tx.message.hash()
5693 };
5694
5695 RuntimeTransaction::try_create(
5696 tx,
5697 MessageHash::Precomputed(message_hash),
5698 None,
5699 self,
5700 self.get_reserved_account_keys(),
5701 )
5702 }?;
5703
5704 let move_precompile_verification_to_svm = self
5705 .feature_set
5706 .is_active(&feature_set::move_precompile_verification_to_svm::id());
5707 if !move_precompile_verification_to_svm && {
5708 verification_mode == TransactionVerificationMode::HashAndVerifyPrecompiles
5709 || verification_mode == TransactionVerificationMode::FullVerification
5710 } {
5711 verify_precompiles(&sanitized_tx, &self.feature_set)?;
5712 }
5713
5714 Ok(sanitized_tx)
5715 }
5716
5717 pub fn fully_verify_transaction(
5718 &self,
5719 tx: VersionedTransaction,
5720 ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5721 self.verify_transaction(tx, TransactionVerificationMode::FullVerification)
5722 }
5723
5724 pub fn check_reserved_keys(&self, tx: &impl SVMMessage) -> Result<()> {
5728 let reserved_keys = self.get_reserved_account_keys();
5731 for (index, key) in tx.account_keys().iter().enumerate() {
5732 if tx.is_writable(index) && reserved_keys.contains(key) {
5733 return Err(TransactionError::ResanitizationNeeded);
5734 }
5735 }
5736
5737 Ok(())
5738 }
5739
5740 fn calculate_capitalization(&self, debug_verify: bool) -> u64 {
5742 let is_startup = true;
5743 self.rc
5744 .accounts
5745 .accounts_db
5746 .verify_accounts_hash_in_bg
5747 .join_background_thread();
5748 self.rc
5749 .accounts
5750 .accounts_db
5751 .update_accounts_hash_with_verify_from(
5752 CalcAccountsHashDataSource::IndexForTests,
5754 debug_verify,
5755 self.slot(),
5756 &self.ancestors,
5757 None,
5758 self.epoch_schedule(),
5759 &self.rent_collector,
5760 is_startup,
5761 )
5762 .1
5763 }
5764
5765 pub fn calculate_and_verify_capitalization(&self, debug_verify: bool) -> bool {
5767 let calculated = self.calculate_capitalization(debug_verify);
5768 let expected = self.capitalization();
5769 if calculated == expected {
5770 true
5771 } else {
5772 warn!(
5773 "Capitalization mismatch: calculated: {} != expected: {}",
5774 calculated, expected
5775 );
5776 false
5777 }
5778 }
5779
5780 pub fn set_capitalization(&self) -> u64 {
5783 let old = self.capitalization();
5784 let debug_verify = false;
5788 self.capitalization
5789 .store(self.calculate_capitalization(debug_verify), Relaxed);
5790 old
5791 }
5792
5793 pub fn get_accounts_hash(&self) -> Option<AccountsHash> {
5798 self.rc
5799 .accounts
5800 .accounts_db
5801 .get_accounts_hash(self.slot())
5802 .map(|(accounts_hash, _)| accounts_hash)
5803 }
5804
5805 pub fn get_incremental_accounts_hash(&self) -> Option<IncrementalAccountsHash> {
5810 self.rc
5811 .accounts
5812 .accounts_db
5813 .get_incremental_accounts_hash(self.slot())
5814 .map(|(incremental_accounts_hash, _)| incremental_accounts_hash)
5815 }
5816
5817 pub fn get_snapshot_hash(&self) -> SnapshotHash {
5827 if self.is_snapshots_lt_hash_enabled() {
5828 self.get_lattice_snapshot_hash()
5829 } else {
5830 self.get_merkle_snapshot_hash()
5831 }
5832 }
5833
5834 pub fn get_merkle_snapshot_hash(&self) -> SnapshotHash {
5844 let accounts_hash = self.get_accounts_hash();
5845 let incremental_accounts_hash = self.get_incremental_accounts_hash();
5846 let accounts_hash_kind = match (accounts_hash, incremental_accounts_hash) {
5847 (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()),
5848 (Some(accounts_hash), None) => accounts_hash.into(),
5849 (None, Some(incremental_accounts_hash)) => incremental_accounts_hash.into(),
5850 (None, None) => panic!("accounts hash is required to get snapshot hash"),
5851 };
5852 let epoch_accounts_hash = self.get_epoch_accounts_hash_to_serialize();
5853 SnapshotHash::new(
5854 &MerkleOrLatticeAccountsHash::Merkle(accounts_hash_kind),
5855 epoch_accounts_hash.as_ref(),
5856 None,
5857 )
5858 }
5859
5860 pub fn get_lattice_snapshot_hash(&self) -> SnapshotHash {
5864 SnapshotHash::new(
5865 &MerkleOrLatticeAccountsHash::Lattice,
5866 None,
5867 Some(self.accounts_lt_hash.lock().unwrap().0.checksum()),
5868 )
5869 }
5870
5871 pub fn load_account_into_read_cache(&self, key: &Pubkey) {
5872 self.rc
5873 .accounts
5874 .accounts_db
5875 .load_account_into_read_cache(&self.ancestors, key);
5876 }
5877
5878 pub fn update_accounts_hash(
5879 &self,
5880 data_source: CalcAccountsHashDataSource,
5881 mut debug_verify: bool,
5882 is_startup: bool,
5883 ) -> AccountsHash {
5884 let (accounts_hash, total_lamports) = self
5885 .rc
5886 .accounts
5887 .accounts_db
5888 .update_accounts_hash_with_verify_from(
5889 data_source,
5890 debug_verify,
5891 self.slot(),
5892 &self.ancestors,
5893 Some(self.capitalization()),
5894 self.epoch_schedule(),
5895 &self.rent_collector,
5896 is_startup,
5897 );
5898 if total_lamports != self.capitalization() {
5899 datapoint_info!(
5900 "capitalization_mismatch",
5901 ("slot", self.slot(), i64),
5902 ("calculated_lamports", total_lamports, i64),
5903 ("capitalization", self.capitalization(), i64),
5904 );
5905
5906 if !debug_verify {
5907 debug_verify = true;
5910 self.rc
5911 .accounts
5912 .accounts_db
5913 .update_accounts_hash_with_verify_from(
5914 data_source,
5915 debug_verify,
5916 self.slot(),
5917 &self.ancestors,
5918 Some(self.capitalization()),
5919 self.epoch_schedule(),
5920 &self.rent_collector,
5921 is_startup,
5922 );
5923 }
5924
5925 panic!(
5926 "capitalization_mismatch. slot: {}, calculated_lamports: {}, capitalization: {}",
5927 self.slot(),
5928 total_lamports,
5929 self.capitalization()
5930 );
5931 }
5932 accounts_hash
5933 }
5934
5935 pub fn update_incremental_accounts_hash(&self, base_slot: Slot) -> IncrementalAccountsHash {
5937 let config = CalcAccountsHashConfig {
5938 use_bg_thread_pool: true,
5939 ancestors: None, epoch_schedule: &self.epoch_schedule,
5941 rent_collector: &self.rent_collector,
5942 store_detailed_debug_info_on_failure: false,
5943 };
5944 let storages = self.get_snapshot_storages(Some(base_slot));
5945 let sorted_storages = SortedStorages::new(&storages);
5946 self.rc
5947 .accounts
5948 .accounts_db
5949 .update_incremental_accounts_hash(
5950 &config,
5951 &sorted_storages,
5952 self.slot(),
5953 HashStats::default(),
5954 )
5955 .0
5956 }
5957
5958 pub fn verify_snapshot_bank(
5961 &self,
5962 test_hash_calculation: bool,
5963 skip_shrink: bool,
5964 force_clean: bool,
5965 latest_full_snapshot_slot: Slot,
5966 base: Option<(Slot, u64)>,
5967 duplicates_lt_hash: Option<Box<DuplicatesLtHash>>,
5968 ) -> bool {
5969 let (verified_accounts, verify_accounts_time_us) = measure_us!({
5977 let should_verify_accounts = !self.rc.accounts.accounts_db.skip_initial_hash_calc;
5978 if should_verify_accounts {
5979 info!("Verifying accounts...");
5980 let verified = self.verify_accounts_hash(
5981 base,
5982 VerifyAccountsHashConfig {
5983 test_hash_calculation,
5984 ignore_mismatch: false,
5985 require_rooted_bank: false,
5986 run_in_background: true,
5987 store_hash_raw_data_for_debug: false,
5988 },
5989 duplicates_lt_hash,
5990 );
5991 info!("Verifying accounts... In background.");
5992 verified
5993 } else {
5994 info!("Verifying accounts... Skipped.");
5995 self.rc
5996 .accounts
5997 .accounts_db
5998 .verify_accounts_hash_in_bg
5999 .verification_complete();
6000 true
6001 }
6002 });
6003
6004 let (_, clean_time_us) = measure_us!({
6005 let should_clean = force_clean || (!skip_shrink && self.slot() > 0);
6006 if should_clean {
6007 info!("Cleaning...");
6008 self.rc.accounts.accounts_db.clean_accounts(
6013 Some(latest_full_snapshot_slot),
6014 true,
6015 self.epoch_schedule(),
6016 self.clean_accounts_old_storages_policy(),
6017 );
6018 info!("Cleaning... Done.");
6019 } else {
6020 info!("Cleaning... Skipped.");
6021 }
6022 });
6023
6024 let (_, shrink_time_us) = measure_us!({
6025 let should_shrink = !skip_shrink && self.slot() > 0;
6026 if should_shrink {
6027 info!("Shrinking...");
6028 self.rc.accounts.accounts_db.shrink_all_slots(
6029 true,
6030 self.epoch_schedule(),
6031 Some(self.slot()),
6033 );
6034 info!("Shrinking... Done.");
6035 } else {
6036 info!("Shrinking... Skipped.");
6037 }
6038 });
6039
6040 info!("Verifying bank...");
6041 let (verified_bank, verify_bank_time_us) = measure_us!(self.verify_hash());
6042 info!("Verifying bank... Done.");
6043
6044 datapoint_info!(
6045 "verify_snapshot_bank",
6046 ("clean_us", clean_time_us, i64),
6047 ("shrink_us", shrink_time_us, i64),
6048 ("verify_accounts_us", verify_accounts_time_us, i64),
6049 ("verify_bank_us", verify_bank_time_us, i64),
6050 );
6051
6052 verified_accounts && verified_bank
6053 }
6054
6055 pub fn hashes_per_tick(&self) -> &Option<u64> {
6057 &self.hashes_per_tick
6058 }
6059
6060 pub fn ticks_per_slot(&self) -> u64 {
6062 self.ticks_per_slot
6063 }
6064
6065 pub fn slots_per_year(&self) -> f64 {
6067 self.slots_per_year
6068 }
6069
6070 pub fn tick_height(&self) -> u64 {
6072 self.tick_height.load(Relaxed)
6073 }
6074
6075 pub fn inflation(&self) -> Inflation {
6077 *self.inflation.read().unwrap()
6078 }
6079
6080 pub fn rent_collector(&self) -> &RentCollector {
6082 &self.rent_collector
6083 }
6084
6085 pub fn capitalization(&self) -> u64 {
6087 self.capitalization.load(Relaxed)
6088 }
6089
6090 pub fn max_tick_height(&self) -> u64 {
6092 self.max_tick_height
6093 }
6094
6095 pub fn block_height(&self) -> u64 {
6097 self.block_height
6098 }
6099
6100 pub fn get_slots_in_epoch(&self, epoch: Epoch) -> u64 {
6102 self.epoch_schedule().get_slots_in_epoch(epoch)
6103 }
6104
6105 pub fn get_leader_schedule_epoch(&self, slot: Slot) -> Epoch {
6108 self.epoch_schedule().get_leader_schedule_epoch(slot)
6109 }
6110
6111 fn update_stakes_cache(
6113 &self,
6114 txs: &[impl SVMMessage],
6115 processing_results: &[TransactionProcessingResult],
6116 ) {
6117 debug_assert_eq!(txs.len(), processing_results.len());
6118 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
6119 txs.iter()
6120 .zip(processing_results)
6121 .filter_map(|(tx, processing_result)| {
6122 processing_result
6123 .processed_transaction()
6124 .map(|processed_tx| (tx, processed_tx))
6125 })
6126 .filter_map(|(tx, processed_tx)| {
6127 processed_tx
6128 .executed_transaction()
6129 .map(|executed_tx| (tx, executed_tx))
6130 })
6131 .filter(|(_, executed_tx)| executed_tx.was_successful())
6132 .flat_map(|(tx, executed_tx)| {
6133 let num_account_keys = tx.account_keys().len();
6134 let loaded_tx = &executed_tx.loaded_transaction;
6135 loaded_tx.accounts.iter().take(num_account_keys)
6136 })
6137 .for_each(|(pubkey, account)| {
6138 self.stakes_cache
6141 .check_and_store(pubkey, account, new_warmup_cooldown_rate_epoch);
6142 });
6143 }
6144
6145 pub fn vote_accounts(&self) -> Arc<VoteAccountsHashMap> {
6148 let stakes = self.stakes_cache.stakes();
6149 Arc::from(stakes.vote_accounts())
6150 }
6151
6152 pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<VoteAccount> {
6154 let stakes = self.stakes_cache.stakes();
6155 let vote_account = stakes.vote_accounts().get(vote_account)?;
6156 Some(vote_account.clone())
6157 }
6158
6159 pub fn current_epoch_stakes(&self) -> &EpochStakes {
6161 self.epoch_stakes
6164 .get(&self.epoch.saturating_add(1))
6165 .expect("Current epoch stakes must exist")
6166 }
6167
6168 pub fn epoch_stakes(&self, epoch: Epoch) -> Option<&EpochStakes> {
6170 self.epoch_stakes.get(&epoch)
6171 }
6172
6173 pub fn epoch_stakes_map(&self) -> &HashMap<Epoch, EpochStakes> {
6174 &self.epoch_stakes
6175 }
6176
6177 pub fn current_epoch_staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
6179 self.current_epoch_stakes().stakes().staked_nodes()
6180 }
6181
6182 pub fn epoch_staked_nodes(&self, epoch: Epoch) -> Option<Arc<HashMap<Pubkey, u64>>> {
6183 Some(self.epoch_stakes.get(&epoch)?.stakes().staked_nodes())
6184 }
6185
6186 pub fn epoch_total_stake(&self, epoch: Epoch) -> Option<u64> {
6188 self.epoch_stakes
6189 .get(&epoch)
6190 .map(|epoch_stakes| epoch_stakes.total_stake())
6191 }
6192
6193 pub fn get_current_epoch_total_stake(&self) -> u64 {
6195 self.current_epoch_stakes().total_stake()
6196 }
6197
6198 pub fn epoch_vote_accounts(&self, epoch: Epoch) -> Option<&VoteAccountsHashMap> {
6201 let epoch_stakes = self.epoch_stakes.get(&epoch)?.stakes();
6202 Some(epoch_stakes.vote_accounts().as_ref())
6203 }
6204
6205 pub fn get_current_epoch_vote_accounts(&self) -> &VoteAccountsHashMap {
6208 self.current_epoch_stakes()
6209 .stakes()
6210 .vote_accounts()
6211 .as_ref()
6212 }
6213
6214 pub fn epoch_authorized_voter(&self, vote_account: &Pubkey) -> Option<&Pubkey> {
6217 self.epoch_stakes
6218 .get(&self.epoch)
6219 .expect("Epoch stakes for bank's own epoch must exist")
6220 .epoch_authorized_voters()
6221 .get(vote_account)
6222 }
6223
6224 pub fn epoch_vote_accounts_for_node_id(&self, node_id: &Pubkey) -> Option<&NodeVoteAccounts> {
6227 self.epoch_stakes
6228 .get(&self.epoch)
6229 .expect("Epoch stakes for bank's own epoch must exist")
6230 .node_id_to_vote_accounts()
6231 .get(node_id)
6232 }
6233
6234 pub fn epoch_node_id_to_stake(&self, epoch: Epoch, node_id: &Pubkey) -> Option<u64> {
6237 self.epoch_stakes(epoch)
6238 .and_then(|epoch_stakes| epoch_stakes.node_id_to_stake(node_id))
6239 }
6240
6241 pub fn total_epoch_stake(&self) -> u64 {
6243 self.epoch_stakes
6244 .get(&self.epoch)
6245 .expect("Epoch stakes for bank's own epoch must exist")
6246 .total_stake()
6247 }
6248
6249 pub fn epoch_vote_account_stake(&self, vote_account: &Pubkey) -> u64 {
6251 *self
6252 .epoch_vote_accounts(self.epoch())
6253 .expect("Bank epoch vote accounts must contain entry for the bank's own epoch")
6254 .get(vote_account)
6255 .map(|(stake, _)| stake)
6256 .unwrap_or(&0)
6257 }
6258
6259 pub fn get_epoch_and_slot_index(&self, slot: Slot) -> (Epoch, SlotIndex) {
6265 self.epoch_schedule().get_epoch_and_slot_index(slot)
6266 }
6267
6268 pub fn get_epoch_info(&self) -> EpochInfo {
6269 let absolute_slot = self.slot();
6270 let block_height = self.block_height();
6271 let (epoch, slot_index) = self.get_epoch_and_slot_index(absolute_slot);
6272 let slots_in_epoch = self.get_slots_in_epoch(epoch);
6273 let transaction_count = Some(self.transaction_count());
6274 EpochInfo {
6275 epoch,
6276 slot_index,
6277 slots_in_epoch,
6278 absolute_slot,
6279 block_height,
6280 transaction_count,
6281 }
6282 }
6283
6284 pub fn is_empty(&self) -> bool {
6285 !self.is_delta.load(Relaxed)
6286 }
6287
6288 pub fn add_mockup_builtin(
6289 &mut self,
6290 program_id: Pubkey,
6291 builtin_function: BuiltinFunctionWithContext,
6292 ) {
6293 self.transaction_processor.add_builtin(
6294 self,
6295 program_id,
6296 "mockup",
6297 ProgramCacheEntry::new_builtin(self.slot, 0, builtin_function),
6298 );
6299 }
6300
6301 pub fn add_precompile(&mut self, program_id: &Pubkey) {
6302 debug!("Adding precompiled program {}", program_id);
6303 self.add_precompiled_account(program_id);
6304 debug!("Added precompiled program {:?}", program_id);
6305 }
6306
6307 pub(crate) fn clean_accounts(&self) {
6312 let highest_slot_to_clean = self.slot().saturating_sub(1);
6319
6320 self.rc.accounts.accounts_db.clean_accounts(
6321 Some(highest_slot_to_clean),
6322 false,
6323 self.epoch_schedule(),
6324 self.clean_accounts_old_storages_policy(),
6325 );
6326 }
6327
6328 pub fn print_accounts_stats(&self) {
6329 self.rc.accounts.accounts_db.print_accounts_stats("");
6330 }
6331
6332 pub fn shrink_candidate_slots(&self) -> usize {
6333 self.rc
6334 .accounts
6335 .accounts_db
6336 .shrink_candidate_slots(self.epoch_schedule())
6337 }
6338
6339 pub(crate) fn shrink_ancient_slots(&self) {
6340 if self.are_ancient_storages_enabled() {
6344 self.rc
6345 .accounts
6346 .accounts_db
6347 .shrink_ancient_slots(self.epoch_schedule())
6348 }
6349 }
6350
6351 pub fn are_ancient_storages_enabled(&self) -> bool {
6353 let can_skip_rewrites = self.bank_hash_skips_rent_rewrites();
6354 let test_skip_rewrites_but_include_in_bank_hash = self
6355 .rc
6356 .accounts
6357 .accounts_db
6358 .test_skip_rewrites_but_include_in_bank_hash;
6359 can_skip_rewrites || test_skip_rewrites_but_include_in_bank_hash
6360 }
6361
6362 fn clean_accounts_old_storages_policy(&self) -> OldStoragesPolicy {
6364 if self.are_ancient_storages_enabled() {
6365 OldStoragesPolicy::Leave
6366 } else {
6367 OldStoragesPolicy::Clean
6368 }
6369 }
6370
6371 pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<CostTracker>> {
6372 self.cost_tracker.read()
6373 }
6374
6375 pub fn write_cost_tracker(&self) -> LockResult<RwLockWriteGuard<CostTracker>> {
6376 self.cost_tracker.write()
6377 }
6378
6379 pub fn should_bank_still_be_processing_txs(
6382 bank_creation_time: &Instant,
6383 max_tx_ingestion_nanos: u128,
6384 ) -> bool {
6385 bank_creation_time.elapsed().as_nanos() <= max_tx_ingestion_nanos
6387 }
6388
6389 pub fn deactivate_feature(&mut self, id: &Pubkey) {
6390 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6391 feature_set.active_mut().remove(id);
6392 feature_set.inactive_mut().insert(*id);
6393 self.feature_set = Arc::new(feature_set);
6394 }
6395
6396 pub fn activate_feature(&mut self, id: &Pubkey) {
6397 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6398 feature_set.inactive_mut().remove(id);
6399 feature_set.active_mut().insert(*id, 0);
6400 self.feature_set = Arc::new(feature_set);
6401 }
6402
6403 pub fn fill_bank_with_ticks_for_tests(&self) {
6404 self.do_fill_bank_with_ticks_for_tests(&BankWithScheduler::no_scheduler_available())
6405 }
6406
6407 pub(crate) fn do_fill_bank_with_ticks_for_tests(&self, scheduler: &InstalledSchedulerRwLock) {
6408 if self.tick_height.load(Relaxed) < self.max_tick_height {
6409 let last_blockhash = self.last_blockhash();
6410 while self.last_blockhash() == last_blockhash {
6411 self.register_tick(&Hash::new_unique(), scheduler)
6412 }
6413 } else {
6414 warn!("Bank already reached max tick height, cannot fill it with more ticks");
6415 }
6416 }
6417
6418 pub fn get_reserved_account_keys(&self) -> &HashSet<Pubkey> {
6421 &self.reserved_account_keys.active
6422 }
6423
6424 fn apply_feature_activations(
6427 &mut self,
6428 caller: ApplyFeatureActivationsCaller,
6429 debug_do_not_add_builtins: bool,
6430 ) {
6431 use ApplyFeatureActivationsCaller as Caller;
6432 let allow_new_activations = match caller {
6433 Caller::FinishInit => false,
6434 Caller::NewFromParent => true,
6435 Caller::WarpFromParent => false,
6436 };
6437 let (feature_set, new_feature_activations) =
6438 self.compute_active_feature_set(allow_new_activations);
6439 self.feature_set = Arc::new(feature_set);
6440
6441 for feature_id in new_feature_activations.iter() {
6443 if let Some(mut account) = self.get_account_with_fixed_root(feature_id) {
6444 if let Some(mut feature) = feature::from_account(&account) {
6445 feature.activated_at = Some(self.slot());
6446 if feature::to_account(&feature, &mut account).is_some() {
6447 self.store_account(feature_id, &account);
6448 }
6449 info!("Feature {} activated at slot {}", feature_id, self.slot());
6450 }
6451 }
6452 }
6453
6454 self.reserved_account_keys = {
6456 let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
6457 reserved_keys.update_active_set(&self.feature_set);
6458 Arc::new(reserved_keys)
6459 };
6460
6461 if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
6462 *self.inflation.write().unwrap() = Inflation::pico();
6463 self.fee_rate_governor.burn_percent = 50; self.rent_collector.rent.burn_percent = 50; }
6466
6467 if !new_feature_activations.is_disjoint(&self.feature_set.full_inflation_features_enabled())
6468 {
6469 *self.inflation.write().unwrap() = Inflation::full();
6470 self.fee_rate_governor.burn_percent = 50; self.rent_collector.rent.burn_percent = 50; }
6473
6474 if !debug_do_not_add_builtins {
6475 self.apply_builtin_program_feature_transitions(
6476 allow_new_activations,
6477 &new_feature_activations,
6478 );
6479 }
6480
6481 if new_feature_activations.contains(&feature_set::update_hashes_per_tick::id()) {
6482 self.apply_updated_hashes_per_tick(DEFAULT_HASHES_PER_TICK);
6483 }
6484
6485 if new_feature_activations.contains(&feature_set::update_hashes_per_tick2::id()) {
6486 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK2);
6487 }
6488
6489 if new_feature_activations.contains(&feature_set::update_hashes_per_tick3::id()) {
6490 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK3);
6491 }
6492
6493 if new_feature_activations.contains(&feature_set::update_hashes_per_tick4::id()) {
6494 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK4);
6495 }
6496
6497 if new_feature_activations.contains(&feature_set::update_hashes_per_tick5::id()) {
6498 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK5);
6499 }
6500
6501 if new_feature_activations.contains(&feature_set::update_hashes_per_tick6::id()) {
6502 self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK6);
6503 }
6504
6505 if new_feature_activations.contains(&feature_set::accounts_lt_hash::id()) {
6506 if self
6510 .rc
6511 .accounts
6512 .accounts_db
6513 .is_experimental_accumulator_hash_enabled()
6514 {
6515 } else {
6518 let parent_slot = self.parent_slot;
6519 info!(
6520 "Calculating the accounts lt hash for slot {parent_slot} \
6521 as part of feature activation; this may take some time...",
6522 );
6523 let parent_ancestors = {
6528 let mut ancestors = self.ancestors.clone();
6529 ancestors.remove(&self.slot());
6530 ancestors
6531 };
6532 let (parent_accounts_lt_hash, duration) = meas_dur!({
6533 self.rc
6534 .accounts
6535 .accounts_db
6536 .calculate_accounts_lt_hash_at_startup_from_index(
6537 &parent_ancestors,
6538 parent_slot,
6539 )
6540 });
6541 *self.accounts_lt_hash.get_mut().unwrap() = parent_accounts_lt_hash;
6542 info!(
6543 "Calculating the accounts lt hash for slot {parent_slot} \
6544 completed in {duration:?}, accounts_lt_hash checksum: {}",
6545 self.accounts_lt_hash.get_mut().unwrap().0.checksum(),
6546 );
6547 }
6548 }
6549
6550 if new_feature_activations.contains(&feature_set::raise_block_limits_to_50m::id()) {
6551 let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits();
6552 self.write_cost_tracker().unwrap().set_limits(
6553 account_cost_limit,
6554 block_cost_limit,
6555 vote_cost_limit,
6556 );
6557 }
6558
6559 if new_feature_activations.contains(&feature_set::remove_accounts_delta_hash::id()) {
6560 self.rc.accounts.accounts_db.stop_background_hasher();
6563 }
6564 }
6565
6566 fn apply_updated_hashes_per_tick(&mut self, hashes_per_tick: u64) {
6567 info!(
6568 "Activating update_hashes_per_tick {} at slot {}",
6569 hashes_per_tick,
6570 self.slot(),
6571 );
6572 self.hashes_per_tick = Some(hashes_per_tick);
6573 }
6574
6575 fn adjust_sysvar_balance_for_rent(&self, account: &mut AccountSharedData) {
6576 account.set_lamports(
6577 self.get_minimum_balance_for_rent_exemption(account.data().len())
6578 .max(account.lamports()),
6579 );
6580 }
6581
6582 fn compute_active_feature_set(&self, include_pending: bool) -> (FeatureSet, AHashSet<Pubkey>) {
6585 let mut active = self.feature_set.active().clone();
6586 let mut inactive = AHashSet::new();
6587 let mut pending = AHashSet::new();
6588 let slot = self.slot();
6589
6590 for feature_id in self.feature_set.inactive() {
6591 let mut activated = None;
6592 if let Some(account) = self.get_account_with_fixed_root(feature_id) {
6593 if let Some(feature) = feature::from_account(&account) {
6594 match feature.activated_at {
6595 None if include_pending => {
6596 pending.insert(*feature_id);
6598 activated = Some(slot);
6599 }
6600 Some(activation_slot) if slot >= activation_slot => {
6601 activated = Some(activation_slot);
6603 }
6604 _ => {}
6605 }
6606 }
6607 }
6608 if let Some(slot) = activated {
6609 active.insert(*feature_id, slot);
6610 } else {
6611 inactive.insert(*feature_id);
6612 }
6613 }
6614
6615 (FeatureSet::new(active, inactive), pending)
6616 }
6617
6618 fn apply_builtin_program_feature_transitions(
6619 &mut self,
6620 only_apply_transitions_for_new_features: bool,
6621 new_feature_activations: &AHashSet<Pubkey>,
6622 ) {
6623 for builtin in BUILTINS.iter() {
6624 let mut builtin_is_bpf = false;
6641 if let Some(core_bpf_migration_config) = &builtin.core_bpf_migration_config {
6642 if new_feature_activations.contains(&core_bpf_migration_config.feature_id) {
6647 if let Err(e) = self
6648 .migrate_builtin_to_core_bpf(&builtin.program_id, core_bpf_migration_config)
6649 {
6650 warn!(
6651 "Failed to migrate builtin {} to Core BPF: {}",
6652 builtin.name, e
6653 );
6654 } else {
6655 builtin_is_bpf = true;
6656 }
6657 } else {
6658 builtin_is_bpf = self
6661 .get_account(&builtin.program_id)
6662 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
6663 .unwrap_or(false);
6664 }
6665 };
6666
6667 if let Some(feature_id) = builtin.enable_feature_id {
6668 let should_enable_builtin_on_feature_transition = !builtin_is_bpf
6669 && if only_apply_transitions_for_new_features {
6670 new_feature_activations.contains(&feature_id)
6671 } else {
6672 self.feature_set.is_active(&feature_id)
6673 };
6674
6675 if should_enable_builtin_on_feature_transition {
6676 self.transaction_processor.add_builtin(
6677 self,
6678 builtin.program_id,
6679 builtin.name,
6680 ProgramCacheEntry::new_builtin(
6681 self.feature_set.activated_slot(&feature_id).unwrap_or(0),
6682 builtin.name.len(),
6683 builtin.entrypoint,
6684 ),
6685 );
6686 }
6687 }
6688 }
6689
6690 for stateless_builtin in STATELESS_BUILTINS.iter() {
6694 if let Some(core_bpf_migration_config) = &stateless_builtin.core_bpf_migration_config {
6695 if new_feature_activations.contains(&core_bpf_migration_config.feature_id) {
6696 if let Err(e) = self.migrate_builtin_to_core_bpf(
6697 &stateless_builtin.program_id,
6698 core_bpf_migration_config,
6699 ) {
6700 warn!(
6701 "Failed to migrate stateless builtin {} to Core BPF: {}",
6702 stateless_builtin.name, e
6703 );
6704 }
6705 }
6706 }
6707 }
6708
6709 for precompile in get_precompiles() {
6710 let should_add_precompile = precompile
6711 .feature
6712 .as_ref()
6713 .map(|feature_id| self.feature_set.is_active(feature_id))
6714 .unwrap_or(false);
6715 if should_add_precompile {
6716 self.add_precompile(&precompile.program_id);
6717 }
6718 }
6719 }
6720
6721 #[allow(dead_code)]
6723 fn replace_program_account(
6724 &mut self,
6725 old_address: &Pubkey,
6726 new_address: &Pubkey,
6727 datapoint_name: &'static str,
6728 ) {
6729 if let Some(old_account) = self.get_account_with_fixed_root(old_address) {
6730 if let Some(new_account) = self.get_account_with_fixed_root(new_address) {
6731 datapoint_info!(datapoint_name, ("slot", self.slot, i64));
6732
6733 self.capitalization
6735 .fetch_sub(old_account.lamports(), Relaxed);
6736
6737 self.store_account(old_address, &new_account);
6739
6740 self.store_account(new_address, &AccountSharedData::default());
6742
6743 self.transaction_processor
6745 .program_cache
6746 .write()
6747 .unwrap()
6748 .remove_programs([*old_address].into_iter());
6749
6750 self.calculate_and_update_accounts_data_size_delta_off_chain(
6751 old_account.data().len(),
6752 new_account.data().len(),
6753 );
6754 }
6755 }
6756 }
6757
6758 pub fn get_total_accounts_stats(&self) -> ScanResult<TotalAccountsStats> {
6760 let accounts = self.get_all_accounts(false)?;
6761 Ok(self.calculate_total_accounts_stats(
6762 accounts
6763 .iter()
6764 .map(|(pubkey, account, _slot)| (pubkey, account)),
6765 ))
6766 }
6767
6768 pub fn calculate_total_accounts_stats<'a>(
6770 &self,
6771 accounts: impl Iterator<Item = (&'a Pubkey, &'a AccountSharedData)>,
6772 ) -> TotalAccountsStats {
6773 let rent_collector = self.rent_collector();
6774 let mut total_accounts_stats = TotalAccountsStats::default();
6775 accounts.for_each(|(pubkey, account)| {
6776 total_accounts_stats.accumulate_account(pubkey, account, rent_collector);
6777 });
6778
6779 total_accounts_stats
6780 }
6781
6782 pub fn get_epoch_accounts_hash_to_serialize(&self) -> Option<EpochAccountsHash> {
6788 let should_get_epoch_accounts_hash = epoch_accounts_hash_utils::is_enabled_this_epoch(self)
6789 && epoch_accounts_hash_utils::is_in_calculation_window(self);
6790 if !should_get_epoch_accounts_hash {
6791 return None;
6792 }
6793
6794 let (epoch_accounts_hash, waiting_time_us) = measure_us!(self
6795 .rc
6796 .accounts
6797 .accounts_db
6798 .epoch_accounts_hash_manager
6799 .wait_get_epoch_accounts_hash());
6800
6801 datapoint_info!(
6802 "bank-get_epoch_accounts_hash_to_serialize",
6803 ("slot", self.slot(), i64),
6804 ("waiting-time-us", waiting_time_us, i64),
6805 );
6806 Some(epoch_accounts_hash)
6807 }
6808
6809 pub fn epoch_accounts_hash(&self) -> Option<EpochAccountsHash> {
6811 self.rc
6812 .accounts
6813 .accounts_db
6814 .epoch_accounts_hash_manager
6815 .try_get_epoch_accounts_hash()
6816 }
6817
6818 pub fn is_in_slot_hashes_history(&self, slot: &Slot) -> bool {
6819 if slot < &self.slot {
6820 if let Ok(slot_hashes) = self.transaction_processor.sysvar_cache().get_slot_hashes() {
6821 return slot_hashes.get(slot).is_some();
6822 }
6823 }
6824 false
6825 }
6826
6827 pub fn check_program_modification_slot(&self) -> bool {
6828 self.check_program_modification_slot
6829 }
6830
6831 pub fn set_check_program_modification_slot(&mut self, check: bool) {
6832 self.check_program_modification_slot = check;
6833 }
6834
6835 pub fn fee_structure(&self) -> &FeeStructure {
6836 &self.fee_structure
6837 }
6838
6839 pub fn block_id(&self) -> Option<Hash> {
6840 *self.block_id.read().unwrap()
6841 }
6842
6843 pub fn set_block_id(&self, block_id: Option<Hash>) {
6844 *self.block_id.write().unwrap() = block_id;
6845 }
6846
6847 pub fn compute_budget(&self) -> Option<ComputeBudget> {
6848 self.compute_budget
6849 }
6850
6851 pub fn add_builtin(&self, program_id: Pubkey, name: &str, builtin: ProgramCacheEntry) {
6852 self.transaction_processor
6853 .add_builtin(self, program_id, name, builtin)
6854 }
6855
6856 pub fn get_bank_hash_stats(&self) -> BankHashStats {
6857 self.bank_hash_stats.load()
6858 }
6859}
6860
6861impl TransactionProcessingCallback for Bank {
6862 fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
6863 self.rc
6864 .accounts
6865 .accounts_db
6866 .account_matches_owners(&self.ancestors, account, owners)
6867 .ok()
6868 }
6869
6870 fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6871 self.rc
6872 .accounts
6873 .accounts_db
6874 .load_with_fixed_root(&self.ancestors, pubkey)
6875 .map(|(acc, _)| acc)
6876 }
6877
6878 fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
6881 let existing_genuine_program =
6882 self.get_account_with_fixed_root(program_id)
6883 .and_then(|account| {
6884 if native_loader::check_id(account.owner()) {
6888 Some(account)
6889 } else {
6890 self.burn_and_purge_account(program_id, account);
6892 None
6893 }
6894 });
6895
6896 if existing_genuine_program.is_some() {
6898 return;
6900 }
6901
6902 assert!(
6903 !self.freeze_started(),
6904 "Can't change frozen bank by adding not-existing new builtin program ({name}, {program_id}). \
6905 Maybe, inconsistent program activation is detected on snapshot restore?"
6906 );
6907
6908 let account = native_loader::create_loadable_account_with_fields(
6910 name,
6911 self.inherit_specially_retained_account_fields(&existing_genuine_program),
6912 );
6913 self.store_account_and_update_capitalization(program_id, &account);
6914 }
6915
6916 fn inspect_account(&self, address: &Pubkey, account_state: AccountState, is_writable: bool) {
6917 if self.is_accounts_lt_hash_enabled() {
6918 self.inspect_account_for_accounts_lt_hash(address, &account_state, is_writable);
6919 }
6920 }
6921
6922 fn get_current_epoch_vote_account_stake(&self, vote_address: &Pubkey) -> u64 {
6923 self.get_current_epoch_vote_accounts()
6924 .get(vote_address)
6925 .map(|(stake, _)| (*stake))
6926 .unwrap_or(0)
6927 }
6928
6929 fn calculate_fee(
6930 &self,
6931 message: &impl SVMMessage,
6932 lamports_per_signature: u64,
6933 prioritization_fee: u64,
6934 feature_set: &FeatureSet,
6935 ) -> FeeDetails {
6936 solana_fee::calculate_fee_details(
6937 message,
6938 false, lamports_per_signature,
6940 prioritization_fee,
6941 FeeFeatures::from(feature_set),
6942 )
6943 }
6944}
6945
6946#[cfg(feature = "dev-context-only-utils")]
6947impl Bank {
6948 pub fn wrap_with_bank_forks_for_tests(self) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6949 let bank_forks = BankForks::new_rw_arc(self);
6950 let bank = bank_forks.read().unwrap().root_bank();
6951 (bank, bank_forks)
6952 }
6953
6954 pub fn default_for_tests() -> Self {
6955 let accounts_db = AccountsDb::default_for_tests();
6956 let accounts = Accounts::new(Arc::new(accounts_db));
6957 Self::default_with_accounts(accounts)
6958 }
6959
6960 pub fn new_with_bank_forks_for_tests(
6961 genesis_config: &GenesisConfig,
6962 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6963 let bank = Self::new_for_tests(genesis_config);
6964 bank.wrap_with_bank_forks_for_tests()
6965 }
6966
6967 pub fn new_for_tests(genesis_config: &GenesisConfig) -> Self {
6968 Self::new_with_config_for_tests(genesis_config, BankTestConfig::default())
6969 }
6970
6971 pub fn new_with_mockup_builtin_for_tests(
6972 genesis_config: &GenesisConfig,
6973 program_id: Pubkey,
6974 builtin_function: BuiltinFunctionWithContext,
6975 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6976 let mut bank = Self::new_for_tests(genesis_config);
6977 bank.add_mockup_builtin(program_id, builtin_function);
6978 bank.wrap_with_bank_forks_for_tests()
6979 }
6980
6981 pub fn new_no_wallclock_throttle_for_tests(
6982 genesis_config: &GenesisConfig,
6983 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6984 let mut bank = Self::new_for_tests(genesis_config);
6985
6986 bank.ns_per_slot = u128::MAX;
6987 bank.wrap_with_bank_forks_for_tests()
6988 }
6989
6990 pub fn new_with_config_for_tests(
6991 genesis_config: &GenesisConfig,
6992 test_config: BankTestConfig,
6993 ) -> Self {
6994 Self::new_with_paths_for_tests(
6995 genesis_config,
6996 Arc::new(RuntimeConfig::default()),
6997 test_config,
6998 Vec::new(),
6999 )
7000 }
7001
7002 pub fn new_with_paths_for_tests(
7003 genesis_config: &GenesisConfig,
7004 runtime_config: Arc<RuntimeConfig>,
7005 test_config: BankTestConfig,
7006 paths: Vec<PathBuf>,
7007 ) -> Self {
7008 Self::new_with_paths(
7009 genesis_config,
7010 runtime_config,
7011 paths,
7012 None,
7013 None,
7014 false,
7015 Some(test_config.accounts_db_config),
7016 None,
7017 Some(Pubkey::new_unique()),
7018 Arc::default(),
7019 None,
7020 None,
7021 )
7022 }
7023
7024 pub fn new_for_benches(genesis_config: &GenesisConfig) -> Self {
7025 Self::new_with_paths_for_benches(genesis_config, Vec::new())
7026 }
7027
7028 pub fn new_with_paths_for_benches(genesis_config: &GenesisConfig, paths: Vec<PathBuf>) -> Self {
7031 Self::new_with_paths(
7032 genesis_config,
7033 Arc::<RuntimeConfig>::default(),
7034 paths,
7035 None,
7036 None,
7037 false,
7038 Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
7039 None,
7040 Some(Pubkey::new_unique()),
7041 Arc::default(),
7042 None,
7043 None,
7044 )
7045 }
7046
7047 #[cfg(feature = "dev-context-only-utils")]
7049 pub fn prepare_batch_for_tests(
7050 &self,
7051 txs: Vec<Transaction>,
7052 ) -> TransactionBatch<RuntimeTransaction<SanitizedTransaction>> {
7053 let transaction_account_lock_limit = self.get_transaction_account_lock_limit();
7054 let sanitized_txs = txs
7055 .into_iter()
7056 .map(RuntimeTransaction::from_transaction_for_tests)
7057 .collect::<Vec<_>>();
7058 let lock_results = self
7059 .rc
7060 .accounts
7061 .lock_accounts(sanitized_txs.iter(), transaction_account_lock_limit);
7062 TransactionBatch::new(lock_results, self, OwnedOrBorrowed::Owned(sanitized_txs))
7063 }
7064
7065 pub fn set_accounts_data_size_initial_for_tests(&mut self, amount: u64) {
7068 self.accounts_data_size_initial = amount;
7069 }
7070
7071 pub fn update_accounts_data_size_delta_off_chain_for_tests(&self, amount: i64) {
7074 self.update_accounts_data_size_delta_off_chain(amount)
7075 }
7076
7077 #[cfg(test)]
7078 fn restore_old_behavior_for_fragile_tests(&self) {
7079 self.lazy_rent_collection.store(true, Relaxed);
7080 }
7081
7082 #[must_use]
7088 pub fn process_transactions<'a>(
7089 &self,
7090 txs: impl Iterator<Item = &'a Transaction>,
7091 ) -> Vec<Result<()>> {
7092 self.try_process_transactions(txs).unwrap()
7093 }
7094
7095 #[must_use]
7101 pub fn process_entry_transactions(&self, txs: Vec<VersionedTransaction>) -> Vec<Result<()>> {
7102 self.try_process_entry_transactions(txs).unwrap()
7103 }
7104
7105 #[cfg(test)]
7106 pub fn flush_accounts_cache_slot_for_tests(&self) {
7107 self.rc
7108 .accounts
7109 .accounts_db
7110 .flush_accounts_cache_slot_for_tests(self.slot())
7111 }
7112
7113 pub fn wait_for_initial_accounts_hash_verification_completed_for_tests(&self) {
7116 self.rc
7117 .accounts
7118 .accounts_db
7119 .verify_accounts_hash_in_bg
7120 .join_background_thread()
7121 }
7122
7123 pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
7124 self.transaction_processor.get_sysvar_cache_for_tests()
7125 }
7126
7127 pub fn update_accounts_hash_for_tests(&self) -> AccountsHash {
7128 self.update_accounts_hash(CalcAccountsHashDataSource::IndexForTests, false, false)
7129 }
7130
7131 pub fn new_program_cache_for_tx_batch_for_slot(&self, slot: Slot) -> ProgramCacheForTxBatch {
7132 ProgramCacheForTxBatch::new_from_cache(
7133 slot,
7134 self.epoch_schedule.get_epoch(slot),
7135 &self.transaction_processor.program_cache.read().unwrap(),
7136 )
7137 }
7138
7139 pub fn get_transaction_processor(&self) -> &TransactionBatchProcessor<BankForks> {
7140 &self.transaction_processor
7141 }
7142
7143 pub fn set_fee_structure(&mut self, fee_structure: &FeeStructure) {
7144 self.fee_structure = fee_structure.clone();
7145 }
7146
7147 pub fn load_program(
7148 &self,
7149 pubkey: &Pubkey,
7150 reload: bool,
7151 effective_epoch: Epoch,
7152 ) -> Option<Arc<ProgramCacheEntry>> {
7153 let environments = self
7154 .transaction_processor
7155 .get_environments_for_epoch(effective_epoch)?;
7156 load_program_with_pubkey(
7157 self,
7158 &environments,
7159 pubkey,
7160 self.slot(),
7161 &mut ExecuteTimings::default(), reload,
7163 )
7164 }
7165
7166 pub fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
7167 match self.get_account_with_fixed_root(pubkey) {
7168 Some(mut account) => {
7169 let min_balance = match get_system_account_kind(&account) {
7170 Some(SystemAccountKind::Nonce) => self
7171 .rent_collector
7172 .rent
7173 .minimum_balance(nonce::State::size()),
7174 _ => 0,
7175 };
7176
7177 lamports
7178 .checked_add(min_balance)
7179 .filter(|required_balance| *required_balance <= account.lamports())
7180 .ok_or(TransactionError::InsufficientFundsForFee)?;
7181 account
7182 .checked_sub_lamports(lamports)
7183 .map_err(|_| TransactionError::InsufficientFundsForFee)?;
7184 self.store_account(pubkey, &account);
7185
7186 Ok(())
7187 }
7188 None => Err(TransactionError::AccountNotFound),
7189 }
7190 }
7191
7192 pub fn set_hash_overrides(&self, hash_overrides: HashOverrides) {
7193 *self.hash_overrides.lock().unwrap() = hash_overrides;
7194 }
7195}
7196
7197fn calculate_data_size_delta(old_data_size: usize, new_data_size: usize) -> i64 {
7200 assert!(old_data_size <= i64::MAX as usize);
7201 assert!(new_data_size <= i64::MAX as usize);
7202 let old_data_size = old_data_size as i64;
7203 let new_data_size = new_data_size as i64;
7204
7205 new_data_size.saturating_sub(old_data_size)
7206}
7207
7208#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7211enum ApplyFeatureActivationsCaller {
7212 FinishInit,
7213 NewFromParent,
7214 WarpFromParent,
7215}
7216
7217#[derive(Debug, Default)]
7223struct CollectRentFromAccountsInfo {
7224 skipped_rewrites: Vec<(Pubkey, AccountHash)>,
7225 rent_collected_info: CollectedInfo,
7226 rent_rewards: Vec<(Pubkey, RewardInfo)>,
7227 time_collecting_rent_us: u64,
7228 time_storing_accounts_us: u64,
7229 num_accounts: usize,
7230}
7231
7232#[derive(Debug, Default)]
7235struct CollectRentInPartitionInfo {
7236 skipped_rewrites: Vec<(Pubkey, AccountHash)>,
7237 rent_collected: u64,
7238 accounts_data_size_reclaimed: u64,
7239 rent_rewards: Vec<(Pubkey, RewardInfo)>,
7240 time_loading_accounts_us: u64,
7241 time_collecting_rent_us: u64,
7242 time_storing_accounts_us: u64,
7243 num_accounts: usize,
7244}
7245
7246impl CollectRentInPartitionInfo {
7247 #[must_use]
7250 fn new(info: CollectRentFromAccountsInfo, time_loading_accounts: Duration) -> Self {
7251 Self {
7252 skipped_rewrites: info.skipped_rewrites,
7253 rent_collected: info.rent_collected_info.rent_amount,
7254 accounts_data_size_reclaimed: info.rent_collected_info.account_data_len_reclaimed,
7255 rent_rewards: info.rent_rewards,
7256 time_loading_accounts_us: time_loading_accounts.as_micros() as u64,
7257 time_collecting_rent_us: info.time_collecting_rent_us,
7258 time_storing_accounts_us: info.time_storing_accounts_us,
7259 num_accounts: info.num_accounts,
7260 }
7261 }
7262
7263 #[must_use]
7268 fn reduce(lhs: Self, rhs: Self) -> Self {
7269 Self {
7270 skipped_rewrites: [lhs.skipped_rewrites, rhs.skipped_rewrites].concat(),
7271 rent_collected: lhs.rent_collected.saturating_add(rhs.rent_collected),
7272 accounts_data_size_reclaimed: lhs
7273 .accounts_data_size_reclaimed
7274 .saturating_add(rhs.accounts_data_size_reclaimed),
7275 rent_rewards: [lhs.rent_rewards, rhs.rent_rewards].concat(),
7276 time_loading_accounts_us: lhs
7277 .time_loading_accounts_us
7278 .saturating_add(rhs.time_loading_accounts_us),
7279 time_collecting_rent_us: lhs
7280 .time_collecting_rent_us
7281 .saturating_add(rhs.time_collecting_rent_us),
7282 time_storing_accounts_us: lhs
7283 .time_storing_accounts_us
7284 .saturating_add(rhs.time_storing_accounts_us),
7285 num_accounts: lhs.num_accounts.saturating_add(rhs.num_accounts),
7286 }
7287 }
7288}
7289
7290#[derive(Debug, Default, Copy, Clone, Serialize)]
7292pub struct TotalAccountsStats {
7293 pub num_accounts: usize,
7295 pub data_len: usize,
7297
7298 pub num_executable_accounts: usize,
7300 pub executable_data_len: usize,
7302
7303 pub num_rent_exempt_accounts: usize,
7305 pub num_rent_paying_accounts: usize,
7307 pub num_rent_paying_accounts_without_data: usize,
7309 pub lamports_in_rent_paying_accounts: u64,
7311}
7312
7313impl TotalAccountsStats {
7314 pub fn accumulate_account(
7315 &mut self,
7316 address: &Pubkey,
7317 account: &AccountSharedData,
7318 rent_collector: &RentCollector,
7319 ) {
7320 let data_len = account.data().len();
7321 self.num_accounts += 1;
7322 self.data_len += data_len;
7323
7324 if account.executable() {
7325 self.num_executable_accounts += 1;
7326 self.executable_data_len += data_len;
7327 }
7328
7329 if !rent_collector.should_collect_rent(address, account.executable())
7330 || rent_collector
7331 .get_rent_due(
7332 account.lamports(),
7333 account.data().len(),
7334 account.rent_epoch(),
7335 )
7336 .is_exempt()
7337 {
7338 self.num_rent_exempt_accounts += 1;
7339 } else {
7340 self.num_rent_paying_accounts += 1;
7341 self.lamports_in_rent_paying_accounts += account.lamports();
7342 if data_len == 0 {
7343 self.num_rent_paying_accounts_without_data += 1;
7344 }
7345 }
7346 }
7347}
7348
7349impl Drop for Bank {
7350 fn drop(&mut self) {
7351 if let Some(drop_callback) = self.drop_callback.read().unwrap().0.as_ref() {
7352 drop_callback.callback(self);
7353 } else {
7354 self.rc
7356 .accounts
7357 .accounts_db
7358 .purge_slot(self.slot(), self.bank_id(), false);
7359 }
7360 }
7361}
7362
7363pub mod test_utils {
7365 use {
7366 super::Bank,
7367 crate::installed_scheduler_pool::BankWithScheduler,
7368 solana_sdk::{
7369 account::{ReadableAccount, WritableAccount},
7370 hash::hashv,
7371 lamports::LamportsError,
7372 pubkey::Pubkey,
7373 },
7374 solana_vote_program::vote_state::{self, BlockTimestamp, VoteStateVersions},
7375 std::sync::Arc,
7376 };
7377 pub fn goto_end_of_slot(bank: Arc<Bank>) {
7378 goto_end_of_slot_with_scheduler(&BankWithScheduler::new_without_scheduler(bank))
7379 }
7380
7381 pub fn goto_end_of_slot_with_scheduler(bank: &BankWithScheduler) {
7382 let mut tick_hash = bank.last_blockhash();
7383 loop {
7384 tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
7385 bank.register_tick(&tick_hash);
7386 if tick_hash == bank.last_blockhash() {
7387 bank.freeze();
7388 return;
7389 }
7390 }
7391 }
7392
7393 pub fn update_vote_account_timestamp(
7394 timestamp: BlockTimestamp,
7395 bank: &Bank,
7396 vote_pubkey: &Pubkey,
7397 ) {
7398 let mut vote_account = bank.get_account(vote_pubkey).unwrap_or_default();
7399 let mut vote_state = vote_state::from(&vote_account).unwrap_or_default();
7400 vote_state.last_timestamp = timestamp;
7401 let versioned = VoteStateVersions::new_current(vote_state);
7402 vote_state::to(&versioned, &mut vote_account).unwrap();
7403 bank.store_account(vote_pubkey, &vote_account);
7404 }
7405
7406 pub fn deposit(
7407 bank: &Bank,
7408 pubkey: &Pubkey,
7409 lamports: u64,
7410 ) -> std::result::Result<u64, LamportsError> {
7411 let mut account = bank
7414 .get_account_with_fixed_root_no_cache(pubkey)
7415 .unwrap_or_default();
7416 account.checked_add_lamports(lamports)?;
7417 bank.store_account(pubkey, &account);
7418 Ok(account.lamports())
7419 }
7420}