Prune abandoned forks (#916)

* Address compiler warning

* Prune abandoned fork choice forks

* New approach to pruning

* Wrap some block hashes in a newtype pattern

For increased type safety.

* Add Graphviz chain dump emitter for debugging

* Fix broken test case

* Make prunes_abandoned_forks use real DiskStore

* Mark finalized blocks in the GraphViz output

* Refine debug stringification of Slot and Epoch

Before this commit: print!("{:?}", Slot(123)) == "Slot(\n123\n)".
After this commit: print!("{:?", Slot(123)) == "Slot(123)".

* Simplify build_block()

* Rewrite test case using more composable test primitives

* Working rewritten test case

* Tighten fork prunning test checks

* Add another pruning test case

* Bugfix: Finalized blocks weren't always properly detected

* Pruning: Add pruning_does_not_touch_blocks_prior_to_finalization test case

* Tighten pruning tests: check if heads are tracked properly

* Add a failing test case for a buggy scenario

* Change name of function to a more accurate one

* Fix failing test case

* Test case: Were skipped slots' states pruned?

* Style fix: Simplify dereferencing

* Tighten pruning tests: check if abandoned states are deleted

* Towards atomicity of db ops

* Correct typo

* Prune also skipped slots' states

* New logic for handling skipped states

* Make skipped slots test pass

* Post conflict resolution fixes

* Formatting fixes

* Tests passing

* Block hashes in Graphviz node labels

* Removed unused changes

* Fix bug with states having < SlotsPerHistoricalRoot roots

* Consolidate State/BlockRootsIterator for pruning

* Address review feedback

* Fix a bug in pruning tests

* Detach prune_abandoned_forks() from its object

* Move migrate.rs from store to beacon_chain

* Move forks pruning onto a background thread

* Bugfix: Heads weren't pruned when prune set contained only the head

* Rename: freeze_to_state() -> process_finalization()

* Eliminate redundant function parameter

Co-authored-by: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
Adam Szkoda
2020-04-20 11:59:56 +02:00
committed by GitHub
parent b374ead24b
commit 9c3f76a33b
19 changed files with 1398 additions and 282 deletions

View File

@@ -12,6 +12,7 @@ use serde_derive::{Deserialize, Serialize};
use ssz::ssz_encode;
use ssz_derive::{Decode, Encode};
use ssz_types::{typenum::Unsigned, BitVector, FixedVector};
use std::fmt;
use swap_or_not_shuffle::compute_shuffled_index;
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
@@ -80,6 +81,8 @@ pub enum Error {
///
/// This represents a serious bug in either the spec or Lighthouse!
ArithError(ArithError),
MissingBeaconBlock(SignedBeaconBlockHash),
MissingBeaconState(BeaconStateHash),
}
/// Control whether an epoch-indexed field can be indexed at the next epoch or not.
@@ -98,6 +101,33 @@ impl AllowNextEpoch {
}
}
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
pub struct BeaconStateHash(Hash256);
impl fmt::Debug for BeaconStateHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "BeaconStateHash({:?})", self.0)
}
}
impl fmt::Display for BeaconStateHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<Hash256> for BeaconStateHash {
fn from(hash: Hash256) -> BeaconStateHash {
BeaconStateHash(hash)
}
}
impl From<BeaconStateHash> for Hash256 {
fn from(beacon_state_hash: BeaconStateHash) -> Hash256 {
beacon_state_hash.0
}
}
/// The state of the `BeaconChain` at some slot.
///
/// Spec v0.11.1
@@ -614,6 +644,14 @@ impl<T: EthSpec> BeaconState<T> {
Ok(&self.block_roots[i])
}
pub fn get_block_state_roots(
&self,
slot: Slot,
) -> Result<(SignedBeaconBlockHash, BeaconStateHash), Error> {
let i = self.get_latest_block_roots_index(slot)?;
Ok((self.block_roots[i].into(), self.state_roots[i].into()))
}
/// Sets the latest state root for slot.
///
/// Spec v0.11.1

View File

@@ -69,7 +69,7 @@ pub use crate::indexed_attestation::IndexedAttestation;
pub use crate::pending_attestation::PendingAttestation;
pub use crate::proposer_slashing::ProposerSlashing;
pub use crate::relative_epoch::{Error as RelativeEpochError, RelativeEpoch};
pub use crate::signed_beacon_block::SignedBeaconBlock;
pub use crate::signed_beacon_block::{SignedBeaconBlock, SignedBeaconBlockHash};
pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader;
pub use crate::signed_voluntary_exit::SignedVoluntaryExit;
pub use crate::signing_root::{SignedRoot, SigningRoot};

View File

@@ -1,11 +1,40 @@
use crate::{test_utils::TestRandom, BeaconBlock, EthSpec, Hash256, Slot};
use bls::Signature;
use std::fmt;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
pub struct SignedBeaconBlockHash(Hash256);
impl fmt::Debug for SignedBeaconBlockHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SignedBeaconBlockHash({:?})", self.0)
}
}
impl fmt::Display for SignedBeaconBlockHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<Hash256> for SignedBeaconBlockHash {
fn from(hash: Hash256) -> SignedBeaconBlockHash {
SignedBeaconBlockHash(hash)
}
}
impl From<SignedBeaconBlockHash> for Hash256 {
fn from(signed_beacon_block_hash: SignedBeaconBlockHash) -> Hash256 {
signed_beacon_block_hash.0
}
}
/// A `BeaconBlock` and a signature from its proposer.
///
/// Spec v0.11.1

View File

@@ -21,11 +21,11 @@ use std::hash::{Hash, Hasher};
use std::iter::Iterator;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, Sub, SubAssign};
#[derive(Eq, Debug, Clone, Copy, Default, Serialize, Deserialize)]
#[derive(Eq, Clone, Copy, Default, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Slot(u64);
#[derive(Eq, Debug, Clone, Copy, Default, Serialize, Deserialize)]
#[derive(Eq, Clone, Copy, Default, Serialize, Deserialize)]
pub struct Epoch(u64);
impl_common!(Slot);

View File

@@ -195,6 +195,16 @@ macro_rules! impl_display {
};
}
macro_rules! impl_debug {
($type: ident) => {
impl fmt::Debug for $type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}({:?})", stringify!($type), self.0)
}
}
};
}
macro_rules! impl_ssz {
($type: ident) => {
impl Encode for $type {
@@ -275,6 +285,7 @@ macro_rules! impl_common {
impl_math_between!($type, u64);
impl_math!($type);
impl_display!($type);
impl_debug!($type);
impl_ssz!($type);
impl_hash!($type);
};