From ef7b641f9e47d988acab96274f08bdfc40799819 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sat, 23 Nov 2019 17:56:45 +1100 Subject: [PATCH] Fail if skipping too many slots --- beacon_node/beacon_chain/src/beacon_chain.rs | 22 ++++++++++++++++++-- beacon_node/beacon_chain/src/errors.rs | 4 ++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 10951f54f2..3c3fa99ff6 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -10,7 +10,7 @@ use lmd_ghost::LmdGhost; use operation_pool::DepositInsertStatus; use operation_pool::{OperationPool, PersistedOperationPool}; use parking_lot::RwLock; -use slog::{debug, error, info, trace, warn, Logger}; +use slog::{crit, debug, error, info, trace, warn, Logger}; use slot_clock::SlotClock; use ssz::Encode; use state_processing::per_block_processing::{ @@ -44,6 +44,7 @@ pub const GRAFFITI: &str = "sigp/lighthouse-0.0.0-prerelease"; const WRITE_BLOCK_PROCESSING_SSZ: bool = cfg!(feature = "write_ssz_files"); const BLOCK_SKIPPING_LOGGING_THRESHOLD: u64 = 3; +const BLOCK_SKIPPING_FAILURE_THRESHOLD: u64 = 128; #[derive(Debug, PartialEq)] pub enum BlockProcessingOutcome { @@ -349,7 +350,23 @@ impl BeaconChain { if slot == head_state.slot { Ok(head_state) } else if slot > head_state.slot { - if slot > head_state.slot + BLOCK_SKIPPING_LOGGING_THRESHOLD { + // It is presently very resource intensive (lots of hashing) to skip slots. + // + // We log warnings or simply fail if there are too many skip slots. This is a + // protection against DoS attacks. + if slot > head_state.slot + BLOCK_SKIPPING_FAILURE_THRESHOLD { + crit!( + self.log, + "Refusing to skip more than {} blocks", BLOCK_SKIPPING_LOGGING_THRESHOLD; + "head_slot" => head_state.slot, + "request_slot" => slot + ); + + return Err(Error::StateSkipTooLarge { + head_slot: head_state.slot, + requested_slot: slot, + }); + } else if slot > head_state.slot + BLOCK_SKIPPING_LOGGING_THRESHOLD { warn!( self.log, "Skipping more than {} blocks", BLOCK_SKIPPING_LOGGING_THRESHOLD; @@ -357,6 +374,7 @@ impl BeaconChain { "request_slot" => slot ) } + let head_state_slot = head_state.slot; let mut state = head_state; while state.slot < slot { diff --git a/beacon_node/beacon_chain/src/errors.rs b/beacon_node/beacon_chain/src/errors.rs index 3261c011d4..fa29432bb1 100644 --- a/beacon_node/beacon_chain/src/errors.rs +++ b/beacon_node/beacon_chain/src/errors.rs @@ -39,6 +39,10 @@ pub enum BeaconChainError { beacon_block_root: Hash256, }, AttestationValidationError(AttestationValidationError), + StateSkipTooLarge { + head_slot: Slot, + requested_slot: Slot, + }, /// Returned when an internal check fails, indicating corrupt data. InvariantViolated(String), SszTypesError(SszTypesError),