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