diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs index 6ceb6ce47a..54edb9feb0 100644 --- a/beacon_node/beacon_chain/src/builder.rs +++ b/beacon_node/beacon_chain/src/builder.rs @@ -419,23 +419,14 @@ where let weak_subj_block_root = weak_subj_block.canonical_root(); let weak_subj_state_root = weak_subj_block.state_root(); - // Check that the given block lies on an epoch boundary. Due to the database only storing + // Check that the given state lies on an epoch boundary. Due to the database only storing // full states on epoch boundaries and at restore points it would be difficult to support // starting from a mid-epoch state. if weak_subj_slot % TEthSpec::slots_per_epoch() != 0 { return Err(format!( - "Checkpoint block at slot {} is not aligned to epoch start. \ - Please supply an aligned checkpoint with block.slot % 32 == 0", - weak_subj_block.slot(), - )); - } - - // Check that the block and state have consistent slots and state roots. - if weak_subj_state.slot() != weak_subj_block.slot() { - return Err(format!( - "Slot of snapshot block ({}) does not match snapshot state ({})", - weak_subj_block.slot(), - weak_subj_state.slot(), + "Checkpoint state at slot {} is not aligned to epoch start. \ + Please supply an aligned checkpoint with state.slot % 32 == 0", + weak_subj_slot, )); } @@ -508,13 +499,12 @@ where let fc_store = BeaconForkChoiceStore::get_forkchoice_store(store, &snapshot) .map_err(|e| format!("Unable to initialize fork choice store: {e:?}"))?; - let current_slot = Some(snapshot.beacon_block.slot()); let fork_choice = ForkChoice::from_anchor( fc_store, snapshot.beacon_block_root, &snapshot.beacon_block, &snapshot.beacon_state, - current_slot, + Some(weak_subj_slot), &self.spec, ) .map_err(|e| format!("Unable to initialize ForkChoice: {:?}", e))?; diff --git a/beacon_node/client/src/builder.rs b/beacon_node/client/src/builder.rs index e47600ae49..e5b9a94c96 100644 --- a/beacon_node/client/src/builder.rs +++ b/beacon_node/client/src/builder.rs @@ -28,6 +28,7 @@ use network::{NetworkConfig, NetworkSenders, NetworkService}; use slasher::Slasher; use slasher_service::SlasherService; use slog::{debug, info, warn, Logger}; +use state_processing::per_slot_processing; use std::net::TcpListener; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -347,8 +348,8 @@ where }; debug!(context.log(), "Downloading finalized block"); - // Find a suitable finalized block on an epoch boundary. - let mut block = remote + // Find a suitable finalized block. + let block = remote .get_beacon_blocks_ssz::(BlockId::Finalized, &spec) .await .map_err(|e| match e { @@ -363,42 +364,13 @@ where debug!(context.log(), "Downloaded finalized block"); - let mut block_slot = block.slot(); - - while block.slot() % slots_per_epoch != 0 { - block_slot = (block_slot / slots_per_epoch - 1) * slots_per_epoch; - - debug!( - context.log(), - "Searching for aligned checkpoint block"; - "block_slot" => block_slot - ); - - if let Some(found_block) = remote - .get_beacon_blocks_ssz::(BlockId::Slot(block_slot), &spec) - .await - .map_err(|e| { - format!("Error fetching block at slot {}: {:?}", block_slot, e) - })? - { - block = found_block; - } - } - - debug!( - context.log(), - "Downloaded aligned finalized block"; - "block_root" => ?block.canonical_root(), - "block_slot" => block.slot(), - ); - let state_root = block.state_root(); debug!( context.log(), "Downloading finalized state"; "state_root" => ?state_root ); - let state = remote + let mut state = remote .get_debug_beacon_states_ssz::(StateId::Root(state_root), &spec) .await .map_err(|e| { @@ -413,13 +385,19 @@ where debug!(context.log(), "Downloaded finalized state"); + while state.slot() % slots_per_epoch != 0 { + per_slot_processing(&mut state, Some(state_root), &spec) + .map_err(|e| format!("Error advancing state: {:?}", e))?; + } + let genesis_state = BeaconState::from_ssz_bytes(&genesis_state_bytes, &spec) .map_err(|e| format!("Unable to parse genesis state SSZ: {:?}", e))?; info!( context.log(), "Loaded checkpoint block and state"; - "slot" => block.slot(), + "block_slot" => block.slot(), + "state_slot" => state.slot(), "block_root" => ?block.canonical_root(), "state_root" => ?state_root, ); diff --git a/consensus/fork_choice/src/fork_choice.rs b/consensus/fork_choice/src/fork_choice.rs index b78e486d51..19415f373b 100644 --- a/consensus/fork_choice/src/fork_choice.rs +++ b/consensus/fork_choice/src/fork_choice.rs @@ -352,7 +352,7 @@ where spec: &ChainSpec, ) -> Result> { // Sanity check: the anchor must lie on an epoch boundary. - if anchor_block.slot() % E::slots_per_epoch() != 0 { + if anchor_state.slot() % E::slots_per_epoch() != 0 { return Err(Error::InvalidAnchor { block_slot: anchor_block.slot(), state_slot: anchor_state.slot(), @@ -388,6 +388,7 @@ where let current_slot = current_slot.unwrap_or_else(|| fc_store.get_current_slot()); let proto_array = ProtoArrayForkChoice::new::( + current_slot, finalized_block_slot, finalized_block_state_root, *fc_store.justified_checkpoint(), diff --git a/consensus/proto_array/src/fork_choice_test_definition.rs b/consensus/proto_array/src/fork_choice_test_definition.rs index 157f072ad3..98d43e4850 100644 --- a/consensus/proto_array/src/fork_choice_test_definition.rs +++ b/consensus/proto_array/src/fork_choice_test_definition.rs @@ -80,6 +80,7 @@ impl ForkChoiceTestDefinition { let junk_shuffling_id = AttestationShufflingId::from_components(Epoch::new(0), Hash256::zero()); let mut fork_choice = ProtoArrayForkChoice::new::( + self.finalized_block_slot, self.finalized_block_slot, Hash256::zero(), self.justified_checkpoint, diff --git a/consensus/proto_array/src/proto_array_fork_choice.rs b/consensus/proto_array/src/proto_array_fork_choice.rs index fe831b3c35..aaa51d4a68 100644 --- a/consensus/proto_array/src/proto_array_fork_choice.rs +++ b/consensus/proto_array/src/proto_array_fork_choice.rs @@ -345,6 +345,7 @@ pub struct ProtoArrayForkChoice { impl ProtoArrayForkChoice { #[allow(clippy::too_many_arguments)] pub fn new( + current_slot: Slot, finalized_block_slot: Slot, finalized_block_state_root: Hash256, justified_checkpoint: Checkpoint, @@ -380,7 +381,7 @@ impl ProtoArrayForkChoice { }; proto_array - .on_block::(block, finalized_block_slot) + .on_block::(block, current_slot) .map_err(|e| format!("Failed to add finalized block to proto_array: {:?}", e))?; Ok(Self { @@ -1108,6 +1109,7 @@ mod test_compute_deltas { }; let mut fc = ProtoArrayForkChoice::new::( + genesis_slot, genesis_slot, junk_state_root, genesis_checkpoint,