Skip to content

Commit 1184d72

Browse files
committed
More type-safe diff base state
1 parent 088cfa0 commit 1184d72

File tree

3 files changed

+79
-43
lines changed

3 files changed

+79
-43
lines changed

beacon_node/beacon_chain/src/schema_change/migration_schema_v24.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{
99
time::{Duration, Instant},
1010
};
1111
use store::{
12-
get_full_state_v22, hdiff::StorageStrategy, hot_cold_store::DiffBaseStateRoot,
12+
get_full_state_v22, hdiff::StorageStrategy, hot_cold_store::OptionalDiffBaseState,
1313
store_full_state_v22, DBColumn, Error, HotColdDB, HotStateSummary, KeyValueStore,
1414
KeyValueStoreOp, StoreItem,
1515
};
@@ -181,7 +181,7 @@ pub fn upgrade_to_v24<T: BeaconChainTypes>(
181181
))
182182
})?;
183183

184-
let diff_base_state_root = DiffBaseStateRoot::new(
184+
let diff_base_state = OptionalDiffBaseState::new(
185185
diff_base_slot,
186186
state_summaries_dag
187187
.ancestor_state_root_at_slot(state_root, diff_base_slot)
@@ -198,7 +198,7 @@ pub fn upgrade_to_v24<T: BeaconChainTypes>(
198198
latest_block_root: old_summary.latest_block_root,
199199
latest_block_slot: old_summary.latest_block_slot,
200200
previous_state_root,
201-
diff_base_state_root,
201+
diff_base_state,
202202
};
203203
let op = new_summary.as_kv_store_op(state_root);
204204
// It's not ncessary to immediately commit the summaries of states that are

beacon_node/store/src/errors.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,13 @@ pub enum Error {
8383
MissingBlock(Hash256),
8484
GenesisStateUnknown,
8585
ArithError(safe_arith::ArithError),
86-
MissmatchDiffBaseStateRoot {
86+
MismatchedDiffBaseState {
8787
expected_slot: Slot,
8888
stored_slot: Slot,
8989
},
90+
SnapshotDiffBaseState {
91+
slot: Slot,
92+
},
9093
LoadAnchorInfo(Box<Error>),
9194
LoadSplit(Box<Error>),
9295
LoadBlobInfo(Box<Error>),

beacon_node/store/src/hot_cold_store.rs

Lines changed: 72 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,7 +1519,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
15191519
?state_root,
15201520
slot = %state.slot(),
15211521
storage_strategy = ?self.hot_storage_strategy(state.slot())?,
1522-
diff_base_state_root = ?summary.diff_base_state_root,
1522+
diff_base_state = %summary.diff_base_state,
15231523
previous_state_root = ?summary.previous_state_root,
15241524
"Storing hot state summary and diffs"
15251525
);
@@ -1656,7 +1656,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
16561656
// FIXME(tree-states): Add cache of hot hdiff buffers
16571657
let Some(HotStateSummary {
16581658
slot,
1659-
diff_base_state_root,
1659+
diff_base_state,
16601660
..
16611661
}) = self.load_hot_state_summary(&state_root)?
16621662
else {
@@ -1665,7 +1665,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
16651665
.into_iter()
16661666
.map(|(state_root, summary)| (state_root, summary.slot))
16671667
.collect::<Vec<(Hash256, Slot)>>();
1668-
existing_summaries.sort_by(|a, b| a.1.cmp(&b.1));
1668+
existing_summaries.sort_by_key(|(_, slot)| *slot);
16691669
// Hot summaries should never be missing, dump the current list of summaries to ease debug
16701670
// TODO(hdiff): this log is for debug and can include a very long list of roots,
16711671
// thousands in non-finality.
@@ -1695,7 +1695,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
16951695
Ok(buffer)
16961696
}
16971697
StorageStrategy::DiffFrom(from_slot) => {
1698-
let from_state_root = diff_base_state_root.get_root(from_slot)?;
1698+
let from_state_root = diff_base_state.get_root(from_slot)?;
16991699
let mut buffer = self.load_hot_hdiff_buffer(from_state_root).map_err(|e| {
17001700
Error::LoadingHotHdiffBufferError(
17011701
format!("load hdiff DiffFrom {from_slot} {state_root}"),
@@ -1708,7 +1708,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
17081708
Ok(buffer)
17091709
}
17101710
StorageStrategy::ReplayFrom(from_slot) => {
1711-
let from_state_root = diff_base_state_root.get_root(from_slot)?;
1711+
let from_state_root = diff_base_state.get_root(from_slot)?;
17121712
self.load_hot_hdiff_buffer(from_state_root).map_err(|e| {
17131713
Error::LoadingHotHdiffBufferError(
17141714
format!("load hdiff ReplayFrom {from_slot} {state_root}"),
@@ -1750,7 +1750,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
17501750
if let Some(HotStateSummary {
17511751
slot,
17521752
latest_block_root,
1753-
diff_base_state_root,
1753+
diff_base_state,
17541754
..
17551755
}) = self.load_hot_state_summary(state_root)?
17561756
{
@@ -1774,7 +1774,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
17741774
state
17751775
}
17761776
StorageStrategy::ReplayFrom(from_slot) => {
1777-
let from_state_root = diff_base_state_root.get_root(from_slot)?;
1777+
let from_state_root = diff_base_state.get_root(from_slot)?;
17781778

17791779
let (mut base_state, _) = self
17801780
.load_hot_state(&from_state_root, update_cache)
@@ -3558,14 +3558,20 @@ fn get_ancestor_state_root<'a, E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>
35583558
Ordering::Greater => {} // keep going
35593559
}
35603560

3561-
// Jump to an older state summary that is ancestor of `state_root`
3562-
if target_slot <= state_summary.diff_base_state_root.slot {
3563-
// As an optimization use the HDiff state root to jump states faster
3564-
state_root = state_summary.diff_base_state_root.state_root;
3565-
} else {
3566-
// Else jump slot by slot
3567-
state_root = state_summary.previous_state_root;
3561+
// Jump to an older state summary that is an ancestor of `state_root`
3562+
if let OptionalDiffBaseState::BaseState(DiffBaseState {
3563+
slot,
3564+
state_root: diff_base_state_root,
3565+
}) = state_summary.diff_base_state
3566+
{
3567+
if target_slot <= slot {
3568+
// As an optimization use the HDiff state root to jump states faster
3569+
state_root = diff_base_state_root;
3570+
}
3571+
continue;
35683572
}
3573+
// Else jump slot by slot
3574+
state_root = state_summary.previous_state_root;
35693575
}
35703576
}
35713577

@@ -3577,45 +3583,72 @@ pub struct HotStateSummary {
35773583
pub slot: Slot,
35783584
pub latest_block_root: Hash256,
35793585
pub latest_block_slot: Slot,
3580-
// FIXME(tree-states): consider not storing the storage strategy and storing a state root instead
3581-
pub diff_base_state_root: DiffBaseStateRoot,
3582-
// FIXME(tree-states): should add this as part of this migration
3586+
pub diff_base_state: OptionalDiffBaseState,
35833587
pub previous_state_root: Hash256,
35843588
}
35853589

3586-
/// Cache for a single state root associated with a slot
3590+
/// Information about the state that a hot state is diffed from or replays blocks from, if any.
3591+
///
3592+
/// In the case of a snapshot, there is no diff base state, so this value will be
3593+
/// `DiffBaseState::Snapshot`.
35873594
#[derive(Debug, Clone, Copy, Encode, Decode)]
3588-
pub struct DiffBaseStateRoot {
3595+
#[ssz(enum_behaviour = "union")]
3596+
pub enum OptionalDiffBaseState {
3597+
Snapshot(Slot),
3598+
BaseState(DiffBaseState),
3599+
}
3600+
3601+
#[derive(Debug, Clone, Copy, Encode, Decode)]
3602+
pub struct DiffBaseState {
35893603
slot: Slot,
35903604
state_root: Hash256,
35913605
}
35923606

3593-
impl DiffBaseStateRoot {
3607+
impl OptionalDiffBaseState {
35943608
pub fn new(slot: Slot, state_root: Hash256) -> Self {
3595-
Self { slot, state_root }
3609+
Self::BaseState(DiffBaseState { slot, state_root })
35963610
}
35973611

3598-
pub fn zero() -> Self {
3599-
Self {
3600-
slot: Slot::new(0),
3601-
state_root: Hash256::ZERO,
3612+
pub fn get_root(&self, slot: Slot) -> Result<Hash256, Error> {
3613+
match *self {
3614+
Self::Snapshot(stored_slot) => {
3615+
if slot == stored_slot {
3616+
Err(Error::SnapshotDiffBaseState { slot })
3617+
} else {
3618+
Err(Error::MismatchedDiffBaseState {
3619+
expected_slot: slot,
3620+
stored_slot,
3621+
})
3622+
}
3623+
}
3624+
Self::BaseState(DiffBaseState {
3625+
slot: stored_slot,
3626+
state_root,
3627+
}) => {
3628+
if stored_slot == slot {
3629+
Ok(state_root)
3630+
} else {
3631+
Err(Error::MismatchedDiffBaseState {
3632+
expected_slot: slot,
3633+
stored_slot,
3634+
})
3635+
}
3636+
}
36023637
}
36033638
}
3639+
}
36043640

3605-
pub fn get_root(&self, slot: Slot) -> Result<Hash256, Error> {
3606-
if self.slot == slot {
3607-
Ok(self.state_root)
3608-
} else {
3609-
Err(Error::MissmatchDiffBaseStateRoot {
3610-
expected_slot: slot,
3611-
stored_slot: self.slot,
3612-
})
3641+
// Succint rendering of (slot, state_root) pair for "Storing hot state summary and diffs" log
3642+
impl std::fmt::Display for OptionalDiffBaseState {
3643+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3644+
match self {
3645+
Self::Snapshot(slot) => write!(f, "{slot}/snapshot"),
3646+
Self::BaseState(base_state) => write!(f, "{base_state}"),
36133647
}
36143648
}
36153649
}
36163650

3617-
// Succint rendering of (slot, state_root) pair for "Storing hot state summary and diffs" log
3618-
impl std::fmt::Display for DiffBaseStateRoot {
3651+
impl std::fmt::Display for DiffBaseState {
36193652
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36203653
write!(f, "{}/{:?}", self.slot, self.state_root)
36213654
}
@@ -3662,10 +3695,10 @@ impl HotStateSummary {
36623695
}
36633696
};
36643697
let diff_base_slot = storage_strategy.diff_base_slot();
3665-
let diff_base_state_root = if let Some(diff_base_slot) = diff_base_slot {
3666-
DiffBaseStateRoot::new(diff_base_slot, get_state_root(diff_base_slot)?)
3698+
let diff_base_state = if let Some(diff_base_slot) = diff_base_slot {
3699+
OptionalDiffBaseState::new(diff_base_slot, get_state_root(diff_base_slot)?)
36673700
} else {
3668-
DiffBaseStateRoot::zero()
3701+
OptionalDiffBaseState::Snapshot(state.slot())
36693702
};
36703703

36713704
let previous_state_root = if state.slot() == 0 {
@@ -3679,7 +3712,7 @@ impl HotStateSummary {
36793712
slot: state.slot(),
36803713
latest_block_root,
36813714
latest_block_slot: state.latest_block_header().slot,
3682-
diff_base_state_root,
3715+
diff_base_state,
36833716
previous_state_root,
36843717
})
36853718
}

0 commit comments

Comments
 (0)