2019-01-23 08:25:05 +00:00
|
|
|
use super::state_transition::Error as TransitionError;
|
2018-12-30 01:59:24 +00:00
|
|
|
use super::{BeaconChain, ClientDB, DBError, SlotClock};
|
2019-01-23 08:25:05 +00:00
|
|
|
use bls::Signature;
|
2019-01-30 13:39:34 +00:00
|
|
|
use log::debug;
|
2018-12-30 01:59:24 +00:00
|
|
|
use slot_clock::TestingSlotClockError;
|
|
|
|
use types::{
|
2019-01-31 05:39:44 +00:00
|
|
|
beacon_state::SlotProcessingError,
|
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),
|
2019-01-23 08:25:05 +00:00
|
|
|
StateTransitionError(TransitionError),
|
2018-12-30 01:59:24 +00:00
|
|
|
PresentSlotIsNone,
|
2019-01-31 05:39:44 +00:00
|
|
|
SlotProcessingError(SlotProcessingError),
|
2018-12-30 01:59:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, U> BeaconChain<T, U>
|
|
|
|
where
|
|
|
|
T: ClientDB,
|
|
|
|
U: SlotClock,
|
|
|
|
{
|
2019-01-23 08:25:05 +00:00
|
|
|
pub fn produce_block(
|
2019-01-24 06:05:48 +00:00
|
|
|
&self,
|
2019-01-23 08:25:05 +00:00
|
|
|
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)?;
|
2019-01-23 08:25:05 +00:00
|
|
|
|
2019-01-30 13:39:34 +00:00
|
|
|
debug!("Producing block for slot {}...", present_slot);
|
|
|
|
|
2019-01-28 01:58:20 +00:00
|
|
|
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()))?;
|
2019-01-23 08:25:05 +00:00
|
|
|
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())?
|
2019-01-23 08:25:05 +00:00
|
|
|
.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
|
|
|
|
2019-01-30 13:39:34 +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)
|
|
|
|
};
|
2019-01-28 06:07:13 +00:00
|
|
|
|
2019-01-30 13:39:34 +00:00
|
|
|
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.
|
2019-01-23 08:25:05 +00:00
|
|
|
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(),
|
|
|
|
},
|
2019-01-23 08:25:05 +00:00
|
|
|
signature: self.spec.empty_signature.clone(), // To be completed by a validator.
|
|
|
|
body: BeaconBlockBody {
|
|
|
|
proposer_slashings: vec![],
|
|
|
|
casper_slashings: vec![],
|
2019-01-28 06:07:13 +00:00
|
|
|
attestations: attestations,
|
2019-01-23 08:25:05 +00:00
|
|
|
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;
|
|
|
|
|
2019-01-30 13:39:34 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-23 08:25:05 +00:00
|
|
|
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
|
|
|
|
2019-01-31 05:39:44 +00:00
|
|
|
impl From<SlotProcessingError> for Error {
|
|
|
|
fn from(e: SlotProcessingError) -> Error {
|
|
|
|
Error::SlotProcessingError(e)
|
2019-01-30 21:49:50 +00:00
|
|
|
}
|
|
|
|
}
|