Use time instead of skip count for denying long skips

This commit is contained in:
Paul Hauner
2019-11-25 18:18:41 +11:00
parent 79168b3063
commit b8bc548aaa
2 changed files with 22 additions and 22 deletions

View File

@@ -26,6 +26,7 @@ use state_processing::{
use std::fs;
use std::io::prelude::*;
use std::sync::Arc;
use std::time::{Duration, Instant};
use store::iter::{BlockRootsIterator, StateRootsIterator};
use store::{Error as DBError, Store};
use tree_hash::TreeHash;
@@ -43,9 +44,6 @@ pub const GRAFFITI: &str = "sigp/lighthouse-0.0.0-prerelease";
/// Only useful for testing.
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 {
/// Block was valid and imported into the block graph.
@@ -350,34 +348,34 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
if slot == head_state.slot {
Ok(head_state)
} else if slot > head_state.slot {
// 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 {
error!(
self.log,
"Refusing to skip more than {} blocks", BLOCK_SKIPPING_FAILURE_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 {
if slot > head_state.slot + T::EthSpec::slots_per_epoch() {
warn!(
self.log,
"Skipping more than {} blocks", BLOCK_SKIPPING_LOGGING_THRESHOLD;
"Skipping more than an epoch";
"head_slot" => head_state.slot,
"request_slot" => slot
)
}
let start_slot = head_state.slot;
let task_start = Instant::now();
let max_task_runtime = Duration::from_millis(self.spec.milliseconds_per_slot);
let head_state_slot = head_state.slot;
let mut state = head_state;
while state.slot < slot {
// Do not allow and forward state skip that takes longer than the maximum task duration.
//
// This is a protection against nodes doing too much work when they're not synced
// to a chain.
if task_start + max_task_runtime < Instant::now() {
return Err(Error::StateSkipTooLarge {
start_slot,
requested_slot: slot,
max_task_runtime,
});
}
match per_slot_processing(&mut state, &self.spec) {
Ok(()) => (),
Err(e) => {

View File

@@ -4,6 +4,7 @@ use ssz_types::Error as SszTypesError;
use state_processing::per_block_processing::errors::AttestationValidationError;
use state_processing::BlockProcessingError;
use state_processing::SlotProcessingError;
use std::time::Duration;
use types::*;
macro_rules! easy_from_to {
@@ -40,8 +41,9 @@ pub enum BeaconChainError {
},
AttestationValidationError(AttestationValidationError),
StateSkipTooLarge {
head_slot: Slot,
start_slot: Slot,
requested_slot: Slot,
max_task_runtime: Duration,
},
/// Returned when an internal check fails, indicating corrupt data.
InvariantViolated(String),