Merge branch 'master' into fork-choices.

This introduces the `Height` type which keeps track of block_height
types.

Further integration into beacon chain with the merge.
This commit is contained in:
Age Manning
2019-02-13 18:04:29 +11:00
90 changed files with 3622 additions and 2883 deletions

View File

@@ -15,7 +15,6 @@ db = { path = "db" }
dirs = "1.0.3"
futures = "0.1.23"
fork_choice = { path = "../eth2/fork_choice" }
genesis = { path = "../eth2/genesis" }
slog = "^2.2.3"
slot_clock = { path = "../eth2/utils/slot_clock" }
slog-term = "^2.4.0"

View File

@@ -11,7 +11,6 @@ boolean-bitfield = { path = "../../eth2/utils/boolean-bitfield" }
db = { path = "../db" }
failure = "0.1"
failure_derive = "0.1"
genesis = { path = "../../eth2/genesis" }
hashing = { path = "../../eth2/utils/hashing" }
fork_choice = { path = "../../eth2/fork_choice" }
parking_lot = "0.7"
@@ -22,4 +21,5 @@ serde_derive = "1.0"
serde_json = "1.0"
slot_clock = { path = "../../eth2/utils/slot_clock" }
ssz = { path = "../../eth2/utils/ssz" }
state_processing = { path = "../../eth2/state_processing" }
types = { path = "../../eth2/types" }

View File

