mirror of
https://gitlab.com/pulsechaincom/lighthouse-pulse.git
synced 2025-01-01 00:41:20 +00:00
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 tree_hash::TreeHash;
|
||||||
use types::*;
|
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)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum BlockProcessingOutcome {
|
pub enum BlockProcessingOutcome {
|
||||||
/// Block was valid and imported into the block graph.
|
/// Block was valid and imported into the block graph.
|
||||||
@ -657,16 +663,41 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
&self,
|
&self,
|
||||||
randao_reveal: Signature,
|
randao_reveal: Signature,
|
||||||
) -> Result<(BeaconBlock, BeaconState<T::EthSpec>), BlockProductionError> {
|
) -> 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();
|
self.metrics.block_production_requests.inc();
|
||||||
let timer = self.metrics.block_production_times.start_timer();
|
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)?;
|
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
|
||||||
|
|
||||||
trace!("Finding attestations for new block...");
|
|
||||||
|
|
||||||
let previous_block_root = if state.slot > 0 {
|
let previous_block_root = if state.slot > 0 {
|
||||||
*state
|
*state
|
||||||
.get_block_root(state.slot - 1)
|
.get_block_root(state.slot - 1)
|
||||||
@ -675,8 +706,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
state.latest_block_header.canonical_root()
|
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) =
|
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 {
|
let mut block = BeaconBlock {
|
||||||
slot: state.slot,
|
slot: state.slot,
|
||||||
@ -691,8 +725,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
deposit_root: Hash256::zero(),
|
deposit_root: Hash256::zero(),
|
||||||
block_hash: Hash256::zero(),
|
block_hash: Hash256::zero(),
|
||||||
},
|
},
|
||||||
// TODO: badass Lighthouse graffiti
|
graffiti,
|
||||||
graffiti: [0; 32],
|
|
||||||
proposer_slashings,
|
proposer_slashings,
|
||||||
attester_slashings,
|
attester_slashings,
|
||||||
attestations: self
|
attestations: self
|
||||||
|
@ -40,9 +40,12 @@ impl From<MetricsError> for BeaconChainError {
|
|||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum BlockProductionError {
|
pub enum BlockProductionError {
|
||||||
UnableToGetBlockRootFromState,
|
UnableToGetBlockRootFromState,
|
||||||
|
UnableToReadSlot,
|
||||||
|
SlotProcessingError(SlotProcessingError),
|
||||||
BlockProcessingError(BlockProcessingError),
|
BlockProcessingError(BlockProcessingError),
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
}
|
}
|
||||||
|
|
||||||
easy_from_to!(BlockProcessingError, BlockProductionError);
|
easy_from_to!(BlockProcessingError, BlockProductionError);
|
||||||
easy_from_to!(BeaconStateError, 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::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use store::MemoryStore;
|
use store::MemoryStore;
|
||||||
|
use store::Store;
|
||||||
use tree_hash::{SignedRoot, TreeHash};
|
use tree_hash::{SignedRoot, TreeHash};
|
||||||
use types::{
|
use types::{
|
||||||
test_utils::TestingBeaconStateBuilder, AggregateSignature, Attestation,
|
test_utils::TestingBeaconStateBuilder, AggregateSignature, Attestation,
|
||||||
AttestationDataAndCustodyBit, BeaconBlock, Bitfield, ChainSpec, Domain, EthSpec, Hash256,
|
AttestationDataAndCustodyBit, BeaconBlock, BeaconState, Bitfield, ChainSpec, Domain, EthSpec,
|
||||||
Keypair, SecretKey, Signature,
|
Hash256, Keypair, RelativeEpoch, SecretKey, Signature, Slot,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum BuildStrategy {
|
||||||
|
OnCanonicalHead,
|
||||||
|
ForkCanonicalChainAt(Slot),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CommonTypes<L, E>
|
pub struct CommonTypes<L, E>
|
||||||
where
|
where
|
||||||
L: LmdGhost<MemoryStore, E>,
|
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.slot_clock.advance_slot();
|
||||||
self.chain.catchup_state().expect("should catchup state");
|
self.chain.catchup_state().expect("should catchup state");
|
||||||
|
|
||||||
let block = self.build_block();
|
let block = self.build_block(build_strategy);
|
||||||
let outcome = self
|
let outcome = self
|
||||||
.chain
|
.chain
|
||||||
.process_block(block)
|
.process_block(block)
|
||||||
@ -96,18 +103,47 @@ where
|
|||||||
self.add_attestations_to_op_pool();
|
self.add_attestations_to_op_pool();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_block(&self) -> BeaconBlock {
|
fn get_state(&self, build_strategy: BuildStrategy) -> BeaconState<E> {
|
||||||
let slot = self.chain.read_slot_clock().unwrap();
|
match build_strategy {
|
||||||
|
BuildStrategy::OnCanonicalHead => self.chain.current_state().clone(),
|
||||||
let sk = {
|
BuildStrategy::ForkCanonicalChainAt(fork_slot) => {
|
||||||
let proposer = self
|
let state_root = self
|
||||||
.chain
|
.chain
|
||||||
.block_proposer(slot)
|
.rev_iter_state_roots(self.chain.head().beacon_state.slot - 1)
|
||||||
.expect("should get block propoer");
|
.find(|(_hash, slot)| *slot == fork_slot)
|
||||||
&self.keypairs[proposer].sk
|
.map(|(hash, _slot)| hash)
|
||||||
|
.expect("could not find state root for fork");
|
||||||
|
|
||||||
|
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 randao_reveal = {
|
||||||
let epoch = slot.epoch(E::slots_per_epoch());
|
let epoch = slot.epoch(E::slots_per_epoch());
|
||||||
@ -118,8 +154,8 @@ where
|
|||||||
|
|
||||||
let (mut block, _state) = self
|
let (mut block, _state) = self
|
||||||
.chain
|
.chain
|
||||||
.produce_block(randao_reveal)
|
.produce_block_on_state(state, slot, randao_reveal)
|
||||||
.expect("should producer block");
|
.expect("should produce block");
|
||||||
|
|
||||||
block.signature = {
|
block.signature = {
|
||||||
let message = block.signed_root();
|
let message = block.signed_root();
|
||||||
@ -195,7 +231,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(not(debug_assertions))]
|
// #[cfg(not(debug_assertions))]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use lmd_ghost::ThreadSafeReducedTree;
|
use lmd_ghost::ThreadSafeReducedTree;
|
||||||
@ -213,7 +249,7 @@ mod test {
|
|||||||
> = BeaconChainHarness::new(VALIDATOR_COUNT);
|
> = BeaconChainHarness::new(VALIDATOR_COUNT);
|
||||||
|
|
||||||
for _ in 0..num_blocks_produced {
|
for _ in 0..num_blocks_produced {
|
||||||
harness.extend_canonical_chain();
|
harness.extend_chain(BuildStrategy::OnCanonicalHead);
|
||||||
}
|
}
|
||||||
|
|
||||||
let state = &harness.chain.head().beacon_state;
|
let state = &harness.chain.head().beacon_state;
|
||||||
|
@ -182,7 +182,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
|
|||||||
&& (!self
|
&& (!self
|
||||||
.chain
|
.chain
|
||||||
.rev_iter_block_roots(local.best_slot)
|
.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)
|
&& (local.latest_finalized_root != spec.zero_hash)
|
||||||
&& (remote.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,
|
"start_slot" => req.start_slot,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut roots: Vec<Hash256> = self
|
let mut roots: Vec<BlockRootSlot> = self
|
||||||
.chain
|
.chain
|
||||||
.rev_iter_block_roots(req.start_slot + req.count)
|
.rev_iter_block_roots(req.start_slot + req.count)
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.take(req.count as usize)
|
.take(req.count as usize)
|
||||||
|
.map(|(block_root, slot)| BlockRootSlot { slot, block_root })
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if roots.len() as u64 != req.count {
|
if roots.len() as u64 != req.count {
|
||||||
@ -285,16 +286,6 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
roots.reverse();
|
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);
|
roots.dedup_by_key(|brs| brs.block_root);
|
||||||
|
|
||||||
network.send_rpc_response(
|
network.send_rpc_response(
|
||||||
@ -392,6 +383,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
|
|||||||
.chain
|
.chain
|
||||||
.rev_iter_block_roots(req.start_slot + (count - 1))
|
.rev_iter_block_roots(req.start_slot + (count - 1))
|
||||||
.take(count as usize)
|
.take(count as usize)
|
||||||
|
.map(|(root, _slot)| root)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
roots.reverse();
|
roots.reverse();
|
||||||
|
Loading…
Reference in New Issue
Block a user