Add new fns to ForkChoice and SlotClock

This commit is contained in:
Paul Hauner 2019-05-27 15:12:51 +10:00
parent 9922ed2239
commit 76602a65fc
No known key found for this signature in database
GPG Key ID: 5E2CFF9B75FA63DF
11 changed files with 88 additions and 108 deletions

View File

@ -82,7 +82,7 @@ impl BlockProcessingOutcome {
pub trait BeaconChainTypes { pub trait BeaconChainTypes {
type Store: store::Store; type Store: store::Store;
type SlotClock: slot_clock::SlotClock; type SlotClock: slot_clock::SlotClock;
type ForkChoice: fork_choice::ForkChoice; type ForkChoice: fork_choice::ForkChoice<Self::Store>;
type EthSpec: types::EthSpec; type EthSpec: types::EthSpec;
} }

View File

@ -5,6 +5,8 @@ use beacon_chain::{
store::{DiskStore, MemoryStore, Store}, store::{DiskStore, MemoryStore, Store},
BeaconChain, BeaconChainTypes, BeaconChain, BeaconChainTypes,
}; };
use fork_choice::ForkChoice;
use slot_clock::SlotClock;
use std::sync::Arc; use std::sync::Arc;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use types::{ use types::{
@ -36,7 +38,7 @@ where
>, >,
{ {
fn initialise_beacon_chain(_config: &ClientConfig) -> BeaconChain<T> { fn initialise_beacon_chain(_config: &ClientConfig) -> BeaconChain<T> {
initialize_chain(MemoryStore::open()) initialize_chain::<_, _, FewValidatorsEthSpec>(MemoryStore::open())
} }
} }
@ -62,18 +64,15 @@ where
fn initialise_beacon_chain(config: &ClientConfig) -> BeaconChain<T> { fn initialise_beacon_chain(config: &ClientConfig) -> BeaconChain<T> {
let store = DiskStore::open(&config.db_name).expect("Unable to open DB."); let store = DiskStore::open(&config.db_name).expect("Unable to open DB.");
initialize_chain(store) initialize_chain::<_, _, FewValidatorsEthSpec>(store)
} }
} }
/// Produces a `BeaconChain` given some pre-initialized `Store`. /// Produces a `BeaconChain` given some pre-initialized `Store`.
fn initialize_chain<T, U: Store, V: EthSpec>(store: U) -> BeaconChain<T> fn initialize_chain<T, U: Store, V: EthSpec>(store: U) -> BeaconChain<T>
where where
T: BeaconChainTypes< T: BeaconChainTypes<Store = U>,
Store = U, T::ForkChoice: ForkChoice<U>,
SlotClock = SystemTimeSlotClock,
ForkChoice = BitwiseLMDGhost<U, V>,
>,
{ {
let spec = T::EthSpec::spec(); let spec = T::EthSpec::spec();
@ -86,14 +85,13 @@ where
genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root()); genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
// Slot clock // Slot clock
let slot_clock = SystemTimeSlotClock::new( let slot_clock = T::SlotClock::new(
spec.genesis_slot, spec.genesis_slot,
genesis_state.genesis_time, genesis_state.genesis_time,
spec.seconds_per_slot, spec.seconds_per_slot,
) );
.expect("Unable to load SystemTimeSlotClock");
// Choose the fork choice // Choose the fork choice
let fork_choice = BitwiseLMDGhost::new(store.clone()); let fork_choice = T::ForkChoice::new(store.clone());
// Genesis chain // Genesis chain
//TODO: Handle error correctly //TODO: Handle error correctly

View File

@ -48,18 +48,6 @@ pub struct BitwiseLMDGhost<T, E> {
} }
impl<T: Store, E: EthSpec> BitwiseLMDGhost<T, E> { impl<T: Store, E: EthSpec> BitwiseLMDGhost<T, E> {
pub fn new(store: Arc<T>) -> Self {
BitwiseLMDGhost {
cache: HashMap::new(),
ancestors: vec![HashMap::new(); 16],
latest_attestation_targets: HashMap::new(),
children: HashMap::new(),
max_known_height: SlotHeight::new(0),
store,
_phantom: PhantomData,
}
}
/// Finds the latest votes weighted by validator balance. Returns a hashmap of block_hash to /// Finds the latest votes weighted by validator balance. Returns a hashmap of block_hash to
/// weighted votes. /// weighted votes.
pub fn get_latest_votes( pub fn get_latest_votes(
@ -229,7 +217,19 @@ impl<T: Store, E: EthSpec> BitwiseLMDGhost<T, E> {
} }
} }
impl<T: Store, E: EthSpec> ForkChoice for BitwiseLMDGhost<T, E> { impl<T: Store, E: EthSpec> ForkChoice<T> for BitwiseLMDGhost<T, E> {
fn new(store: Arc<T>) -> Self {
BitwiseLMDGhost {
cache: HashMap::new(),
ancestors: vec![HashMap::new(); 16],
latest_attestation_targets: HashMap::new(),
children: HashMap::new(),
max_known_height: SlotHeight::new(0),
store,
_phantom: PhantomData,
}
}
fn add_block( fn add_block(
&mut self, &mut self,
block: &BeaconBlock, block: &BeaconBlock,

View File

@ -21,8 +21,7 @@ pub mod longest_chain;
pub mod optimized_lmd_ghost; pub mod optimized_lmd_ghost;
pub mod slow_lmd_ghost; pub mod slow_lmd_ghost;
// use store::stores::BeaconBlockAtSlotError; use std::sync::Arc;
// use store::DBError;
use store::Error as DBError; use store::Error as DBError;
use types::{BeaconBlock, ChainSpec, Hash256}; use types::{BeaconBlock, ChainSpec, Hash256};
@ -34,7 +33,10 @@ pub use slow_lmd_ghost::SlowLMDGhost;
/// Defines the interface for Fork Choices. Each Fork choice will define their own data structures /// 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. /// 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 /// The main fork choice algorithm is specified in `find_head
pub trait ForkChoice: Send + Sync { pub trait ForkChoice<T>: Send + Sync {
/// Create a new `ForkChoice` which reads from `store`.
fn new(store: Arc<T>) -> Self;
/// Called when a block has been added. Allows generic block-level data structures to be /// Called when a block has been added. Allows generic block-level data structures to be
/// built for a given fork-choice. /// built for a given fork-choice.
fn add_block( fn add_block(
@ -78,22 +80,6 @@ impl From<DBError> for ForkChoiceError {
} }
} }
/*
impl From<BeaconBlockAtSlotError> for ForkChoiceError {
fn from(e: BeaconBlockAtSlotError) -> ForkChoiceError {
match e {
BeaconBlockAtSlotError::UnknownBeaconBlock(hash) => {
ForkChoiceError::MissingBeaconBlock(hash)
}
BeaconBlockAtSlotError::InvalidBeaconBlock(hash) => {
ForkChoiceError::MissingBeaconBlock(hash)
}
BeaconBlockAtSlotError::DBError(string) => ForkChoiceError::StorageError(string),
}
}
}
*/
/// Fork choice options that are currently implemented. /// Fork choice options that are currently implemented.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ForkChoiceAlgorithm { pub enum ForkChoiceAlgorithm {

View File

@ -10,16 +10,14 @@ pub struct LongestChain<T> {
store: Arc<T>, store: Arc<T>,
} }
impl<T: Store> LongestChain<T> { impl<T: Store> ForkChoice<T> for LongestChain<T> {
pub fn new(store: Arc<T>) -> Self { fn new(store: Arc<T>) -> Self {
LongestChain { LongestChain {
head_block_hashes: Vec::new(), head_block_hashes: Vec::new(),
store, store,
} }
} }
}
impl<T: Store> ForkChoice for LongestChain<T> {
fn add_block( fn add_block(
&mut self, &mut self,
block: &BeaconBlock, block: &BeaconBlock,

View File

@ -48,18 +48,6 @@ pub struct OptimizedLMDGhost<T, E> {
} }
impl<T: Store, E: EthSpec> OptimizedLMDGhost<T, E> { impl<T: Store, E: EthSpec> OptimizedLMDGhost<T, E> {
pub fn new(store: Arc<T>) -> Self {
OptimizedLMDGhost {
cache: HashMap::new(),
ancestors: vec![HashMap::new(); 16],
latest_attestation_targets: HashMap::new(),
children: HashMap::new(),
max_known_height: SlotHeight::new(0),
store,
_phantom: PhantomData,
}
}
/// Finds the latest votes weighted by validator balance. Returns a hashmap of block_hash to /// Finds the latest votes weighted by validator balance. Returns a hashmap of block_hash to
/// weighted votes. /// weighted votes.
pub fn get_latest_votes( pub fn get_latest_votes(
@ -200,7 +188,19 @@ impl<T: Store, E: EthSpec> OptimizedLMDGhost<T, E> {
} }
} }
impl<T: Store, E: EthSpec> ForkChoice for OptimizedLMDGhost<T, E> { impl<T: Store, E: EthSpec> ForkChoice<T> for OptimizedLMDGhost<T, E> {
fn new(store: Arc<T>) -> Self {
OptimizedLMDGhost {
cache: HashMap::new(),
ancestors: vec![HashMap::new(); 16],
latest_attestation_targets: HashMap::new(),
children: HashMap::new(),
max_known_height: SlotHeight::new(0),
store,
_phantom: PhantomData,
}
}
fn add_block( fn add_block(
&mut self, &mut self,
block: &BeaconBlock, block: &BeaconBlock,

View File

@ -20,15 +20,6 @@ pub struct SlowLMDGhost<T, E> {
} }
impl<T: Store, E: EthSpec> SlowLMDGhost<T, E> { impl<T: Store, E: EthSpec> SlowLMDGhost<T, E> {
pub fn new(store: Arc<T>) -> Self {
SlowLMDGhost {
latest_attestation_targets: HashMap::new(),
children: HashMap::new(),
store,
_phantom: PhantomData,
}
}
/// Finds the latest votes weighted by validator balance. Returns a hashmap of block_hash to /// Finds the latest votes weighted by validator balance. Returns a hashmap of block_hash to
/// weighted votes. /// weighted votes.
pub fn get_latest_votes( pub fn get_latest_votes(
@ -94,7 +85,16 @@ impl<T: Store, E: EthSpec> SlowLMDGhost<T, E> {
} }
} }
impl<T: Store, E: EthSpec> ForkChoice for SlowLMDGhost<T, E> { impl<T: Store, E: EthSpec> ForkChoice<T> for SlowLMDGhost<T, E> {
fn new(store: Arc<T>) -> Self {
SlowLMDGhost {
latest_attestation_targets: HashMap::new(),
children: HashMap::new(),
store,
_phantom: PhantomData,
}
}
/// Process when a block is added /// Process when a block is added
fn add_block( fn add_block(
&mut self, &mut self,

View File

@ -6,9 +6,14 @@ pub use crate::testing_slot_clock::{Error as TestingSlotClockError, TestingSlotC
use std::time::Duration; use std::time::Duration;
pub use types::Slot; pub use types::Slot;
pub trait SlotClock: Send + Sync { pub trait SlotClock: Send + Sync + Sized {
type Error; type Error;
/// Create a new `SlotClock`.
///
/// Returns an Error if `slot_duration_seconds == 0`.
fn new(genesis_slot: Slot, genesis_seconds: u64, slot_duration_seconds: u64) -> Self;
fn present_slot(&self) -> Result<Option<Slot>, Self::Error>; fn present_slot(&self) -> Result<Option<Slot>, Self::Error>;
fn duration_to_next_slot(&self) -> Result<Option<Duration>, Self::Error>; fn duration_to_next_slot(&self) -> Result<Option<Duration>, Self::Error>;

View File

@ -18,31 +18,25 @@ pub struct SystemTimeSlotClock {
slot_duration_seconds: u64, slot_duration_seconds: u64,
} }
impl SystemTimeSlotClock {
/// Create a new `SystemTimeSlotClock`.
///
/// Returns an Error if `slot_duration_seconds == 0`.
pub fn new(
genesis_slot: Slot,
genesis_seconds: u64,
slot_duration_seconds: u64,
) -> Result<SystemTimeSlotClock, Error> {
if slot_duration_seconds == 0 {
Err(Error::SlotDurationIsZero)
} else {
Ok(Self {
genesis_slot,
genesis_seconds,
slot_duration_seconds,
})
}
}
}
impl SlotClock for SystemTimeSlotClock { impl SlotClock for SystemTimeSlotClock {
type Error = Error; type Error = Error;
/// Create a new `SystemTimeSlotClock`.
///
/// Returns an Error if `slot_duration_seconds == 0`.
fn new(genesis_slot: Slot, genesis_seconds: u64, slot_duration_seconds: u64) -> Self {
Self {
genesis_slot,
genesis_seconds,
slot_duration_seconds,
}
}
fn present_slot(&self) -> Result<Option<Slot>, Error> { fn present_slot(&self) -> Result<Option<Slot>, Error> {
if self.slot_duration_seconds == 0 {
return Err(Error::SlotDurationIsZero);
}
let syslot_time = SystemTime::now(); let syslot_time = SystemTime::now();
let duration_since_epoch = syslot_time.duration_since(SystemTime::UNIX_EPOCH)?; let duration_since_epoch = syslot_time.duration_since(SystemTime::UNIX_EPOCH)?;
let duration_since_genesis = let duration_since_genesis =

View File

@ -8,30 +8,28 @@ pub enum Error {}
/// Determines the present slot based upon the present system time. /// Determines the present slot based upon the present system time.
pub struct TestingSlotClock { pub struct TestingSlotClock {
slot: RwLock<u64>, slot: RwLock<Slot>,
} }
impl TestingSlotClock { impl TestingSlotClock {
/// Create a new `TestingSlotClock`.
///
/// Returns an Error if `slot_duration_seconds == 0`.
pub fn new(slot: u64) -> TestingSlotClock {
TestingSlotClock {
slot: RwLock::new(slot),
}
}
pub fn set_slot(&self, slot: u64) { pub fn set_slot(&self, slot: u64) {
*self.slot.write().expect("TestingSlotClock poisoned.") = slot; *self.slot.write().expect("TestingSlotClock poisoned.") = Slot::from(slot);
} }
} }
impl SlotClock for TestingSlotClock { impl SlotClock for TestingSlotClock {
type Error = Error; type Error = Error;
/// Create a new `TestingSlotClock` at `genesis_slot`.
fn new(genesis_slot: Slot, _genesis_seconds: u64, _slot_duration_seconds: u64) -> Self {
TestingSlotClock {
slot: RwLock::new(genesis_slot),
}
}
fn present_slot(&self) -> Result<Option<Slot>, Error> { fn present_slot(&self) -> Result<Option<Slot>, Error> {
let slot = *self.slot.read().expect("TestingSlotClock poisoned."); let slot = *self.slot.read().expect("TestingSlotClock poisoned.");
Ok(Some(Slot::new(slot))) Ok(Some(slot))
} }
/// Always returns a duration of 1 second. /// Always returns a duration of 1 second.
@ -46,7 +44,9 @@ mod tests {
#[test] #[test]
fn test_slot_now() { fn test_slot_now() {
let clock = TestingSlotClock::new(10); let null = 0;
let clock = TestingSlotClock::new(Slot::new(10), null, null);
assert_eq!(clock.present_slot(), Ok(Some(Slot::new(10)))); assert_eq!(clock.present_slot(), Ok(Some(Slot::new(10))));
clock.set_slot(123); clock.set_slot(123);
assert_eq!(clock.present_slot(), Ok(Some(Slot::new(123)))); assert_eq!(clock.present_slot(), Ok(Some(Slot::new(123))));

View File

@ -155,8 +155,7 @@ impl<B: BeaconNodeDuties + 'static, S: Signer + 'static> Service<B, S> {
// build the validator slot clock // build the validator slot clock
let slot_clock = let slot_clock =
SystemTimeSlotClock::new(genesis_slot, genesis_time, config.spec.seconds_per_slot) SystemTimeSlotClock::new(genesis_slot, genesis_time, config.spec.seconds_per_slot);
.expect("Unable to instantiate SystemTimeSlotClock.");
let current_slot = slot_clock let current_slot = slot_clock
.present_slot() .present_slot()