From 73ebb4bc2eb4e4326fc9bc8adf8ce3749d094728 Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sat, 9 Mar 2019 14:11:49 +1100 Subject: [PATCH] Add incomplete per-block processing benchmarks Still needs to fill block with operations --- eth2/state_processing/benches/benches.rs | 9 +- .../benches/block_processing_benches.rs | 276 ++++++++++++++++++ .../benches/epoch_processing_benches.rs | 23 +- .../src/beacon_block_bencher.rs | 46 +++ .../src/beacon_state_bencher.rs | 213 ++++++++++++++ .../benching_utils/src/lib.rs | 198 +------------ .../src/per_block_processing.rs | 18 +- .../src/per_epoch_processing/tests.rs | 7 +- eth2/types/src/beacon_block.rs | 16 +- 9 files changed, 583 insertions(+), 223 deletions(-) create mode 100644 eth2/state_processing/benches/block_processing_benches.rs create mode 100644 eth2/state_processing/benching_utils/src/beacon_block_bencher.rs create mode 100644 eth2/state_processing/benching_utils/src/beacon_state_bencher.rs diff --git a/eth2/state_processing/benches/benches.rs b/eth2/state_processing/benches/benches.rs index e42e91fb4..52b939a69 100644 --- a/eth2/state_processing/benches/benches.rs +++ b/eth2/state_processing/benches/benches.rs @@ -1,8 +1,11 @@ use criterion::{criterion_group, criterion_main}; +mod block_processing_benches; mod epoch_processing_benches; -use epoch_processing_benches::epoch_processing_16k_validators; - -criterion_group!(benches, epoch_processing_16k_validators); +criterion_group!( + benches, + // epoch_processing_benches::epoch_processing_16k_validators, + block_processing_benches::block_processing_16k_validators, +); criterion_main!(benches); diff --git a/eth2/state_processing/benches/block_processing_benches.rs b/eth2/state_processing/benches/block_processing_benches.rs new file mode 100644 index 000000000..b5fdaa5bd --- /dev/null +++ b/eth2/state_processing/benches/block_processing_benches.rs @@ -0,0 +1,276 @@ +use benching_utils::{BeaconBlockBencher, BeaconStateBencher}; +use criterion::Criterion; +use criterion::{black_box, Benchmark}; +use state_processing::{ + per_block_processing, + per_block_processing::{ + process_attestations, process_attester_slashings, process_deposits, process_eth1_data, + process_exits, process_proposer_slashings, process_randao, process_transfers, + verify_block_signature, + }, +}; +use types::*; + +/// Run the benchmarking suite on a foundation spec with 16,384 validators. +pub fn block_processing_16k_validators(c: &mut Criterion) { + let spec = ChainSpec::foundation(); + + let validator_count = 16_384; + + let (state, keypairs) = build_state(validator_count, &spec); + let block = build_block(&state, &keypairs, &spec); + + bench_block_processing( + c, + &block, + &state, + &spec, + &format!("{}_validators", validator_count), + ); +} + +fn build_state(validator_count: usize, spec: &ChainSpec) -> (BeaconState, Vec) { + let mut builder = BeaconStateBencher::new(validator_count, &spec); + + // Set the state to be just before an epoch transition. + let target_slot = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch); + builder.teleport_to_slot(target_slot, &spec); + + // Builds all caches; benches will not contain shuffling/committee building times. + builder.build_caches(&spec).unwrap(); + + builder.build() +} + +fn build_block(state: &BeaconState, keypairs: &[Keypair], spec: &ChainSpec) -> BeaconBlock { + let mut builder = BeaconBlockBencher::new(spec); + + builder.set_slot(state.slot); + + let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap(); + let keypair = &keypairs[proposer_index]; + + builder.set_randao_reveal(&keypair.sk, &state.fork, spec); + + builder.build(&keypair.sk, &state.fork, spec) +} + +/// Run the detailed benchmarking suite on the given `BeaconState`. +/// +/// `desc` will be added to the title of each bench. +fn bench_block_processing( + c: &mut Criterion, + initial_block: &BeaconBlock, + initial_state: &BeaconState, + initial_spec: &ChainSpec, + desc: &str, +) { + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("verify_block_signature", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| black_box(verify_block_signature(&mut state, &block, &spec).unwrap()), + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("process_randao", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| black_box(process_randao(&mut state, &block, &spec).unwrap()), + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("process_eth1_data", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| black_box(process_eth1_data(&mut state, &block.eth1_data).unwrap()), + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("process_proposer_slashings", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| { + black_box( + process_proposer_slashings( + &mut state, + &block.body.proposer_slashings, + &spec, + ) + .unwrap(), + ) + }, + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("process_attester_slashings", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| { + black_box( + process_attester_slashings( + &mut state, + &block.body.attester_slashings, + &spec, + ) + .unwrap(), + ) + }, + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("process_attestations", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| { + black_box( + process_attestations(&mut state, &block.body.attestations, &spec).unwrap(), + ) + }, + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("process_deposits", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| { + black_box(process_deposits(&mut state, &block.body.deposits, &spec).unwrap()) + }, + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("process_exits", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| { + black_box( + process_exits(&mut state, &block.body.voluntary_exits, &spec).unwrap(), + ) + }, + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("process_transfers", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| { + black_box(process_transfers(&mut state, &block.body.transfers, &spec).unwrap()) + }, + ) + }) + .sample_size(10), + ); + + let state = initial_state.clone(); + let block = initial_block.clone(); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("per_block_processing", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| black_box(per_block_processing(&mut state, &block, &spec).unwrap()), + ) + }) + .sample_size(10), + ); + + let mut state = initial_state.clone(); + state.drop_cache(RelativeEpoch::Previous); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("build_previous_state_epoch_cache", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| { + black_box( + state + .build_epoch_cache(RelativeEpoch::Previous, &spec) + .unwrap(), + ) + }, + ) + }) + .sample_size(10), + ); + + let mut state = initial_state.clone(); + state.drop_cache(RelativeEpoch::Current); + let spec = initial_spec.clone(); + c.bench( + &format!("block_processing_{}", desc), + Benchmark::new("build_current_state_epoch_cache", move |b| { + b.iter_with_setup( + || state.clone(), + |mut state| { + black_box( + state + .build_epoch_cache(RelativeEpoch::Current, &spec) + .unwrap(), + ) + }, + ) + }) + .sample_size(10), + ); +} diff --git a/eth2/state_processing/benches/epoch_processing_benches.rs b/eth2/state_processing/benches/epoch_processing_benches.rs index 941180455..149d8f28e 100644 --- a/eth2/state_processing/benches/epoch_processing_benches.rs +++ b/eth2/state_processing/benches/epoch_processing_benches.rs @@ -19,18 +19,19 @@ pub fn epoch_processing_16k_validators(c: &mut Criterion) { let validator_count = 16_384; let mut builder = BeaconStateBencher::new(validator_count, &spec); - builder.teleport_to_end_of_epoch(spec.genesis_epoch + 4, &spec); - builder.insert_attestations(&spec); - let mut state = builder.build(); - // Build all the caches so the following state does _not_ include the cache-building time. - state - .build_epoch_cache(RelativeEpoch::Previous, &spec) - .unwrap(); - state - .build_epoch_cache(RelativeEpoch::Current, &spec) - .unwrap(); - state.build_epoch_cache(RelativeEpoch::Next, &spec).unwrap(); + // Set the state to be just before an epoch transition. + let target_slot = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch); + builder.teleport_to_slot(target_slot, &spec); + + // Builds all caches; benches will not contain shuffling/committee building times. + builder.build_caches(&spec).unwrap(); + + // Inserts one attestation with full participation for each committee able to include an + // attestation in this state. + builder.insert_attestations(&spec); + + let (state, _keypairs) = builder.build(); // Assert that the state has the maximum possible attestations. let committees_per_epoch = spec.get_epoch_committee_count(validator_count); diff --git a/eth2/state_processing/benching_utils/src/beacon_block_bencher.rs b/eth2/state_processing/benching_utils/src/beacon_block_bencher.rs new file mode 100644 index 000000000..67b7ccc9d --- /dev/null +++ b/eth2/state_processing/benching_utils/src/beacon_block_bencher.rs @@ -0,0 +1,46 @@ +use ssz::{SignedRoot, TreeHash}; +use types::*; + +pub struct BeaconBlockBencher { + block: BeaconBlock, +} + +impl BeaconBlockBencher { + pub fn new(spec: &ChainSpec) -> Self { + Self { + block: BeaconBlock::genesis(spec.zero_hash, spec), + } + } + + pub fn set_slot(&mut self, slot: Slot) { + self.block.slot = slot; + } + + /// Signs the block. + pub fn sign(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { + let proposal = self.block.proposal(spec); + let message = proposal.signed_root(); + let epoch = self.block.slot.epoch(spec.slots_per_epoch); + let domain = spec.get_domain(epoch, Domain::Proposal, fork); + self.block.signature = Signature::new(&message, domain, sk); + } + + /// Sets the randao to be a signature across the blocks epoch. + pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { + let epoch = self.block.slot.epoch(spec.slots_per_epoch); + let message = epoch.hash_tree_root(); + let domain = spec.get_domain(epoch, Domain::Randao, fork); + self.block.randao_reveal = Signature::new(&message, domain, sk); + } + + /// Signs and returns the block, consuming the builder. + pub fn build(mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) -> BeaconBlock { + self.sign(sk, fork, spec); + self.block + } + + /// Returns the block, consuming the builder. + pub fn build_without_signing(self) -> BeaconBlock { + self.block + } +} diff --git a/eth2/state_processing/benching_utils/src/beacon_state_bencher.rs b/eth2/state_processing/benching_utils/src/beacon_state_bencher.rs new file mode 100644 index 000000000..0ee4a75e9 --- /dev/null +++ b/eth2/state_processing/benching_utils/src/beacon_state_bencher.rs @@ -0,0 +1,213 @@ +use bls::get_withdrawal_credentials; +use int_to_bytes::int_to_bytes48; +use rayon::prelude::*; +use types::beacon_state::BeaconStateBuilder; +use types::*; + +pub struct BeaconStateBencher { + state: BeaconState, + keypairs: Vec, +} + +impl BeaconStateBencher { + pub fn new(validator_count: usize, spec: &ChainSpec) -> Self { + let keypairs: Vec = (0..validator_count) + .collect::>() + .par_iter() + .map(|&i| { + let secret = int_to_bytes48(i as u64 + 1); + let sk = SecretKey::from_bytes(&secret).unwrap(); + let pk = PublicKey::from_secret_key(&sk); + Keypair { sk, pk } + }) + .collect(); + + let validators = keypairs + .iter() + .map(|keypair| { + let withdrawal_credentials = Hash256::from_slice(&get_withdrawal_credentials( + &keypair.pk, + spec.bls_withdrawal_prefix_byte, + )); + + Validator { + pubkey: keypair.pk.clone(), + withdrawal_credentials, + activation_epoch: spec.far_future_epoch, + exit_epoch: spec.far_future_epoch, + withdrawable_epoch: spec.far_future_epoch, + initiated_exit: false, + slashed: false, + } + }) + .collect(); + + let mut state_builder = BeaconStateBuilder::new( + 0, + Eth1Data { + deposit_root: Hash256::zero(), + block_hash: Hash256::zero(), + }, + spec, + ); + + let balances = vec![32_000_000_000; validator_count]; + + state_builder.import_existing_validators( + validators, + balances, + validator_count as u64, + spec, + ); + + Self { + state: state_builder.build(spec).unwrap(), + keypairs, + } + } + + pub fn build(self) -> (BeaconState, Vec) { + (self.state, self.keypairs) + } + + pub fn build_caches(&mut self, spec: &ChainSpec) -> Result<(), BeaconStateError> { + let state = &mut self.state; + + state.build_epoch_cache(RelativeEpoch::Previous, &spec)?; + state.build_epoch_cache(RelativeEpoch::Current, &spec)?; + state.build_epoch_cache(RelativeEpoch::Next, &spec)?; + + Ok(()) + } + + /// Sets the `BeaconState` to be in a slot, calling `teleport_to_epoch` to update the epoch. + pub fn teleport_to_slot(&mut self, slot: Slot, spec: &ChainSpec) { + self.teleport_to_epoch(slot.epoch(spec.slots_per_epoch), spec); + self.state.slot = slot; + } + + /// Sets the `BeaconState` to be in the first slot of the given epoch. + /// + /// Sets all justification/finalization parameters to be be as "perfect" as possible (i.e., + /// highest justified and finalized slots, full justification bitfield, etc). + fn teleport_to_epoch(&mut self, epoch: Epoch, spec: &ChainSpec) { + let state = &mut self.state; + + let slot = epoch.start_slot(spec.slots_per_epoch); + + state.slot = slot; + state.validator_registry_update_epoch = epoch - 1; + + state.previous_shuffling_epoch = epoch - 1; + state.current_shuffling_epoch = epoch; + + state.previous_shuffling_seed = Hash256::from_low_u64_le(0); + state.current_shuffling_seed = Hash256::from_low_u64_le(1); + + state.previous_justified_epoch = epoch - 2; + state.justified_epoch = epoch - 1; + state.justification_bitfield = u64::max_value(); + state.finalized_epoch = epoch - 1; + } + + /// Creates a full set of attestations for the `BeaconState`. Each attestation has full + /// participation from its committee and references the expected beacon_block hashes. + /// + /// These attestations should be fully conducive to justification and finalization. + pub fn insert_attestations(&mut self, spec: &ChainSpec) { + let state = &mut self.state; + + state + .build_epoch_cache(RelativeEpoch::Previous, spec) + .unwrap(); + state + .build_epoch_cache(RelativeEpoch::Current, spec) + .unwrap(); + + let current_epoch = state.current_epoch(spec); + let previous_epoch = state.previous_epoch(spec); + + let first_slot = previous_epoch.start_slot(spec.slots_per_epoch).as_u64(); + let last_slot = current_epoch.end_slot(spec.slots_per_epoch).as_u64() + - spec.min_attestation_inclusion_delay; + let last_slot = std::cmp::min(state.slot.as_u64(), last_slot); + + for slot in first_slot..last_slot + 1 { + let slot = Slot::from(slot); + + let committees = state + .get_crosslink_committees_at_slot(slot, spec) + .unwrap() + .clone(); + + for (committee, shard) in committees { + state + .latest_attestations + .push(committee_to_pending_attestation( + state, &committee, shard, slot, spec, + )) + } + } + } +} + +fn committee_to_pending_attestation( + state: &BeaconState, + committee: &[usize], + shard: u64, + slot: Slot, + spec: &ChainSpec, +) -> PendingAttestation { + let current_epoch = state.current_epoch(spec); + let previous_epoch = state.previous_epoch(spec); + + let mut aggregation_bitfield = Bitfield::new(); + let mut custody_bitfield = Bitfield::new(); + + for (i, _) in committee.iter().enumerate() { + aggregation_bitfield.set(i, true); + custody_bitfield.set(i, true); + } + + let is_previous_epoch = + state.slot.epoch(spec.slots_per_epoch) != slot.epoch(spec.slots_per_epoch); + + let justified_epoch = if is_previous_epoch { + state.previous_justified_epoch + } else { + state.justified_epoch + }; + + let epoch_boundary_root = if is_previous_epoch { + *state + .get_block_root(previous_epoch.start_slot(spec.slots_per_epoch), spec) + .unwrap() + } else { + *state + .get_block_root(current_epoch.start_slot(spec.slots_per_epoch), spec) + .unwrap() + }; + + let justified_block_root = *state + .get_block_root(justified_epoch.start_slot(spec.slots_per_epoch), spec) + .unwrap(); + + PendingAttestation { + aggregation_bitfield, + data: AttestationData { + slot, + shard, + beacon_block_root: *state.get_block_root(slot, spec).unwrap(), + epoch_boundary_root, + crosslink_data_root: Hash256::zero(), + latest_crosslink: Crosslink { + epoch: slot.epoch(spec.slots_per_epoch), + crosslink_data_root: Hash256::zero(), + }, + justified_epoch, + justified_block_root, + }, + custody_bitfield, + inclusion_slot: slot + spec.min_attestation_inclusion_delay, + } +} diff --git a/eth2/state_processing/benching_utils/src/lib.rs b/eth2/state_processing/benching_utils/src/lib.rs index c70b7828a..ba9548814 100644 --- a/eth2/state_processing/benching_utils/src/lib.rs +++ b/eth2/state_processing/benching_utils/src/lib.rs @@ -1,195 +1,5 @@ -use bls::get_withdrawal_credentials; -use int_to_bytes::int_to_bytes48; -use rayon::prelude::*; -use types::beacon_state::BeaconStateBuilder; -use types::*; +mod beacon_block_bencher; +mod beacon_state_bencher; -pub struct BeaconStateBencher { - state: BeaconState, -} - -impl BeaconStateBencher { - pub fn new(validator_count: usize, spec: &ChainSpec) -> Self { - let keypairs: Vec = (0..validator_count) - .collect::>() - .par_iter() - .map(|&i| { - let secret = int_to_bytes48(i as u64 + 1); - let sk = SecretKey::from_bytes(&secret).unwrap(); - let pk = PublicKey::from_secret_key(&sk); - Keypair { sk, pk } - }) - .collect(); - - let validators = keypairs - .iter() - .map(|keypair| { - let withdrawal_credentials = Hash256::from_slice(&get_withdrawal_credentials( - &keypair.pk, - spec.bls_withdrawal_prefix_byte, - )); - - Validator { - pubkey: keypair.pk.clone(), - withdrawal_credentials, - activation_epoch: spec.far_future_epoch, - exit_epoch: spec.far_future_epoch, - withdrawable_epoch: spec.far_future_epoch, - initiated_exit: false, - slashed: false, - } - }) - .collect(); - - let mut state_builder = BeaconStateBuilder::new( - 0, - Eth1Data { - deposit_root: Hash256::zero(), - block_hash: Hash256::zero(), - }, - spec, - ); - - let balances = vec![32_000_000_000; validator_count]; - - state_builder.import_existing_validators( - validators, - balances, - validator_count as u64, - spec, - ); - - Self { - state: state_builder.build(spec).unwrap(), - } - } - - pub fn build(self) -> BeaconState { - self.state - } - - /// 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., - /// highest justified and finalized slots, full justification bitfield, etc). - pub fn teleport_to_end_of_epoch(&mut self, epoch: Epoch, spec: &ChainSpec) { - let state = &mut self.state; - - let slot = epoch.end_slot(spec.slots_per_epoch); - - state.slot = slot; - state.validator_registry_update_epoch = epoch - 1; - - state.previous_shuffling_epoch = epoch - 1; - state.current_shuffling_epoch = epoch; - - state.previous_shuffling_seed = Hash256::from_low_u64_le(0); - state.current_shuffling_seed = Hash256::from_low_u64_le(1); - - state.previous_justified_epoch = epoch - 2; - state.justified_epoch = epoch - 1; - state.justification_bitfield = u64::max_value(); - state.finalized_epoch = epoch - 1; - } - - /// Creates a full set of attestations for the `BeaconState`. Each attestation has full - /// participation from its committee and references the expected beacon_block hashes. - /// - /// These attestations should be fully conducive to justification and finalization. - pub fn insert_attestations(&mut self, spec: &ChainSpec) { - let state = &mut self.state; - - state - .build_epoch_cache(RelativeEpoch::Previous, spec) - .unwrap(); - state - .build_epoch_cache(RelativeEpoch::Current, spec) - .unwrap(); - - let current_epoch = state.current_epoch(spec); - let previous_epoch = state.previous_epoch(spec); - - let first_slot = previous_epoch.start_slot(spec.slots_per_epoch).as_u64(); - let last_slot = current_epoch.end_slot(spec.slots_per_epoch).as_u64() - - spec.min_attestation_inclusion_delay; - let last_slot = std::cmp::min(state.slot.as_u64(), last_slot); - - for slot in first_slot..last_slot + 1 { - let slot = Slot::from(slot); - - let committees = state - .get_crosslink_committees_at_slot(slot, spec) - .unwrap() - .clone(); - - for (committee, shard) in committees { - state - .latest_attestations - .push(committee_to_pending_attestation( - state, &committee, shard, slot, spec, - )) - } - } - } -} - -fn committee_to_pending_attestation( - state: &BeaconState, - committee: &[usize], - shard: u64, - slot: Slot, - spec: &ChainSpec, -) -> PendingAttestation { - let current_epoch = state.current_epoch(spec); - let previous_epoch = state.previous_epoch(spec); - - let mut aggregation_bitfield = Bitfield::new(); - let mut custody_bitfield = Bitfield::new(); - - for (i, _) in committee.iter().enumerate() { - aggregation_bitfield.set(i, true); - custody_bitfield.set(i, true); - } - - let is_previous_epoch = - state.slot.epoch(spec.slots_per_epoch) != slot.epoch(spec.slots_per_epoch); - - let justified_epoch = if is_previous_epoch { - state.previous_justified_epoch - } else { - state.justified_epoch - }; - - let epoch_boundary_root = if is_previous_epoch { - *state - .get_block_root(previous_epoch.start_slot(spec.slots_per_epoch), spec) - .unwrap() - } else { - *state - .get_block_root(current_epoch.start_slot(spec.slots_per_epoch), spec) - .unwrap() - }; - - let justified_block_root = *state - .get_block_root(justified_epoch.start_slot(spec.slots_per_epoch), spec) - .unwrap(); - - PendingAttestation { - aggregation_bitfield, - data: AttestationData { - slot, - shard, - beacon_block_root: *state.get_block_root(slot, spec).unwrap(), - epoch_boundary_root, - crosslink_data_root: Hash256::zero(), - latest_crosslink: Crosslink { - epoch: slot.epoch(spec.slots_per_epoch), - crosslink_data_root: Hash256::zero(), - }, - justified_epoch, - justified_block_root, - }, - custody_bitfield, - inclusion_slot: slot + spec.min_attestation_inclusion_delay, - } -} +pub use beacon_block_bencher::BeaconBlockBencher; +pub use beacon_state_bencher::BeaconStateBencher; diff --git a/eth2/state_processing/src/per_block_processing.rs b/eth2/state_processing/src/per_block_processing.rs index 1ab1eed71..149e0bf79 100644 --- a/eth2/state_processing/src/per_block_processing.rs +++ b/eth2/state_processing/src/per_block_processing.rs @@ -1,7 +1,6 @@ use self::verify_proposer_slashing::verify_proposer_slashing; use errors::{BlockInvalid as Invalid, BlockProcessingError as Error, IntoWithIndex}; use hashing::hash; -use log::debug; use ssz::{ssz_encode, SignedRoot, TreeHash}; use types::*; @@ -70,22 +69,21 @@ fn per_block_processing_signature_optional( // Verify that `block.slot == state.slot`. verify!(block.slot == state.slot, Invalid::StateSlotMismatch); - // Ensure the current epoch cache is built. + // Ensure the current and previous epoch cache is built. state.build_epoch_cache(RelativeEpoch::Current, spec)?; + state.build_epoch_cache(RelativeEpoch::Previous, spec)?; if should_verify_block_signature { verify_block_signature(&state, &block, &spec)?; } process_randao(&mut state, &block, &spec)?; process_eth1_data(&mut state, &block.eth1_data)?; - process_proposer_slashings(&mut state, &block.body.proposer_slashings[..], spec)?; - process_attester_slashings(&mut state, &block.body.attester_slashings[..], spec)?; - process_attestations(&mut state, &block.body.attestations[..], spec)?; - process_deposits(&mut state, &block.body.deposits[..], spec)?; - process_exits(&mut state, &block.body.voluntary_exits[..], spec)?; - process_transfers(&mut state, &block.body.transfers[..], spec)?; - - debug!("per_block_processing complete."); + process_proposer_slashings(&mut state, &block.body.proposer_slashings, spec)?; + process_attester_slashings(&mut state, &block.body.attester_slashings, spec)?; + process_attestations(&mut state, &block.body.attestations, spec)?; + process_deposits(&mut state, &block.body.deposits, spec)?; + process_exits(&mut state, &block.body.voluntary_exits, spec)?; + process_transfers(&mut state, &block.body.transfers, spec)?; Ok(()) } diff --git a/eth2/state_processing/src/per_epoch_processing/tests.rs b/eth2/state_processing/src/per_epoch_processing/tests.rs index 8ff687904..f3c68a173 100644 --- a/eth2/state_processing/src/per_epoch_processing/tests.rs +++ b/eth2/state_processing/src/per_epoch_processing/tests.rs @@ -11,8 +11,11 @@ fn runs_without_error() { let spec = ChainSpec::few_validators(); let mut builder = BeaconStateBencher::new(8, &spec); - builder.teleport_to_end_of_epoch(spec.genesis_epoch + 4, &spec); - let mut state = builder.build(); + + let target_slot = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch); + builder.teleport_to_slot(target_slot, &spec); + + let (mut state, _keypairs) = builder.build(); per_epoch_processing(&mut state, &spec).unwrap(); } diff --git a/eth2/types/src/beacon_block.rs b/eth2/types/src/beacon_block.rs index 2e1e24ef7..9e1b3f7ae 100644 --- a/eth2/types/src/beacon_block.rs +++ b/eth2/types/src/beacon_block.rs @@ -1,9 +1,9 @@ use crate::test_utils::TestRandom; -use crate::{BeaconBlockBody, ChainSpec, Eth1Data, Hash256, Slot}; +use crate::{BeaconBlockBody, ChainSpec, Eth1Data, Hash256, Proposal, Slot}; use bls::Signature; use rand::RngCore; use serde_derive::Serialize; -use ssz::TreeHash; +use ssz::{SignedRoot, TreeHash}; use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; use test_random_derive::TestRandom; @@ -33,7 +33,6 @@ impl BeaconBlock { deposit_root: spec.zero_hash, block_hash: spec.zero_hash, }, - signature: spec.empty_signature.clone(), body: BeaconBlockBody { proposer_slashings: vec![], attester_slashings: vec![], @@ -42,6 +41,7 @@ impl BeaconBlock { voluntary_exits: vec![], transfers: vec![], }, + signature: spec.empty_signature.clone(), } } @@ -49,6 +49,16 @@ impl BeaconBlock { pub fn canonical_root(&self) -> Hash256 { Hash256::from_slice(&self.hash_tree_root()[..]) } + + /// Returns an unsigned proposal for block. + pub fn proposal(&self, spec: &ChainSpec) -> Proposal { + Proposal { + slot: self.slot, + shard: spec.beacon_chain_shard_number, + block_root: Hash256::from_slice(&self.signed_root()), + signature: spec.empty_signature.clone(), + } + } } #[cfg(test)]