Skip to content

Commit 9800ab8

Browse files
committed
Attempt to fix archive node V24 upgrade
1 parent 2485beb commit 9800ab8

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

beacon_node/store/src/hot_cold_store.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2900,12 +2900,28 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
29002900
Ok(ops)
29012901
}
29022902

2903-
/// Returns a single block root from the cold DB
2903+
/// Return a single block root from the cold DB.
2904+
///
2905+
/// If the slot is unavailable due to partial block history, `Ok(None)` will be returned.
29042906
pub fn get_cold_block_root(&self, slot: Slot) -> Result<Option<Hash256>, Error> {
29052907
Ok(self
29062908
.cold_db
29072909
.get_bytes(DBColumn::BeaconBlockRoots, &slot.as_u64().to_be_bytes())?
2908-
.map(|bytes| Hash256::from_ssz_bytes(&bytes).unwrap()))
2910+
.map(|bytes| Hash256::from_ssz_bytes(&bytes))
2911+
.transpose()?)
2912+
}
2913+
2914+
/// Return a single state root from the cold DB.
2915+
///
2916+
/// If the slot is unavailable due to partial state history, `Ok(None)` will be returned.
2917+
///
2918+
/// This function will usually only work on an archive node.
2919+
pub fn get_cold_state_root(&self, slot: Slot) -> Result<Option<Hash256>, Error> {
2920+
Ok(self
2921+
.cold_db
2922+
.get_bytes(DBColumn::BeaconStateRoots, &slot.as_u64().to_be_bytes())?
2923+
.map(|bytes| Hash256::from_ssz_bytes(&bytes))
2924+
.transpose()?)
29092925
}
29102926

29112927
/// Try to prune all execution payloads, returning early if there is no need to prune.
@@ -3448,6 +3464,11 @@ pub enum StateSummaryIteratorError {
34483464
},
34493465
BelowTarget(Slot),
34503466
LoadSummaryError(Box<Error>),
3467+
LoadStateRootError(Box<Error>),
3468+
MissingStateRoot {
3469+
target_slot: Slot,
3470+
state_upper_limit: Slot,
3471+
},
34513472
OutOfBoundsInitialSlot,
34523473
}
34533474

@@ -3463,10 +3484,35 @@ fn get_ancestor_state_root<'a, E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>
34633484
return Ok(*target_state_root);
34643485
}
34653486

3487+
// Fetch the anchor info prior to obtaining the split lock. We don't need to hold a lock because
3488+
// the `state_upper_limit` can't increase (and rug us) unless state pruning runs, and it never
3489+
// runs concurrently.
3490+
let state_upper_limit = store.get_anchor_info().state_upper_limit;
3491+
34663492
// Hold the split lock so that state summaries are not pruned concurrently with this function
34673493
// running.
34683494
let split = store.split.read_recursive();
34693495

3496+
// If the state root is in range of the freezer DB's linear state root storage, fetch it
3497+
// directly from there. This is useful on archive nodes to avoid some of the complexity of
3498+
// traversing the sparse portion of the hdiff grid (prior to the split slot). It is also
3499+
// necessary for the v24 schema migration on archive nodes, where there isn't yet any grid
3500+
// to traverse.
3501+
//
3502+
// FIXME(tree-states): still need to add logic below to somehow traverse the grid on non-archive
3503+
// nodes.
3504+
if target_slot < split.slot && target_slot >= state_upper_limit {
3505+
drop(split);
3506+
return store
3507+
.get_cold_state_root(target_slot)
3508+
.map_err(Box::new)
3509+
.map_err(StateSummaryIteratorError::LoadStateRootError)?
3510+
.ok_or_else(|| StateSummaryIteratorError::MissingStateRoot {
3511+
target_slot,
3512+
state_upper_limit,
3513+
});
3514+
}
3515+
34703516
let mut state_root = {
34713517
// We can not start loading summaries from `state_root` since its summary has not yet been
34723518
// imported. This code path is called during block import.

0 commit comments

Comments
 (0)