-
Notifications
You must be signed in to change notification settings - Fork 1k
Serializes block_id into snapshot #11355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -488,6 +488,7 @@ pub struct BankFieldsToDeserialize { | |
| pub(crate) accounts_data_len: u64, | ||
| pub(crate) accounts_lt_hash: AccountsLtHash, | ||
| pub(crate) bank_hash_stats: BankHashStats, | ||
| pub(crate) block_id: Option<Hash>, // Option wrapper can be removed in version after v4.1 | ||
| } | ||
|
|
||
| /// Bank's common fields shared by all supported snapshot versions for serialization. | ||
|
|
@@ -526,6 +527,7 @@ pub struct BankFieldsToSerialize { | |
| pub accounts_data_len: u64, | ||
| pub versioned_epoch_stakes: HashMap<u64, VersionedEpochStakes>, | ||
| pub accounts_lt_hash: AccountsLtHash, | ||
| pub block_id: Hash, | ||
| } | ||
|
|
||
| // Can't derive PartialEq because RwLock doesn't implement PartialEq | ||
|
|
@@ -677,6 +679,7 @@ impl BankFieldsToSerialize { | |
| accounts_data_len: u64::default(), | ||
| versioned_epoch_stakes: HashMap::default(), | ||
| accounts_lt_hash: AccountsLtHash(LtHash([0x7E57; LtHash::NUM_ELEMENTS])), | ||
| block_id: Hash::default(), | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -2020,7 +2023,7 @@ impl Bank { | |
| accounts_lt_hash: Mutex::new(fields.accounts_lt_hash), | ||
| cache_for_accounts_lt_hash: DashMap::default(), | ||
| stats_for_accounts_lt_hash: AccountsLtHashStats::default(), | ||
| block_id: RwLock::new(None), | ||
| block_id: RwLock::new(fields.block_id), | ||
| bank_hash_stats: AtomicBankHashStats::new(&fields.bank_hash_stats), | ||
| epoch_rewards_calculation_cache: Arc::new(Mutex::new(HashMap::default())), | ||
| expected_bank_hash: RwLock::new(None), | ||
|
|
@@ -2128,6 +2131,7 @@ impl Bank { | |
| accounts_data_len: self.load_accounts_data_size(), | ||
| versioned_epoch_stakes: self.epoch_stakes.clone(), | ||
| accounts_lt_hash: self.accounts_lt_hash.lock().unwrap().clone(), | ||
| block_id: self.block_id().expect("block id must be set"), | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AshwinSekar - here we require that Codex told me this may not be safe though. Can you confirm, please? Here's its review comments:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Legacy shreds have been removed on all live clusters and we explicitly drop such shreds on ingest. Also if |
||
| } | ||
| } | ||
|
|
||
|
|
@@ -6162,6 +6166,45 @@ impl Bank { | |
| self.stakes_cache.stakes().clone() | ||
| } | ||
| } | ||
|
|
||
| /// Calculates and sets block id for `bank`. | ||
| /// | ||
| /// This fn operates recursively. Since calculating the block id requires | ||
| /// the bank's parent's block id, if the bank's parent's block id is unset, | ||
| /// it will be calculated and set first. | ||
| /// | ||
| /// Note this fn will also freeze `bank`. | ||
| /// | ||
| /// Only to be called from dev contexts. | ||
| /// Couldn't make the fn actually DCOU, since it is called by | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So is the issue here that warping a slot should in fact be dcou, but it's not due to how our crates are layed out? Is this something that can be fixed by moving the test-validator to dev-bins?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think the only use for warping is for dev context stuff, yes? I reserve the right to be wrong here though 😸
Maybe? I dunno. Just gotta put everything that calls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like trying to put a bandaid over the real issue: That warp_slot is DCOU and isn't documented as so because no ones fixed it. So it should be fixed first, which might provide some other benefits as well. Or it's not actually DCOU and the _for_dcou should be removed.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, might be able to refactor code to mark warping as dcou. IMO seems quite a large endeavor to block this PR on though. I can rename There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess it really depends how time pressing this feature is.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This PR doesn't change any of the semantics around warping. I don't understand why it should be gated on solana-test-validator. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the other conversation, it sounds like warping in the validator can be removed entirely. Would that change this PR at all?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turning into a mess. Merge this and solve the DCOU issue later |
||
| /// Validator::new() when warping a slot. | ||
| pub fn calculate_and_set_block_id_for_dcou(bank: &Bank) { | ||
| if bank.block_id().is_some() { | ||
| // done! | ||
| return; | ||
| } | ||
|
|
||
| let Some(parent) = bank.parent() else { | ||
| // If bank doesn't have a parent, then use bank hash for block id, | ||
| // as parent's block id is not available for the calculation below. | ||
| // Must freeze() to ensure bank hash has been calculated. | ||
| bank.freeze(); | ||
| bank.set_block_id(Some(bank.hash())); | ||
| return; | ||
| }; | ||
|
|
||
| let parent_block_id = parent.block_id().unwrap_or_else(|| { | ||
| // if the parent's block id isn't set, we recurse so it gets set | ||
| Self::calculate_and_set_block_id_for_dcou(&parent); | ||
| parent.block_id().unwrap() | ||
| }); | ||
|
|
||
| // must freeze() to ensure bank hash has been calculated | ||
| bank.freeze(); | ||
| let block_id = | ||
| solana_sha256_hasher::hashv(&[parent_block_id.as_ref(), bank.hash().as_ref()]); | ||
|
AshwinSekar marked this conversation as resolved.
|
||
| bank.set_block_id(Some(block_id)); | ||
| } | ||
| } | ||
|
|
||
| impl InvokeContextCallback for Bank { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ mod tests { | |
| accounts_file::{AccountsFile, AccountsFileError, StorageAccess}, | ||
| }, | ||
| solana_epoch_schedule::EpochSchedule, | ||
| solana_hash::Hash, | ||
| solana_native_token::LAMPORTS_PER_SOL, | ||
| solana_pubkey::Pubkey, | ||
| solana_stake_interface::state::Stake, | ||
|
|
@@ -108,6 +109,7 @@ mod tests { | |
|
|
||
| let accounts_db = &bank2.rc.accounts.accounts_db; | ||
|
|
||
| bank2.set_block_id(Some(Hash::default())); | ||
| bank2.squash(); | ||
| bank2.force_flush_accounts_cache(); | ||
|
|
||
|
|
@@ -120,6 +122,7 @@ mod tests { | |
| let mut bank_fields = bank2.get_fields_to_serialize(); | ||
| let versioned_epoch_stakes = mem::take(&mut bank_fields.versioned_epoch_stakes); | ||
| let accounts_lt_hash = Some(bank_fields.accounts_lt_hash.clone().into()); | ||
| let block_id = Some(bank_fields.block_id); | ||
| serde_snapshot::serialize_bank_snapshot_into( | ||
| &mut writer, | ||
| bank_fields, | ||
|
|
@@ -131,6 +134,7 @@ mod tests { | |
| unused_epoch_accounts_hash: None, | ||
| versioned_epoch_stakes, | ||
| accounts_lt_hash, | ||
| block_id, | ||
| }, | ||
| ) | ||
| .unwrap(); | ||
|
|
@@ -193,6 +197,7 @@ mod tests { | |
| let bank0 = Arc::new(Bank::new_for_tests(&genesis_config)); | ||
| bank0.squash(); | ||
| let mut bank = Bank::new_from_parent(bank0.clone(), *bank0.leader(), 1); | ||
| bank.set_block_id(Some(Hash::default())); | ||
| bank.freeze(); | ||
| add_root_and_flush_write_cache(&bank0); | ||
|
|
||
|
|
@@ -277,6 +282,7 @@ mod tests { | |
| while !bank.is_complete() { | ||
| bank.fill_bank_with_ticks_for_tests(); | ||
| } | ||
| bank.set_block_id(Some(Hash::default())); | ||
|
|
||
| // Set extra field | ||
| bank.fee_rate_governor.lamports_per_signature = 7000; | ||
|
|
@@ -356,7 +362,7 @@ mod tests { | |
| #[cfg_attr( | ||
| feature = "frozen-abi", | ||
| derive(AbiExample), | ||
| frozen_abi(digest = "7NL9Sugo2js3PtueK7izqSwX5dGWKDMDVnjo6MirVPWE") | ||
| frozen_abi(digest = "ELfWa1ABrJu9sQABjieyqnWioDaHNykbmYqsQr7yYYBb") | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Digest changed because we added ❯ diff -u ./*7NL9Sugo2js3PtueK7izqSwX5dGWKDMDVnjo6MirVPWE* ./*ELfWa1ABrJu9sQABjieyqnWioDaHNykbmYqsQr7yYYBb*
--- ./bank__serde_snapshot__tests__test_bank_serialize__BankAbiTestWrapper_frozen_abi__test_api_digest_7NL9Sugo2js3PtueK7izqSwX5dGWKDMDVnjo6MirVPWE 2026-03-17 16:41:50
+++ ./bank__serde_snapshot__tests__test_bank_serialize__BankAbiTestWrapper_frozen_abi__test_api_digest_ELfWa1ABrJu9sQABjieyqnWioDaHNykbmYqsQr7yYYBb 2026-03-17 16:40:05
@@ -1275,7 +1275,7 @@
element u8
primitive u8
element solana_runtime::serde_snapshot::ExtraFieldsToSerialize
- struct ExtraFieldsToSerialize (fields = 5)
+ struct ExtraFieldsToSerialize (fields = 6)
field lamports_per_signature: u64
primitive u64
field unused_incremental_snapshot_persistence: core::option::Option<solana_runtime::serde_snapshot::UnusedIncrementalSnapshotPersistence>
@@ -4480,3 +4480,73 @@
primitive u16
element serde_with::ser::SerializeAsWrap<'_, u16, serde_with::Same>
primitive u16
+ field block_id: core::option::Option<solana_hash::Hash>
+ enum Option (variants = 2)
+ variant(0) None (unit)
+ variant(1) Some(solana_hash::Hash) (newtype)
+ struct Hash([u8; 32]) (newtype)
+ tuple (elements = 32)
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8
+ element u8
+ primitive u8 |
||
| )] | ||
| #[derive(serde::Serialize)] | ||
| pub struct BankAbiTestWrapper { | ||
|
|
@@ -369,6 +375,7 @@ mod tests { | |
| S: serde::Serializer, | ||
| { | ||
| let bank = Bank::default_for_tests(); | ||
| bank.set_block_id(Some(Hash::default())); | ||
| let snapshot_storages = AccountsDb::example().get_storages(0..1).0; | ||
| // ensure there is at least one snapshot storage example for ABI digesting | ||
| assert!(!snapshot_storages.is_empty()); | ||
|
|
@@ -394,6 +401,7 @@ mod tests { | |
| unused_epoch_accounts_hash: Some(Hash::new_unique()), | ||
| versioned_epoch_stakes, | ||
| accounts_lt_hash: Some(AccountsLtHash(LtHash::identity()).into()), | ||
| block_id: Some(Hash::new_unique()), | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.