Skip to content

Commit d7774ed

Browse files
committed
Allow Checkpoint Sync on State Beyond Finalization (#5128)
Squashed commit of the following: commit 36a5d49 Author: ethDreamer <[email protected]> Date: Fri Feb 9 11:27:33 2024 +0800 Update beacon_node/client/src/builder.rs Co-authored-by: realbigsean <[email protected]> commit 9b8b953 Author: Mark Mackey <[email protected]> Date: Mon Feb 5 12:15:55 2024 +0800 fix up some loose ends commit 2b82413 Author: Mark Mackey <[email protected]> Date: Tue Jan 30 15:00:55 2024 +0800 Properly Persist AnchorState in ForkChoice commit 8c071ce Author: Mark Mackey <[email protected]> Date: Mon Jan 29 17:18:34 2024 +0800 Fix Beacon Chain Tests commit 433aac5 Author: Mark Mackey <[email protected]> Date: Thu Jan 25 16:42:33 2024 +0800 Enforce Checkpoint State Inside DA Boundary commit 76a386f Author: Mark Mackey <[email protected]> Date: Thu Jan 25 15:03:27 2024 +0800 Cleanup some TODOs commit 117ee3c Author: Mark Mackey <[email protected]> Date: Thu Jan 18 10:43:02 2024 +0100 Add Peers with Lower Finalization on NonRevertible commit 3ef3af3 Author: Mark Mackey <[email protected]> Date: Wed Jan 17 21:33:38 2024 +0100 Added AnchorState to ForkChoice commit aebc66d Author: Mark Mackey <[email protected]> Date: Wed Jan 10 11:22:46 2024 +0100 Allow Checkpoint Sync from Non-Finalized States
1 parent dea1ba6 commit d7774ed

File tree

21 files changed

+396
-74
lines changed

21 files changed

+396
-74
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

beacon_node/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ clap = { workspace = true }
2929
slog = { workspace = true }
3030
dirs = { workspace = true }
3131
directory = { workspace = true }
32+
eth2 = { workspace = true }
3233
futures = { workspace = true }
3334
environment = { workspace = true }
3435
task_executor = { workspace = true }

beacon_node/beacon_chain/src/beacon_fork_choice_store.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,9 @@ pub struct PersistedForkChoiceStore {
389389
pub equivocating_indices: BTreeSet<u64>,
390390
}
391391

392-
impl Into<PersistedForkChoiceStore> for PersistedForkChoiceStoreV11 {
393-
fn into(self) -> PersistedForkChoiceStore {
394-
PersistedForkChoiceStore {
392+
impl Into<PersistedForkChoiceStoreV17> for PersistedForkChoiceStoreV11 {
393+
fn into(self) -> PersistedForkChoiceStoreV17 {
394+
PersistedForkChoiceStoreV17 {
395395
balances_cache: self.balances_cache,
396396
time: self.time,
397397
finalized_checkpoint: self.finalized_checkpoint,
@@ -405,7 +405,7 @@ impl Into<PersistedForkChoiceStore> for PersistedForkChoiceStoreV11 {
405405
}
406406
}
407407

408-
impl Into<PersistedForkChoiceStoreV11> for PersistedForkChoiceStore {
408+
impl Into<PersistedForkChoiceStoreV11> for PersistedForkChoiceStoreV17 {
409409
fn into(self) -> PersistedForkChoiceStoreV11 {
410410
PersistedForkChoiceStoreV11 {
411411
balances_cache: self.balances_cache,

beacon_node/beacon_chain/src/builder.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::{
2323
};
2424
use eth1::Config as Eth1Config;
2525
use execution_layer::ExecutionLayer;
26-
use fork_choice::{ForkChoice, ResetPayloadStatuses};
26+
use fork_choice::{AnchorState, ForkChoice, ResetPayloadStatuses};
2727
use futures::channel::mpsc::Sender;
2828
use kzg::{Kzg, TrustedSetup};
2929
use operation_pool::{OperationPool, PersistedOperationPool};
@@ -417,6 +417,7 @@ where
417417
genesis.beacon_block_root,
418418
&genesis.beacon_block,
419419
&genesis.beacon_state,
420+
AnchorState::Finalized,
420421
current_slot,
421422
&self.spec,
422423
)
@@ -433,6 +434,7 @@ where
433434
mut weak_subj_state: BeaconState<TEthSpec>,
434435
weak_subj_block: SignedBeaconBlock<TEthSpec>,
435436
genesis_state: BeaconState<TEthSpec>,
437+
anchor_state: AnchorState,
436438
) -> Result<Self, String> {
437439
let store = self
438440
.store
@@ -557,6 +559,7 @@ where
557559
snapshot.beacon_block_root,
558560
&snapshot.beacon_block,
559561
&snapshot.beacon_state,
562+
anchor_state,
560563
Some(weak_subj_slot),
561564
&self.spec,
562565
)
@@ -703,6 +706,7 @@ where
703706
None
704707
};
705708

709+
let anchor_state = fork_choice.anchor_state();
706710
let initial_head_block_root = fork_choice
707711
.get_head(current_slot, &self.spec)
708712
.map_err(|e| format!("Unable to get fork choice head: {:?}", e))?;
@@ -752,6 +756,7 @@ where
752756
Some(current_slot),
753757
&self.spec,
754758
self.chain_config.progressive_balances_mode,
759+
anchor_state,
755760
&log,
756761
)?;
757762
}

beacon_node/beacon_chain/src/canonical_head.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ use crate::{
4747
};
4848
use eth2::types::{EventKind, SseChainReorg, SseFinalizedCheckpoint, SseHead, SseLateHead};
4949
use fork_choice::{
50-
ExecutionStatus, ForkChoiceStore, ForkChoiceView, ForkchoiceUpdateParameters, ProtoBlock,
51-
ResetPayloadStatuses,
50+
AnchorState, ExecutionStatus, ForkChoiceStore, ForkChoiceView, ForkchoiceUpdateParameters,
51+
ProtoBlock, ResetPayloadStatuses,
5252
};
5353
use itertools::process_results;
5454
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
@@ -109,6 +109,8 @@ pub struct CachedHead<E: EthSpec> {
109109
justified_hash: Option<ExecutionBlockHash>,
110110
/// The `execution_payload.block_hash` of the finalized block. Set to `None` before Bellatrix.
111111
finalized_hash: Option<ExecutionBlockHash>,
112+
/// The state of the finalized checkpoint
113+
anchor_state: AnchorState,
112114
}
113115

114116
impl<E: EthSpec> CachedHead<E> {
@@ -226,6 +228,11 @@ impl<E: EthSpec> CachedHead<E> {
226228
finalized_hash: self.finalized_hash,
227229
}
228230
}
231+
232+
/// Returns the anchor state
233+
pub fn anchor_state(&self) -> AnchorState {
234+
self.anchor_state
235+
}
229236
}
230237

231238
/// Represents the "canonical head" of the beacon chain.
@@ -266,6 +273,7 @@ impl<T: BeaconChainTypes> CanonicalHead<T> {
266273
head_hash: forkchoice_update_params.head_hash,
267274
justified_hash: forkchoice_update_params.justified_hash,
268275
finalized_hash: forkchoice_update_params.finalized_hash,
276+
anchor_state: fork_choice_view.anchor_state,
269277
};
270278

271279
Self {
@@ -318,6 +326,7 @@ impl<T: BeaconChainTypes> CanonicalHead<T> {
318326
head_hash: forkchoice_update_params.head_hash,
319327
justified_hash: forkchoice_update_params.justified_hash,
320328
finalized_hash: forkchoice_update_params.finalized_hash,
329+
anchor_state: fork_choice_view.anchor_state,
321330
};
322331

323332
*fork_choice_write_lock = fork_choice;
@@ -447,6 +456,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
447456
self.canonical_head.cached_head_read_lock().snapshot.clone()
448457
}
449458

459+
/// Returns the `AnchorState` of the finalized checkpoint
460+
/// TODO: determine if this puts a burdon on the fork choice lock
461+
pub fn finalized_checkpoint_anchor_state(&self) -> AnchorState {
462+
self.canonical_head.cached_head_read_lock().anchor_state()
463+
}
464+
450465
/// Returns the beacon block at the head of the canonical chain.
451466
///
452467
/// See `Self::head` for more information.
@@ -576,6 +591,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
576591
head_block_root: old_cached_head.head_block_root(),
577592
justified_checkpoint: old_cached_head.justified_checkpoint(),
578593
finalized_checkpoint: old_cached_head.finalized_checkpoint(),
594+
anchor_state: old_cached_head.anchor_state(),
579595
};
580596

581597
let mut fork_choice_write_lock = self.canonical_head.fork_choice_write_lock();
@@ -702,6 +718,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
702718
head_hash: new_forkchoice_update_parameters.head_hash,
703719
justified_hash: new_forkchoice_update_parameters.justified_hash,
704720
finalized_hash: new_forkchoice_update_parameters.finalized_hash,
721+
anchor_state: new_view.anchor_state,
705722
};
706723

707724
let new_head = {
@@ -729,6 +746,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
729746
head_hash: new_forkchoice_update_parameters.head_hash,
730747
justified_hash: new_forkchoice_update_parameters.justified_hash,
731748
finalized_hash: new_forkchoice_update_parameters.finalized_hash,
749+
anchor_state: new_view.anchor_state,
732750
};
733751

734752
let mut cached_head_write_lock = self.canonical_head.cached_head_write_lock();

beacon_node/beacon_chain/src/fork_revert.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{BeaconForkChoiceStore, BeaconSnapshot};
2-
use fork_choice::{ForkChoice, PayloadVerificationStatus};
2+
use fork_choice::{AnchorState, ForkChoice, PayloadVerificationStatus};
33
use itertools::process_results;
44
use slog::{info, warn, Logger};
55
use state_processing::state_advance::complete_state_advance;
@@ -97,13 +97,15 @@ pub fn revert_to_fork_boundary<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>
9797
/// WARNING: this function is destructive and causes fork choice to permanently forget all
9898
/// chains other than the chain leading to `head_block_root`. It should only be used in extreme
9999
/// circumstances when there is no better alternative.
100+
#[allow(clippy::too_many_arguments)]
100101
pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>>(
101102
head_block_root: Hash256,
102103
head_state: &BeaconState<E>,
103104
store: Arc<HotColdDB<E, Hot, Cold>>,
104105
current_slot: Option<Slot>,
105106
spec: &ChainSpec,
106107
progressive_balances_mode: ProgressiveBalancesMode,
108+
anchor_state: AnchorState,
107109
log: &Logger,
108110
) -> Result<ForkChoice<BeaconForkChoiceStore<E, Hot, Cold>, E>, String> {
109111
// Fetch finalized block.
@@ -157,6 +159,7 @@ pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: It
157159
finalized_block_root,
158160
&finalized_snapshot.beacon_block,
159161
&finalized_snapshot.beacon_state,
162+
anchor_state,
160163
current_slot,
161164
spec,
162165
)

beacon_node/beacon_chain/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub use eth1_chain::{Eth1Chain, Eth1ChainBackend};
8484
pub use events::ServerSentEventHandler;
8585
pub use execution_layer::EngineState;
8686
pub use execution_payload::NotifyExecutionLayer;
87-
pub use fork_choice::{ExecutionStatus, ForkchoiceUpdateParameters};
87+
pub use fork_choice::{AnchorState, ExecutionStatus, ForkchoiceUpdateParameters};
8888
pub use kzg::TrustedSetup;
8989
pub use metrics::scrape_for_metrics;
9090
pub use migrate::MigratorConfig;

beacon_node/beacon_chain/src/persisted_fork_choice.rs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,34 @@ use store::{DBColumn, Error, StoreItem};
55
use superstruct::superstruct;
66

77
// If adding a new version you should update this type alias and fix the breakages.
8-
pub type PersistedForkChoice = PersistedForkChoiceV17;
8+
pub type PersistedForkChoice = PersistedForkChoiceV20;
99

1010
#[superstruct(
11-
variants(V11, V17),
11+
variants(V11, V17, V20),
1212
variant_attributes(derive(Encode, Decode)),
1313
no_enum
1414
)]
1515
pub struct PersistedForkChoice {
16-
pub fork_choice: fork_choice::PersistedForkChoice,
16+
#[superstruct(only(V11, V17))]
17+
pub fork_choice: fork_choice::PersistedForkChoiceV19,
18+
#[superstruct(only(V20))]
19+
pub fork_choice: fork_choice::PersistedForkChoiceV20,
1720
#[superstruct(only(V11))]
1821
pub fork_choice_store: PersistedForkChoiceStoreV11,
19-
#[superstruct(only(V17))]
22+
#[superstruct(only(V17, V20))]
2023
pub fork_choice_store: PersistedForkChoiceStoreV17,
2124
}
2225

