Integrate fork choice into beacon_chain.
- Adds fork_choice to beacon_chain struct. - Adds add_attestation inside process_free_attestation. - Adds add_block inside process_block. - Shifts core fork-choice logic into lib.rs.
This commit is contained in:
parent
fb270a5a41
commit
eae68865d1
@ -2,6 +2,7 @@ use db::{
|
|||||||
stores::{BeaconBlockStore, BeaconStateStore},
|
stores::{BeaconBlockStore, BeaconStateStore},
|
||||||
ClientDB, DBError,
|
ClientDB, DBError,
|
||||||
};
|
};
|
||||||
|
use fork_choice::{ForkChoice, ForkChoiceError};
|
||||||
use genesis::{genesis_beacon_block, genesis_beacon_state};
|
use genesis::{genesis_beacon_block, genesis_beacon_state};
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use parking_lot::{RwLock, RwLockReadGuard};
|
use parking_lot::{RwLock, RwLockReadGuard};
|
||||||
@ -14,11 +15,8 @@ use types::{
|
|||||||
AttestationData, BeaconBlock, BeaconBlockBody, BeaconState, ChainSpec, Eth1Data,
|
AttestationData, BeaconBlock, BeaconBlockBody, BeaconState, ChainSpec, Eth1Data,
|
||||||
FreeAttestation, Hash256, PublicKey, Signature,
|
FreeAttestation, Hash256, PublicKey, Signature,
|
||||||
};
|
};
|
||||||
use fork_choice::{longest_chain, basic_lmd_ghost};
|
|
||||||
use fork_choice::{ForkChoice};
|
|
||||||
|
|
||||||
use crate::attestation_aggregator::{AttestationAggregator, Outcome as AggregationOutcome};
|
use crate::attestation_aggregator::{AttestationAggregator, Outcome as AggregationOutcome};
|
||||||
use crate::attestation_targets::AttestationTargets;
|
|
||||||
use crate::block_graph::BlockGraph;
|
use crate::block_graph::BlockGraph;
|
||||||
use crate::checkpoint::CheckPoint;
|
use crate::checkpoint::CheckPoint;
|
||||||
|
|
||||||
@ -29,6 +27,9 @@ pub enum Error {
|
|||||||
CommitteesError(CommitteesError),
|
CommitteesError(CommitteesError),
|
||||||
DBInconsistent(String),
|
DBInconsistent(String),
|
||||||
DBError(String),
|
DBError(String),
|
||||||
|
ForkChoiceError(ForkChoiceError),
|
||||||
|
MissingBeaconBlock(Hash256),
|
||||||
|
MissingBeaconState(Hash256),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -60,7 +61,7 @@ pub enum BlockProcessingOutcome {
|
|||||||
InvalidBlock(InvalidBlock),
|
InvalidBlock(InvalidBlock),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BeaconChain<T: ClientDB + Sized, U: SlotClock> {
|
pub struct BeaconChain<T: ClientDB + Sized, U: SlotClock, F: ForkChoice> {
|
||||||
pub block_store: Arc<BeaconBlockStore<T>>,
|
pub block_store: Arc<BeaconBlockStore<T>>,
|
||||||
pub state_store: Arc<BeaconStateStore<T>>,
|
pub state_store: Arc<BeaconStateStore<T>>,
|
||||||
pub slot_clock: U,
|
pub slot_clock: U,
|
||||||
@ -70,14 +71,15 @@ pub struct BeaconChain<T: ClientDB + Sized, U: SlotClock> {
|
|||||||
finalized_head: RwLock<CheckPoint>,
|
finalized_head: RwLock<CheckPoint>,
|
||||||
justified_head: RwLock<CheckPoint>,
|
justified_head: RwLock<CheckPoint>,
|
||||||
pub state: RwLock<BeaconState>,
|
pub state: RwLock<BeaconState>,
|
||||||
pub latest_attestation_targets: RwLock<AttestationTargets>,
|
|
||||||
pub spec: ChainSpec,
|
pub spec: ChainSpec,
|
||||||
|
pub fork_choice: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> BeaconChain<T, U>
|
impl<T, U, F> BeaconChain<T, U, F>
|
||||||
where
|
where
|
||||||
T: ClientDB,
|
T: ClientDB,
|
||||||
U: SlotClock,
|
U: SlotClock,
|
||||||
|
F: ForkChoice,
|
||||||
{
|
{
|
||||||
/// Instantiate a new Beacon Chain, from genesis.
|
/// Instantiate a new Beacon Chain, from genesis.
|
||||||
pub fn genesis(
|
pub fn genesis(
|
||||||
@ -85,6 +87,7 @@ where
|
|||||||
block_store: Arc<BeaconBlockStore<T>>,
|
block_store: Arc<BeaconBlockStore<T>>,
|
||||||
slot_clock: U,
|
slot_clock: U,
|
||||||
spec: ChainSpec,
|
spec: ChainSpec,
|
||||||
|
fork_choice: F,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
if spec.initial_validators.is_empty() {
|
if spec.initial_validators.is_empty() {
|
||||||
return Err(Error::InsufficientValidators);
|
return Err(Error::InsufficientValidators);
|
||||||
@ -121,8 +124,6 @@ where
|
|||||||
));
|
));
|
||||||
let attestation_aggregator = RwLock::new(AttestationAggregator::new());
|
let attestation_aggregator = RwLock::new(AttestationAggregator::new());
|
||||||
|
|
||||||
let latest_attestation_targets = RwLock::new(AttestationTargets::new());
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
block_store,
|
block_store,
|
||||||
state_store,
|
state_store,
|
||||||
@ -133,8 +134,8 @@ where
|
|||||||
justified_head,
|
justified_head,
|
||||||
finalized_head,
|
finalized_head,
|
||||||
canonical_head,
|
canonical_head,
|
||||||
latest_attestation_targets,
|
|
||||||
spec: spec,
|
spec: spec,
|
||||||
|
fork_choice,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +210,7 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the the validator index (if any) for the given public key.
|
/// Returns the validator index (if any) for the given public key.
|
||||||
///
|
///
|
||||||
/// Information is retrieved from the present `beacon_state.validator_registry`.
|
/// Information is retrieved from the present `beacon_state.validator_registry`.
|
||||||
pub fn validator_index(&self, pubkey: &PublicKey) -> Option<usize> {
|
pub fn validator_index(&self, pubkey: &PublicKey) -> Option<usize> {
|
||||||
@ -338,29 +339,27 @@ where
|
|||||||
/// - Create a new `Attestation`.
|
/// - Create a new `Attestation`.
|
||||||
/// - Aggregate it to an existing `Attestation`.
|
/// - Aggregate it to an existing `Attestation`.
|
||||||
pub fn process_free_attestation(
|
pub fn process_free_attestation(
|
||||||
&self,
|
&mut self,
|
||||||
free_attestation: FreeAttestation,
|
free_attestation: FreeAttestation,
|
||||||
) -> Result<AggregationOutcome, Error> {
|
) -> Result<AggregationOutcome, Error> {
|
||||||
self.attestation_aggregator
|
let aggregation_outcome = self
|
||||||
|
.attestation_aggregator
|
||||||
.write()
|
.write()
|
||||||
.process_free_attestation(&self.state.read(), &free_attestation, &self.spec)
|
.process_free_attestation(&self.state.read(), &free_attestation, &self.spec)?;
|
||||||
.map_err(|e| e.into())
|
// TODO: Check this comment
|
||||||
}
|
//.map_err(|e| e.into())?;
|
||||||
|
|
||||||
/// Set the latest attestation target for some validator.
|
// return if the attestation is invalid
|
||||||
pub fn insert_latest_attestation_target(&self, validator_index: u64, block_root: Hash256) {
|
if !aggregation_outcome.valid {
|
||||||
let mut targets = self.latest_attestation_targets.write();
|
return Ok(aggregation_outcome);
|
||||||
targets.insert(validator_index, block_root);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the latest attestation target for some validator.
|
|
||||||
pub fn get_latest_attestation_target(&self, validator_index: u64) -> Option<Hash256> {
|
|
||||||
let targets = self.latest_attestation_targets.read();
|
|
||||||
|
|
||||||
match targets.get(validator_index) {
|
|
||||||
Some(hash) => Some(hash.clone()),
|
|
||||||
None => None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// valid attestation, proceed with fork-choice logic
|
||||||
|
self.fork_choice.add_attestation(
|
||||||
|
free_attestation.validator_index,
|
||||||
|
&free_attestation.data.beacon_block_root,
|
||||||
|
)?;
|
||||||
|
Ok(aggregation_outcome)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dumps the entire canonical chain, from the head to genesis to a vector for analysis.
|
/// Dumps the entire canonical chain, from the head to genesis to a vector for analysis.
|
||||||
@ -417,7 +416,7 @@ where
|
|||||||
/// Accept some block and attempt to add it to block DAG.
|
/// Accept some block and attempt to add it to block DAG.
|
||||||
///
|
///
|
||||||
/// Will accept blocks from prior slots, however it will reject any block from a future slot.
|
/// Will accept blocks from prior slots, however it will reject any block from a future slot.
|
||||||
pub fn process_block(&self, block: BeaconBlock) -> Result<BlockProcessingOutcome, Error> {
|
pub fn process_block(&mut self, block: BeaconBlock) -> Result<BlockProcessingOutcome, Error> {
|
||||||
debug!("Processing block with slot {}...", block.slot());
|
debug!("Processing block with slot {}...", block.slot());
|
||||||
|
|
||||||
let block_root = block.canonical_root();
|
let block_root = block.canonical_root();
|
||||||
@ -471,7 +470,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the recieved block to its parent state (which has been transitioned into this
|
// Apply the received block to its parent state (which has been transitioned into this
|
||||||
// slot).
|
// slot).
|
||||||
if let Err(e) = state.per_block_processing(&block, &self.spec) {
|
if let Err(e) = state.per_block_processing(&block, &self.spec) {
|
||||||
return Ok(BlockProcessingOutcome::InvalidBlock(
|
return Ok(BlockProcessingOutcome::InvalidBlock(
|
||||||
@ -495,6 +494,9 @@ where
|
|||||||
self.block_graph
|
self.block_graph
|
||||||
.add_leaf(&parent_block_root, block_root.clone());
|
.add_leaf(&parent_block_root, block_root.clone());
|
||||||
|
|
||||||
|
// run the fork_choice add_block logic
|
||||||
|
self.fork_choice.add_block(&block, &block_root)?;
|
||||||
|
|
||||||
// If the parent block was the parent_block, automatically update the canonical head.
|
// If the parent block was the parent_block, automatically update the canonical head.
|
||||||
//
|
//
|
||||||
// TODO: this is a first-in-best-dressed scenario that is not ideal; fork_choice should be
|
// TODO: this is a first-in-best-dressed scenario that is not ideal; fork_choice should be
|
||||||
@ -574,15 +576,11 @@ where
|
|||||||
Some((block, state))
|
Some((block, state))
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, we give it the option of choosing which fork choice to use
|
// TODO: Left this as is, modify later
|
||||||
pub fn fork_choice(&self, fork_choice: ForkChoice) -> Result<(), Error> {
|
pub fn fork_choice(&mut self) -> Result<(), Error> {
|
||||||
let present_head = &self.finalized_head().beacon_block_root;
|
let present_head = &self.finalized_head().beacon_block_root.clone();
|
||||||
|
|
||||||
let new_head = match fork_choice {
|
let new_head = self.fork_choice.find_head(present_head)?;
|
||||||
ForkChoice::BasicLMDGhost => basic_lmd_ghost(&self.finalized_head().beacon_block_root)?,
|
|
||||||
// TODO: Implement others
|
|
||||||
_ => present_head
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_head != *present_head {
|
if new_head != *present_head {
|
||||||
let block = self
|
let block = self
|
||||||
@ -601,18 +599,21 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl From<DBError> for Error {
|
impl From<DBError> for Error {
|
||||||
fn from(e: DBError) -> Error {
|
fn from(e: DBError) -> Error {
|
||||||
Error::DBError(e.message)
|
Error::DBError(e.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ForkChoiceError> for Error {
|
||||||
|
fn from(e: ForkChoiceError) -> Error {
|
||||||
|
Error::ForkChoiceError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<CommitteesError> for Error {
|
impl From<CommitteesError> for Error {
|
||||||
fn from(e: CommitteesError) -> Error {
|
fn from(e: CommitteesError) -> Error {
|
||||||
Error::CommitteesError(e)
|
Error::CommitteesError(e)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
mod attestation_aggregator;
|
mod attestation_aggregator;
|
||||||
mod attestation_targets;
|
|
||||||
mod beacon_chain;
|
mod beacon_chain;
|
||||||
mod block_graph;
|
mod block_graph;
|
||||||
mod checkpoint;
|
mod checkpoint;
|
||||||
|
@ -23,8 +23,51 @@ pub mod longest_chain;
|
|||||||
pub mod optimised_lmd_ghost;
|
pub mod optimised_lmd_ghost;
|
||||||
pub mod protolambda_lmd_ghost;
|
pub mod protolambda_lmd_ghost;
|
||||||
|
|
||||||
|
use db::DBError;
|
||||||
|
use types::{BeaconBlock, Hash256};
|
||||||
|
|
||||||
|
/// Defines the interface for Fork Choices. Each Fork choice will define their own data structures
|
||||||
|
/// which can be built in block processing through the `add_block` and `add_attestation` functions.
|
||||||
|
/// The main fork choice algorithm is specified in `find_head`.
|
||||||
|
pub trait ForkChoice {
|
||||||
|
/// Called when a block has been added. Allows generic block-level data structures to be
|
||||||
|
/// built for a given fork-choice.
|
||||||
|
fn add_block(
|
||||||
|
&mut self,
|
||||||
|
block: &BeaconBlock,
|
||||||
|
block_hash: &Hash256,
|
||||||
|
) -> Result<(), ForkChoiceError>;
|
||||||
|
/// Called when an attestation has been added. Allows generic attestation-level data structures to be built for a given fork choice.
|
||||||
|
// This can be generalised to a full attestation if required later.
|
||||||
|
fn add_attestation(
|
||||||
|
&mut self,
|
||||||
|
validator_index: u64,
|
||||||
|
target_block_hash: &Hash256,
|
||||||
|
) -> Result<(), ForkChoiceError>;
|
||||||
|
/// The fork-choice algorithm to find the current canonical head of the chain.
|
||||||
|
// TODO: Remove the justified_start_block parameter and make it internal
|
||||||
|
fn find_head(&mut self, justified_start_block: &Hash256) -> Result<Hash256, ForkChoiceError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Possible fork choice errors that can occur.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum ForkChoiceError {
|
||||||
|
MissingBeaconBlock(Hash256),
|
||||||
|
MissingBeaconState(Hash256),
|
||||||
|
IncorrectBeaconState(Hash256),
|
||||||
|
CannotFindBestChild,
|
||||||
|
ChildrenNotFound,
|
||||||
|
StorageError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DBError> for ForkChoiceError {
|
||||||
|
fn from(e: DBError) -> ForkChoiceError {
|
||||||
|
ForkChoiceError::StorageError(e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fork choice options that are currently implemented.
|
/// Fork choice options that are currently implemented.
|
||||||
pub enum ForkChoice {
|
pub enum ForkChoiceAlgorithms {
|
||||||
/// Chooses the longest chain becomes the head. Not for production.
|
/// Chooses the longest chain becomes the head. Not for production.
|
||||||
LongestChain,
|
LongestChain,
|
||||||
/// A simple and highly inefficient implementation of LMD ghost.
|
/// A simple and highly inefficient implementation of LMD ghost.
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
extern crate fast_math;
|
extern crate fast_math;
|
||||||
|
use crate::{ForkChoice, ForkChoiceError};
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use db::{
|
use db::{
|
||||||
stores::{BeaconBlockStore, BeaconStateStore},
|
stores::{BeaconBlockStore, BeaconStateStore},
|
||||||
ClientDB, DBError,
|
ClientDB,
|
||||||
};
|
};
|
||||||
use fast_math::log2_raw;
|
use fast_math::log2_raw;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -11,7 +12,7 @@ use std::sync::Arc;
|
|||||||
use types::{
|
use types::{
|
||||||
readers::{BeaconBlockReader, BeaconStateReader},
|
readers::{BeaconBlockReader, BeaconStateReader},
|
||||||
validator_registry::get_active_validator_indices,
|
validator_registry::get_active_validator_indices,
|
||||||
Attestation, BeaconBlock, Hash256,
|
BeaconBlock, Hash256,
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: Sort out global constants
|
//TODO: Sort out global constants
|
||||||
@ -46,7 +47,7 @@ pub struct OptimisedLMDGhost<T: ClientDB + Sized> {
|
|||||||
children: HashMap<Hash256, Vec<Hash256>>,
|
children: HashMap<Hash256, Vec<Hash256>>,
|
||||||
/// The latest attestation targets as a map of validator index to block hash.
|
/// The latest attestation targets as a map of validator index to block hash.
|
||||||
//TODO: Could this be a fixed size vec
|
//TODO: Could this be a fixed size vec
|
||||||
latest_attestation_targets: HashMap<usize, Hash256>,
|
latest_attestation_targets: HashMap<u64, Hash256>,
|
||||||
/// Block storage access.
|
/// Block storage access.
|
||||||
block_store: Arc<BeaconBlockStore<T>>,
|
block_store: Arc<BeaconBlockStore<T>>,
|
||||||
/// State storage access.
|
/// State storage access.
|
||||||
@ -82,7 +83,7 @@ where
|
|||||||
.into_beacon_block()?
|
.into_beacon_block()?
|
||||||
.slot;
|
.slot;
|
||||||
|
|
||||||
(block_slot - self.GENESIS_SLOT) as u32
|
(block_slot - GENESIS_SLOT) as u32
|
||||||
};
|
};
|
||||||
|
|
||||||
// verify we haven't exceeded the block height
|
// verify we haven't exceeded the block height
|
||||||
@ -202,7 +203,7 @@ impl<T: ClientDB + Sized> ForkChoice for OptimisedLMDGhost<T> {
|
|||||||
.get_reader(&block.parent_root)?
|
.get_reader(&block.parent_root)?
|
||||||
.ok_or_else(|| ForkChoiceError::MissingBeaconBlock(block.parent_root))?
|
.ok_or_else(|| ForkChoiceError::MissingBeaconBlock(block.parent_root))?
|
||||||
.slot()
|
.slot()
|
||||||
- self.GENESIS_SLOT;
|
- GENESIS_SLOT;
|
||||||
|
|
||||||
let parent_hash = &block.parent_root;
|
let parent_hash = &block.parent_root;
|
||||||
|
|
||||||
@ -228,8 +229,14 @@ impl<T: ClientDB + Sized> ForkChoice for OptimisedLMDGhost<T> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_attestation(&mut self, attestation: &Attestation) -> Result<(), ForkChoiceError> {
|
fn add_attestation(
|
||||||
// simply add the attestation to the latest_message_target mapping
|
&mut self,
|
||||||
|
validator_index: u64,
|
||||||
|
target_block_root: &Hash256,
|
||||||
|
) -> Result<(), ForkChoiceError> {
|
||||||
|
// simply add the attestation to the latest_attestation_target
|
||||||
|
self.latest_attestation_targets
|
||||||
|
.insert(validator_index, target_block_root.clone());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +249,7 @@ impl<T: ClientDB + Sized> ForkChoice for OptimisedLMDGhost<T> {
|
|||||||
//.into_beacon_block()?;
|
//.into_beacon_block()?;
|
||||||
|
|
||||||
let block_slot = block.slot();
|
let block_slot = block.slot();
|
||||||
let block_height = block_slot - self.GENESIS_SLOT;
|
let block_height = block_slot - GENESIS_SLOT;
|
||||||
let state_root = block.state_root();
|
let state_root = block.state_root();
|
||||||
|
|
||||||
// get latest votes
|
// get latest votes
|
||||||
@ -262,12 +269,12 @@ impl<T: ClientDB + Sized> ForkChoice for OptimisedLMDGhost<T> {
|
|||||||
let active_validator_indices =
|
let active_validator_indices =
|
||||||
get_active_validator_indices(¤t_state.validator_registry, block_slot);
|
get_active_validator_indices(¤t_state.validator_registry, block_slot);
|
||||||
|
|
||||||
for i in active_validator_indices {
|
for index in active_validator_indices {
|
||||||
let balance =
|
let balance =
|
||||||
std::cmp::min(current_state.validator_balances[i], self.MAX_DEPOSIT_AMOUNT)
|
std::cmp::min(current_state.validator_balances[index], MAX_DEPOSIT_AMOUNT)
|
||||||
/ self.FORK_CHOICE_BALANCE_INCREMENT;
|
/ FORK_CHOICE_BALANCE_INCREMENT;
|
||||||
if balance > 0 {
|
if balance > 0 {
|
||||||
if let Some(target) = self.latest_attestation_targets.get(&(i as usize)) {
|
if let Some(target) = self.latest_attestation_targets.get(&(index as u64)) {
|
||||||
*latest_votes.entry(*target).or_insert_with(|| 0) += balance;
|
*latest_votes.entry(*target).or_insert_with(|| 0) += balance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,7 +338,7 @@ impl<T: ClientDB + Sized> ForkChoice for OptimisedLMDGhost<T> {
|
|||||||
.get_reader(¤t_head)?
|
.get_reader(¤t_head)?
|
||||||
.ok_or_else(|| ForkChoiceError::MissingBeaconBlock(*justified_block_start))?
|
.ok_or_else(|| ForkChoiceError::MissingBeaconBlock(*justified_block_start))?
|
||||||
.slot()
|
.slot()
|
||||||
- self.GENESIS_SLOT;
|
- GENESIS_SLOT;
|
||||||
|
|
||||||
// prune the latest votes for votes that are not part of current chosen chain
|
// prune the latest votes for votes that are not part of current chosen chain
|
||||||
// more specifically, only keep votes that have head as an ancestor
|
// more specifically, only keep votes that have head as an ancestor
|
||||||
@ -342,40 +349,6 @@ impl<T: ClientDB + Sized> ForkChoice for OptimisedLMDGhost<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the interface for Fork Choices. Each Fork choice will define their own data structures
|
|
||||||
/// which can be built in block processing through the `add_block` and `add_attestation` functions.
|
|
||||||
/// The main fork choice algorithm is specified in `find_head`.
|
|
||||||
pub trait ForkChoice {
|
|
||||||
/// Called when a block has been added. Allows generic block-level data structures to be
|
|
||||||
/// built for a given fork-choice.
|
|
||||||
fn add_block(
|
|
||||||
&mut self,
|
|
||||||
block: &BeaconBlock,
|
|
||||||
block_hash: &Hash256,
|
|
||||||
) -> Result<(), ForkChoiceError>;
|
|
||||||
/// Called when an attestation has been added. Allows generic attestation-level data structures to be built for a given fork choice.
|
|
||||||
fn add_attestation(&mut self, attestation: &Attestation) -> Result<(), ForkChoiceError>;
|
|
||||||
/// The fork-choice algorithm to find the current canonical head of the chain.
|
|
||||||
// TODO: Remove the justified_start_block parameter and make it internal
|
|
||||||
fn find_head(&mut self, justified_start_block: &Hash256) -> Result<Hash256, ForkChoiceError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Possible fork choice errors that can occur.
|
|
||||||
pub enum ForkChoiceError {
|
|
||||||
MissingBeaconBlock(Hash256),
|
|
||||||
MissingBeaconState(Hash256),
|
|
||||||
IncorrectBeaconState(Hash256),
|
|
||||||
CannotFindBestChild,
|
|
||||||
ChildrenNotFound,
|
|
||||||
StorageError(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DBError> for ForkChoiceError {
|
|
||||||
fn from(e: DBError) -> ForkChoiceError {
|
|
||||||
ForkChoiceError::StorageError(e.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Type for storing blocks in a memory cache. Key is comprised of block-hash plus the height.
|
/// Type for storing blocks in a memory cache. Key is comprised of block-hash plus the height.
|
||||||
#[derive(PartialEq, Eq, Hash)]
|
#[derive(PartialEq, Eq, Hash)]
|
||||||
pub struct CacheKey<T> {
|
pub struct CacheKey<T> {
|
||||||
|
Loading…
Reference in New Issue
Block a user