@@ -1,3 +1,4 @@
use state_processing::validate_attestation_without_signature;
use std::collections::{HashMap, HashSet};
use types::{
beacon_state::CommitteesError, AggregateSignature, Attestation, AttestationData, BeaconState,
@@ -16,6 +17,7 @@ const PHASE_0_CUSTODY_BIT: bool = false;
///
/// Note: `Attestations` are stored in memory and never deleted. This is not scalable and must be
/// rectified in a future revision.
#[derive(Default)]
pub struct AttestationAggregator {
store: HashMap<Vec<u8>, Attestation>,
}
@@ -172,9 +174,7 @@ impl AttestationAggregator {
self.store
.values()
.filter_map(|attestation| {
if state
.validate_attestation_without_signature(attestation, spec)
.is_ok()
if validate_attestation_without_signature(&state, attestation, spec).is_ok()
&& !known_attestation_data.contains(&attestation.data)
{
Some(attestation.clone())

View File

@@ -1,24 +1,25 @@
use crate::attestation_aggregator::{AttestationAggregator, Outcome as AggregationOutcome};
use crate::checkpoint::CheckPoint;
use db::{
stores::{BeaconBlockStore, BeaconStateStore},
ClientDB, DBError,
};
use fork_choice::{ForkChoice, ForkChoiceError};
use genesis::{genesis_beacon_block, genesis_beacon_state};
use log::{debug, trace};
use parking_lot::{RwLock, RwLockReadGuard};
use slot_clock::SlotClock;
use ssz::ssz_encode;
use state_processing::{
BlockProcessable, BlockProcessingError, SlotProcessable, SlotProcessingError,
};
use std::sync::Arc;
use types::{
beacon_state::{BlockProcessingError, CommitteesError, SlotProcessingError},
beacon_state::CommitteesError,
readers::{BeaconBlockReader, BeaconStateReader},
AttestationData, BeaconBlock, BeaconBlockBody, BeaconState, ChainSpec, Eth1Data,
FreeAttestation, Hash256, PublicKey, Signature,
AttestationData, BeaconBlock, BeaconBlockBody, BeaconState, ChainSpec, Crosslink, Deposit,
Epoch, Eth1Data, FreeAttestation, Hash256, PublicKey, Signature, Slot,
};
use crate::attestation_aggregator::{AttestationAggregator, Outcome as AggregationOutcome};
use crate::checkpoint::CheckPoint;
#[derive(Debug, PartialEq)]
pub enum Error {
InsufficientValidators,
@@ -67,7 +68,6 @@ pub struct BeaconChain<T: ClientDB + Sized, U: SlotClock, F: ForkChoice> {
pub attestation_aggregator: RwLock<AttestationAggregator>,
canonical_head: RwLock<CheckPoint>,
finalized_head: RwLock<CheckPoint>,
justified_head: RwLock<CheckPoint>,
pub state: RwLock<BeaconState>,
pub spec: ChainSpec,
pub fork_choice: RwLock<F>,
@@ -84,18 +84,26 @@ where
state_store: Arc<BeaconStateStore<T>>,
block_store: Arc<BeaconBlockStore<T>>,
slot_clock: U,
genesis_time: u64,
latest_eth1_data: Eth1Data,
initial_validator_deposits: Vec<Deposit>,
spec: ChainSpec,
fork_choice: F,
) -> Result<Self, Error> {
if spec.initial_validators.is_empty() {
if initial_validator_deposits.is_empty() {
return Err(Error::InsufficientValidators);
}
let genesis_state = genesis_beacon_state(&spec);
let genesis_state = BeaconState::genesis(
genesis_time,
initial_validator_deposits,
latest_eth1_data,
&spec,
);
let state_root = genesis_state.canonical_root();
state_store.put(&state_root, &ssz_encode(&genesis_state)[..])?;
let genesis_block = genesis_beacon_block(state_root, &spec);
let genesis_block = BeaconBlock::genesis(state_root, &spec);
let block_root = genesis_block.canonical_root();
block_store.put(&block_root, &ssz_encode(&genesis_block)[..])?;
@@ -105,12 +113,6 @@ where
genesis_state.clone(),
state_root,
));
let justified_head = RwLock::new(CheckPoint::new(
genesis_block.clone(),
block_root,
genesis_state.clone(),
state_root,
));
let canonical_head = RwLock::new(CheckPoint::new(
genesis_block.clone(),
block_root,
@@ -125,7 +127,6 @@ where
slot_clock,
attestation_aggregator,
state: RwLock::new(genesis_state.clone()),
justified_head,
finalized_head,
canonical_head,
spec,
@@ -193,10 +194,10 @@ where
/// It is important to note that this is _not_ the state corresponding to the canonical head
/// block, instead it is that state which may or may not have had additional per slot/epoch
/// processing applied to it.
pub fn advance_state(&self, slot: u64) -> Result<(), SlotProcessingError> {
pub fn advance_state(&self, slot: Slot) -> Result<(), SlotProcessingError> {
let state_slot = self.state.read().slot;
let head_block_root = self.head().beacon_block_root;
for _ in state_slot..slot {
for _ in state_slot.as_u64()..slot.as_u64() {
self.state
.write()
.per_slot_processing(head_block_root, &self.spec)?;
@@ -222,19 +223,6 @@ where
None
}
/// Returns the number of slots the validator has been required to propose.
///
/// Returns `None` if the `validator_index` is invalid.
///
/// Information is retrieved from the present `beacon_state.validator_registry`.
pub fn proposer_slots(&self, validator_index: usize) -> Option<u64> {
if let Some(validator) = self.state.read().validator_registry.get(validator_index) {
Some(validator.proposer_slots)
} else {
None
}
}
/// Reads the slot clock, returns `None` if the slot is unavailable.
///
/// The slot might be unavailable due to an error with the system clock, or if the present time
@@ -243,9 +231,10 @@ where
/// This is distinct to `present_slot`, which simply reads the latest state. If a
/// call to `read_slot_clock` results in a higher slot than a call to `present_slot`,
/// `self.state` should undergo per slot processing.
pub fn read_slot_clock(&self) -> Option<u64> {
pub fn read_slot_clock(&self) -> Option<Slot> {
match self.slot_clock.present_slot() {
Ok(some_slot) => some_slot,
Ok(Some(some_slot)) => Some(some_slot),
Ok(None) => None,
_ => None,
}
}
@@ -255,7 +244,7 @@ where
/// This is distinct to `read_slot_clock`, which reads from the actual system clock. If
/// `self.state` has not been transitioned it is possible for the system clock to be on a
/// different slot to what is returned from this call.
pub fn present_slot(&self) -> u64 {
pub fn present_slot(&self) -> Slot {
self.state.read().slot
}
@@ -263,7 +252,7 @@ where
///
/// Information is read from the present `beacon_state` shuffling, so only information from the
/// present and prior epoch is available.
pub fn block_proposer(&self, slot: u64) -> Result<usize, CommitteesError> {
pub fn block_proposer(&self, slot: Slot) -> Result<usize, CommitteesError> {
let index = self
.state
.read()
@@ -273,8 +262,8 @@ where
}
/// Returns the justified slot for the present state.
pub fn justified_slot(&self) -> u64 {
self.state.read().justified_slot
pub fn justified_epoch(&self) -> Epoch {
self.state.read().justified_epoch
}
/// Returns the attestation slot and shard for a given validator index.
@@ -284,7 +273,7 @@ where
pub fn validator_attestion_slot_and_shard(
&self,
validator_index: usize,
) -> Result<Option<(u64, u64)>, CommitteesError> {
) -> Result<Option<(Slot, u64)>, CommitteesError> {
if let Some((slot, shard, _committee)) = self
.state
.read()
@@ -298,11 +287,14 @@ where
/// Produce an `AttestationData` that is valid for the present `slot` and given `shard`.
pub fn produce_attestation_data(&self, shard: u64) -> Result<AttestationData, Error> {
let justified_slot = self.justified_slot();
let justified_epoch = self.justified_epoch();
let justified_block_root = *self
.state
.read()
.get_block_root(justified_slot, &self.spec)
.get_block_root(
justified_epoch.start_slot(self.spec.epoch_length),
&self.spec,
)
.ok_or_else(|| Error::BadRecentBlockRoots)?;
let epoch_boundary_root = *self
@@ -320,8 +312,11 @@ where
beacon_block_root: self.head().beacon_block_root,
epoch_boundary_root,
shard_block_root: Hash256::zero(),
latest_crosslink_root: Hash256::zero(),
justified_slot,
latest_crosslink: Crosslink {
epoch: self.state.read().slot.epoch(self.spec.epoch_length),
shard_block_root: Hash256::zero(),
},
justified_epoch,
justified_block_root,
})
}
@@ -450,7 +445,7 @@ where
// Transition the parent state to the present slot.
let mut state = parent_state;
for _ in state.slot..present_slot {
for _ in state.slot.as_u64()..present_slot.as_u64() {
if let Err(e) = state.per_slot_processing(parent_block_root, &self.spec) {
return Ok(BlockProcessingOutcome::InvalidBlock(
InvalidBlock::SlotProcessingError(e),
@@ -520,7 +515,7 @@ where
attestations.len()
);
let parent_root = *state.get_block_root(state.slot.saturating_sub(1), &self.spec)?;
let parent_root = *state.get_block_root(state.slot.saturating_sub(1_u64), &self.spec)?;
let mut block = BeaconBlock {
slot: state.slot,
@@ -535,11 +530,8 @@ where
signature: self.spec.empty_signature.clone(), // To be completed by a validator.
body: BeaconBlockBody {
proposer_slashings: vec![],
casper_slashings: vec![],
attester_slashings: vec![],
attestations,
custody_reseeds: vec![],
custody_challenges: vec![],
custody_responses: vec![],
deposits: vec![],
exits: vec![],
},

View File

@@ -22,7 +22,6 @@ parking_lot = "0.7"
failure = "0.1"
failure_derive = "0.1"
fork_choice = { path = "../../../eth2/fork_choice" }
genesis = { path = "../../../eth2/genesis" }
hashing = { path = "../../../eth2/utils/hashing" }
log = "0.4"
env_logger = "0.6.0"

View File

@@ -1,6 +1,7 @@
use super::TestValidator;
use super::ValidatorHarness;
use beacon_chain::BeaconChain;
pub use beacon_chain::{CheckPoint, Error as BeaconChainError};
use bls::create_proof_of_possession;
use db::{
stores::{BeaconBlockStore, BeaconStateStore},
MemoryDB,
@@ -14,7 +15,10 @@ use std::fs::File;
use std::io::prelude::*;
use std::iter::FromIterator;
use std::sync::Arc;
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Validator};
use types::{
BeaconBlock, ChainSpec, Deposit, DepositData, DepositInput, Eth1Data, FreeAttestation, Hash256,
Keypair, Slot,
};
/// The beacon chain harness simulates a single beacon node with `validator_count` validators connected
/// to it. Each validator is provided a borrow to the beacon chain, where it may read
@@ -27,7 +31,7 @@ pub struct BeaconChainHarness {
pub beacon_chain: Arc<BeaconChain<MemoryDB, TestingSlotClock, OptimisedLMDGhost<MemoryDB>>>,
pub block_store: Arc<BeaconBlockStore<MemoryDB>>,
pub state_store: Arc<BeaconStateStore<MemoryDB>>,
pub validators: Vec<TestValidator>,
pub validators: Vec<ValidatorHarness>,
pub spec: Arc<ChainSpec>,
}
@@ -36,16 +40,17 @@ impl BeaconChainHarness {
///
/// - A keypair, `BlockProducer` and `Attester` for each validator.
/// - A new BeaconChain struct where the given validators are in the genesis.
pub fn new(mut spec: ChainSpec, validator_count: usize) -> Self {
pub fn new(spec: ChainSpec, validator_count: usize) -> Self {
let db = Arc::new(MemoryDB::open());
let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
let state_store = Arc::new(BeaconStateStore::new(db.clone()));
let slot_clock = TestingSlotClock::new(spec.genesis_slot);
let genesis_time = 1_549_935_547; // 12th Feb 2018 (arbitrary value in the past).
let slot_clock = TestingSlotClock::new(spec.genesis_slot.as_u64());
let fork_choice = OptimisedLMDGhost::new(block_store.clone(), state_store.clone());
// Remove the validators present in the spec (if any).
spec.initial_validators = Vec::with_capacity(validator_count);
spec.initial_balances = Vec::with_capacity(validator_count);
let latest_eth1_data = Eth1Data {
deposit_root: Hash256::zero(),
block_hash: Hash256::zero(),
};
debug!("Generating validator keypairs...");
@@ -55,25 +60,25 @@ impl BeaconChainHarness {
.map(|_| Keypair::random())
.collect();
debug!("Creating validator records...");
debug!("Creating validator deposits...");
spec.initial_validators = keypairs
let initial_validator_deposits = keypairs
.par_iter()
.map(|keypair| Validator {
pubkey: keypair.pk.clone(),
activation_slot: 0,
..std::default::Default::default()
.map(|keypair| Deposit {
branch: vec![], // branch verification is not specified.
index: 0, // index verification is not specified.
deposit_data: DepositData {
amount: 32_000_000_000, // 32 ETH (in Gwei)
timestamp: genesis_time - 1,
deposit_input: DepositInput {
pubkey: keypair.pk.clone(),
withdrawal_credentials: Hash256::zero(), // Withdrawal not possible.
proof_of_possession: create_proof_of_possession(&keypair),
},
},
})
.collect();
debug!("Setting validator balances...");
spec.initial_balances = spec
.initial_validators
.par_iter()
.map(|_| 32_000_000_000) // 32 ETH
.collect();
debug!("Creating the BeaconChain...");
// Create the Beacon Chain
@@ -82,6 +87,9 @@ impl BeaconChainHarness {
state_store.clone(),
block_store.clone(),
slot_clock,
genesis_time,
latest_eth1_data,
initial_validator_deposits,
spec.clone(),
fork_choice,
)
@@ -93,12 +101,14 @@ impl BeaconChainHarness {
debug!("Creating validator producer and attester instances...");
// Spawn the test validator instances.
let validators: Vec<TestValidator> = keypairs
let validators: Vec<ValidatorHarness> = keypairs
.iter()
.map(|keypair| TestValidator::new(keypair.clone(), beacon_chain.clone(), spec.clone()))
.map(|keypair| {
ValidatorHarness::new(keypair.clone(), beacon_chain.clone(), spec.clone())
})
.collect();
debug!("Created {} TestValidators", validators.len());
debug!("Created {} ValidatorHarnesss", validators.len());
Self {
db,
@@ -115,12 +125,12 @@ impl BeaconChainHarness {
/// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
///
/// Returns the new slot.
pub fn increment_beacon_chain_slot(&mut self) -> u64 {
pub fn increment_beacon_chain_slot(&mut self) -> Slot {
let slot = self.beacon_chain.present_slot() + 1;
debug!("Incrementing BeaconChain slot to {}.", slot);
self.beacon_chain.slot_clock.set_slot(slot);
self.beacon_chain.slot_clock.set_slot(slot.as_u64());
self.beacon_chain.advance_state(slot).unwrap();
slot
}
@@ -136,7 +146,7 @@ impl BeaconChainHarness {
.beacon_chain
.state
.read()
.get_crosslink_committees_at_slot(present_slot, &self.spec)
.get_crosslink_committees_at_slot(present_slot, false, &self.spec)
.unwrap()
.iter()
.fold(vec![], |mut acc, (committee, _slot)| {
@@ -226,7 +236,7 @@ impl BeaconChainHarness {
}
/// Write the output of `chain_dump` to a JSON file.
pub fn dump_to_file(&self, filename: String, chain_dump: &Vec<CheckPoint>) {
pub fn dump_to_file(&self, filename: String, chain_dump: &[CheckPoint]) {
let json = serde_json::to_string(chain_dump).unwrap();
let mut file = File::create(filename).unwrap();
file.write_all(json.as_bytes())

View File

@@ -1,5 +1,5 @@
mod harness;
mod validator;
mod beacon_chain_harness;
mod validator_harness;
pub use self::harness::BeaconChainHarness;
pub use self::validator::TestValidator;
pub use self::beacon_chain_harness::BeaconChainHarness;
pub use self::validator_harness::ValidatorHarness;

View File

@@ -1,6 +0,0 @@
mod direct_beacon_node;
mod direct_duties;
mod signer;
mod validator;
pub use self::validator::TestValidator;

View File

@@ -12,7 +12,7 @@ use fork_choice::ForkChoice;
use parking_lot::RwLock;
use slot_clock::SlotClock;
use std::sync::Arc;
use types::{AttestationData, BeaconBlock, FreeAttestation, PublicKey, Signature};
use types::{AttestationData, BeaconBlock, FreeAttestation, Signature, Slot};
// mod attester;
// mod producer;
@@ -52,7 +52,7 @@ impl<T: ClientDB, U: SlotClock, F: ForkChoice> DirectBeaconNode<T, U, F> {
impl<T: ClientDB, U: SlotClock, F: ForkChoice> AttesterBeaconNode for DirectBeaconNode<T, U, F> {
fn produce_attestation_data(
&self,
_slot: u64,
_slot: Slot,
shard: u64,
) -> Result<Option<AttestationData>, NodeError> {
match self.beacon_chain.produce_attestation_data(shard) {
@@ -71,31 +71,17 @@ impl<T: ClientDB, U: SlotClock, F: ForkChoice> AttesterBeaconNode for DirectBeac
}
impl<T: ClientDB, U: SlotClock, F: ForkChoice> BeaconBlockNode for DirectBeaconNode<T, U, F> {
/// Requests the `proposer_nonce` from the `BeaconChain`.
fn proposer_nonce(&self, pubkey: &PublicKey) -> Result<u64, BeaconBlockNodeError> {
let validator_index = self
.beacon_chain
.validator_index(pubkey)
.ok_or_else(|| BeaconBlockNodeError::RemoteFailure("pubkey unknown.".to_string()))?;
self.beacon_chain
.proposer_slots(validator_index)
.ok_or_else(|| {
BeaconBlockNodeError::RemoteFailure("validator_index unknown.".to_string())
})
}
/// Requests a new `BeaconBlock from the `BeaconChain`.
fn produce_beacon_block(
&self,
slot: u64,
slot: Slot,
randao_reveal: &Signature,
) -> Result<Option<BeaconBlock>, BeaconBlockNodeError> {
let (block, _state) = self
.beacon_chain
.produce_block(randao_reveal.clone())
.ok_or_else(|| {
BeaconBlockNodeError::RemoteFailure(format!("Did not produce block."))
BeaconBlockNodeError::RemoteFailure("Did not produce block.".to_string())
})?;
if block.slot == slot {

View File

@@ -9,7 +9,7 @@ use db::ClientDB;
use fork_choice::ForkChoice;
use slot_clock::SlotClock;
use std::sync::Arc;
use types::PublicKey;
use types::{PublicKey, Slot};
/// Connects directly to a borrowed `BeaconChain` and reads attester/proposer duties directly from
/// it.
@@ -28,7 +28,7 @@ impl<T: ClientDB, U: SlotClock, F: ForkChoice> DirectDuties<T, U, F> {
}
impl<T: ClientDB, U: SlotClock, F: ForkChoice> ProducerDutiesReader for DirectDuties<T, U, F> {
fn is_block_production_slot(&self, slot: u64) -> Result<bool, ProducerDutiesReaderError> {
fn is_block_production_slot(&self, slot: Slot) -> Result<bool, ProducerDutiesReaderError> {
let validator_index = self
.beacon_chain
.validator_index(&self.pubkey)
@@ -50,7 +50,7 @@ impl<T: ClientDB, U: SlotClock, F: ForkChoice> AttesterDutiesReader for DirectDu
}
}
fn attestation_shard(&self, slot: u64) -> Result<Option<u64>, AttesterDutiesReaderError> {
fn attestation_shard(&self, slot: Slot) -> Result<Option<u64>, AttesterDutiesReaderError> {
if let Some(validator_index) = self.validator_index() {
match self
.beacon_chain
@@ -61,7 +61,7 @@ impl<T: ClientDB, U: SlotClock, F: ForkChoice> AttesterDutiesReader for DirectDu
}
Ok(Some(_)) => Ok(None),
Ok(None) => Err(AttesterDutiesReaderError::UnknownEpoch),
Err(_) => panic!("Error when getting validator attestation shard."),
Err(_) => unreachable!("Error when getting validator attestation shard."),
}
} else {
Err(AttesterDutiesReaderError::UnknownValidator)

View File

@@ -4,12 +4,12 @@ use std::sync::RwLock;
use types::{Keypair, Signature};
/// A test-only struct used to perform signing for a proposer or attester.
pub struct TestSigner {
pub struct LocalSigner {
keypair: Keypair,
should_sign: RwLock<bool>,
}
impl TestSigner {
impl LocalSigner {
/// Produce a new TestSigner with signing enabled by default.
pub fn new(keypair: Keypair) -> Self {
Self {
@@ -30,7 +30,7 @@ impl TestSigner {
}
}
impl BlockProposerSigner for TestSigner {
impl BlockProposerSigner for LocalSigner {
fn sign_block_proposal(&self, message: &[u8]) -> Option<Signature> {
self.bls_sign(message)
}
@@ -40,7 +40,7 @@ impl BlockProposerSigner for TestSigner {
}
}
impl AttesterSigner for TestSigner {
impl AttesterSigner for LocalSigner {
fn sign_attestation_message(&self, message: &[u8]) -> Option<Signature> {
self.bls_sign(message)
}

View File

@@ -1,16 +1,20 @@
use super::direct_beacon_node::DirectBeaconNode;
use super::direct_duties::DirectDuties;
use super::signer::TestSigner;
mod direct_beacon_node;
mod direct_duties;
mod local_signer;
use attester::PollOutcome as AttestationPollOutcome;
use attester::{Attester, Error as AttestationPollError};
use beacon_chain::BeaconChain;
use block_producer::PollOutcome as BlockPollOutcome;
use block_producer::{BlockProducer, Error as BlockPollError};
use db::MemoryDB;
use direct_beacon_node::DirectBeaconNode;
use direct_duties::DirectDuties;
use fork_choice::{optimised_lmd_ghost::OptimisedLMDGhost, slow_lmd_ghost::SlowLMDGhost};
use local_signer::LocalSigner;
use slot_clock::TestingSlotClock;
use std::sync::Arc;
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair};
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Slot};
#[derive(Debug, PartialEq)]
pub enum BlockProduceError {
@@ -29,29 +33,29 @@ pub enum AttestationProduceError {
/// The test validator connects directly to a borrowed `BeaconChain` struct. It is useful for
/// testing that the core proposer and attester logic is functioning. Also for supporting beacon
/// chain tests.
pub struct TestValidator {
pub struct ValidatorHarness {
pub block_producer: BlockProducer<
TestingSlotClock,
DirectBeaconNode<MemoryDB, TestingSlotClock, OptimisedLMDGhost<MemoryDB>>,
DirectDuties<MemoryDB, TestingSlotClock, OptimisedLMDGhost<MemoryDB>>,
TestSigner,
LocalSigner,
>,
pub attester: Attester<
TestingSlotClock,
DirectBeaconNode<MemoryDB, TestingSlotClock, OptimisedLMDGhost<MemoryDB>>,
DirectDuties<MemoryDB, TestingSlotClock, OptimisedLMDGhost<MemoryDB>>,
TestSigner,
LocalSigner,
>,
pub spec: Arc<ChainSpec>,
pub epoch_map: Arc<DirectDuties<MemoryDB, TestingSlotClock, OptimisedLMDGhost<MemoryDB>>>,
pub keypair: Keypair,
pub beacon_node: Arc<DirectBeaconNode<MemoryDB, TestingSlotClock, OptimisedLMDGhost<MemoryDB>>>,
pub slot_clock: Arc<TestingSlotClock>,
pub signer: Arc<TestSigner>,
pub signer: Arc<LocalSigner>,
}
impl TestValidator {
/// Create a new TestValidator that signs with the given keypair, operates per the given spec and connects to the
impl ValidatorHarness {
/// Create a new ValidatorHarness that signs with the given keypair, operates per the given spec and connects to the
/// supplied beacon node.
///
/// A `BlockProducer` and `Attester` is created..
@@ -60,14 +64,13 @@ impl TestValidator {
beacon_chain: Arc<BeaconChain<MemoryDB, TestingSlotClock, OptimisedLMDGhost<MemoryDB>>>,
spec: Arc<ChainSpec>,
) -> Self {
let slot_clock = Arc::new(TestingSlotClock::new(spec.genesis_slot));
let signer = Arc::new(TestSigner::new(keypair.clone()));
let slot_clock = Arc::new(TestingSlotClock::new(spec.genesis_slot.as_u64()));
let signer = Arc::new(LocalSigner::new(keypair.clone()));
let beacon_node = Arc::new(DirectBeaconNode::new(beacon_chain.clone()));
let epoch_map = Arc::new(DirectDuties::new(keypair.pk.clone(), beacon_chain.clone()));
let block_producer = BlockProducer::new(
spec.clone(),
keypair.pk.clone(),
epoch_map.clone(),
slot_clock.clone(),
beacon_node.clone(),
@@ -128,7 +131,7 @@ impl TestValidator {
/// Set the validators slot clock to the specified slot.
///
/// The validators slot clock will always read this value until it is set to something else.
pub fn set_slot(&mut self, slot: u64) {
self.slot_clock.set_slot(slot)
pub fn set_slot(&mut self, slot: Slot) {
self.slot_clock.set_slot(slot.as_u64())
}
}

View File

@@ -1,13 +1,13 @@
use env_logger::{Builder, Env};
use log::debug;
use test_harness::BeaconChainHarness;
use types::ChainSpec;
use types::{ChainSpec, Slot};
#[test]
#[ignore]
fn it_can_build_on_genesis_block() {
let mut spec = ChainSpec::foundation();
spec.genesis_slot = spec.epoch_length * 8;
spec.genesis_slot = Slot::new(spec.epoch_length * 8);
/*
spec.shard_count = spec.shard_count / 8;

View File

@@ -2,7 +2,7 @@ use super::BLOCKS_DB_COLUMN as DB_COLUMN;
use super::{ClientDB, DBError};
use ssz::Decodable;
use std::sync::Arc;
use types::{readers::BeaconBlockReader, BeaconBlock, Hash256};
use types::{readers::BeaconBlockReader, BeaconBlock, Hash256, Slot};
#[derive(Clone, Debug, PartialEq)]
pub enum BeaconBlockAtSlotError {
@@ -71,7 +71,7 @@ impl<T: ClientDB> BeaconBlockStore<T> {
pub fn block_at_slot(
&self,
head_hash: &Hash256,
slot: u64,
slot: Slot,
) -> Result<Option<(Hash256, impl BeaconBlockReader)>, BeaconBlockAtSlotError> {
let mut current_hash = *head_hash;
@@ -119,12 +119,12 @@ mod tests {
let mut rng = XorShiftRng::from_seed([42; 16]);
let mut block = BeaconBlock::random_for_test(&mut rng);
block.slot = 10;
block.slot = Slot::from(10_u64);
let block_root = block.canonical_root();
bs.put(&block_root, &ssz_encode(&block)).unwrap();
let result = bs.block_at_slot(&block_root, 11).unwrap();
let result = bs.block_at_slot(&block_root, Slot::from(11_u64)).unwrap();
assert_eq!(result, None);
}
@@ -138,7 +138,7 @@ mod tests {
db.put(DB_COLUMN, hash, ssz).unwrap();
assert_eq!(
store.block_at_slot(hash, 42),
store.block_at_slot(hash, Slot::from(42_u64)),
Err(BeaconBlockAtSlotError::DBError(
"Bad BeaconBlock SSZ.".into()
))
@@ -156,7 +156,7 @@ mod tests {
db.put(DB_COLUMN, hash, ssz).unwrap();
assert_eq!(
store.block_at_slot(other_hash, 42),
store.block_at_slot(other_hash, Slot::from(42_u64)),
Err(BeaconBlockAtSlotError::UnknownBeaconBlock(*other_hash))
);
}
@@ -221,7 +221,7 @@ mod tests {
Hash256::from(&[2; 32][..]),
Hash256::from(&[3; 32][..]),
];
let slots = [0, 1, 3, 4, 5];
let slots: Vec<Slot> = vec![0, 1, 3, 4, 5].iter().map(|x| Slot::new(*x)).collect();
// Generate a vec of random blocks and store them in the DB.
let block_count = 5;
@@ -249,14 +249,14 @@ mod tests {
assert_eq!(reader.slot(), slots[slot_index]);
}
let ssz = bs.block_at_slot(&hashes[4], 2).unwrap();
let ssz = bs.block_at_slot(&hashes[4], Slot::new(2)).unwrap();
assert_eq!(ssz, None);
let ssz = bs.block_at_slot(&hashes[4], 6).unwrap();
let ssz = bs.block_at_slot(&hashes[4], Slot::new(6)).unwrap();
assert_eq!(ssz, None);
let bad_hash = &Hash256::from("unknown".as_bytes());
let ssz = bs.block_at_slot(bad_hash, 2);
let ssz = bs.block_at_slot(bad_hash, Slot::new(2));
assert_eq!(
ssz,
Err(BeaconBlockAtSlotError::UnknownBeaconBlock(*bad_hash))

View File

@@ -8,6 +8,7 @@ use std::path::PathBuf;
use crate::config::LighthouseConfig;
use crate::rpc::start_server;
use beacon_chain::BeaconChain;
use bls::create_proof_of_possession;
use clap::{App, Arg};
use db::{
stores::{BeaconBlockStore, BeaconStateStore},
@@ -17,7 +18,7 @@ use fork_choice::optimised_lmd_ghost::OptimisedLMDGhost;
use slog::{error, info, o, Drain};
use slot_clock::SystemTimeSlotClock;
use std::sync::Arc;
use types::ChainSpec;
use types::{ChainSpec, Deposit, DepositData, DepositInput, Eth1Data, Hash256, Keypair};
fn main() {
let decorator = slog_term::TermDecorator::new().build();
@@ -76,17 +77,51 @@ fn main() {
let state_store = Arc::new(BeaconStateStore::new(db.clone()));
// Slot clock
let slot_clock = SystemTimeSlotClock::new(spec.genesis_time, spec.slot_duration)
let genesis_time = 1_549_935_547; // 12th Feb 2018 (arbitrary value in the past).
let slot_clock = SystemTimeSlotClock::new(genesis_time, spec.slot_duration)
.expect("Unable to load SystemTimeSlotClock");
// Choose the fork choice
let fork_choice = OptimisedLMDGhost::new(block_store.clone(), state_store.clone());
/*
* Generate some random data to start a chain with.
*
* This is will need to be replace for production usage.
*/
let latest_eth1_data = Eth1Data {
deposit_root: Hash256::zero(),
block_hash: Hash256::zero(),
};
let keypairs: Vec<Keypair> = (0..10)
.collect::<Vec<usize>>()
.iter()
.map(|_| Keypair::random())
.collect();
let initial_validator_deposits = keypairs
.iter()
.map(|keypair| Deposit {
branch: vec![], // branch verification is not specified.
index: 0, // index verification is not specified.
deposit_data: DepositData {
amount: 32_000_000_000, // 32 ETH (in Gwei)
timestamp: genesis_time - 1,
deposit_input: DepositInput {
pubkey: keypair.pk.clone(),
withdrawal_credentials: Hash256::zero(), // Withdrawal not possible.
proof_of_possession: create_proof_of_possession(&keypair),
},
},
})
.collect();
// Genesis chain
// TODO: persist chain to storage.
let _chain_result = BeaconChain::genesis(
state_store.clone(),
block_store.clone(),
slot_clock,
genesis_time,
latest_eth1_data,
initial_validator_deposits,
spec,
fork_choice,
);

View File

@@ -25,7 +25,7 @@ impl BeaconBlockService for BeaconBlockServiceInstance {
// TODO: build a legit block.
let mut block = BeaconBlockProto::new();
block.set_slot(req.get_slot());
block.set_block_root("cats".as_bytes().to_vec());
block.set_block_root(b"cats".to_vec());
let mut resp = ProduceBeaconBlockResponse::new();
resp.set_block(block);