Add incomplete progress on fork choice
This commit is contained in:
parent
41a36da765
commit
85b23f9f1b
@ -4,7 +4,7 @@ use crate::fork_choice::{Error as ForkChoiceError, ForkChoice};
|
|||||||
use crate::metrics::Metrics;
|
use crate::metrics::Metrics;
|
||||||
use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
|
use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
|
||||||
use lmd_ghost::LmdGhost;
|
use lmd_ghost::LmdGhost;
|
||||||
use log::{debug, trace};
|
use log::trace;
|
||||||
use operation_pool::DepositInsertStatus;
|
use operation_pool::DepositInsertStatus;
|
||||||
use operation_pool::OperationPool;
|
use operation_pool::OperationPool;
|
||||||
use parking_lot::{RwLock, RwLockReadGuard};
|
use parking_lot::{RwLock, RwLockReadGuard};
|
||||||
@ -300,18 +300,20 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
_ => return Err(Error::UnableToReadSlot),
|
_ => return Err(Error::UnableToReadSlot),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut state = self.state.write();
|
if self.state.read().slot < present_slot {
|
||||||
|
let mut state = self.state.write();
|
||||||
|
|
||||||
// If required, transition the new state to the present slot.
|
// If required, transition the new state to the present slot.
|
||||||
for _ in state.slot.as_u64()..present_slot.as_u64() {
|
for _ in state.slot.as_u64()..present_slot.as_u64() {
|
||||||
// Ensure the next epoch state caches are built in case of an epoch transition.
|
// Ensure the next epoch state caches are built in case of an epoch transition.
|
||||||
state.build_committee_cache(RelativeEpoch::Next, spec)?;
|
state.build_committee_cache(RelativeEpoch::Next, spec)?;
|
||||||
|
|
||||||
per_slot_processing(&mut *state, spec)?;
|
per_slot_processing(&mut *state, spec)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.build_all_caches(spec)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.build_all_caches(spec)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,13 +384,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
|
|
||||||
/// Returns the block proposer for a given slot.
|
/// Returns the block proposer for a given slot.
|
||||||
///
|
///
|
||||||
/// Information is read from the present `beacon_state` shuffling, so only information from the
|
/// Information is read from the present `beacon_state` shuffling, only information from the
|
||||||
/// present and prior epoch is available.
|
/// present epoch is available.
|
||||||
pub fn block_proposer(&self, slot: Slot) -> Result<usize, BeaconStateError> {
|
pub fn block_proposer(&self, slot: Slot) -> Result<usize, Error> {
|
||||||
self.state
|
// Ensures that the present state has been advanced to the present slot, skipping slots if
|
||||||
.write()
|
// blocks are not present.
|
||||||
.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
|
self.catchup_state()?;
|
||||||
|
|
||||||
|
// TODO: permit lookups of the proposer at any slot.
|
||||||
let index = self.state.read().get_beacon_proposer_index(
|
let index = self.state.read().get_beacon_proposer_index(
|
||||||
slot,
|
slot,
|
||||||
RelativeEpoch::Current,
|
RelativeEpoch::Current,
|
||||||
@ -559,6 +562,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
.read()
|
.read()
|
||||||
.finalized_epoch
|
.finalized_epoch
|
||||||
.start_slot(T::EthSpec::slots_per_epoch());
|
.start_slot(T::EthSpec::slots_per_epoch());
|
||||||
|
|
||||||
if block.slot <= finalized_slot {
|
if block.slot <= finalized_slot {
|
||||||
return Ok(BlockProcessingOutcome::FinalizedSlot);
|
return Ok(BlockProcessingOutcome::FinalizedSlot);
|
||||||
}
|
}
|
||||||
@ -573,7 +577,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
return Ok(BlockProcessingOutcome::GenesisBlock);
|
return Ok(BlockProcessingOutcome::GenesisBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
let present_slot = self.present_slot();
|
let present_slot = self
|
||||||
|
.read_slot_clock()
|
||||||
|
.ok_or_else(|| Error::UnableToReadSlot)?;
|
||||||
|
|
||||||
if block.slot > present_slot {
|
if block.slot > present_slot {
|
||||||
return Ok(BlockProcessingOutcome::FutureSlot {
|
return Ok(BlockProcessingOutcome::FutureSlot {
|
||||||
@ -719,8 +725,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
signature: Signature::empty_signature(), // To be completed by a validator.
|
signature: Signature::empty_signature(), // To be completed by a validator.
|
||||||
body: BeaconBlockBody {
|
body: BeaconBlockBody {
|
||||||
randao_reveal,
|
randao_reveal,
|
||||||
|
// TODO: replace with real data.
|
||||||
eth1_data: Eth1Data {
|
eth1_data: Eth1Data {
|
||||||
// TODO: replace with real data
|
|
||||||
deposit_count: 0,
|
deposit_count: 0,
|
||||||
deposit_root: Hash256::zero(),
|
deposit_root: Hash256::zero(),
|
||||||
block_hash: Hash256::zero(),
|
block_hash: Hash256::zero(),
|
||||||
@ -739,11 +745,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!(
|
|
||||||
"Produced block with {} attestations, updating state.",
|
|
||||||
block.body.attestations.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
per_block_processing_without_verifying_block_signature(&mut state, &block, &self.spec)?;
|
per_block_processing_without_verifying_block_signature(&mut state, &block, &self.spec)?;
|
||||||
|
|
||||||
let state_root = state.canonical_root();
|
let state_root = state.canonical_root();
|
||||||
|
@ -2,6 +2,7 @@ use crate::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome};
|
|||||||
use lmd_ghost::LmdGhost;
|
use lmd_ghost::LmdGhost;
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use slot_clock::TestingSlotClock;
|
use slot_clock::TestingSlotClock;
|
||||||
|
use state_processing::per_slot_processing;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use store::MemoryStore;
|
use store::MemoryStore;
|
||||||
@ -13,7 +14,7 @@ use types::{
|
|||||||
Hash256, Keypair, RelativeEpoch, SecretKey, Signature, Slot,
|
Hash256, Keypair, RelativeEpoch, SecretKey, Signature, Slot,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum BuildStrategy {
|
pub enum BuildStrategy {
|
||||||
OnCanonicalHead,
|
OnCanonicalHead,
|
||||||
ForkCanonicalChainAt(Slot),
|
ForkCanonicalChainAt(Slot),
|
||||||
@ -89,22 +90,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extend_chain(&self, build_strategy: BuildStrategy) {
|
pub fn advance_slot(&self) {
|
||||||
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(build_strategy);
|
|
||||||
let outcome = self
|
|
||||||
.chain
|
|
||||||
.process_block(block)
|
|
||||||
.expect("should process block");
|
|
||||||
assert_eq!(outcome, BlockProcessingOutcome::Processed);
|
|
||||||
|
|
||||||
self.add_attestations_to_op_pool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_state(&self, build_strategy: BuildStrategy) -> BeaconState<E> {
|
pub fn extend_chain(&self, build_strategy: BuildStrategy, blocks: usize) {
|
||||||
match build_strategy {
|
// Get an initial state to build the block upon, based on the build strategy.
|
||||||
|
let mut state = match build_strategy {
|
||||||
BuildStrategy::OnCanonicalHead => self.chain.current_state().clone(),
|
BuildStrategy::OnCanonicalHead => self.chain.current_state().clone(),
|
||||||
BuildStrategy::ForkCanonicalChainAt(fork_slot) => {
|
BuildStrategy::ForkCanonicalChainAt(fork_slot) => {
|
||||||
let state_root = self
|
let state_root = self
|
||||||
@ -120,18 +113,80 @@ where
|
|||||||
.expect("should read db")
|
.expect("should read db")
|
||||||
.expect("should find state root")
|
.expect("should find state root")
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
fn build_block(&self, build_strategy: BuildStrategy) -> BeaconBlock {
|
// Get an initial slot to build upon, based on the build strategy.
|
||||||
let mut state = self.get_state(build_strategy);
|
let mut slot = match build_strategy {
|
||||||
state.build_all_caches(&self.spec).unwrap();
|
|
||||||
|
|
||||||
let slot = match build_strategy {
|
|
||||||
BuildStrategy::OnCanonicalHead => self.chain.read_slot_clock().unwrap(),
|
BuildStrategy::OnCanonicalHead => self.chain.read_slot_clock().unwrap(),
|
||||||
BuildStrategy::ForkCanonicalChainAt(slot) => slot,
|
BuildStrategy::ForkCanonicalChainAt(slot) => slot,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for _ in 0..blocks {
|
||||||
|
while self.chain.read_slot_clock().expect("should have a slot") < slot {
|
||||||
|
self.advance_slot();
|
||||||
|
}
|
||||||
|
|
||||||
|
let (block, new_state) = self.build_block(state.clone(), slot, build_strategy);
|
||||||
|
|
||||||
|
let outcome = self
|
||||||
|
.chain
|
||||||
|
.process_block(block)
|
||||||
|
.expect("should process block");
|
||||||
|
|
||||||
|
assert_eq!(outcome, BlockProcessingOutcome::Processed);
|
||||||
|
|
||||||
|
state = new_state;
|
||||||
|
slot += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.add_attestations_to_op_pool();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_block(
|
||||||
|
&self,
|
||||||
|
mut state: BeaconState<E>,
|
||||||
|
slot: Slot,
|
||||||
|
build_strategy: BuildStrategy,
|
||||||
|
) -> (BeaconBlock, BeaconState<E>) {
|
||||||
|
if slot < state.slot {
|
||||||
|
panic!("produce slot cannot be prior to the state slot");
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..slot.as_u64() - state.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)
|
||||||
|
.expect("should be able to build caches");
|
||||||
|
|
||||||
|
per_slot_processing(&mut state, &self.spec)
|
||||||
|
.expect("should be able to advance state to slot");
|
||||||
|
}
|
||||||
|
|
||||||
|
state.drop_all_caches();
|
||||||
|
state.build_all_caches(&self.spec).unwrap();
|
||||||
|
|
||||||
|
// dbg!(slot);
|
||||||
|
// dbg!(state.generate_seed(state.current_epoch(), &self.spec));
|
||||||
|
dbg!(state.generate_seed(state.next_epoch(), &self.spec));
|
||||||
|
/*
|
||||||
|
dbg!(self
|
||||||
|
.chain
|
||||||
|
.current_state()
|
||||||
|
.generate_seed(state.current_epoch(), &self.spec));
|
||||||
|
// dbg!(state.generate_seed(state.next_epoch(), &self.spec));
|
||||||
|
dbg!(state.canonical_root());
|
||||||
|
dbg!(&state.committee_caches[0]);
|
||||||
|
dbg!(self.chain.current_state().canonical_root());
|
||||||
|
dbg!(&self.chain.current_state().committee_caches[0]);
|
||||||
|
|
||||||
|
dbg!(state.get_beacon_proposer_index(slot, RelativeEpoch::Current, &self.spec));
|
||||||
|
dbg!(self.chain.current_state().get_beacon_proposer_index(
|
||||||
|
slot,
|
||||||
|
RelativeEpoch::Current,
|
||||||
|
&self.spec
|
||||||
|
));
|
||||||
|
*/
|
||||||
|
|
||||||
let proposer_index = match build_strategy {
|
let proposer_index = match build_strategy {
|
||||||
BuildStrategy::OnCanonicalHead => self
|
BuildStrategy::OnCanonicalHead => self
|
||||||
.chain
|
.chain
|
||||||
@ -152,7 +207,7 @@ where
|
|||||||
Signature::new(&message, domain, sk)
|
Signature::new(&message, domain, sk)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut block, _state) = self
|
let (mut block, state) = self
|
||||||
.chain
|
.chain
|
||||||
.produce_block_on_state(state, slot, randao_reveal)
|
.produce_block_on_state(state, slot, randao_reveal)
|
||||||
.expect("should produce block");
|
.expect("should produce block");
|
||||||
@ -164,7 +219,7 @@ where
|
|||||||
Signature::new(&message, domain, sk)
|
Signature::new(&message, domain, sk)
|
||||||
};
|
};
|
||||||
|
|
||||||
block
|
(block, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_attestations_to_op_pool(&self) {
|
fn add_attestations_to_op_pool(&self) {
|
||||||
@ -239,18 +294,30 @@ mod test {
|
|||||||
|
|
||||||
pub const VALIDATOR_COUNT: usize = 16;
|
pub const VALIDATOR_COUNT: usize = 16;
|
||||||
|
|
||||||
|
fn get_harness(
|
||||||
|
validator_count: usize,
|
||||||
|
) -> BeaconChainHarness<ThreadSafeReducedTree<MemoryStore, MinimalEthSpec>, MinimalEthSpec>
|
||||||
|
{
|
||||||
|
let harness = BeaconChainHarness::new(validator_count);
|
||||||
|
|
||||||
|
// Move past the zero slot.
|
||||||
|
harness.advance_slot();
|
||||||
|
|
||||||
|
harness
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_finalize() {
|
fn can_finalize() {
|
||||||
let num_blocks_produced = MinimalEthSpec::slots_per_epoch() * 5;
|
let num_blocks_produced = MinimalEthSpec::slots_per_epoch() * 5;
|
||||||
|
|
||||||
let harness: BeaconChainHarness<
|
let harness = get_harness(VALIDATOR_COUNT);
|
||||||
ThreadSafeReducedTree<MemoryStore, MinimalEthSpec>,
|
|
||||||
MinimalEthSpec,
|
|
||||||
> = BeaconChainHarness::new(VALIDATOR_COUNT);
|
|
||||||
|
|
||||||
|
harness.extend_chain(BuildStrategy::OnCanonicalHead, num_blocks_produced as usize);
|
||||||
|
/*
|
||||||
for _ in 0..num_blocks_produced {
|
for _ in 0..num_blocks_produced {
|
||||||
harness.extend_chain(BuildStrategy::OnCanonicalHead);
|
harness.extend_chain(BuildStrategy::OnCanonicalHead);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
let state = &harness.chain.head().beacon_state;
|
let state = &harness.chain.head().beacon_state;
|
||||||
|
|
||||||
|
@ -703,6 +703,9 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
let active_index_root = self.get_active_index_root(epoch, spec)?;
|
let active_index_root = self.get_active_index_root(epoch, spec)?;
|
||||||
let epoch_bytes = int_to_bytes32(epoch.as_u64());
|
let epoch_bytes = int_to_bytes32(epoch.as_u64());
|
||||||
|
|
||||||
|
dbg!(randao);
|
||||||
|
dbg!(active_index_root);
|
||||||
|
|
||||||
let mut preimage = [0; 32 * 3];
|
let mut preimage = [0; 32 * 3];
|
||||||
preimage[0..32].copy_from_slice(&randao[..]);
|
preimage[0..32].copy_from_slice(&randao[..]);
|
||||||
preimage[32..64].copy_from_slice(&active_index_root[..]);
|
preimage[32..64].copy_from_slice(&active_index_root[..]);
|
||||||
|
Loading…
Reference in New Issue
Block a user