lighthouse/beacon_node/beacon_chain/src/block_production.rs

124 lines
3.7 KiB
Rust
Raw Normal View History

use super::state_transition::Error as TransitionError;
2018-12-30 01:59:24 +00:00
use super::{BeaconChain, ClientDB, DBError, SlotClock};
use bls::Signature;
use log::debug;
2018-12-30 01:59:24 +00:00
use slot_clock::TestingSlotClockError;
use types::{
2019-01-30 21:49:50 +00:00
beacon_state::CommitteesError,
2018-12-30 01:59:24 +00:00
readers::{BeaconBlockReader, BeaconStateReader},
2019-01-24 01:10:03 +00:00
BeaconBlock, BeaconBlockBody, BeaconState, Eth1Data, Hash256,
2018-12-30 01:59:24 +00:00
};
#[derive(Debug, PartialEq)]
pub enum Error {
DBError(String),
StateTransitionError(TransitionError),
2018-12-30 01:59:24 +00:00
PresentSlotIsNone,
2019-01-30 21:49:50 +00:00
CommitteesError(CommitteesError),
2018-12-30 01:59:24 +00:00
}
impl<T, U> BeaconChain<T, U>
where
T: ClientDB,
U: SlotClock,
{
pub fn produce_block(
2019-01-24 06:05:48 +00:00
&self,
randao_reveal: Signature,
2019-01-24 06:05:48 +00:00
) -> Result<(BeaconBlock, BeaconState), Error>
where
Error: From<<U>::Error>,
{
// TODO: allow producing a block from a previous (or future?) slot.
2018-12-30 01:59:24 +00:00
let present_slot = self
.slot_clock
2019-01-24 06:05:48 +00:00
.present_slot()
.map_err(|e| e.into())?
2018-12-30 01:59:24 +00:00
.ok_or(Error::PresentSlotIsNone)?;
debug!("Producing block for slot {}...", present_slot);
let parent_root = self.head().beacon_block_root;
2019-01-04 07:30:24 +00:00
let parent_block_reader = self
2018-12-30 01:59:24 +00:00
.block_store
2019-01-04 07:30:24 +00:00
.get_reader(&parent_root)?
.ok_or_else(|| Error::DBError("Block not found.".to_string()))?;
let parent_state = self
2018-12-30 01:59:24 +00:00
.state_store
2019-01-04 07:30:24 +00:00
.get_reader(&parent_block_reader.state_root())?
.ok_or_else(|| Error::DBError("State not found.".to_string()))?
.into_beacon_state()
.ok_or_else(|| Error::DBError("State invalid.".to_string()))?;
2018-12-30 01:59:24 +00:00
debug!("Finding attesatations for block...");
2019-01-30 21:49:50 +00:00
let attestations = {
let mut next_state = parent_state.clone();
next_state.per_slot_processing(Hash256::zero(), &self.spec)?;
self.attestation_aggregator
.read()
.unwrap()
.get_attestations_for_state(&next_state, &self.spec)
};
debug!("Found {} attestation(s).", attestations.len());
2018-12-30 01:59:24 +00:00
let mut block = BeaconBlock {
slot: present_slot,
2019-01-24 06:05:48 +00:00
parent_root: parent_root.clone(),
2018-12-30 01:59:24 +00:00
state_root: Hash256::zero(), // Updated after the state is calculated.
randao_reveal: randao_reveal,
2019-01-24 01:10:03 +00:00
eth1_data: Eth1Data {
// TODO: replace with real data
deposit_root: Hash256::zero(),
block_hash: Hash256::zero(),
},
signature: self.spec.empty_signature.clone(), // To be completed by a validator.
body: BeaconBlockBody {
proposer_slashings: vec![],
casper_slashings: vec![],
attestations: attestations,
custody_reseeds: vec![],
custody_challenges: vec![],
custody_responses: vec![],
deposits: vec![],
exits: vec![],
},
2018-12-30 01:59:24 +00:00
};
2019-01-25 05:47:24 +00:00
let state =
self.state_transition_without_verifying_block_signature(parent_state, &block)?;
2018-12-30 01:59:24 +00:00
let state_root = state.canonical_root();
block.state_root = state_root;
debug!("Block produced.");
2018-12-30 01:59:24 +00:00
Ok((block, state))
}
}
impl From<DBError> for Error {
fn from(e: DBError) -> Error {
Error::DBError(e.message)
}
}
impl From<TransitionError> for Error {
fn from(e: TransitionError) -> Error {
Error::StateTransitionError(e)
}
}
2018-12-30 01:59:24 +00:00
impl From<TestingSlotClockError> for Error {
fn from(_: TestingSlotClockError) -> Error {
unreachable!(); // Testing clock never throws an error.
}
}
2019-01-30 21:49:50 +00:00
impl From<CommitteesError> for Error {
fn from(e: CommitteesError) -> Error {
Error::CommitteesError(e)
}
}