Refactor block prod. to produce for forks
This commit is contained in:
parent
55196dff64
commit
55818e285a
@ -23,6 +23,12 @@ use store::{Error as DBError, Store};
|
||||
use tree_hash::TreeHash;
|
||||
use types::*;
|
||||
|
||||
// Text included in blocks.
|
||||
// Must be 32-bytes or panic.
|
||||
//
|
||||
// |-------must be this long------|
|
||||
pub const GRAFFITI: &str = "sigp/lighthouse-0.0.0-prerelease";
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum BlockProcessingOutcome {
|
||||
/// Block was valid and imported into the block graph.
|
||||
@ -657,16 +663,41 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
&self,
|
||||
randao_reveal: Signature,
|
||||
) -> Result<(BeaconBlock, BeaconState<T::EthSpec>), BlockProductionError> {
|
||||
debug!("Producing block at slot {}...", self.state.read().slot);
|
||||
let state = self.state.read().clone();
|
||||
let slot = self
|
||||
.read_slot_clock()
|
||||
.ok_or_else(|| BlockProductionError::UnableToReadSlot)?;
|
||||
|
||||
self.produce_block_on_state(state, slot, randao_reveal)
|
||||
}
|
||||
|
||||
/// Produce a block for some `slot` upon the given `state`.
|
||||
///
|
||||
/// Typically the `self.produce_block()` function should be used, instead of calling this
|
||||
/// function directly. This function is useful for purposefully creating forks or blocks at
|
||||
/// non-current slots.
|
||||
///
|
||||
/// The given state will be advanced to the given `produce_at_slot`, then a block will be
|
||||
/// produced at that slot height.
|
||||
pub fn produce_block_on_state(
|
||||
&self,
|
||||
mut state: BeaconState<T::EthSpec>,
|
||||
produce_at_slot: Slot,
|
||||
randao_reveal: Signature,
|
||||
) -> Result<(BeaconBlock, BeaconState<T::EthSpec>), BlockProductionError> {
|
||||
self.metrics.block_production_requests.inc();
|
||||
let timer = self.metrics.block_production_times.start_timer();
|
||||
|
||||
let mut state = self.state.read().clone();
|
||||
// If required, transition the new state to the present slot.
|
||||
for _ in state.slot.as_u64()..produce_at_slot.as_u64() {
|
||||
// Ensure the next epoch state caches are built in case of an epoch transition.
|
||||
state.build_committee_cache(RelativeEpoch::Next, &self.spec)?;
|
||||
|
||||
per_slot_processing(&mut state, &self.spec)?;
|
||||
}
|
||||
|
||||
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
|
||||
|
||||
trace!("Finding attestations for new block...");
|
||||
|
||||
let previous_block_root = if state.slot > 0 {
|
||||
*state
|
||||
.get_block_root(state.slot - 1)
|
||||
@ -675,8 +706,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
state.latest_block_header.canonical_root()
|
||||
};
|
||||
|
||||
let mut graffiti: [u8; 32] = [0; 32];
|
||||
graffiti.copy_from_slice(GRAFFITI.as_bytes());
|
||||
|
||||
let (proposer_slashings, attester_slashings) =
|
||||
self.op_pool.get_slashings(&*self.state.read(), &self.spec);
|
||||
self.op_pool.get_slashings(&state, &self.spec);
|
||||
|
||||
let mut block = BeaconBlock {
|
||||
slot: state.slot,
|
||||
@ -691,8 +725,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
deposit_root: Hash256::zero(),
|
||||
block_hash: Hash256::zero(),
|
||||
},
|
||||
// TODO: badass Lighthouse graffiti
|
||||
graffiti: [0; 32],
|
||||
graffiti,
|
||||
proposer_slashings,
|
||||
attester_slashings,
|
||||
attestations: self
|
||||
|
@ -40,9 +40,12 @@ impl From<MetricsError> for BeaconChainError {
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum BlockProductionError {
|
||||
UnableToGetBlockRootFromState,
|
||||
UnableToReadSlot,
|
||||
SlotProcessingError(SlotProcessingError),
|
||||
BlockProcessingError(BlockProcessingError),
|
||||
BeaconStateError(BeaconStateError),
|
||||
}
|
||||
|
||||
easy_from_to!(BlockProcessingError, BlockProductionError);
|
||||
easy_from_to!(BeaconStateError, BlockProductionError);
|
||||
easy_from_to!(SlotProcessingError, BlockProductionError);
|
||||
|
@ -5,13 +5,20 @@ use slot_clock::TestingSlotClock;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use store::MemoryStore;
|
||||
use store::Store;
|
||||
use tree_hash::{SignedRoot, TreeHash};
|
||||
use types::{
|
||||
test_utils::TestingBeaconStateBuilder, AggregateSignature, Attestation,
|
||||
AttestationDataAndCustodyBit, BeaconBlock, Bitfield, ChainSpec, Domain, EthSpec, Hash256,
|
||||
Keypair, SecretKey, Signature,
|
||||
AttestationDataAndCustodyBit, BeaconBlock, BeaconState, Bitfield, ChainSpec, Domain, EthSpec,
|
||||
Hash256, Keypair, RelativeEpoch, SecretKey, Signature, Slot,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum BuildStrategy {
|
||||
OnCanonicalHead,
|
||||
ForkCanonicalChainAt(Slot),
|
||||
}
|
||||
|
||||
pub struct CommonTypes<L, E>
|
||||
where
|
||||
L: LmdGhost<MemoryStore, E>,
|
||||
@ -82,11 +89,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_canonical_chain(&self) {
|
||||
pub fn extend_chain(&self, build_strategy: BuildStrategy) {
|
||||
self.chain.slot_clock.advance_slot();
|
||||
self.chain.catchup_state().expect("should catchup state");
|
||||
|
||||
let block = self.build_block();
|
||||
let block = self.build_block(build_strategy);
|
||||
let outcome = self
|
||||
.chain
|
||||
.process_block(block)
|
||||
@ -96,18 +103,47 @@ where
|
||||
self.add_attestations_to_op_pool();
|
||||
}
|
||||
|
||||
fn build_block(&self) -> BeaconBlock {
|
||||
let slot = self.chain.read_slot_clock().unwrap();
|
||||
fn get_state(&self, build_strategy: BuildStrategy) -> BeaconState<E> {
|
||||
match build_strategy {
|
||||
BuildStrategy::OnCanonicalHead => self.chain.current_state().clone(),
|
||||
BuildStrategy::ForkCanonicalChainAt(fork_slot) => {
|
||||
let state_root = self
|
||||
.chain
|
||||
.rev_iter_state_roots(self.chain.head().beacon_state.slot - 1)
|
||||
.find(|(_hash, slot)| *slot == fork_slot)
|
||||
.map(|(hash, _slot)| hash)
|
||||
.expect("could not find state root for fork");
|
||||
|
||||
let sk = {
|
||||
let proposer = self
|
||||
.chain
|
||||
.block_proposer(slot)
|
||||
.expect("should get block propoer");
|
||||
&self.keypairs[proposer].sk
|
||||
self.chain
|
||||
.store
|
||||
.get(&state_root)
|
||||
.expect("should read db")
|
||||
.expect("should find state root")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_block(&self, build_strategy: BuildStrategy) -> BeaconBlock {
|
||||
let mut state = self.get_state(build_strategy);
|
||||
state.build_all_caches(&self.spec).unwrap();
|
||||
|
||||
let slot = match build_strategy {
|
||||
BuildStrategy::OnCanonicalHead => self.chain.read_slot_clock().unwrap(),
|
||||
BuildStrategy::ForkCanonicalChainAt(slot) => slot,
|
||||
};
|
||||
|
||||
let fork = &self.chain.head().beacon_state.fork;
|
||||
let proposer_index = match build_strategy {
|
||||
BuildStrategy::OnCanonicalHead => self
|
||||
.chain
|
||||
.block_proposer(slot)
|
||||
.expect("should get block proposer from chain"),
|
||||
_ => state
|
||||
.get_beacon_proposer_index(slot, RelativeEpoch::Current, &self.spec)
|
||||
.expect("should get block proposer from state"),
|
||||
};
|
||||
|
||||
let sk = &self.keypairs[proposer_index].sk;
|
||||
let fork = &state.fork.clone();
|
||||
|
||||
let randao_reveal = {
|
||||
let epoch = slot.epoch(E::slots_per_epoch());
|
||||
@ -118,8 +154,8 @@ where
|
||||
|
||||
let (mut block, _state) = self
|
||||
.chain
|
||||
.produce_block(randao_reveal)
|
||||
.expect("should producer block");
|
||||
.produce_block_on_state(state, slot, randao_reveal)
|
||||
.expect("should produce block");
|
||||
|
||||
block.signature = {
|
||||
let message = block.signed_root();
|
||||
@ -195,7 +231,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(not(debug_assertions))]
|
||||
// #[cfg(not(debug_assertions))]
|
||||
mod test {
|
||||
use super::*;
|
||||
use lmd_ghost::ThreadSafeReducedTree;
|
||||
@ -213,7 +249,7 @@ mod test {
|
||||
> = BeaconChainHarness::new(VALIDATOR_COUNT);
|
||||
|
||||
for _ in 0..num_blocks_produced {
|
||||
harness.extend_canonical_chain();
|
||||
harness.extend_chain(BuildStrategy::OnCanonicalHead);
|
||||
}
|
||||
|
||||
let state = &harness.chain.head().beacon_state;
|
||||
|
@ -182,7 +182,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
|
||||
&& (!self
|
||||
.chain
|
||||
.rev_iter_block_roots(local.best_slot)
|
||||
.any(|root| root == remote.latest_finalized_root))
|
||||
.any(|(root, _slot)| root == remote.latest_finalized_root))
|
||||
&& (local.latest_finalized_root != spec.zero_hash)
|
||||
&& (remote.latest_finalized_root != spec.zero_hash)
|
||||
{
|
||||
@ -266,11 +266,12 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
|
||||
"start_slot" => req.start_slot,
|
||||
);
|
||||
|
||||
let mut roots: Vec<Hash256> = self
|
||||
let mut roots: Vec<BlockRootSlot> = self
|
||||
.chain
|
||||
.rev_iter_block_roots(req.start_slot + req.count)
|
||||
.skip(1)
|
||||
.take(req.count as usize)
|
||||
.map(|(block_root, slot)| BlockRootSlot { slot, block_root })
|
||||
.collect();
|
||||
|
||||
if roots.len() as u64 != req.count {
|
||||
@ -285,16 +286,6 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
|
||||
}
|
||||
|
||||
roots.reverse();
|
||||
|
||||
let mut roots: Vec<BlockRootSlot> = roots
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, block_root)| BlockRootSlot {
|
||||
slot: req.start_slot + Slot::from(i),
|
||||
block_root: *block_root,
|
||||
})
|
||||
.collect();
|
||||
|
||||
roots.dedup_by_key(|brs| brs.block_root);
|
||||
|
||||
network.send_rpc_response(
|
||||
@ -392,6 +383,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
|
||||
.chain
|
||||
.rev_iter_block_roots(req.start_slot + (count - 1))
|
||||
.take(count as usize)
|
||||
.map(|(root, _slot)| root)
|
||||
.collect();
|
||||
|
||||
roots.reverse();
|
||||
|
Loading…
Reference in New Issue
Block a user