diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 12e1a8fc1..562d253ce 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -1191,7 +1191,6 @@ pub struct AccountsDb { exhaustively_verify_refcounts: bool, /// A special accounts hash that occurs once per epoch - #[allow(dead_code)] pub(crate) epoch_accounts_hash: Mutex>, } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 00e57f62e..22cbb2ab6 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -53,6 +53,7 @@ use { blockhash_queue::BlockhashQueue, builtins::{self, BuiltinAction, BuiltinFeatureTransition, Builtins}, cost_tracker::CostTracker, + epoch_accounts_hash::{self, EpochAccountsHash}, epoch_stakes::{EpochStakes, NodeVoteAccounts}, expected_rent_collection::{ExpectedRentCollection, SlotInfoInEpoch}, inline_spl_associated_token_account, inline_spl_token, @@ -6835,6 +6836,21 @@ impl Bank { self.last_blockhash().as_ref(), ]); + let epoch_accounts_hash = self.epoch_accounts_hash(); + if self.should_include_epoch_accounts_hash() { + // Nothing is writing a value into the epoch accounts hash yet—this is not a problem + // for normal clusters, as the feature gating this `if` block is always false. + // However, some tests enable all features, so this `if` block can be true. + // + // For now, check to see if the epoch accounts hash is `Some` before hashing. Once the + // writer-side is implemented, change this to be an `.expect()` or `.unwrap()`, as it + // will be required for the epoch accounts hash calculation to have compleleted and + // for this value to be `Some`. + if let Some(epoch_accounts_hash) = epoch_accounts_hash { + hash = hashv(&[hash.as_ref(), epoch_accounts_hash.as_ref().as_ref()]); + } + } + let buf = self .hard_forks .read() @@ -6853,13 +6869,17 @@ impl Bank { } info!( - "bank frozen: {} hash: {} accounts_delta: {} signature_count: {} last_blockhash: {} capitalization: {}", + "bank frozen: {} hash: {} accounts_delta: {} signature_count: {} last_blockhash: {} capitalization: {}{}", self.slot(), hash, accounts_delta_hash.hash, self.signature_count(), self.last_blockhash(), self.capitalization(), + match epoch_accounts_hash { + None => "".to_string(), + Some(epoch_accounts_hash) => format!(", epoch_accounts_hash: {}", epoch_accounts_hash.as_ref()), + }, ); info!( @@ -6870,6 +6890,22 @@ impl Bank { hash } + /// The epoch accounts hash is hashed into the bank's hash once per epoch at a predefined slot. + /// Should it be included in *this* bank? + fn should_include_epoch_accounts_hash(&self) -> bool { + if !self + .feature_set + .is_active(&feature_set::epoch_accounts_hash::id()) + { + return false; + } + + let first_slot_in_epoch = self.epoch_schedule().get_first_slot_in_epoch(self.epoch); + let stop_offset = epoch_accounts_hash::calculation_offset_stop(self); + let stop_slot = first_slot_in_epoch + stop_offset; + self.parent_slot() < stop_slot && self.slot() >= stop_slot + } + /// Recalculate the hash_internal_state from the account stores. Would be used to verify a /// snapshot. /// return true if all is good @@ -7843,6 +7879,17 @@ impl Bank { total_accounts_stats } + + /// Convenience fn to get the Epoch Accounts Hash + fn epoch_accounts_hash(&self) -> Option { + *self + .rc + .accounts + .accounts_db + .epoch_accounts_hash + .lock() + .unwrap() + } } /// Compute how much an account has changed size. This function is useful when the data size delta diff --git a/runtime/src/epoch_accounts_hash.rs b/runtime/src/epoch_accounts_hash.rs index 48c55c430..15aa9110d 100644 --- a/runtime/src/epoch_accounts_hash.rs +++ b/runtime/src/epoch_accounts_hash.rs @@ -38,7 +38,6 @@ pub fn calculation_offset_start(bank: &Bank) -> Slot { /// and referred to as the "stop" slot for the EAH calculation. All nodes must complete the EAH /// calculation before this slot! #[must_use] -#[allow(dead_code)] pub fn calculation_offset_stop(bank: &Bank) -> Slot { let slots_per_epoch = bank.epoch_schedule().slots_per_epoch; slots_per_epoch / 4 * 3 diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index fc0573dbd..0ee39158a 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -514,6 +514,10 @@ pub mod cap_accounts_data_allocations_per_transaction { solana_sdk::declare_id!("9gxu85LYRAcZL38We8MYJ4A9AwgBBPtVBAqebMcT1241"); } +pub mod epoch_accounts_hash { + solana_sdk::declare_id!("5GpmAKxaGsWWbPp4bNXFLJxZVvG92ctxf7jQnzTQjF3n"); +} + lazy_static! { /// Map of feature identifiers to user-visible description pub static ref FEATURE_NAMES: HashMap = [ @@ -637,6 +641,7 @@ lazy_static! { (stop_sibling_instruction_search_at_parent::id(), "stop the search in get_processed_sibling_instruction when the parent instruction is reached #27289"), (vote_state_update_root_fix::id(), "fix root in vote state updates #27361"), (cap_accounts_data_allocations_per_transaction::id(), "cap accounts data allocations per transaction #27375"), + (epoch_accounts_hash::id(), "enable epoch accounts hash calculation #27539"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter()