Update BeaconStateBuilder API

This commit is contained in:
Paul Hauner 2019-02-26 22:00:07 +13:00
parent 5cfc9cb21d
commit af17fb1d03
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
6 changed files with 89 additions and 50 deletions

View File

@ -10,6 +10,7 @@ harness = false
[dev-dependencies]
criterion = "0.2"
state_processing = { path = "../../../eth2/state_processing" }
[dependencies]
attester = { path = "../../../eth2/attester" }

View File

@ -1,6 +1,7 @@
use criterion::Criterion;
use criterion::{black_box, criterion_group, criterion_main, Benchmark};
// use env_logger::{Builder, Env};
use state_processing::SlotProcessable;
use test_harness::BeaconChainHarness;
use types::{ChainSpec, Hash256};

View File

@ -2,24 +2,30 @@ use criterion::Criterion;
use criterion::{black_box, criterion_group, criterion_main};
// use env_logger::{Builder, Env};
use state_processing::SlotProcessable;
use types::*;
use types::beacon_state::BeaconStateBuilder;
use types::*;
fn epoch_processing(c: &mut Criterion) {
// Builder::from_env(Env::default().default_filter_or("debug")).init();
let mut builder = BeaconStateBuilder::with_random_validators(8);
let mut builder = BeaconStateBuilder::new(8);
builder.spec = ChainSpec::few_validators();
builder.genesis().unwrap();
builder.build().unwrap();
builder.teleport_to_end_of_epoch(builder.spec.genesis_epoch + 4);
let mut state = builder.build().unwrap();
let mut state = builder.cloned_state();
// Build all the caches so the following state does _not_ include the cache-building time.
state.build_epoch_cache(RelativeEpoch::Previous, &builder.spec).unwrap();
state.build_epoch_cache(RelativeEpoch::Current, &builder.spec).unwrap();
state.build_epoch_cache(RelativeEpoch::Next, &builder.spec).unwrap();
state
.build_epoch_cache(RelativeEpoch::Previous, &builder.spec)
.unwrap();
state
.build_epoch_cache(RelativeEpoch::Current, &builder.spec)
.unwrap();
state
.build_epoch_cache(RelativeEpoch::Next, &builder.spec)
.unwrap();
let cached_state = state.clone();

View File

@ -8,13 +8,13 @@ use types::*;
fn runs_without_error() {
Builder::from_env(Env::default().default_filter_or("error")).init();
let mut builder = BeaconStateBuilder::with_random_validators(8);
let mut builder = BeaconStateBuilder::new(8);
builder.spec = ChainSpec::few_validators();
builder.genesis().unwrap();
builder.build().unwrap();
builder.teleport_to_end_of_epoch(builder.spec.genesis_epoch + 4);
let mut state = builder.build().unwrap();
let mut state = builder.cloned_state();
let spec = &builder.spec;
state.per_epoch_processing(spec).unwrap();

View File

@ -6,20 +6,19 @@ use bls::create_proof_of_possession;
/// Building the `BeaconState` is a three step processes:
///
/// 1. Create a new `BeaconStateBuilder`.
/// 2. Run the `genesis` function to generate a new BeaconState.
/// 2. Call `Self::build()` or `Self::build_fast()` generate a `BeaconState`.
/// 3. (Optional) Use builder functions to modify the `BeaconState`.
/// 4. Call `build()` to obtain a cloned `BeaconState`.
/// 4. Call `Self::cloned_state()` to obtain a `BeaconState` cloned from this struct.
///
/// Step (2) is necessary because step (3) requires an existing `BeaconState` object. (2) is not
/// included in (1) to allow for modifying params before generating the `BeaconState` (e.g., the
/// spec).
/// Step (2) happens prior to step (3) because some functionality requires an existing
/// `BeaconState`.
///
/// Step (4) produces a clone of the BeaconState and doesn't consume the `BeaconStateBuilder` to
/// allow access to the `keypairs` and `spec`.
/// allow access to `self.keypairs` and `self.spec`.
pub struct BeaconStateBuilder {
pub validator_count: usize,
pub state: Option<BeaconState>,
pub genesis_time: u64,
pub initial_validator_deposits: Vec<Deposit>,
pub latest_eth1_data: Eth1Data,
pub spec: ChainSpec,
pub keypairs: Vec<Keypair>,
@ -27,21 +26,41 @@ pub struct BeaconStateBuilder {
impl BeaconStateBuilder {
/// Create a new builder with the given number of validators.
pub fn with_random_validators(validator_count: usize) -> Self {
pub fn new(validator_count: usize) -> Self {
let genesis_time = 10_000_000;
let keypairs: Vec<Keypair> = (0..validator_count)
let latest_eth1_data = Eth1Data {
deposit_root: Hash256::zero(),
block_hash: Hash256::zero(),
};
let spec = ChainSpec::foundation();
Self {
validator_count,
state: None,
genesis_time,
latest_eth1_data,
spec,
keypairs: vec![],
}
}
pub fn build(&mut self) -> Result<(), BeaconStateError> {
self.keypairs = (0..self.validator_count)
.collect::<Vec<usize>>()
.iter()
.map(|_| Keypair::random())
.collect();
let initial_validator_deposits = keypairs
let initial_validator_deposits = self.keypairs
.iter()
.map(|keypair| Deposit {
branch: vec![], // branch verification is not specified.
index: 0, // index verification is not specified.
deposit_data: DepositData {
amount: 32_000_000_000, // 32 ETH (in Gwei)
timestamp: genesis_time - 1,
timestamp: self.genesis_time - 1,
deposit_input: DepositInput {
pubkey: keypair.pk.clone(),
withdrawal_credentials: Hash256::zero(), // Withdrawal not possible.
@ -50,27 +69,10 @@ impl BeaconStateBuilder {
},
})
.collect();
let latest_eth1_data = Eth1Data {
deposit_root: Hash256::zero(),
block_hash: Hash256::zero(),
};
let spec = ChainSpec::foundation();
Self {
state: None,
genesis_time,
initial_validator_deposits,
latest_eth1_data,
spec,
keypairs,
}
}
/// Runs the `BeaconState::genesis` function and produces a `BeaconState`.
pub fn genesis(&mut self) -> Result<(), BeaconStateError> {
let state = BeaconState::genesis(
self.genesis_time,
self.initial_validator_deposits.clone(),
initial_validator_deposits,
self.latest_eth1_data.clone(),
&self.spec,
)?;
@ -80,6 +82,40 @@ impl BeaconStateBuilder {
Ok(())
}
pub fn build_fast(&mut self) -> Result<(), BeaconStateError> {
let common_keypair = Keypair::random();
let mut validator_registry = Vec::with_capacity(self.validator_count);
let mut validator_balances = Vec::with_capacity(self.validator_count);
self.keypairs = Vec::with_capacity(self.validator_count);
for _ in 0..self.validator_count {
self.keypairs.push(common_keypair.clone());
validator_balances.push(32_000_000_000);
validator_registry.push(Validator {
pubkey: common_keypair.pk.clone(),
withdrawal_credentials: Hash256::zero(),
activation_epoch: self.spec.genesis_epoch,
..Validator::default()
})
}
let state = BeaconState {
validator_registry,
validator_balances,
..BeaconState::genesis(
self.genesis_time,
vec![],
self.latest_eth1_data.clone(),
&self.spec,
)?
};
self.state = Some(state);
Ok(())
}
/// Sets the `BeaconState` to be in the last slot of the given epoch.
///
/// Sets all justification/finalization parameters to be be as "perfect" as possible (i.e.,
@ -145,11 +181,8 @@ impl BeaconStateBuilder {
}
/// Returns a cloned `BeaconState`.
pub fn build(&self) -> Result<BeaconState, BeaconStateError> {
match &self.state {
Some(state) => Ok(state.clone()),
None => panic!("Genesis required"),
}
pub fn cloned_state(&self) -> BeaconState {
self.state.as_ref().expect("Genesis required").clone()
}
}

View File

@ -7,9 +7,7 @@ use ssz::{ssz_encode, Decodable};
#[test]
pub fn can_produce_genesis_block() {
let mut builder = BeaconStateBuilder::with_random_validators(2);
builder.genesis().unwrap();
let mut builder = BeaconStateBuilder::new(2);
builder.build().unwrap();
}
@ -19,12 +17,12 @@ pub fn can_produce_genesis_block() {
pub fn get_attestation_participants_consistency() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let mut builder = BeaconStateBuilder::with_random_validators(8);
let mut builder = BeaconStateBuilder::new(8);
builder.spec = ChainSpec::few_validators();
builder.genesis().unwrap();
builder.build().unwrap();
let mut state = builder.build().unwrap();
let mut state = builder.cloned_state();
let spec = builder.spec.clone();
state