Skip to content

Commit ceb59e3

Browse files
committed
Don't log extra diffs as roots
1 parent f020adb commit ceb59e3

File tree

3 files changed

+56
-25
lines changed

3 files changed

+56
-25
lines changed

beacon_node/beacon_chain/src/migrate.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::sync::{mpsc, Arc};
88
use std::thread;
99
use std::time::{Duration, SystemTime, UNIX_EPOCH};
1010
use store::hot_cold_store::{migrate_database, HotColdDBError};
11-
use store::{Error, ItemStore, StoreOp};
11+
use store::{Error, ItemStore, Split, StoreOp};
1212
pub use store::{HotColdDB, MemoryStore};
1313
use types::{BeaconState, BeaconStateHash, Checkpoint, Epoch, EthSpec, Hash256, Slot};
1414

@@ -319,19 +319,24 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
319319
}
320320
};
321321

322-
match migrate_database(
322+
let split_prior_to_migration = match migrate_database(
323323
db.clone(),
324324
finalized_state_root.into(),
325325
finalized_block_root,
326326
&finalized_state,
327327
) {
328-
Ok(()) => {}
328+
Ok(split_change) => {
329+
// Migration run, return the split before the migration
330+
split_change.previous
331+
}
329332
Err(Error::HotColdDBError(HotColdDBError::FreezeSlotUnaligned(slot))) => {
330333
debug!(
331334
log,
332335
"Database migration postponed, unaligned finalized block";
333336
"slot" => slot.as_u64()
334337
);
338+
// Migration did not run, return the current split info
339+
db.get_split_info()
335340
}
336341
Err(e) => {
337342
warn!(
@@ -348,6 +353,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
348353
finalized_state_root.into(),
349354
&finalized_state,
350355
notif.finalized_checkpoint,
356+
split_prior_to_migration,
351357
log,
352358
) {
353359
Ok(PruningOutcome::Successful {
@@ -457,6 +463,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
457463
new_finalized_state_root: Hash256,
458464
new_finalized_state: &BeaconState<E>,
459465
new_finalized_checkpoint: Checkpoint,
466+
split_prior_to_migration: Split,
460467
log: &Logger,
461468
) -> Result<PruningOutcome, BeaconChainError> {
462469
let new_finalized_slot = new_finalized_checkpoint
@@ -483,6 +490,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
483490
"Starting database pruning";
484491
"new_finalized_checkpoint" => ?new_finalized_checkpoint,
485492
"new_finalized_state_root" => ?new_finalized_state_root,
493+
"split_prior_to_migration" => ?split_prior_to_migration,
486494
);
487495

488496
let state_summaries_dag = {
@@ -521,13 +529,21 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
521529
// To debug faulty trees log if we unexpectedly have more than one root. These trees may not
522530
// result in an error, as they may not be queried in the codepaths below.
523531
let state_summaries_dag_roots = state_summaries_dag.tree_roots();
524-
if state_summaries_dag_roots.len() > 1 {
532+
let state_summaries_dag_roots_post_split = state_summaries_dag_roots
533+
.iter()
534+
.filter(|(_, s)| s.slot >= split_prior_to_migration.slot)
535+
.collect::<Vec<_>>();
536+
// Because of the additional HDiffs kept for the grid prior to finalization the tree_roots
537+
// function will consider them roots. Those are expected. We just want to assert that the
538+
// relevant tree of states (post-split) is well-formed.
539+
if state_summaries_dag_roots_post_split.len() > 1 {
525540
warn!(
526541
log,
527542
"State summaries DAG found more than one root";
528543
"location" => "pruning",
529544
"new_finalized_state_root" => ?new_finalized_state_root,
530-
"state_summaries_dag_roots" => ?state_summaries_dag_roots
545+
"split_prior_to_migration_slot" => split_prior_to_migration.slot,
546+
"state_summaries_dag_roots_post_split" => ?state_summaries_dag_roots_post_split
531547
);
532548
}
533549

@@ -693,6 +709,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
693709
"Extra pruning information";
694710
"new_finalized_checkpoint" => ?new_finalized_checkpoint,
695711
"new_finalized_state_root" => ?new_finalized_state_root,
712+
"split_prior_to_migration" => ?split_prior_to_migration,
696713
"newly_finalized_blocks" => newly_finalized_blocks.len(),
697714
"newly_finalized_state_roots" => newly_finalized_state_roots.len(),
698715
"newly_finalized_states_min_slot" => newly_finalized_states_min_slot,

beacon_node/beacon_chain/src/summaries_dag.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,14 @@ impl StateSummariesDAG {
238238
self.state_summaries_by_state_root
239239
.iter()
240240
.filter_map(|(state_root, summary)| {
241-
if summary.previous_state_root == Hash256::ZERO {
242-
Some((*state_root, *summary))
243-
} else {
241+
if self
242+
.state_summaries_by_state_root
243+
.contains_key(&summary.previous_state_root)
244+
{
245+
// Summaries with a known parent are not roots
244246
None
247+
} else {
248+
Some((*state_root, *summary))
245249
}
246250
})
247251
.collect()

beacon_node/store/src/hot_cold_store.rs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3302,7 +3302,7 @@ pub fn migrate_database<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>>(
33023302
finalized_state_root: Hash256,
33033303
finalized_block_root: Hash256,
33043304
finalized_state: &BeaconState<E>,
3305-
) -> Result<(), Error> {
3305+
) -> Result<SplitChange, Error> {
33063306
debug!(
33073307
store.log,
33083308
"Freezer migration started";
@@ -3312,12 +3312,12 @@ pub fn migrate_database<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>>(
33123312
// 0. Check that the migration is sensible.
33133313
// The new finalized state must increase the current split slot, and lie on an epoch
33143314
// boundary (in order for the hot state summary scheme to work).
3315-
let current_split_slot = store.split.read_recursive().slot;
3315+
let current_split = *store.split.read_recursive();
33163316
let anchor_info = store.anchor_info.read_recursive().clone();
33173317

3318-
if finalized_state.slot() < current_split_slot {
3318+
if finalized_state.slot() < current_split.slot {
33193319
return Err(HotColdDBError::FreezeSlotError {
3320-
current_split_slot,
3320+
current_split_slot: current_split.slot,
33213321
proposed_split_slot: finalized_state.slot(),
33223322
}
33233323
.into());
@@ -3334,7 +3334,7 @@ pub fn migrate_database<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>>(
33343334
// Iterate in descending order until the current split slot
33353335
let state_roots: Vec<_> =
33363336
process_results(RootsIterator::new(&store, finalized_state), |iter| {
3337-
iter.take_while(|(_, _, slot)| *slot >= current_split_slot)
3337+
iter.take_while(|(_, _, slot)| *slot >= current_split.slot)
33383338
.collect()
33393339
})?;
33403340

@@ -3392,41 +3392,42 @@ pub fn migrate_database<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>>(
33923392
// in the worst case we will restart with the old split and re-run the migration.
33933393
store.cold_db.do_atomically(cold_db_block_ops)?;
33943394
store.cold_db.sync()?;
3395-
{
3395+
let new_split = {
33963396
let mut split_guard = store.split.write();
3397-
let latest_split_slot = split_guard.slot;
3397+
let latest_split = *split_guard;
33983398

33993399
// Detect a situation where the split point is (erroneously) changed from more than one
34003400
// place in code.
3401-
if latest_split_slot != current_split_slot {
3401+
if latest_split.slot != current_split.slot {
34023402
error!(
34033403
store.log,
34043404
"Race condition detected: Split point changed while copying states to the freezer";
3405-
"previous split slot" => current_split_slot,
3406-
"current split slot" => latest_split_slot,
3405+
"previous split slot" => current_split.slot,
3406+
"current split slot" => latest_split.slot,
34073407
);
34083408

34093409
// Assume the freezing procedure will be retried in case this happens.
34103410
return Err(Error::SplitPointModified(
3411-
current_split_slot,
3412-
latest_split_slot,
3411+
current_split.slot,
3412+
latest_split.slot,
34133413
));
34143414
}
34153415

34163416
// Before updating the in-memory split value, we flush it to disk first, so that should the
34173417
// OS process die at this point, we pick up from the right place after a restart.
3418-
let split = Split {
3418+
let new_split = Split {
34193419
slot: finalized_state.slot(),
34203420
state_root: finalized_state_root,
34213421
block_root: finalized_block_root,
34223422
};
3423-
store.hot_db.put_sync(&SPLIT_KEY, &split)?;
3423+
store.hot_db.put_sync(&SPLIT_KEY, &new_split)?;
34243424

34253425
// Split point is now persisted in the hot database on disk. The in-memory split point
34263426
// hasn't been modified elsewhere since we keep a write lock on it. It's safe to update
34273427
// the in-memory split point now.
3428-
*split_guard = split;
3429-
}
3428+
*split_guard = new_split;
3429+
new_split
3430+
};
34303431

34313432
// Update the cache's view of the finalized state.
34323433
store.update_finalized_state(
@@ -3441,7 +3442,16 @@ pub fn migrate_database<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>>(
34413442
"slot" => finalized_state.slot()
34423443
);
34433444

3444-
Ok(())
3445+
Ok(SplitChange {
3446+
previous: current_split,
3447+
new: new_split,
3448+
})
3449+
}
3450+
3451+
#[derive(Debug)]
3452+
pub struct SplitChange {
3453+
pub previous: Split,
3454+
pub new: Split,
34453455
}
34463456

34473457
/// Struct for storing the split slot and state root in the database.

0 commit comments

Comments
 (0)