Verifies EAH in SnapshotHash (#28775)

This commit is contained in:
Brooks Prumo 2022-11-14 15:02:08 -06:00 committed by GitHub
parent 1e2989501f
commit 503da50f2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 8 deletions

View File

@ -149,6 +149,30 @@ contain the EAH.
Same as (4).
#### Snapshot Verification
If a snapshot archive includes an EAH, we want to verify the EAH is correct at
load time (instead of waiting until `stop slot`, which could be far in the
future).
If the snapshot archive is for a slot within the `calculation window`†¹, then it
*must* include an EAH. The snapshot hash itself will now also incorporate the
EAH. In pseudo code:
```pseudo
if slot is in calculation window
let snapshot hash = hash(accounts hash, epoch accounts hash)
else
let snapshot hash = accounts hash
endif
```
Since loading from a snapshot archive already verifies the snapshot archive's
hash against the deserialized bank, the EAH will be implicitly verified as
well.
†¹: The `calculation window` is `[start slot, stop slot)`, based on the epoch
of the referenced `Bank`.
#### Corner Cases
#### Minimum Slots per Epoch

View File

@ -6984,7 +6984,8 @@ impl Bank {
pub fn get_snapshot_hash(&self) -> SnapshotHash {
let accounts_hash = self.get_accounts_hash();
SnapshotHash::new(&accounts_hash)
let epoch_accounts_hash = self.get_epoch_accounts_hash_to_serialize();
SnapshotHash::new(&accounts_hash, epoch_accounts_hash.as_ref())
}
pub fn get_thread_pool(&self) -> &ThreadPool {

View File

@ -1,5 +1,11 @@
//! Helper types and functions for handling and dealing with snapshot hashes.
use solana_sdk::{clock::Slot, hash::Hash};
use {
crate::epoch_accounts_hash::EpochAccountsHash,
solana_sdk::{
clock::Slot,
hash::{Hash, Hasher},
},
};
/// At startup, when loading from snapshots, the starting snapshot hashes need to be passed to
/// SnapshotPackagerService, which is in charge of pushing the hashes to CRDS. This struct wraps
@ -48,11 +54,19 @@ pub struct IncrementalSnapshotHashes {
pub struct SnapshotHash(pub Hash);
impl SnapshotHash {
/// Make a snapshot hash from an accounts hash
///
/// Will soon also incorporate the epoch accounts hash
/// Make a snapshot hash from an accounts hash and epoch accounts hash
#[must_use]
pub fn new(accounts_hash: &Hash) -> Self {
Self(*accounts_hash)
pub fn new(accounts_hash: &Hash, epoch_accounts_hash: Option<&EpochAccountsHash>) -> Self {
let snapshot_hash = match epoch_accounts_hash {
None => *accounts_hash,
Some(epoch_accounts_hash) => {
let mut hasher = Hasher::default();
hasher.hash(accounts_hash.as_ref());
hasher.hash(epoch_accounts_hash.as_ref().as_ref());
hasher.result()
}
};
Self(snapshot_hash)
}
}

View File

@ -3,6 +3,7 @@ use {
accounts::Accounts,
accounts_db::SnapshotStorages,
bank::{Bank, BankSlotDelta},
epoch_accounts_hash::EpochAccountsHash,
rent_collector::RentCollector,
snapshot_archive_info::{SnapshotArchiveInfo, SnapshotArchiveInfoGetter},
snapshot_hash::SnapshotHash,
@ -107,6 +108,7 @@ impl AccountsPackage {
incremental_snapshot_archives_dir: incremental_snapshot_archives_dir
.as_ref()
.to_path_buf(),
epoch_accounts_hash: bank.get_epoch_accounts_hash_to_serialize(),
};
Ok(Self::_new(
package_type,
@ -177,6 +179,7 @@ impl AccountsPackage {
snapshot_version: SnapshotVersion::default(),
full_snapshot_archives_dir: PathBuf::default(),
incremental_snapshot_archives_dir: PathBuf::default(),
epoch_accounts_hash: Option::default(),
}),
enqueued: Instant::now(),
}
@ -217,6 +220,7 @@ pub struct SupplementalSnapshotInfo {
pub snapshot_version: SnapshotVersion,
pub full_snapshot_archives_dir: PathBuf,
pub incremental_snapshot_archives_dir: PathBuf,
pub epoch_accounts_hash: Option<EpochAccountsHash>,
}
/// Accounts packages are sent to the Accounts Hash Verifier for processing. There are multiple
@ -247,7 +251,8 @@ impl SnapshotPackage {
let Some(snapshot_info) = accounts_package.snapshot_info else {
panic!("The AccountsPackage must have snapshot info in order to make a SnapshotPackage!");
};
let snapshot_hash = SnapshotHash::new(&accounts_hash);
let snapshot_hash =
SnapshotHash::new(&accounts_hash, snapshot_info.epoch_accounts_hash.as_ref());
let mut snapshot_storages = accounts_package.snapshot_storages;
let snapshot_archive_path = match snapshot_type {
SnapshotType::FullSnapshot => snapshot_utils::build_full_snapshot_archive_path(