diff --git a/eth2/types/src/beacon_state/epoch_cache/tests.rs b/eth2/types/src/beacon_state/epoch_cache/tests.rs index 14fc3c88b3..67005ab4bc 100644 --- a/eth2/types/src/beacon_state/epoch_cache/tests.rs +++ b/eth2/types/src/beacon_state/epoch_cache/tests.rs @@ -1,138 +1 @@ #![cfg(test)] - -use super::*; -use crate::beacon_state::FewValidatorsEthSpec; -use crate::test_utils::*; -use swap_or_not_shuffle::shuffle_list; - -fn execute_sane_cache_test( - state: BeaconState, - epoch: Epoch, - validator_count: usize, - spec: &ChainSpec, -) { - let active_indices: Vec = (0..validator_count).collect(); - let seed = state.generate_seed(epoch, spec).unwrap(); - let start_shard = 0; - let relative_epoch = RelativeEpoch::from_epoch(state.current_epoch(), epoch).unwrap(); - - let mut ordered_indices = state - .get_cached_active_validator_indices(relative_epoch) - .unwrap() - .to_vec(); - ordered_indices.sort_unstable(); - assert_eq!( - active_indices, ordered_indices, - "Validator indices mismatch" - ); - - let shuffling = - shuffle_list(active_indices, spec.shuffle_round_count, &seed[..], false).unwrap(); - - let mut expected_indices_iter = shuffling.iter(); - let mut expected_shards_iter = (start_shard..start_shard + T::shard_count() as u64).into_iter(); - - // Loop through all slots in the epoch being tested. - for slot in epoch.slot_iter(spec.slots_per_epoch) { - let crosslink_committees = state.get_crosslink_committees_at_slot(slot).unwrap(); - - // Assert that the number of committees in this slot is consistent with the reported number - // of committees in an epoch. - assert_eq!( - crosslink_committees.len() as u64, - state.get_epoch_committee_count(relative_epoch).unwrap() / T::slots_per_epoch() - ); - - for cc in crosslink_committees { - // Assert that shards are assigned contiguously across committees. - assert_eq!(expected_shards_iter.next().unwrap(), cc.shard); - // Assert that a committee lookup via slot is identical to a committee lookup via - // shard. - assert_eq!( - state - .get_crosslink_committee_for_shard(cc.shard, relative_epoch) - .unwrap(), - cc - ); - - // Loop through each validator in the committee. - for &i in cc.committee { - // Assert the validators are assigned contiguously across committees. - assert_eq!( - i, - *expected_indices_iter.next().unwrap(), - "Non-sequential validators." - ); - } - } - } - - // Assert that all validators were assigned to a committee. - assert!(expected_indices_iter.next().is_none()); - - // Assert that all shards were assigned to a committee. - assert!(expected_shards_iter.next().is_none()); -} - -fn sane_cache_test( - validator_count: usize, - state_epoch: Epoch, - cache_epoch: RelativeEpoch, -) { - let spec = &T::spec(); - - let mut builder = - TestingBeaconStateBuilder::from_single_keypair(validator_count, &Keypair::random(), spec); - - let slot = state_epoch.start_slot(spec.slots_per_epoch); - builder.teleport_to_slot(slot, spec); - - let (mut state, _keypairs): (BeaconState, _) = builder.build(); - - state - .build_epoch_cache(RelativeEpoch::Previous, spec) - .unwrap(); - state - .build_epoch_cache(RelativeEpoch::Current, spec) - .unwrap(); - state.build_epoch_cache(RelativeEpoch::Next, spec).unwrap(); - - let cache_epoch = cache_epoch.into_epoch(state_epoch); - - execute_sane_cache_test(state, cache_epoch, validator_count as usize, &spec); -} - -fn sane_cache_test_suite(cached_epoch: RelativeEpoch) { - let spec = T::spec(); - - let validator_count = (spec.shard_count * spec.target_committee_size) + 1; - - sane_cache_test::(validator_count as usize, Epoch::new(0), cached_epoch); - - sane_cache_test::( - validator_count as usize, - spec.genesis_epoch + 4, - cached_epoch, - ); - - sane_cache_test::( - validator_count as usize, - spec.genesis_epoch + T::slots_per_historical_root() as u64 * T::slots_per_epoch() * 4, - cached_epoch, - ); -} - -#[test] -fn current_epoch_suite() { - sane_cache_test_suite::(RelativeEpoch::Current); -} - -#[test] -fn previous_epoch_suite() { - sane_cache_test_suite::(RelativeEpoch::Previous); -} - -#[test] -fn next_epoch_suite() { - sane_cache_test_suite::(RelativeEpoch::Next); -} diff --git a/eth2/types/src/beacon_state/tests.rs b/eth2/types/src/beacon_state/tests.rs index 3a937a9bcf..d6dcddaf67 100644 --- a/eth2/types/src/beacon_state/tests.rs +++ b/eth2/types/src/beacon_state/tests.rs @@ -1,6 +1,5 @@ #![cfg(test)] use super::*; -use crate::beacon_state::FewValidatorsEthSpec; use crate::test_utils::*; use std::ops::RangeInclusive; @@ -149,3 +148,147 @@ fn tree_hash_cache() { let root = state.update_tree_hash_cache().unwrap(); assert_eq!(root.as_bytes(), &state.tree_hash_root()[..]); } + +/// Tests committee-specific components +#[cfg(test)] +mod committees { + use super::*; + use crate::beacon_state::FewValidatorsEthSpec; + use swap_or_not_shuffle::shuffle_list; + + fn execute_committee_consistency_test( + state: BeaconState, + epoch: Epoch, + validator_count: usize, + spec: &ChainSpec, + ) { + let active_indices: Vec = (0..validator_count).collect(); + let seed = state.generate_seed(epoch, spec).unwrap(); + let start_shard = 0; + let relative_epoch = RelativeEpoch::from_epoch(state.current_epoch(), epoch).unwrap(); + + let mut ordered_indices = state + .get_cached_active_validator_indices(relative_epoch) + .unwrap() + .to_vec(); + ordered_indices.sort_unstable(); + assert_eq!( + active_indices, ordered_indices, + "Validator indices mismatch" + ); + + let shuffling = + shuffle_list(active_indices, spec.shuffle_round_count, &seed[..], false).unwrap(); + + let mut expected_indices_iter = shuffling.iter(); + let mut expected_shards_iter = + (start_shard..start_shard + T::shard_count() as u64).into_iter(); + + // Loop through all slots in the epoch being tested. + for slot in epoch.slot_iter(spec.slots_per_epoch) { + let crosslink_committees = state.get_crosslink_committees_at_slot(slot).unwrap(); + + // Assert that the number of committees in this slot is consistent with the reported number + // of committees in an epoch. + assert_eq!( + crosslink_committees.len() as u64, + state.get_epoch_committee_count(relative_epoch).unwrap() / T::slots_per_epoch() + ); + + for cc in crosslink_committees { + // Assert that shards are assigned contiguously across committees. + assert_eq!(expected_shards_iter.next().unwrap(), cc.shard); + // Assert that a committee lookup via slot is identical to a committee lookup via + // shard. + assert_eq!( + state + .get_crosslink_committee_for_shard(cc.shard, relative_epoch) + .unwrap(), + cc + ); + + // Loop through each validator in the committee. + for &i in cc.committee { + // Assert the validators are assigned contiguously across committees. + assert_eq!( + i, + *expected_indices_iter.next().unwrap(), + "Non-sequential validators." + ); + } + } + } + + // Assert that all validators were assigned to a committee. + assert!(expected_indices_iter.next().is_none()); + + // Assert that all shards were assigned to a committee. + assert!(expected_shards_iter.next().is_none()); + } + + fn committee_consistency_test( + validator_count: usize, + state_epoch: Epoch, + cache_epoch: RelativeEpoch, + ) { + let spec = &T::spec(); + + let mut builder = TestingBeaconStateBuilder::from_single_keypair( + validator_count, + &Keypair::random(), + spec, + ); + + let slot = state_epoch.start_slot(spec.slots_per_epoch); + builder.teleport_to_slot(slot, spec); + + let (mut state, _keypairs): (BeaconState, _) = builder.build(); + + state + .build_epoch_cache(RelativeEpoch::Previous, spec) + .unwrap(); + state + .build_epoch_cache(RelativeEpoch::Current, spec) + .unwrap(); + state.build_epoch_cache(RelativeEpoch::Next, spec).unwrap(); + + let cache_epoch = cache_epoch.into_epoch(state_epoch); + + execute_committee_consistency_test(state, cache_epoch, validator_count as usize, &spec); + } + + fn committee_consistency_test_suite(cached_epoch: RelativeEpoch) { + let spec = T::spec(); + + let validator_count = (spec.shard_count * spec.target_committee_size) + 1; + + committee_consistency_test::(validator_count as usize, Epoch::new(0), cached_epoch); + + committee_consistency_test::( + validator_count as usize, + spec.genesis_epoch + 4, + cached_epoch, + ); + + committee_consistency_test::( + validator_count as usize, + spec.genesis_epoch + T::slots_per_historical_root() as u64 * T::slots_per_epoch() * 4, + cached_epoch, + ); + } + + #[test] + fn current_epoch_committee_consistency() { + committee_consistency_test_suite::(RelativeEpoch::Current); + } + + #[test] + fn previous_epoch_committee_consistency() { + committee_consistency_test_suite::(RelativeEpoch::Previous); + } + + #[test] + fn next_epoch_committee_consistency() { + committee_consistency_test_suite::(RelativeEpoch::Next); + } +}