23-
impl Into<PersistedForkChoice> for PersistedForkChoiceV11 {
24-
fn into(self) -> PersistedForkChoice {
25-
PersistedForkChoice {
26+
impl Into<PersistedForkChoiceV17> for PersistedForkChoiceV11 {
27+
fn into(self) -> PersistedForkChoiceV17 {
28+
PersistedForkChoiceV17 {
2629
fork_choice: self.fork_choice,
2730
fork_choice_store: self.fork_choice_store.into(),
2831
}
2932
}
3033
}
3134

32-
impl Into<PersistedForkChoiceV11> for PersistedForkChoice {
35+
impl Into<PersistedForkChoiceV11> for PersistedForkChoiceV17 {
3336
fn into(self) -> PersistedForkChoiceV11 {
3437
PersistedForkChoiceV11 {
3538
fork_choice: self.fork_choice,
@@ -38,6 +41,24 @@ impl Into<PersistedForkChoiceV11> for PersistedForkChoice {
3841
}
3942
}
4043

44+
impl Into<PersistedForkChoiceV20> for PersistedForkChoiceV17 {
45+
fn into(self) -> PersistedForkChoiceV20 {
46+
PersistedForkChoiceV20 {
47+
fork_choice: self.fork_choice.into(),
48+
fork_choice_store: self.fork_choice_store,
49+
}
50+
}
51+
}
52+
53+
impl Into<PersistedForkChoiceV17> for PersistedForkChoiceV20 {
54+
fn into(self) -> PersistedForkChoiceV17 {
55+
PersistedForkChoiceV17 {
56+
fork_choice: self.fork_choice.into(),
57+
fork_choice_store: self.fork_choice_store,
58+
}
59+
}
60+
}
61+
4162
macro_rules! impl_store_item {
4263
($type:ty) => {
4364
impl StoreItem for $type {
@@ -58,3 +79,4 @@ macro_rules! impl_store_item {
5879

5980
impl_store_item!(PersistedForkChoiceV11);
6081
impl_store_item!(PersistedForkChoiceV17);
82+
impl_store_item!(PersistedForkChoiceV20);

beacon_node/beacon_chain/src/schema_change.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
mod migration_schema_v17;
33
mod migration_schema_v18;
44
mod migration_schema_v19;
5+
mod migration_schema_v20;
56

67
use crate::beacon_chain::BeaconChainTypes;
78
use crate::types::ChainSpec;
@@ -78,6 +79,14 @@ pub fn migrate_schema<T: BeaconChainTypes>(
7879
let ops = migration_schema_v19::downgrade_from_v19::<T>(db.clone(), log)?;
7980
db.store_schema_version_atomically(to, ops)
8081
}
82+
(SchemaVersion(19), SchemaVersion(20)) => {
83+
let ops = migration_schema_v20::upgrade_to_v20::<T>(db.clone(), log)?;
84+
db.store_schema_version_atomically(to, ops)
85+
}
86+
(SchemaVersion(20), SchemaVersion(19)) => {
87+
let ops = migration_schema_v20::downgrade_from_v20::<T>(db.clone(), log)?;
88+
db.store_schema_version_atomically(to, ops)
89+
}
8190
// Anything else is an error.
8291
(_, _) => Err(HotColdDBError::UnsupportedSchemaVersion {
8392
target_version: to,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use crate::beacon_chain::{BeaconChainTypes, FORK_CHOICE_DB_KEY};
2+
use crate::persisted_fork_choice::{PersistedForkChoiceV17, PersistedForkChoiceV20};
3+
use slog::{debug, Logger};
4+
use std::sync::Arc;
5+
use store::{Error, HotColdDB, KeyValueStoreOp, StoreItem};
6+
7+
pub fn upgrade_to_v20<T: BeaconChainTypes>(
8+
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
9+
log: Logger,
10+
) -> Result<Vec<KeyValueStoreOp>, Error> {
11+
let v17 = db
12+
.get_item::<PersistedForkChoiceV17>(&FORK_CHOICE_DB_KEY)?
13+
.ok_or_else(|| Error::SchemaMigrationError("fork choice missing from database".into()))?;
14+
15+
let v20: PersistedForkChoiceV20 = v17.into();
16+
17+
debug!(log, "Adding anchor_state to fork choice");
18+
19+
Ok(vec![v20.as_kv_store_op(FORK_CHOICE_DB_KEY)])
20+
}
21+
22+
pub fn downgrade_from_v20<T: BeaconChainTypes>(
23+
db: Arc<HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>>,
24+
log: Logger,
25+
) -> Result<Vec<KeyValueStoreOp>, Error> {
26+
let v20 = db
27+
.get_item::<PersistedForkChoiceV20>(&FORK_CHOICE_DB_KEY)?
28+
.ok_or_else(|| Error::SchemaMigrationError("fork choice missing from database".into()))?;
29+
30+
let v17: PersistedForkChoiceV17 = v20.into();
31+
32+
debug!(log, "Dropping anchor_state from fork choice.");
33+
34+
Ok(vec![v17.as_kv_store_op(FORK_CHOICE_DB_KEY)])
35+
}

0 commit comments

Comments
 (0)