diff --git a/eth2/types/src/beacon_state/beacon_state_types.rs b/eth2/types/src/beacon_state/beacon_state_types.rs index 494884cd83..795cc734e2 100644 --- a/eth2/types/src/beacon_state/beacon_state_types.rs +++ b/eth2/types/src/beacon_state/beacon_state_types.rs @@ -123,16 +123,20 @@ impl EthSpec for MainnetEthSpec { pub type FoundationBeaconState = BeaconState; -/// Ethereum Foundation specifications, modified to be suitable for < 1000 validators. +/// Ethereum Foundation minimal spec, as defined here: +/// +/// https://github.com/ethereum/eth2.0-specs/blob/v0.6.3/configs/constant_presets/minimal.yaml +/// +/// Spec v0.6.3 #[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)] pub struct MinimalEthSpec; impl EthSpec for MinimalEthSpec { type ShardCount = U8; - type SlotsPerHistoricalRoot = U8192; - type LatestRandaoMixesLength = U8192; - type LatestActiveIndexRootsLength = U8192; - type LatestSlashedExitLength = U8192; + type SlotsPerHistoricalRoot = U64; + type LatestRandaoMixesLength = U64; + type LatestActiveIndexRootsLength = U64; + type LatestSlashedExitLength = U64; type SlotsPerEpoch = U8; type GenesisEpoch = U0; diff --git a/eth2/types/src/beacon_state/committee_cache.rs b/eth2/types/src/beacon_state/committee_cache.rs index 4efceb8ac5..418213a684 100644 --- a/eth2/types/src/beacon_state/committee_cache.rs +++ b/eth2/types/src/beacon_state/committee_cache.rs @@ -50,24 +50,8 @@ impl CommitteeCache { spec.target_committee_size, ) as usize; - let shuffling_start_shard = match relative_epoch { - RelativeEpoch::Current => state.latest_start_shard, - RelativeEpoch::Previous => { - let shard_delta = - T::get_shard_delta(active_validator_indices.len(), spec.target_committee_size); - - (state.latest_start_shard + T::ShardCount::to_u64() - shard_delta) - % T::ShardCount::to_u64() - } - RelativeEpoch::Next => { - let current_active_validators = - get_active_validator_count(&state.validator_registry, state.current_epoch()); - let shard_delta = - T::get_shard_delta(current_active_validators, spec.target_committee_size); - - (state.latest_start_shard + shard_delta) % T::ShardCount::to_u64() - } - }; + let shuffling_start_shard = + Self::compute_start_shard(state, relative_epoch, active_validator_indices.len(), spec); let seed = state.generate_seed(epoch, spec)?; @@ -100,6 +84,37 @@ impl CommitteeCache { }) } + /// Compute the shard which must be attested to first in a given relative epoch. + /// + /// The `active_validator_count` must be the number of validators active at `relative_epoch`. + /// + /// Spec v0.6.3 + pub fn compute_start_shard( + state: &BeaconState, + relative_epoch: RelativeEpoch, + active_validator_count: usize, + spec: &ChainSpec, + ) -> u64 { + match relative_epoch { + RelativeEpoch::Current => state.latest_start_shard, + RelativeEpoch::Previous => { + let shard_delta = + T::get_shard_delta(active_validator_count, spec.target_committee_size); + + (state.latest_start_shard + T::ShardCount::to_u64() - shard_delta) + % T::ShardCount::to_u64() + } + RelativeEpoch::Next => { + let current_active_validators = + get_active_validator_count(&state.validator_registry, state.current_epoch()); + let shard_delta = + T::get_shard_delta(current_active_validators, spec.target_committee_size); + + (state.latest_start_shard + shard_delta) % T::ShardCount::to_u64() + } + } + } + /// Returns `true` if the cache has been initialized at the supplied `epoch`. /// /// An non-initialized cache does not provide any useful information. diff --git a/eth2/types/src/beacon_state/committee_cache/tests.rs b/eth2/types/src/beacon_state/committee_cache/tests.rs index b7054a7fd1..f25a4f727a 100644 --- a/eth2/types/src/beacon_state/committee_cache/tests.rs +++ b/eth2/types/src/beacon_state/committee_cache/tests.rs @@ -170,7 +170,7 @@ impl EthSpec for ExcessShardsEthSpec { fn starts_on_the_correct_shard() { let spec = &ExcessShardsEthSpec::default_spec(); - let num_validators = ExcessShardsEthSpec::shard_count(); + let num_validators = spec.target_committee_size * ExcessShardsEthSpec::shard_count(); let epoch = Epoch::new(100_000_000); let slot = epoch.start_slot(ExcessShardsEthSpec::slots_per_epoch()); diff --git a/eth2/types/src/beacon_state/tests.rs b/eth2/types/src/beacon_state/tests.rs index 316a901512..fd30a816ed 100644 --- a/eth2/types/src/beacon_state/tests.rs +++ b/eth2/types/src/beacon_state/tests.rs @@ -214,8 +214,9 @@ mod committees { ) { 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 start_shard = + CommitteeCache::compute_start_shard(&state, relative_epoch, active_indices.len(), spec); let mut ordered_indices = state .get_cached_active_validator_indices(relative_epoch) @@ -231,8 +232,9 @@ mod committees { 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(); + let mut expected_shards_iter = (0..T::ShardCount::to_u64()) + .into_iter() + .map(|i| (start_shard + i) % T::ShardCount::to_u64()); // Loop through all slots in the epoch being tested. for slot in epoch.slot_iter(T::slots_per_epoch()) { diff --git a/eth2/types/src/chain_spec.rs b/eth2/types/src/chain_spec.rs index 89ea97070c..16c3d30f30 100644 --- a/eth2/types/src/chain_spec.rs +++ b/eth2/types/src/chain_spec.rs @@ -223,7 +223,11 @@ impl ChainSpec { } } - /// Returns a `ChainSpec` compatible with the specification suitable for 8 validators. + /// Ethereum Foundation minimal spec, as defined here: + /// + /// https://github.com/ethereum/eth2.0-specs/blob/v0.6.3/configs/constant_presets/minimal.yaml + /// + /// Spec v0.6.3 pub fn minimal() -> Self { let genesis_slot = Slot::new(0); @@ -235,11 +239,13 @@ impl ChainSpec { .expect("correct multiaddr")]; Self { - boot_nodes, - target_committee_size: 1, - chain_id: 2, // lighthouse testnet chain id - genesis_slot, + target_committee_size: 4, shuffle_round_count: 10, + min_attestation_inclusion_delay: 2, + slots_per_eth1_voting_period: 16, + genesis_slot, + chain_id: 2, // lighthouse testnet chain id + boot_nodes, ..ChainSpec::mainnet() } } diff --git a/tests/ef_tests/src/eth_specs.rs b/tests/ef_tests/src/eth_specs.rs deleted file mode 100644 index e6ac4e5fc8..0000000000 --- a/tests/ef_tests/src/eth_specs.rs +++ /dev/null @@ -1,33 +0,0 @@ -use serde_derive::{Deserialize, Serialize}; -use types::{ - typenum::{U64, U8}, - ChainSpec, EthSpec, FewValidatorsEthSpec, FoundationEthSpec, -}; - -/// "Minimal" testing specification, as defined here: -/// -/// https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/configs/constant_presets/minimal.yaml -/// -/// Spec v0.6.1 -#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)] -pub struct MinimalEthSpec; - -impl EthSpec for MinimalEthSpec { - type ShardCount = U8; - type SlotsPerHistoricalRoot = U64; - type LatestRandaoMixesLength = U64; - type LatestActiveIndexRootsLength = U64; - type LatestSlashedExitLength = U64; - - fn spec() -> ChainSpec { - let mut spec = FewValidatorsEthSpec::spec(); - spec.target_committee_size = 4; - spec.shuffle_round_count = 10; - spec.min_attestation_inclusion_delay = 2; - spec.slots_per_epoch = 8; - spec.slots_per_eth1_voting_period = 16; - spec - } -} - -pub type MainnetEthSpec = FoundationEthSpec; diff --git a/tests/ef_tests/tests/tests.rs b/tests/ef_tests/tests/tests.rs index 48c23b4ef6..06e8f223df 100644 --- a/tests/ef_tests/tests/tests.rs +++ b/tests/ef_tests/tests/tests.rs @@ -98,7 +98,6 @@ fn operations_exit() { } #[test] -#[should_panic] fn operations_proposer_slashing() { yaml_files_in_test_dir(&Path::new("operations").join("proposer_slashing")) .into_par_iter() @@ -108,7 +107,6 @@ fn operations_proposer_slashing() { } #[test] -#[should_panic] fn operations_attester_slashing() { yaml_files_in_test_dir(&Path::new("operations").join("attester_slashing")) .into_par_iter() @@ -118,7 +116,6 @@ fn operations_attester_slashing() { } #[test] -#[should_panic] fn operations_attestation() { yaml_files_in_test_dir(&Path::new("operations").join("attestation")) .into_par_iter() @@ -137,7 +134,6 @@ fn operations_block_header() { } #[test] -#[should_panic] fn sanity_blocks() { yaml_files_in_test_dir(&Path::new("sanity").join("blocks")) .into_par_iter()