From f4b169ce80b8b5acbc1b32b9ab488acabdb0bc84 Mon Sep 17 00:00:00 2001 From: Grant Wuerker Date: Mon, 29 Jul 2019 22:51:42 +0200 Subject: [PATCH] Integration tests for free attestation processing --- beacon_node/beacon_chain/src/fork_choice.rs | 7 +- beacon_node/beacon_chain/src/test_utils.rs | 6 +- beacon_node/beacon_chain/tests/tests.rs | 92 ++++++++++++++++++++- 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/beacon_node/beacon_chain/src/fork_choice.rs b/beacon_node/beacon_chain/src/fork_choice.rs index 0f98ac9ce..7d1830afe 100644 --- a/beacon_node/beacon_chain/src/fork_choice.rs +++ b/beacon_node/beacon_chain/src/fork_choice.rs @@ -3,7 +3,7 @@ use lmd_ghost::LmdGhost; use state_processing::common::get_attesting_indices_unsorted; use std::sync::Arc; use store::{Error as StoreError, Store}; -use types::{Attestation, BeaconBlock, BeaconState, BeaconStateError, Epoch, EthSpec, Hash256}; +use types::{Attestation, BeaconBlock, BeaconState, BeaconStateError, Epoch, EthSpec, Hash256, Slot}; use state_processing::common; type Result = std::result::Result; @@ -186,6 +186,11 @@ impl ForkChoice { }).is_some()) } + // Returns the latest message for a given validator + pub fn latest_message(&self, validator_index: usize) -> Option<(Hash256, Slot)> { + self.backend.latest_message(validator_index) + } + /// Inform the fork choice that the given block (and corresponding root) have been finalized so /// it may prune it's storage. /// diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index 991d29418..9a440b887 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -171,7 +171,7 @@ where if let BlockProcessingOutcome::Processed { block_root } = outcome { head_block_root = Some(block_root); - self.add_attestations_to_op_pool( + self.add_free_attestations( &attestation_strategy, &new_state, block_root, @@ -256,10 +256,10 @@ where (block, state) } - /// Adds attestations to the `BeaconChain` operations pool to be included in future blocks. + /// Adds attestations to the `BeaconChain` operations pool and fork choice. /// /// The `attestation_strategy` dictates which validators should attest. - fn add_attestations_to_op_pool( + fn add_free_attestations( &self, attestation_strategy: &AttestationStrategy, state: &BeaconState, diff --git a/beacon_node/beacon_chain/tests/tests.rs b/beacon_node/beacon_chain/tests/tests.rs index 882d9f235..2f4e5bade 100644 --- a/beacon_node/beacon_chain/tests/tests.rs +++ b/beacon_node/beacon_chain/tests/tests.rs @@ -1,4 +1,3 @@ -#![cfg(not(debug_assertions))] use beacon_chain::test_utils::{ AttestationStrategy, BeaconChainHarness, BlockStrategy, CommonTypes, PersistedBeaconChain, @@ -8,7 +7,7 @@ use lmd_ghost::ThreadSafeReducedTree; use rand::Rng; use store::{MemoryStore, Store}; use types::test_utils::{SeedableRng, TestRandom, XorShiftRng}; -use types::{Deposit, EthSpec, Hash256, MinimalEthSpec, Slot}; +use types::{Deposit, EthSpec, Hash256, MinimalEthSpec, Slot, RelativeEpoch}; // Should ideally be divisible by 3. pub const VALIDATOR_COUNT: usize = 24; @@ -265,3 +264,92 @@ fn roundtrip_operation_pool() { assert_eq!(harness.chain.op_pool, restored_op_pool); } + +#[test] +fn free_attestations_added_to_fork_choice_some_none() { + let num_blocks_produced = MinimalEthSpec::slots_per_epoch() / 2; + + let harness = get_harness(VALIDATOR_COUNT); + + harness.extend_chain( + num_blocks_produced as usize, + BlockStrategy::OnCanonicalHead, + AttestationStrategy::AllValidators, + ); + + let state = &harness.chain.head().beacon_state; + let fork_choice = &harness.chain.fork_choice; + + let validators: Vec = (0..VALIDATOR_COUNT).collect(); + let slots: Vec = validators + .iter() + .map(|&v| + state.get_attestation_duties(v, RelativeEpoch::Current) + .expect("should get attester duties") + .unwrap() + .slot + ).collect(); + let validator_slots: Vec<(&usize, Slot)> = validators.iter().zip(slots).collect(); + + for (validator, slot) in validator_slots.clone() { + let latest_message = fork_choice.latest_message(*validator); + + if slot <= num_blocks_produced && slot != 0{ + assert_eq!( + latest_message.unwrap().1, slot, + "Latest message slot should be equal to attester duty." + ) + } else { + assert!( + latest_message.is_none(), + "Latest message slot should be None." + ) + } + } +} + +#[test] +fn free_attestations_added_to_fork_choice_all_updated() { + let num_blocks_produced = MinimalEthSpec::slots_per_epoch() * 2 - 1; + + let harness = get_harness(VALIDATOR_COUNT); + + harness.extend_chain( + num_blocks_produced as usize, + BlockStrategy::OnCanonicalHead, + AttestationStrategy::AllValidators, + ); + + let state = &harness.chain.head().beacon_state; + let fork_choice = &harness.chain.fork_choice; + + let validators: Vec = (0..VALIDATOR_COUNT).collect(); + let slots: Vec = validators + .iter() + .map(|&v| + state.get_attestation_duties(v, RelativeEpoch::Current) + .expect("should get attester duties") + .unwrap() + .slot + ).collect(); + let validator_slots: Vec<(&usize, Slot)> = validators.iter().zip(slots).collect(); + + for (validator, slot) in validator_slots { + let latest_message = fork_choice.latest_message(*validator); + + assert_eq!( + latest_message.unwrap().1, slot, + "Latest message slot should be equal to attester duty." + ); + + if slot != num_blocks_produced { + let block_root = state.get_block_root(slot) + .expect("Should get block root at slot"); + + assert_eq!( + latest_message.unwrap().0, *block_root, + "Latest message block root should be equal to block at slot." + ); + } + } +} \ No newline at end of file