From c61cf26622d08e031d72f59d3d3764f6bcd073bd Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Tue, 25 Feb 2025 18:08:44 +1100 Subject: [PATCH] Blacklist invalid block root in block verification and blacklist invalid finalized epochs in sync. --- .../beacon_chain/src/block_verification.rs | 36 +++++++++++++++---- .../network/src/sync/range_sync/range.rs | 13 +++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 1265276376..5f8c90d12e 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -90,6 +90,7 @@ use std::borrow::Cow; use std::fmt::Debug; use std::fs; use std::io::Write; +use std::str::FromStr; use std::sync::Arc; use store::{Error as DBError, HotStateSummary, KeyValueStore, StoreOp}; use strum::AsRefStr; @@ -146,7 +147,9 @@ pub enum BlockError { /// /// It's unclear if this block is valid, but it cannot be processed without already knowing /// its parent. - ParentUnknown { parent_root: Hash256 }, + ParentUnknown { + parent_root: Hash256, + }, /// The block slot is greater than the present slot. /// /// ## Peer scoring @@ -161,7 +164,10 @@ pub enum BlockError { /// ## Peer scoring /// /// The peer has incompatible state transition logic and is faulty. - StateRootMismatch { block: Hash256, local: Hash256 }, + StateRootMismatch { + block: Hash256, + local: Hash256, + }, /// The block was a genesis block, these blocks cannot be re-imported. GenesisBlock, /// The slot is finalized, no need to import. @@ -180,7 +186,9 @@ pub enum BlockError { /// /// It's unclear if this block is valid, but it conflicts with finality and shouldn't be /// imported. - NotFinalizedDescendant { block_parent_root: Hash256 }, + NotFinalizedDescendant { + block_parent_root: Hash256, + }, /// Block is already known and valid, no need to re-import. /// /// ## Peer scoring @@ -207,7 +215,10 @@ pub enum BlockError { /// ## Peer scoring /// /// The block is invalid and the peer is faulty. - IncorrectBlockProposer { block: u64, local_shuffling: u64 }, + IncorrectBlockProposer { + block: u64, + local_shuffling: u64, + }, /// The `block.proposal_index` is not known. /// /// ## Peer scoring @@ -225,7 +236,10 @@ pub enum BlockError { /// ## Peer scoring /// /// The block is invalid and the peer is faulty. - BlockIsNotLaterThanParent { block_slot: Slot, parent_slot: Slot }, + BlockIsNotLaterThanParent { + block_slot: Slot, + parent_slot: Slot, + }, /// At least one block in the chain segment did not have it's parent root set to the root of /// the prior block. /// @@ -281,7 +295,10 @@ pub enum BlockError { /// If it's actually our fault (e.g. our execution node database is corrupt) we have bigger /// problems to worry about than losing peers, and we're doing the network a favour by /// disconnecting. - ParentExecutionPayloadInvalid { parent_root: Hash256 }, + ParentExecutionPayloadInvalid { + parent_root: Hash256, + }, + KnownInvalidExecutionPayload(Hash256), /// The block is a slashable equivocation from the proposer. /// /// ## Peer scoring @@ -1326,6 +1343,13 @@ impl ExecutionPendingBlock { chain: &Arc>, notify_execution_layer: NotifyExecutionLayer, ) -> Result { + if block_root + == Hash256::from_str("2db899881ed8546476d0b92c6aa9110bea9a4cd0dbeb5519eb0ea69575f1f359") + .expect("valid hash") + { + return Err(BlockError::KnownInvalidExecutionPayload(block_root)); + } + chain .observed_slashable .write() diff --git a/beacon_node/network/src/sync/range_sync/range.rs b/beacon_node/network/src/sync/range_sync/range.rs index 78679403bb..7ca880c3b9 100644 --- a/beacon_node/network/src/sync/range_sync/range.rs +++ b/beacon_node/network/src/sync/range_sync/range.rs @@ -120,6 +120,19 @@ where .finalized_epoch .start_slot(T::EthSpec::slots_per_epoch()); + // Prevent syncing from peers that had finalized an invalid chain on Holesky. + let non_finality_start_epoch = Epoch::new(115969); + let possible_finality_start_epoch = Epoch::new(116052); + if remote_info.finalized_epoch >= non_finality_start_epoch + && remote_info.finalized_epoch <= possible_finality_start_epoch + { + if !self.failed_chains.contains(&remote_info.finalized_root) { + self.failed_chains.insert(remote_info.finalized_root); + } + network.goodbye_peer(peer_id, GoodbyeReason::IrrelevantNetwork); + return; + } + // NOTE: A peer that has been re-status'd may now exist in multiple finalized chains. This // is OK since we since only one finalized chain at a time.