Skip to content

Commit c2c7fb8

Browse files
Make DAG construction more permissive (#7460)
Workaround/fix for: - #7323 - Remove the `StateSummariesNotContiguousError`. This allows us to continue with DAG construction and pruning, even in the case where the DAG is disjointed. We will treat any disjoint summaries as roots of their own tree, and prune them (as they are not descended from finalized). This should be safe, as canonical summaries should not be disjoint (if they are, then the DB is already corrupt).
1 parent 851ee2b commit c2c7fb8

File tree

4 files changed

+31
-37
lines changed

4 files changed

+31
-37
lines changed

beacon_node/beacon_chain/src/migrate.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,8 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
572572
if state_summaries_dag_roots.len() > 1 {
573573
warn!(
574574
state_summaries_dag_roots = ?state_summaries_dag_roots,
575-
"Prune state summaries dag found more than one root"
575+
error = "summaries dag found more than one root",
576+
"Notify the devs your hot DB has some inconsistency. Pruning will fix it but devs want to know about it",
576577
);
577578
}
578579

beacon_node/beacon_chain/src/schema_change/migration_schema_v22.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub fn upgrade_to_v22<T: BeaconChainTypes>(
4141
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
4242
genesis_state_root: Option<Hash256>,
4343
) -> Result<(), Error> {
44-
info!("Upgrading from v21 to v22");
44+
info!("Upgrading DB schema from v21 to v22");
4545

4646
let old_anchor = db.get_anchor_info();
4747

beacon_node/beacon_chain/src/schema_change/migration_schema_v23.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use ssz::{Decode, Encode};
88
use ssz_derive::{Decode, Encode};
99
use std::sync::Arc;
1010
use store::{DBColumn, Error, HotColdDB, KeyValueStore, KeyValueStoreOp, StoreItem};
11+
use tracing::{debug, info};
1112
use types::{Hash256, Slot};
1213

1314
/// Dummy value to use for the canonical head block root, see below.
@@ -16,6 +17,8 @@ pub const DUMMY_CANONICAL_HEAD_BLOCK_ROOT: Hash256 = Hash256::repeat_byte(0xff);
1617
pub fn upgrade_to_v23<T: BeaconChainTypes>(
1718
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
1819
) -> Result<Vec<KeyValueStoreOp>, Error> {
20+
info!("Upgrading DB schema from v22 to v23");
21+
1922
// 1) Set the head-tracker to empty
2023
let Some(persisted_beacon_chain_v22) =
2124
db.get_item::<PersistedBeaconChainV22>(&BEACON_CHAIN_DB_KEY)?
@@ -37,10 +40,24 @@ pub fn upgrade_to_v23<T: BeaconChainTypes>(
3740
.hot_db
3841
.iter_column_keys::<Hash256>(DBColumn::BeaconStateTemporary)
3942
{
43+
let state_root = state_root_result?;
44+
debug!(
45+
?state_root,
46+
"Deleting temporary state flag on v23 schema migration"
47+
);
4048
ops.push(KeyValueStoreOp::DeleteKey(
4149
DBColumn::BeaconStateTemporary,
42-
state_root_result?.as_slice().to_vec(),
50+
state_root.as_slice().to_vec(),
4351
));
52+
// Here we SHOULD delete the items for key `state_root` in columns `BeaconState` and
53+
// `BeaconStateSummary`. However, in the event we have dangling temporary states at the time
54+
// of the migration, the first pruning routine will prune them. They will be a tree branch /
55+
// root not part of the finalized tree and trigger a warning log once.
56+
//
57+
// We believe there may be race conditions concerning temporary flags where a necessary
58+
// canonical state is marked as temporary. In current stable, a restart with that DB will
59+
// corrupt the DB. In the unlikely case this happens we choose to leave the states and
60+
// allow pruning to clean them.
4461
}
4562

4663
Ok(ops)

beacon_node/beacon_chain/src/summaries_dag.rs

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@ pub enum Error {
4343
state_root: Hash256,
4444
latest_block_root: Hash256,
4545
},
46-
StateSummariesNotContiguous {
47-
state_root: Hash256,
48-
state_slot: Slot,
49-
latest_block_root: Hash256,
50-
parent_block_root: Box<Hash256>,
51-
parent_block_latest_state_summary: Box<Option<(Slot, Hash256)>>,
52-
},
5346
MissingChildStateRoot(Hash256),
5447
RequestedSlotAboveSummary {
5548
starting_state_root: Hash256,
@@ -163,34 +156,17 @@ impl StateSummariesDAG {
163156
**state_root
164157
} else {
165158
// Common case: not a skipped slot.
159+
//
160+
// If we can't find a state summmary for the parent block and previous slot,
161+
// then there is some amount of disjointedness in the DAG. We set the parent
162+
// state root to 0x0 in this case, and will prune any dangling states.
166163
let parent_block_root = summary.block_parent_root;
167-
if let Some(parent_block_summaries) =
168-
state_summaries_by_block_root.get(&parent_block_root)
169-
{
170-
*parent_block_summaries
171-
.get(&previous_slot)
172-
// Should never error: summaries are contiguous, so if there's an
173-
// entry it must contain at least one summary at the previous slot.
174-
.ok_or(Error::StateSummariesNotContiguous {
175-
state_root: *state_root,
176-
state_slot: summary.slot,
177-
latest_block_root: summary.latest_block_root,
178-
parent_block_root: parent_block_root.into(),
179-
parent_block_latest_state_summary: parent_block_summaries
180-
.iter()
181-
.max_by(|a, b| a.0.cmp(b.0))
182-
.map(|(slot, (state_root, _))| (*slot, **state_root))
183-
.into(),
184-
})?
185-
.0
186-
} else {
187-
// We don't know of any summary with this parent block root. We'll
188-
// consider this summary to be a root of `state_summaries_v22`
189-
// collection and mark it as zero.
190-
// The test store_tests::finalizes_non_epoch_start_slot manages to send two
191-
// disjoint trees on its second migration.
192-
Hash256::ZERO
193-
}
164+
state_summaries_by_block_root
165+
.get(&parent_block_root)
166+
.and_then(|parent_block_summaries| {
167+
parent_block_summaries.get(&previous_slot)
168+
})
169+
.map_or(Hash256::ZERO, |(parent_state_root, _)| **parent_state_root)
194170
}
195171
};
196172

0 commit comments

Comments
 (0)