mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-16 20:39:10 +00:00
Refine state transition to allow first transition
This commit is contained in:
@@ -13,6 +13,8 @@ failure = "0.1"
|
||||
failure_derive = "0.1"
|
||||
genesis = { path = "../../eth2/genesis" }
|
||||
hashing = { path = "../../eth2/utils/hashing" }
|
||||
log = "0.4"
|
||||
env_logger = "0.6"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
||||
@@ -96,7 +96,9 @@ impl AttestationAggregator {
|
||||
self.store
|
||||
.values()
|
||||
.filter_map(|attestation| {
|
||||
if state.validate_attestation(attestation, spec).is_ok()
|
||||
if state
|
||||
.validate_attestation_without_signature(attestation, spec)
|
||||
.is_ok()
|
||||
&& !known_attestation_data.contains(&attestation.data)
|
||||
{
|
||||
Some(attestation.clone())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use super::state_transition::Error as TransitionError;
|
||||
use super::{BeaconChain, ClientDB, DBError, SlotClock};
|
||||
use log::debug;
|
||||
use slot_clock::{SystemTimeSlotClockError, TestingSlotClockError};
|
||||
use ssz::{ssz_encode, Encodable};
|
||||
use types::{
|
||||
@@ -65,6 +66,8 @@ where
|
||||
where
|
||||
V: BeaconBlockReader + Encodable + Sized,
|
||||
{
|
||||
debug!("Processing block with slot {}...", block.slot());
|
||||
|
||||
let block = block
|
||||
.into_beacon_block()
|
||||
.ok_or(Error::UnableToDecodeBlock)?;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::state_transition::Error as TransitionError;
|
||||
use super::{BeaconChain, ClientDB, DBError, SlotClock};
|
||||
use bls::Signature;
|
||||
use log::debug;
|
||||
use slot_clock::TestingSlotClockError;
|
||||
use types::{
|
||||
readers::{BeaconBlockReader, BeaconStateReader},
|
||||
@@ -33,6 +34,8 @@ where
|
||||
.map_err(|e| e.into())?
|
||||
.ok_or(Error::PresentSlotIsNone)?;
|
||||
|
||||
debug!("Producing block for slot {}...", present_slot);
|
||||
|
||||
let parent_root = self.head().beacon_block_root;
|
||||
let parent_block_reader = self
|
||||
.block_store
|
||||
@@ -45,6 +48,8 @@ where
|
||||
.into_beacon_state()
|
||||
.ok_or_else(|| Error::DBError("State invalid.".to_string()))?;
|
||||
|
||||
debug!("Finding attesatations for block...");
|
||||
|
||||
let attestations = self
|
||||
.attestation_aggregator
|
||||
.read()
|
||||
@@ -52,6 +57,8 @@ where
|
||||
// TODO: advance the parent_state slot.
|
||||
.get_attestations_for_state(&parent_state, &self.spec);
|
||||
|
||||
debug!("Found {} attestation(s).", attestations.len());
|
||||
|
||||
let mut block = BeaconBlock {
|
||||
slot: present_slot,
|
||||
parent_root: parent_root.clone(),
|
||||
@@ -81,6 +88,8 @@ where
|
||||
|
||||
block.state_root = state_root;
|
||||
|
||||
debug!("Block produced.");
|
||||
|
||||
Ok((block, state))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::{BeaconChain, CheckPoint, ClientDB, SlotClock};
|
||||
use std::sync::RwLockReadGuard;
|
||||
use types::{beacon_state::SlotProcessingError, BeaconBlock, BeaconState, Hash256};
|
||||
use types::{beacon_state::CommitteesError, BeaconBlock, BeaconState, Hash256};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
PastSlot,
|
||||
UnableToDetermineProducer,
|
||||
CommitteesError(CommitteesError),
|
||||
}
|
||||
|
||||
impl<T, U> BeaconChain<T, U>
|
||||
@@ -64,10 +64,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SlotProcessingError> for Error {
|
||||
fn from(e: SlotProcessingError) -> Error {
|
||||
match e {
|
||||
SlotProcessingError::UnableToDetermineProducer => Error::UnableToDetermineProducer,
|
||||
}
|
||||
impl From<CommitteesError> for Error {
|
||||
fn from(e: CommitteesError) -> Error {
|
||||
Error::CommitteesError(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
use super::{BeaconChain, ClientDB, DBError, SlotClock};
|
||||
|
||||
impl<T, U> BeaconChain<T, U>
|
||||
where
|
||||
T: ClientDB,
|
||||
U: SlotClock,
|
||||
{
|
||||
pub fn per_epoch_processing(&self) {}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
use super::{BeaconChain, ClientDB, SlotClock};
|
||||
use types::{beacon_state::Error as BeaconStateError, PublicKey};
|
||||
use types::{beacon_state::CommitteesError, PublicKey};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
SlotClockError,
|
||||
BeaconStateError(BeaconStateError),
|
||||
CommitteesError(CommitteesError),
|
||||
}
|
||||
|
||||
impl<T, U> BeaconChain<T, U>
|
||||
@@ -45,7 +45,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block_proposer(&self, slot: u64) -> Result<usize, Error> {
|
||||
pub fn block_proposer(&self, slot: u64) -> Result<usize, CommitteesError> {
|
||||
// TODO: fix unwrap
|
||||
let present_slot = self.present_slot().unwrap();
|
||||
// TODO: fix unwrap
|
||||
@@ -67,12 +67,14 @@ where
|
||||
let present_slot = self.present_slot()?;
|
||||
let state = self.state(present_slot).ok()?;
|
||||
|
||||
Some(state.attestation_slot_and_shard_for_validator(validator_index, &self.spec))
|
||||
state
|
||||
.attestation_slot_and_shard_for_validator(validator_index, &self.spec)
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BeaconStateError> for Error {
|
||||
fn from(e: BeaconStateError) -> Error {
|
||||
Error::BeaconStateError(e)
|
||||
impl From<CommitteesError> for Error {
|
||||
fn from(e: CommitteesError) -> Error {
|
||||
Error::CommitteesError(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ pub mod block_processing;
|
||||
pub mod block_production;
|
||||
mod canonical_head;
|
||||
pub mod dump;
|
||||
pub mod epoch_processing;
|
||||
mod finalized_head;
|
||||
mod info;
|
||||
mod lmd_ghost;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use super::{BeaconChain, ClientDB, DBError, SlotClock};
|
||||
use bls::{PublicKey, Signature};
|
||||
use boolean_bitfield::BooleanBitfield;
|
||||
use hashing::hash;
|
||||
use log::debug;
|
||||
use slot_clock::{SystemTimeSlotClockError, TestingSlotClockError};
|
||||
use ssz::{ssz_encode, TreeHash};
|
||||
use types::{
|
||||
beacon_state::{AttestationValidationError, SlotProcessingError},
|
||||
beacon_state::{AttestationValidationError, CommitteesError, EpochProcessingError},
|
||||
readers::BeaconBlockReader,
|
||||
AttestationData, BeaconBlock, BeaconState, Exit, Fork, Hash256, PendingAttestation,
|
||||
BeaconBlock, BeaconState, Exit, Fork, Hash256, PendingAttestation,
|
||||
};
|
||||
|
||||
// TODO: define elsehwere.
|
||||
@@ -51,6 +51,8 @@ pub enum Error {
|
||||
BadCustodyChallenges,
|
||||
BadCustodyResponses,
|
||||
SlotClockError(SystemTimeSlotClockError),
|
||||
CommitteesError(CommitteesError),
|
||||
EpochProcessingError(EpochProcessingError),
|
||||
}
|
||||
|
||||
impl<T, U> BeaconChain<T, U>
|
||||
@@ -82,6 +84,11 @@ where
|
||||
) -> Result<BeaconState, Error> {
|
||||
ensure!(state.slot < block.slot, Error::StateAlreadyTransitioned);
|
||||
|
||||
debug!(
|
||||
"Starting state transition from slot {} to {}...",
|
||||
state.slot, block.slot
|
||||
);
|
||||
|
||||
for _ in state.slot..block.slot {
|
||||
state.per_slot_processing(block.parent_root.clone(), &self.spec)?;
|
||||
}
|
||||
@@ -113,6 +120,8 @@ where
|
||||
);
|
||||
}
|
||||
|
||||
debug!("Block signature is valid.");
|
||||
|
||||
/*
|
||||
* RANDAO
|
||||
*/
|
||||
@@ -127,6 +136,8 @@ where
|
||||
Error::BadRandaoSignature
|
||||
);
|
||||
|
||||
debug!("RANDAO signature is valid.");
|
||||
|
||||
// TODO: check this is correct.
|
||||
let new_mix = {
|
||||
let mut mix = state.latest_randao_mixes
|
||||
@@ -228,6 +239,11 @@ where
|
||||
state.latest_attestations.push(pending_attestation);
|
||||
}
|
||||
|
||||
debug!(
|
||||
"{} attestations verified & processed.",
|
||||
block.body.attestations.len()
|
||||
);
|
||||
|
||||
/*
|
||||
* Deposits
|
||||
*/
|
||||
@@ -294,9 +310,11 @@ where
|
||||
);
|
||||
|
||||
if state.slot % self.spec.epoch_length == 0 {
|
||||
state.per_epoch_processing(&self.spec).unwrap();
|
||||
state.per_epoch_processing(&self.spec)?;
|
||||
}
|
||||
|
||||
debug!("State transition complete.");
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
}
|
||||
@@ -337,16 +355,20 @@ impl From<SystemTimeSlotClockError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SlotProcessingError> for Error {
|
||||
fn from(e: SlotProcessingError) -> Error {
|
||||
match e {
|
||||
SlotProcessingError::UnableToDetermineProducer => Error::NoBlockProducer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AttestationValidationError> for Error {
|
||||
fn from(e: AttestationValidationError) -> Error {
|
||||
Error::InvalidAttestation(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CommitteesError> for Error {
|
||||
fn from(e: CommitteesError) -> Error {
|
||||
Error::CommitteesError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EpochProcessingError> for Error {
|
||||
fn from(e: EpochProcessingError) -> Error {
|
||||
Error::EpochProcessingError(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ failure = "0.1"
|
||||
failure_derive = "0.1"
|
||||
genesis = { path = "../../../eth2/genesis" }
|
||||
hashing = { path = "../../../eth2/utils/hashing" }
|
||||
log = "0.4"
|
||||
env_logger = "0.6.0"
|
||||
rayon = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
||||
@@ -5,6 +5,8 @@ use db::{
|
||||
stores::{BeaconBlockStore, BeaconStateStore},
|
||||
MemoryDB,
|
||||
};
|
||||
use log::debug;
|
||||
use rayon::prelude::*;
|
||||
use slot_clock::TestingSlotClock;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
@@ -26,26 +28,40 @@ impl BeaconChainHarness {
|
||||
let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
|
||||
let state_store = Arc::new(BeaconStateStore::new(db.clone()));
|
||||
|
||||
let slot_clock = TestingSlotClock::new(0);
|
||||
let slot_clock = TestingSlotClock::new(spec.genesis_slot);
|
||||
|
||||
// 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);
|
||||
|
||||
// Insert `validator_count` new `Validator` records into the spec, retaining the keypairs
|
||||
// for later user.
|
||||
let mut keypairs = Vec::with_capacity(validator_count);
|
||||
for _ in 0..validator_count {
|
||||
let keypair = Keypair::random();
|
||||
debug!("Generating validator keypairs...");
|
||||
|
||||
spec.initial_validators.push(Validator {
|
||||
let keypairs: Vec<Keypair> = (0..validator_count)
|
||||
.collect::<Vec<usize>>()
|
||||
.par_iter()
|
||||
.map(|_| Keypair::random())
|
||||
.collect();
|
||||
|
||||
debug!("Creating validator records...");
|
||||
|
||||
spec.initial_validators = keypairs
|
||||
.par_iter()
|
||||
.map(|keypair| Validator {
|
||||
pubkey: keypair.pk.clone(),
|
||||
activation_slot: 0,
|
||||
..std::default::Default::default()
|
||||
});
|
||||
spec.initial_balances.push(32_000_000_000); // 32 ETH
|
||||
})
|
||||
.collect();
|
||||
|
||||
keypairs.push(keypair);
|
||||
}
|
||||
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
|
||||
let beacon_chain = Arc::new(
|
||||
@@ -58,11 +74,15 @@ impl BeaconChainHarness {
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
debug!("Creating validator producer and attester instances...");
|
||||
|
||||
// Spawn the test validator instances.
|
||||
let mut validators = Vec::with_capacity(validator_count);
|
||||
for keypair in keypairs {
|
||||
validators.push(TestValidator::new(keypair.clone(), beacon_chain.clone()));
|
||||
}
|
||||
let validators: Vec<TestValidator> = keypairs
|
||||
.par_iter()
|
||||
.map(|keypair| TestValidator::new(keypair.clone(), beacon_chain.clone(), &spec))
|
||||
.collect();
|
||||
|
||||
debug!("Created {} TestValidators", validators.len());
|
||||
|
||||
Self {
|
||||
db,
|
||||
@@ -83,6 +103,9 @@ impl BeaconChainHarness {
|
||||
.present_slot()
|
||||
.expect("Unable to determine slot.")
|
||||
+ 1;
|
||||
|
||||
debug!("Incrementing BeaconChain slot to {}.", slot);
|
||||
|
||||
self.beacon_chain.slot_clock.set_slot(slot);
|
||||
}
|
||||
|
||||
@@ -93,16 +116,24 @@ impl BeaconChainHarness {
|
||||
pub fn gather_free_attesations(&mut self) -> Vec<FreeAttestation> {
|
||||
let present_slot = self.beacon_chain.present_slot().unwrap();
|
||||
|
||||
let mut free_attestations = vec![];
|
||||
for validator in &mut self.validators {
|
||||
// Advance the validator slot.
|
||||
validator.set_slot(present_slot);
|
||||
let free_attestations: Vec<FreeAttestation> = self
|
||||
.validators
|
||||
.par_iter_mut()
|
||||
.filter_map(|validator| {
|
||||
// Advance the validator slot.
|
||||
validator.set_slot(present_slot);
|
||||
|
||||
// Prompt the validator to produce an attestation (if required).
|
||||
validator.produce_free_attestation().ok()
|
||||
})
|
||||
.collect();
|
||||
|
||||
debug!(
|
||||
"Gathered {} FreeAttestations for slot {}.",
|
||||
free_attestations.len(),
|
||||
present_slot
|
||||
);
|
||||
|
||||
// Prompt the validator to produce an attestation (if required).
|
||||
if let Ok(free_attestation) = validator.produce_free_attestation() {
|
||||
free_attestations.push(free_attestation);
|
||||
}
|
||||
}
|
||||
free_attestations
|
||||
}
|
||||
|
||||
@@ -115,6 +146,11 @@ impl BeaconChainHarness {
|
||||
|
||||
let proposer = self.beacon_chain.block_proposer(present_slot).unwrap();
|
||||
|
||||
debug!(
|
||||
"Producing block from validator #{} for slot {}.",
|
||||
proposer, present_slot
|
||||
);
|
||||
|
||||
self.validators[proposer].produce_block().unwrap()
|
||||
}
|
||||
|
||||
@@ -131,7 +167,9 @@ impl BeaconChainHarness {
|
||||
.unwrap();
|
||||
}
|
||||
let block = self.produce_block();
|
||||
debug!("Submitting block for processing...");
|
||||
self.beacon_chain.process_block(block).unwrap();
|
||||
debug!("...block processed by BeaconChain.");
|
||||
}
|
||||
|
||||
pub fn chain_dump(&self) -> Result<Vec<SlotDump>, DumpError> {
|
||||
|
||||
@@ -52,9 +52,10 @@ impl TestValidator {
|
||||
pub fn new(
|
||||
keypair: Keypair,
|
||||
beacon_chain: Arc<BeaconChain<MemoryDB, TestingSlotClock>>,
|
||||
spec: &ChainSpec,
|
||||
) -> Self {
|
||||
let spec = Arc::new(ChainSpec::foundation());
|
||||
let slot_clock = Arc::new(TestingSlotClock::new(0));
|
||||
let spec = Arc::new(spec.clone());
|
||||
let slot_clock = Arc::new(TestingSlotClock::new(spec.genesis_slot));
|
||||
let signer = Arc::new(TestSigner::new(keypair.clone()));
|
||||
let beacon_node = Arc::new(BenchingBeaconNode::new(beacon_chain.clone()));
|
||||
let epoch_map = Arc::new(DirectDuties::new(keypair.pk.clone(), beacon_chain.clone()));
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
use env_logger::{Builder, Env};
|
||||
use log::debug;
|
||||
use test_harness::BeaconChainHarness;
|
||||
use types::ChainSpec;
|
||||
|
||||
#[test]
|
||||
fn it_can_build_on_genesis_block() {
|
||||
let validator_count = 10;
|
||||
let spec = ChainSpec::foundation();
|
||||
let mut harness = BeaconChainHarness::new(spec, validator_count);
|
||||
let mut spec = ChainSpec::foundation();
|
||||
spec.genesis_slot = spec.epoch_length * 8;
|
||||
|
||||
/*
|
||||
spec.shard_count = spec.shard_count / 8;
|
||||
spec.target_committee_size = spec.target_committee_size / 8;
|
||||
*/
|
||||
let validator_count = 1000;
|
||||
|
||||
let mut harness = BeaconChainHarness::new(spec, validator_count as usize);
|
||||
|
||||
harness.advance_chain_with_block();
|
||||
}
|
||||
@@ -13,13 +22,21 @@ fn it_can_build_on_genesis_block() {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn it_can_produce_past_first_epoch_boundary() {
|
||||
Builder::from_env(Env::default().default_filter_or("debug")).init();
|
||||
|
||||
let validator_count = 100;
|
||||
|
||||
debug!("Starting harness build...");
|
||||
|
||||
let mut harness = BeaconChainHarness::new(ChainSpec::foundation(), validator_count);
|
||||
|
||||
let blocks = harness.spec.epoch_length + 1;
|
||||
debug!("Harness built, tests starting..");
|
||||
|
||||
for _ in 0..blocks {
|
||||
let blocks = harness.spec.epoch_length * 3 + 1;
|
||||
|
||||
for i in 0..blocks {
|
||||
harness.advance_chain_with_block();
|
||||
debug!("Produced block {}/{}.", i, blocks);
|
||||
}
|
||||
let dump = harness.chain_dump().expect("Chain dump failed.");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user