Move BeaconChainHarness to interop spec
This commit is contained in:
parent
2706025a34
commit
7edc5f37b9
@ -13,8 +13,8 @@ use std::sync::Arc;
|
||||
use std::time::SystemTime;
|
||||
use tree_hash::{SignedRoot, TreeHash};
|
||||
use types::{
|
||||
test_utils::generate_deterministic_keypairs, BeaconBlock, BeaconState, ChainSpec, Deposit,
|
||||
DepositData, Domain, EthSpec, Fork, Hash256, PublicKey, Signature,
|
||||
BeaconBlock, BeaconState, ChainSpec, Deposit, DepositData, Domain, EthSpec, Fork, Hash256,
|
||||
Keypair, PublicKey, Signature,
|
||||
};
|
||||
|
||||
enum BuildStrategy<T: BeaconChainTypes> {
|
||||
@ -33,21 +33,21 @@ pub struct BeaconChainBuilder<T: BeaconChainTypes> {
|
||||
|
||||
impl<T: BeaconChainTypes> BeaconChainBuilder<T> {
|
||||
pub fn recent_genesis(
|
||||
validator_count: usize,
|
||||
keypairs: &[Keypair],
|
||||
minutes: u64,
|
||||
spec: ChainSpec,
|
||||
log: Logger,
|
||||
) -> Result<Self, String> {
|
||||
Self::quick_start(recent_genesis_time(minutes), validator_count, spec, log)
|
||||
Self::quick_start(recent_genesis_time(minutes), keypairs, spec, log)
|
||||
}
|
||||
|
||||
pub fn quick_start(
|
||||
genesis_time: u64,
|
||||
validator_count: usize,
|
||||
keypairs: &[Keypair],
|
||||
spec: ChainSpec,
|
||||
log: Logger,
|
||||
) -> Result<Self, String> {
|
||||
let genesis_state = interop_genesis_state(validator_count, genesis_time, &spec)?;
|
||||
let genesis_state = interop_genesis_state(keypairs, genesis_time, &spec)?;
|
||||
|
||||
Ok(Self::from_genesis_state(genesis_state, spec, log))
|
||||
}
|
||||
@ -167,11 +167,10 @@ fn genesis_block<T: EthSpec>(genesis_state: &BeaconState<T>, spec: &ChainSpec) -
|
||||
/// Reference:
|
||||
/// https://github.com/ethereum/eth2.0-pm/tree/6e41fcf383ebeb5125938850d8e9b4e9888389b4/interop/mocked_start
|
||||
fn interop_genesis_state<T: EthSpec>(
|
||||
validator_count: usize,
|
||||
keypairs: &[Keypair],
|
||||
genesis_time: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<BeaconState<T>, String> {
|
||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||
let eth1_block_hash = Hash256::from_slice(&[0x42; 32]);
|
||||
let eth1_timestamp = 2_u64.pow(40);
|
||||
let amount = spec.max_effective_balance;
|
||||
@ -187,7 +186,7 @@ fn interop_genesis_state<T: EthSpec>(
|
||||
.map(|keypair| {
|
||||
let mut data = DepositData {
|
||||
withdrawal_credentials: withdrawal_credentials(&keypair.pk),
|
||||
pubkey: keypair.pk.into(),
|
||||
pubkey: keypair.pk.clone().into(),
|
||||
amount,
|
||||
signature: Signature::empty_signature().into(),
|
||||
};
|
||||
@ -269,7 +268,7 @@ fn recent_genesis_time(minutes: u64) -> u64 {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use types::{EthSpec, MinimalEthSpec};
|
||||
use types::{test_utils::generate_deterministic_keypairs, EthSpec, MinimalEthSpec};
|
||||
|
||||
type TestEthSpec = MinimalEthSpec;
|
||||
|
||||
@ -279,7 +278,9 @@ mod test {
|
||||
let genesis_time = 42;
|
||||
let spec = &TestEthSpec::default_spec();
|
||||
|
||||
let state = interop_genesis_state::<TestEthSpec>(validator_count, genesis_time, spec)
|
||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||
|
||||
let state = interop_genesis_state::<TestEthSpec>(&keypairs, genesis_time, spec)
|
||||
.expect("should build state");
|
||||
|
||||
assert_eq!(
|
||||
|
@ -34,6 +34,7 @@ pub enum BeaconChainError {
|
||||
MissingBeaconBlock(Hash256),
|
||||
MissingBeaconState(Hash256),
|
||||
SlotProcessingError(SlotProcessingError),
|
||||
UnableToAdvanceState(String),
|
||||
NoStateForAttestation {
|
||||
beacon_block_root: Hash256,
|
||||
},
|
||||
|
@ -1,22 +1,28 @@
|
||||
use crate::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome, InteropEth1ChainBackend};
|
||||
use crate::{
|
||||
AttestationProcessingOutcome, BeaconChain, BeaconChainBuilder, BeaconChainTypes,
|
||||
BlockProcessingOutcome, InteropEth1ChainBackend,
|
||||
};
|
||||
use lmd_ghost::LmdGhost;
|
||||
use rayon::prelude::*;
|
||||
use sloggers::{null::NullLoggerBuilder, Build};
|
||||
use sloggers::{terminal::TerminalLoggerBuilder, types::Severity, Build};
|
||||
use slot_clock::TestingSlotClock;
|
||||
use state_processing::per_slot_processing;
|
||||
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, BeaconState, BitList, ChainSpec, Domain, EthSpec,
|
||||
Hash256, Keypair, RelativeEpoch, SecretKey, Signature, Slot,
|
||||
AggregateSignature, Attestation, AttestationDataAndCustodyBit, BeaconBlock, BeaconState,
|
||||
BitList, ChainSpec, Domain, EthSpec, Hash256, Keypair, RelativeEpoch, SecretKey, Signature,
|
||||
Slot,
|
||||
};
|
||||
|
||||
pub use types::test_utils::generate_deterministic_keypairs;
|
||||
|
||||
pub use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
|
||||
|
||||
pub const HARNESS_GENESIS_TIME: u64 = 1567552690; // 4th September 2019
|
||||
|
||||
/// Indicates how the `BeaconChainHarness` should produce blocks.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum BlockStrategy {
|
||||
@ -84,46 +90,21 @@ where
|
||||
E: EthSpec,
|
||||
{
|
||||
/// Instantiate a new harness with `validator_count` initial validators.
|
||||
pub fn new(validator_count: usize) -> Self {
|
||||
let state_builder = TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(
|
||||
validator_count,
|
||||
&E::default_spec(),
|
||||
);
|
||||
let (genesis_state, keypairs) = state_builder.build();
|
||||
|
||||
Self::from_state_and_keypairs(genesis_state, keypairs)
|
||||
}
|
||||
|
||||
/// Instantiate a new harness with an initial validator for each key supplied.
|
||||
pub fn from_keypairs(keypairs: Vec<Keypair>) -> Self {
|
||||
let state_builder = TestingBeaconStateBuilder::from_keypairs(keypairs, &E::default_spec());
|
||||
let (genesis_state, keypairs) = state_builder.build();
|
||||
|
||||
Self::from_state_and_keypairs(genesis_state, keypairs)
|
||||
}
|
||||
|
||||
/// Instantiate a new harness with the given genesis state and a keypair for each of the
|
||||
/// initial validators in the given state.
|
||||
pub fn from_state_and_keypairs(genesis_state: BeaconState<E>, keypairs: Vec<Keypair>) -> Self {
|
||||
pub fn new(keypairs: Vec<Keypair>) -> Self {
|
||||
let spec = E::default_spec();
|
||||
|
||||
let log = TerminalLoggerBuilder::new()
|
||||
.level(Severity::Warning)
|
||||
.build()
|
||||
.expect("logger should build");
|
||||
|
||||
let store = Arc::new(MemoryStore::open());
|
||||
|
||||
let mut genesis_block = BeaconBlock::empty(&spec);
|
||||
genesis_block.state_root = Hash256::from_slice(&genesis_state.tree_hash_root());
|
||||
|
||||
let builder = NullLoggerBuilder;
|
||||
let log = builder.build().expect("logger should build");
|
||||
|
||||
let chain = BeaconChain::from_genesis(
|
||||
store,
|
||||
InteropEth1ChainBackend::default(),
|
||||
genesis_state,
|
||||
genesis_block,
|
||||
spec.clone(),
|
||||
log,
|
||||
)
|
||||
.expect("Terminate if beacon chain generation fails");
|
||||
let chain =
|
||||
BeaconChainBuilder::quick_start(HARNESS_GENESIS_TIME, &keypairs, spec.clone(), log)
|
||||
.unwrap_or_else(|e| panic!("Failed to create beacon chain builder: {}", e))
|
||||
.build(store.clone(), InteropEth1ChainBackend::default())
|
||||
.unwrap_or_else(|e| panic!("Failed to build beacon chain: {}", e));
|
||||
|
||||
Self {
|
||||
chain,
|
||||
@ -163,7 +144,10 @@ where
|
||||
BlockStrategy::ForkCanonicalChainAt { previous_slot, .. } => previous_slot,
|
||||
};
|
||||
|
||||
self.get_state_at_slot(state_slot)
|
||||
self.chain
|
||||
.state_at_slot(state_slot)
|
||||
.expect("should find state for slot")
|
||||
.clone()
|
||||
};
|
||||
|
||||
// Determine the first slot where a block should be built.
|
||||
@ -201,21 +185,6 @@ where
|
||||
head_block_root.expect("did not produce any blocks")
|
||||
}
|
||||
|
||||
fn get_state_at_slot(&self, state_slot: Slot) -> BeaconState<E> {
|
||||
let state_root = self
|
||||
.chain
|
||||
.rev_iter_state_roots()
|
||||
.find(|(_hash, slot)| *slot == state_slot)
|
||||
.map(|(hash, _slot)| hash)
|
||||
.expect("could not find state root");
|
||||
|
||||
self.chain
|
||||
.store
|
||||
.get(&state_root)
|
||||
.expect("should read db")
|
||||
.expect("should find state root")
|
||||
}
|
||||
|
||||
/// Returns a newly created block, signed by the proposer for the given slot.
|
||||
fn build_block(
|
||||
&self,
|
||||
@ -289,9 +258,14 @@ where
|
||||
)
|
||||
.into_iter()
|
||||
.for_each(|attestation| {
|
||||
self.chain
|
||||
match self
|
||||
.chain
|
||||
.process_attestation(attestation)
|
||||
.expect("should process attestation");
|
||||
.expect("should not error during attestation processing")
|
||||
{
|
||||
AttestationProcessingOutcome::Processed => (),
|
||||
other => panic!("did not successfully process attestation: {:?}", other),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,14 @@
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use beacon_chain::test_utils::{
|
||||
use beacon_chain::AttestationProcessingOutcome;
|
||||
use beacon_chain::{
|
||||
test_utils::{
|
||||
AttestationStrategy, BeaconChainHarness, BlockStrategy, CommonTypes, PersistedBeaconChain,
|
||||
BEACON_CHAIN_DB_KEY,
|
||||
},
|
||||
BlockProcessingOutcome,
|
||||
};
|
||||
use beacon_chain::AttestationProcessingOutcome;
|
||||
use lmd_ghost::ThreadSafeReducedTree;
|
||||
use rand::Rng;
|
||||
use store::{MemoryStore, Store};
|
||||
@ -25,7 +28,7 @@ lazy_static! {
|
||||
type TestForkChoice = ThreadSafeReducedTree<MemoryStore, MinimalEthSpec>;
|
||||
|
||||
fn get_harness(validator_count: usize) -> BeaconChainHarness<TestForkChoice, MinimalEthSpec> {
|
||||
let harness = BeaconChainHarness::from_keypairs(KEYPAIRS[0..validator_count].to_vec());
|
||||
let harness = BeaconChainHarness::new(KEYPAIRS[0..validator_count].to_vec());
|
||||
|
||||
harness.advance_slot();
|
||||
|
||||
@ -461,3 +464,32 @@ fn free_attestations_added_to_fork_choice_all_updated() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn produces_and_processes_with_genesis_skip_slots() {
|
||||
let num_validators = 8;
|
||||
let harness_a = get_harness(num_validators);
|
||||
let harness_b = get_harness(num_validators);
|
||||
let skip_slots = 9;
|
||||
|
||||
for _ in 0..skip_slots {
|
||||
harness_a.advance_slot();
|
||||
harness_b.advance_slot();
|
||||
}
|
||||
|
||||
harness_a.extend_chain(
|
||||
1,
|
||||
BlockStrategy::OnCanonicalHead,
|
||||
// No attestation required for test.
|
||||
AttestationStrategy::SomeValidators(vec![]),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
harness_b
|
||||
.chain
|
||||
.process_block(harness_a.chain.head().beacon_block.clone()),
|
||||
Ok(BlockProcessingOutcome::Processed {
|
||||
block_root: harness_a.chain.head().beacon_block_root
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ pub mod error;
|
||||
pub mod notifier;
|
||||
|
||||
use beacon_chain::{
|
||||
lmd_ghost::ThreadSafeReducedTree, slot_clock::SystemTimeSlotClock, store::Store, BeaconChain,
|
||||
BeaconChainBuilder,
|
||||
lmd_ghost::ThreadSafeReducedTree, slot_clock::SystemTimeSlotClock, store::Store,
|
||||
test_utils::generate_deterministic_keypairs, BeaconChain, BeaconChainBuilder,
|
||||
};
|
||||
use exit_future::Signal;
|
||||
use futures::{future::Future, Stream};
|
||||
@ -106,7 +106,7 @@ where
|
||||
"method" => "recent"
|
||||
);
|
||||
BeaconChainBuilder::recent_genesis(
|
||||
*validator_count,
|
||||
&generate_deterministic_keypairs(*validator_count),
|
||||
*minutes,
|
||||
spec.clone(),
|
||||
log.clone(),
|
||||
@ -125,7 +125,7 @@ where
|
||||
);
|
||||
BeaconChainBuilder::quick_start(
|
||||
*genesis_time,
|
||||
*validator_count,
|
||||
&generate_deterministic_keypairs(*validator_count),
|
||||
spec.clone(),
|
||||
log.clone(),
|
||||
)?
|
||||
|
@ -4,7 +4,8 @@
|
||||
extern crate lazy_static;
|
||||
|
||||
use beacon_chain::test_utils::{
|
||||
AttestationStrategy, BeaconChainHarness as BaseBeaconChainHarness, BlockStrategy,
|
||||
generate_deterministic_keypairs, AttestationStrategy,
|
||||
BeaconChainHarness as BaseBeaconChainHarness, BlockStrategy,
|
||||
};
|
||||
use lmd_ghost::{LmdGhost, ThreadSafeReducedTree as BaseThreadSafeReducedTree};
|
||||
use rand::{prelude::*, rngs::StdRng};
|
||||
@ -51,7 +52,7 @@ struct ForkedHarness {
|
||||
impl ForkedHarness {
|
||||
/// A new standard instance of with constant parameters.
|
||||
pub fn new() -> Self {
|
||||
let harness = BeaconChainHarness::new(VALIDATOR_COUNT);
|
||||
let harness = BeaconChainHarness::new(generate_deterministic_keypairs(VALIDATOR_COUNT));
|
||||
|
||||
// Move past the zero slot.
|
||||
harness.advance_slot();
|
||||
|
Loading…
Reference in New Issue
Block a user