From e74d49fc8aa3b2943b63b6d3b83add023274bc2e Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sat, 8 Jun 2019 07:57:25 -0400 Subject: [PATCH] Remove dupe info between ChainSpec and EthSpec --- beacon_node/beacon_chain/src/beacon_chain.rs | 91 ++++++++----------- beacon_node/beacon_chain/src/iter.rs | 7 +- beacon_node/client/src/beacon_chain_types.rs | 18 ++-- beacon_node/client/src/client_config.rs | 7 +- beacon_node/client/src/lib.rs | 11 ++- beacon_node/eth2-libp2p/src/behaviour.rs | 2 +- beacon_node/http_server/src/api.rs | 3 +- beacon_node/network/src/sync/simple_sync.rs | 10 +- beacon_node/rpc/src/beacon_node.rs | 3 +- beacon_node/rpc/src/validator.rs | 10 +- beacon_node/src/run.rs | 6 +- beacon_node/store/src/block_at_slot.rs | 8 +- eth2/fork_choice/benches/benches.rs | 2 +- eth2/fork_choice/examples/example.rs | 2 +- eth2/fork_choice/src/bitwise_lmd_ghost.rs | 2 +- eth2/fork_choice/src/optimized_lmd_ghost.rs | 2 +- eth2/fork_choice/src/slow_lmd_ghost.rs | 2 +- eth2/fork_choice/src/test_utils.rs | 6 +- eth2/fork_choice/tests/tests.rs | 4 +- eth2/operation_pool/src/lib.rs | 12 +-- .../benches/bench_epoch_processing.rs | 6 +- eth2/state_processing/benches/benches.rs | 6 +- .../src/per_block_processing.rs | 4 +- .../block_processing_builder.rs | 8 +- .../src/per_block_processing/tests.rs | 15 +-- .../validate_attestation.rs | 2 +- .../verify_proposer_slashing.rs | 12 +-- .../per_block_processing/verify_transfer.rs | 4 +- .../src/per_epoch_processing.rs | 2 +- .../src/per_epoch_processing/tests.rs | 4 +- .../validator_statuses.rs | 6 +- .../src/per_slot_processing.rs | 2 +- eth2/types/src/beacon_state.rs | 2 +- .../src/beacon_state/beacon_state_types.rs | 45 +++++---- .../types/src/beacon_state/committee_cache.rs | 17 +++- .../src/beacon_state/committee_cache/tests.rs | 28 +++--- eth2/types/src/beacon_state/tests.rs | 22 ++--- eth2/types/src/chain_spec.rs | 18 ++-- .../testing_attestation_data_builder.rs | 8 +- .../builders/testing_beacon_block_builder.rs | 34 ++++--- .../builders/testing_beacon_state_builder.rs | 8 +- .../testing_proposer_slashing_builder.rs | 7 +- .../builders/testing_transfer_builder.rs | 4 +- .../src/cases/epoch_processing_crosslinks.rs | 4 +- .../epoch_processing_registry_updates.rs | 2 +- .../src/cases/operations_attester_slashing.rs | 5 +- .../ef_tests/src/cases/operations_deposit.rs | 2 +- tests/ef_tests/src/cases/operations_exit.rs | 4 +- .../src/cases/operations_proposer_slashing.rs | 5 +- .../ef_tests/src/cases/operations_transfer.rs | 4 +- tests/ef_tests/src/cases/shuffling.rs | 2 +- tests/ef_tests/src/eth_specs.rs | 8 +- .../src/attestation_producer/mod.rs | 4 +- validator_client/src/block_producer/mod.rs | 10 +- validator_client/src/config.rs | 10 +- validator_client/src/duties/mod.rs | 2 +- validator_client/src/service.rs | 17 +++- 57 files changed, 299 insertions(+), 252 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index a9374aa6a..4d77d7aa5 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -96,6 +96,7 @@ pub trait BeaconChainTypes { /// Represents the "Beacon Chain" component of Ethereum 2.0. Allows import of blocks and block /// operations and chooses a canonical head. pub struct BeaconChain { + pub spec: ChainSpec, /// Persistent storage for blocks, states, etc. Typically an on-disk store, such as LevelDB. pub store: Arc, /// Reports the current slot, typically based upon the system clock. @@ -148,6 +149,7 @@ impl BeaconChain { genesis_state.build_all_caches(&spec)?; Ok(Self { + spec, store, slot_clock, op_pool: OperationPool::new(), @@ -160,7 +162,10 @@ impl BeaconChain { } /// Attempt to load an existing instance from the given `store`. - pub fn from_store(store: Arc) -> Result>, Error> { + pub fn from_store( + store: Arc, + spec: ChainSpec, + ) -> Result>, Error> { let key = Hash256::from_slice(&BEACON_CHAIN_DB_KEY.as_bytes()); let p: PersistedBeaconChain = match store.get(&key) { Err(e) => return Err(e.into()), @@ -168,8 +173,6 @@ impl BeaconChain { Ok(Some(p)) => p, }; - let spec = T::EthSpec::spec(); - let slot_clock = T::SlotClock::new( spec.genesis_slot, p.state.genesis_time, @@ -179,6 +182,7 @@ impl BeaconChain { let fork_choice = T::ForkChoice::new(store.clone()); Ok(Some(BeaconChain { + spec, store, slot_clock, op_pool: OperationPool::default(), @@ -363,10 +367,10 @@ impl BeaconChain { // If required, transition the new state to the present slot. for _ in state.slot.as_u64()..present_slot.as_u64() { - per_slot_processing(&mut state, &T::EthSpec::spec())?; + per_slot_processing(&mut state, &self.spec)?; } - state.build_all_caches(&T::EthSpec::spec())?; + state.build_all_caches(&self.spec)?; state }; @@ -400,7 +404,7 @@ impl BeaconChain { /// Ensures the current canonical `BeaconState` has been transitioned to match the `slot_clock`. pub fn catchup_state(&self) -> Result<(), Error> { - let spec = &T::EthSpec::spec(); + let spec = &self.spec; let present_slot = match self.slot_clock.present_slot() { Ok(Some(slot)) => slot, @@ -426,7 +430,7 @@ impl BeaconChain { /// /// Ideally this shouldn't be required, however we leave it here for testing. pub fn ensure_state_caches_are_built(&self) -> Result<(), Error> { - self.state.write().build_all_caches(&T::EthSpec::spec())?; + self.state.write().build_all_caches(&self.spec)?; Ok(()) } @@ -469,7 +473,7 @@ impl BeaconChain { /// genesis. pub fn slots_since_genesis(&self) -> Option { let now = self.read_slot_clock()?; - let genesis_slot = T::EthSpec::spec().genesis_slot; + let genesis_slot = self.spec.genesis_slot; if now < genesis_slot { None @@ -494,12 +498,12 @@ impl BeaconChain { pub fn block_proposer(&self, slot: Slot) -> Result { self.state .write() - .build_committee_cache(RelativeEpoch::Current, &T::EthSpec::spec())?; + .build_committee_cache(RelativeEpoch::Current, &self.spec)?; let index = self.state.read().get_beacon_proposer_index( slot, RelativeEpoch::Current, - &T::EthSpec::spec(), + &self.spec, )?; Ok(index) @@ -530,7 +534,7 @@ impl BeaconChain { /// Produce an `AttestationData` that is valid for the present `slot` and given `shard`. pub fn produce_attestation_data(&self, shard: u64) -> Result { - let slots_per_epoch = T::EthSpec::spec().slots_per_epoch; + let slots_per_epoch = T::EthSpec::slots_per_epoch(); self.metrics.attestation_production_requests.inc(); let timer = self.metrics.attestation_production_times.start_timer(); @@ -591,9 +595,9 @@ impl BeaconChain { self.metrics.attestation_processing_requests.inc(); let timer = self.metrics.attestation_processing_times.start_timer(); - let result = - self.op_pool - .insert_attestation(attestation, &*self.state.read(), &T::EthSpec::spec()); + let result = self + .op_pool + .insert_attestation(attestation, &*self.state.read(), &self.spec); if result.is_ok() { self.metrics.attestation_processing_successes.inc(); @@ -610,19 +614,19 @@ impl BeaconChain { deposit: Deposit, ) -> Result { self.op_pool - .insert_deposit(deposit, &*self.state.read(), &T::EthSpec::spec()) + .insert_deposit(deposit, &*self.state.read(), &self.spec) } /// Accept some exit and queue it for inclusion in an appropriate block. pub fn process_voluntary_exit(&self, exit: VoluntaryExit) -> Result<(), ExitValidationError> { self.op_pool - .insert_voluntary_exit(exit, &*self.state.read(), &T::EthSpec::spec()) + .insert_voluntary_exit(exit, &*self.state.read(), &self.spec) } /// Accept some transfer and queue it for inclusion in an appropriate block. pub fn process_transfer(&self, transfer: Transfer) -> Result<(), TransferValidationError> { self.op_pool - .insert_transfer(transfer, &*self.state.read(), &T::EthSpec::spec()) + .insert_transfer(transfer, &*self.state.read(), &self.spec) } /// Accept some proposer slashing and queue it for inclusion in an appropriate block. @@ -630,11 +634,8 @@ impl BeaconChain { &self, proposer_slashing: ProposerSlashing, ) -> Result<(), ProposerSlashingValidationError> { - self.op_pool.insert_proposer_slashing( - proposer_slashing, - &*self.state.read(), - &T::EthSpec::spec(), - ) + self.op_pool + .insert_proposer_slashing(proposer_slashing, &*self.state.read(), &self.spec) } /// Accept some attester slashing and queue it for inclusion in an appropriate block. @@ -642,11 +643,8 @@ impl BeaconChain { &self, attester_slashing: AttesterSlashing, ) -> Result<(), AttesterSlashingValidationError> { - self.op_pool.insert_attester_slashing( - attester_slashing, - &*self.state.read(), - &T::EthSpec::spec(), - ) + self.op_pool + .insert_attester_slashing(attester_slashing, &*self.state.read(), &self.spec) } /// Accept some block and attempt to add it to block DAG. @@ -708,18 +706,18 @@ impl BeaconChain { // Transition the parent state to the block slot. let mut state: BeaconState = parent_state; for _ in state.slot.as_u64()..block.slot.as_u64() { - if let Err(e) = per_slot_processing(&mut state, &T::EthSpec::spec()) { + if let Err(e) = per_slot_processing(&mut state, &self.spec) { return Ok(BlockProcessingOutcome::InvalidBlock( InvalidBlock::SlotProcessingError(e), )); } } - state.build_committee_cache(RelativeEpoch::Current, &T::EthSpec::spec())?; + state.build_committee_cache(RelativeEpoch::Current, &self.spec)?; // Apply the received block to its parent state (which has been transitioned into this // slot). - if let Err(e) = per_block_processing(&mut state, &block, &T::EthSpec::spec()) { + if let Err(e) = per_block_processing(&mut state, &block, &self.spec) { return Ok(BlockProcessingOutcome::InvalidBlock( InvalidBlock::PerBlockProcessingError(e), )); @@ -740,7 +738,7 @@ impl BeaconChain { // Register the new block with the fork choice service. self.fork_choice .write() - .add_block(&block, &block_root, &T::EthSpec::spec())?; + .add_block(&block, &block_root, &self.spec)?; // Execute the fork choice algorithm, enthroning a new head if discovered. // @@ -771,7 +769,7 @@ impl BeaconChain { let mut state = self.state.read().clone(); - state.build_committee_cache(RelativeEpoch::Current, &T::EthSpec::spec())?; + state.build_committee_cache(RelativeEpoch::Current, &self.spec)?; trace!("Finding attestations for new block..."); @@ -783,9 +781,8 @@ impl BeaconChain { state.latest_block_header.canonical_root() }; - let (proposer_slashings, attester_slashings) = self - .op_pool - .get_slashings(&*self.state.read(), &T::EthSpec::spec()); + let (proposer_slashings, attester_slashings) = + self.op_pool.get_slashings(&*self.state.read(), &self.spec); let mut block = BeaconBlock { slot: state.slot, @@ -806,16 +803,12 @@ impl BeaconChain { attester_slashings, attestations: self .op_pool - .get_attestations(&*self.state.read(), &T::EthSpec::spec()), - deposits: self - .op_pool - .get_deposits(&*self.state.read(), &T::EthSpec::spec()), + .get_attestations(&*self.state.read(), &self.spec), + deposits: self.op_pool.get_deposits(&*self.state.read(), &self.spec), voluntary_exits: self .op_pool - .get_voluntary_exits(&*self.state.read(), &T::EthSpec::spec()), - transfers: self - .op_pool - .get_transfers(&*self.state.read(), &T::EthSpec::spec()), + .get_voluntary_exits(&*self.state.read(), &self.spec), + transfers: self.op_pool.get_transfers(&*self.state.read(), &self.spec), }, }; @@ -824,11 +817,7 @@ impl BeaconChain { block.body.attestations.len() ); - per_block_processing_without_verifying_block_signature( - &mut state, - &block, - &T::EthSpec::spec(), - )?; + per_block_processing_without_verifying_block_signature(&mut state, &block, &self.spec)?; let state_root = state.canonical_root(); @@ -849,7 +838,7 @@ impl BeaconChain { let justified_root = { let root = self.head().beacon_state.current_justified_root; - if root == T::EthSpec::spec().zero_hash { + if root == self.spec.zero_hash { self.genesis_block_root } else { root @@ -860,7 +849,7 @@ impl BeaconChain { let beacon_block_root = self .fork_choice .write() - .find_head(&justified_root, &T::EthSpec::spec())?; + .find_head(&justified_root, &self.spec)?; // End fork choice metrics timer. timer.observe_duration(); @@ -920,7 +909,7 @@ impl BeaconChain { loop { let beacon_block_root = last_slot.beacon_block.previous_block_root; - if beacon_block_root == T::EthSpec::spec().zero_hash { + if beacon_block_root == self.spec.zero_hash { break; // Genesis has been reached. } diff --git a/beacon_node/beacon_chain/src/iter.rs b/beacon_node/beacon_chain/src/iter.rs index 3147fb207..48caaf618 100644 --- a/beacon_node/beacon_chain/src/iter.rs +++ b/beacon_node/beacon_chain/src/iter.rs @@ -85,8 +85,11 @@ mod test { use types::{test_utils::TestingBeaconStateBuilder, FoundationEthSpec, Keypair}; fn get_state() -> BeaconState { - let builder = - TestingBeaconStateBuilder::from_single_keypair(0, &Keypair::random(), &T::spec()); + let builder = TestingBeaconStateBuilder::from_single_keypair( + 0, + &Keypair::random(), + &T::default_spec(), + ); let (state, _keypairs) = builder.build(); state } diff --git a/beacon_node/client/src/beacon_chain_types.rs b/beacon_node/client/src/beacon_chain_types.rs index 37b1d261d..9747b1dd8 100644 --- a/beacon_node/client/src/beacon_chain_types.rs +++ b/beacon_node/client/src/beacon_chain_types.rs @@ -10,7 +10,8 @@ use slot_clock::SlotClock; use std::sync::Arc; use tree_hash::TreeHash; use types::{ - test_utils::TestingBeaconStateBuilder, BeaconBlock, EthSpec, Hash256, LighthouseTestnetEthSpec, + test_utils::TestingBeaconStateBuilder, BeaconBlock, ChainSpec, EthSpec, Hash256, + LighthouseTestnetEthSpec, }; /// The number initial validators when starting the `LighthouseTestnet`. @@ -18,8 +19,12 @@ const TESTNET_VALIDATOR_COUNT: usize = 16; /// Provides a new, initialized `BeaconChain` pub trait InitialiseBeaconChain { - fn initialise_beacon_chain(store: Arc, log: Logger) -> BeaconChain { - maybe_load_from_store_for_testnet::<_, T::Store, T::EthSpec>(store, log) + fn initialise_beacon_chain( + store: Arc, + spec: ChainSpec, + log: Logger, + ) -> BeaconChain { + maybe_load_from_store_for_testnet::<_, T::Store, T::EthSpec>(store, spec, log) } } @@ -48,13 +53,14 @@ impl InitialiseBeaconChain for TestnetDiskBeaconChainTyp /// Loads a `BeaconChain` from `store`, if it exists. Otherwise, create a new chain from genesis. fn maybe_load_from_store_for_testnet( store: Arc, + spec: ChainSpec, log: Logger, ) -> BeaconChain where T: BeaconChainTypes, T::ForkChoice: ForkChoice, { - if let Ok(Some(beacon_chain)) = BeaconChain::from_store(store.clone()) { + if let Ok(Some(beacon_chain)) = BeaconChain::from_store(store.clone(), spec.clone()) { info!( log, "Loaded BeaconChain from store"; @@ -65,8 +71,6 @@ where beacon_chain } else { info!(log, "Initializing new BeaconChain from genesis"); - let spec = T::EthSpec::spec(); - let state_builder = TestingBeaconStateBuilder::from_default_keypairs_file_if_exists( TESTNET_VALIDATOR_COUNT, &spec, @@ -92,7 +96,7 @@ where slot_clock, genesis_state, genesis_block, - spec.clone(), + spec, fork_choice, ) .expect("Terminate if beacon chain generation fails") diff --git a/beacon_node/client/src/client_config.rs b/beacon_node/client/src/client_config.rs index baa9205ce..a729531ad 100644 --- a/beacon_node/client/src/client_config.rs +++ b/beacon_node/client/src/client_config.rs @@ -4,24 +4,26 @@ use network::NetworkConfig; use serde_derive::{Deserialize, Serialize}; use std::fs; use std::path::PathBuf; +use types::ChainSpec; /// The core configuration of a Lighthouse beacon node. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ClientConfig { pub data_dir: String, - pub spec: String, + pub spec_constants: String, pub db_type: String, db_name: String, pub network: network::NetworkConfig, pub rpc: rpc::RPCConfig, pub http: HttpServerConfig, //pub ipc_conf: + pub spec: ChainSpec, } impl Default for ClientConfig { fn default() -> Self { Self { data_dir: ".lighthouse".to_string(), - spec: "testnet".to_string(), + spec_constants: "testnet".to_string(), db_type: "disk".to_string(), db_name: "chain_db".to_string(), // Note: there are no default bootnodes specified. @@ -29,6 +31,7 @@ impl Default for ClientConfig { network: NetworkConfig::new(vec![]), rpc: rpc::RPCConfig::default(), http: HttpServerConfig::default(), + spec: ChainSpec::lighthouse_testnet(8), } } } diff --git a/beacon_node/client/src/lib.rs b/beacon_node/client/src/lib.rs index 36d1c7d1f..ae28858c5 100644 --- a/beacon_node/client/src/lib.rs +++ b/beacon_node/client/src/lib.rs @@ -17,7 +17,6 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::runtime::TaskExecutor; use tokio::timer::Interval; -use types::EthSpec; pub use beacon_chain::BeaconChainTypes; pub use beacon_chain_types::InitialiseBeaconChain; @@ -58,10 +57,14 @@ where ) -> error::Result { let metrics_registry = Registry::new(); let store = Arc::new(store); - let spec = T::EthSpec::spec(); + let seconds_per_slot = config.spec.seconds_per_slot; // Load a `BeaconChain` from the store, or create a new one if it does not exist. - let beacon_chain = Arc::new(T::initialise_beacon_chain(store, log.clone())); + let beacon_chain = Arc::new(T::initialise_beacon_chain( + store, + config.spec.clone(), + log.clone(), + )); // Registry all beacon chain metrics with the global registry. beacon_chain .metrics @@ -143,7 +146,7 @@ where // set up the validator work interval - start at next slot and proceed every slot let interval = { // Set the interval to start at the next slot, and every slot after - let slot_duration = Duration::from_secs(spec.seconds_per_slot); + let slot_duration = Duration::from_secs(seconds_per_slot); //TODO: Handle checked add correctly Interval::new(Instant::now() + duration_to_next_slot, slot_duration) }; diff --git a/beacon_node/eth2-libp2p/src/behaviour.rs b/beacon_node/eth2-libp2p/src/behaviour.rs index 8f3a000e1..476cddfbb 100644 --- a/beacon_node/eth2-libp2p/src/behaviour.rs +++ b/beacon_node/eth2-libp2p/src/behaviour.rs @@ -261,7 +261,7 @@ mod test { #[test] fn ssz_encoding() { - let original = PubsubMessage::Block(BeaconBlock::empty(&FoundationEthSpec::spec())); + let original = PubsubMessage::Block(BeaconBlock::empty(&FoundationEthSpec::default_spec())); let encoded = ssz_encode(&original); diff --git a/beacon_node/http_server/src/api.rs b/beacon_node/http_server/src/api.rs index 2594f9c28..a91080899 100644 --- a/beacon_node/http_server/src/api.rs +++ b/beacon_node/http_server/src/api.rs @@ -10,7 +10,6 @@ use persistent::Read; use router::Router; use serde_json::json; use std::sync::Arc; -use types::EthSpec; /// Yields a handler for the HTTP API. pub fn build_handler( @@ -65,7 +64,7 @@ fn handle_fork(req: &mut Request) -> IronResult SimpleSync { hello: HelloMessage, network: &mut NetworkContext, ) { - let spec = T::EthSpec::spec(); + let spec = &self.chain.spec; let remote = PeerSyncInfo::from(hello); let local = PeerSyncInfo::from(&self.chain); @@ -214,7 +214,7 @@ impl SimpleSync { debug!(self.log, "Peer has high finalized epoch"; "peer" => format!("{:?}", peer_id)); let start_slot = local .latest_finalized_epoch - .start_slot(spec.slots_per_epoch); + .start_slot(T::EthSpec::slots_per_epoch()); let required_slots = remote.best_slot - start_slot; self.request_block_roots( @@ -231,7 +231,7 @@ impl SimpleSync { debug!(self.log, "Peer has higher best slot"; "peer" => format!("{:?}", peer_id)); let start_slot = local .latest_finalized_epoch - .start_slot(spec.slots_per_epoch); + .start_slot(T::EthSpec::slots_per_epoch()); let required_slots = remote.best_slot - start_slot; self.request_block_roots( @@ -795,7 +795,7 @@ impl SimpleSync { fn slot_is_finalized(&self, slot: Slot) -> bool { slot <= hello_message(&self.chain) .latest_finalized_epoch - .start_slot(T::EthSpec::spec().slots_per_epoch) + .start_slot(T::EthSpec::slots_per_epoch()) } /// Generates our current state in the form of a HELLO RPC message. @@ -806,7 +806,7 @@ impl SimpleSync { /// Build a `HelloMessage` representing the state of the given `beacon_chain`. fn hello_message(beacon_chain: &BeaconChain) -> HelloMessage { - let spec = T::EthSpec::spec(); + let spec = &beacon_chain.spec; let state = &beacon_chain.head().beacon_state; HelloMessage { diff --git a/beacon_node/rpc/src/beacon_node.rs b/beacon_node/rpc/src/beacon_node.rs index 8b49b193e..631601ac9 100644 --- a/beacon_node/rpc/src/beacon_node.rs +++ b/beacon_node/rpc/src/beacon_node.rs @@ -5,7 +5,6 @@ use protos::services::{Empty, Fork, NodeInfoResponse}; use protos::services_grpc::BeaconNodeService; use slog::{trace, warn}; use std::sync::Arc; -use types::EthSpec; #[derive(Clone)] pub struct BeaconNodeServiceInstance { @@ -33,7 +32,7 @@ impl BeaconNodeService for BeaconNodeServiceInstance { fork.set_current_version(state_fork.current_version.to_vec()); fork.set_epoch(state_fork.epoch.into()); - let spec = T::EthSpec::spec(); + let spec = &self.chain.spec; node_info.set_fork(fork); node_info.set_genesis_time(genesis_time); diff --git a/beacon_node/rpc/src/validator.rs b/beacon_node/rpc/src/validator.rs index 2cd374d25..b13303e25 100644 --- a/beacon_node/rpc/src/validator.rs +++ b/beacon_node/rpc/src/validator.rs @@ -14,7 +14,6 @@ pub struct ValidatorServiceInstance { pub chain: Arc>, pub log: slog::Logger, } -//TODO: Refactor Errors impl ValidatorService for ValidatorServiceInstance { /// For a list of validator public keys, this function returns the slot at which each @@ -29,14 +28,15 @@ impl ValidatorService for ValidatorServiceInstance { let validators = req.get_validators(); trace!(self.log, "RPC request"; "endpoint" => "GetValidatorDuties", "epoch" => req.get_epoch()); - let spec = T::EthSpec::spec(); + let spec = &self.chain.spec; let state = &self.chain.current_state(); let epoch = Epoch::from(req.get_epoch()); let mut resp = GetDutiesResponse::new(); let resp_validators = resp.mut_active_validators(); let relative_epoch = - match RelativeEpoch::from_epoch(state.slot.epoch(spec.slots_per_epoch), epoch) { + match RelativeEpoch::from_epoch(state.slot.epoch(T::EthSpec::slots_per_epoch()), epoch) + { Ok(v) => v, Err(e) => { // incorrect epoch @@ -52,7 +52,7 @@ impl ValidatorService for ValidatorServiceInstance { }; let validator_proposers: Result, _> = epoch - .slot_iter(spec.slots_per_epoch) + .slot_iter(T::EthSpec::slots_per_epoch()) .map(|slot| state.get_beacon_proposer_index(slot, relative_epoch, &spec)) .collect(); let validator_proposers = match validator_proposers { @@ -148,7 +148,7 @@ impl ValidatorService for ValidatorServiceInstance { // check if the validator needs to propose a block if let Some(slot) = validator_proposers.iter().position(|&v| val_index == v) { duty.set_block_production_slot( - epoch.start_slot(spec.slots_per_epoch).as_u64() + slot as u64, + epoch.start_slot(T::EthSpec::slots_per_epoch()).as_u64() + slot as u64, ); } else { // no blocks to propose this epoch diff --git a/beacon_node/src/run.rs b/beacon_node/src/run.rs index f3d656ad3..0638e9ec9 100644 --- a/beacon_node/src/run.rs +++ b/beacon_node/src/run.rs @@ -27,11 +27,11 @@ pub fn run_beacon_node(config: ClientConfig, log: &slog::Logger) -> error::Resul .db_path() .ok_or_else::(|| "Unable to access database path".into())?; let db_type = &config.db_type; - let spec = &config.spec; + let spec_constants = &config.spec_constants; let other_config = config.clone(); - let result = match (db_type.as_str(), spec.as_str()) { + let result = match (db_type.as_str(), spec_constants.as_str()) { ("disk", "testnet") => { run::(&db_path, config, executor, runtime, log) } @@ -50,7 +50,7 @@ pub fn run_beacon_node(config: ClientConfig, log: &slog::Logger) -> error::Resul "Started beacon node"; "p2p_listen_addresses" => format!("{:?}", &other_config.network.listen_addresses()), "data_dir" => format!("{:?}", other_config.data_dir()), - "spec" => &other_config.spec, + "spec_constants" => &other_config.spec_constants, "db_type" => &other_config.db_type, ); } diff --git a/beacon_node/store/src/block_at_slot.rs b/beacon_node/store/src/block_at_slot.rs index 260a35114..b7346e90d 100644 --- a/beacon_node/store/src/block_at_slot.rs +++ b/beacon_node/store/src/block_at_slot.rs @@ -61,7 +61,7 @@ mod tests { #[test] fn read_slot() { - let spec = FewValidatorsEthSpec::spec(); + let spec = FewValidatorsEthSpec::default_spec(); let test_slot = |slot: Slot| { let mut block = BeaconBlock::empty(&spec); @@ -85,7 +85,7 @@ mod tests { #[test] fn read_previous_block_root() { - let spec = FewValidatorsEthSpec::spec(); + let spec = FewValidatorsEthSpec::default_spec(); let test_root = |root: Hash256| { let mut block = BeaconBlock::empty(&spec); @@ -130,7 +130,7 @@ mod tests { fn chain_without_skips() { let n: usize = 10; let store = MemoryStore::open(); - let spec = FewValidatorsEthSpec::spec(); + let spec = FewValidatorsEthSpec::default_spec(); let slots: Vec = (0..n).collect(); let blocks_and_roots = build_chain(&store, &slots, &spec); @@ -154,7 +154,7 @@ mod tests { #[test] fn chain_with_skips() { let store = MemoryStore::open(); - let spec = FewValidatorsEthSpec::spec(); + let spec = FewValidatorsEthSpec::default_spec(); let slots = vec![0, 1, 2, 5]; diff --git a/eth2/fork_choice/benches/benches.rs b/eth2/fork_choice/benches/benches.rs index 065cde655..b0495a80c 100644 --- a/eth2/fork_choice/benches/benches.rs +++ b/eth2/fork_choice/benches/benches.rs @@ -19,7 +19,7 @@ fn setup( let store = MemoryStore::open(); let builder: TestingForkChoiceBuilder = TestingForkChoiceBuilder::new(validator_count, chain_length, Arc::new(store)); - let spec = TestedEthSpec::spec(); + let spec = TestedEthSpec::default_spec(); (builder, spec) } diff --git a/eth2/fork_choice/examples/example.rs b/eth2/fork_choice/examples/example.rs index 927cf23b7..7e42ad144 100644 --- a/eth2/fork_choice/examples/example.rs +++ b/eth2/fork_choice/examples/example.rs @@ -17,7 +17,7 @@ fn main() { .map(|_| builder.build()) .collect(); - let spec = &FoundationEthSpec::spec(); + let spec = &FoundationEthSpec::default_spec(); println!("Running {} times...", repetitions); for fc in fork_choosers { diff --git a/eth2/fork_choice/src/bitwise_lmd_ghost.rs b/eth2/fork_choice/src/bitwise_lmd_ghost.rs index f78a8e780..3ed57bf4d 100644 --- a/eth2/fork_choice/src/bitwise_lmd_ghost.rs +++ b/eth2/fork_choice/src/bitwise_lmd_ghost.rs @@ -68,7 +68,7 @@ impl BitwiseLMDGhost { .ok_or_else(|| ForkChoiceError::MissingBeaconState(*state_root))?; let active_validator_indices = - current_state.get_active_validator_indices(block_slot.epoch(spec.slots_per_epoch)); + current_state.get_active_validator_indices(block_slot.epoch(E::slots_per_epoch())); for index in active_validator_indices { let balance = std::cmp::min(current_state.balances[index], spec.max_effective_balance) diff --git a/eth2/fork_choice/src/optimized_lmd_ghost.rs b/eth2/fork_choice/src/optimized_lmd_ghost.rs index b389d0981..7a48c461e 100644 --- a/eth2/fork_choice/src/optimized_lmd_ghost.rs +++ b/eth2/fork_choice/src/optimized_lmd_ghost.rs @@ -68,7 +68,7 @@ impl OptimizedLMDGhost { .ok_or_else(|| ForkChoiceError::MissingBeaconState(*state_root))?; let active_validator_indices = - current_state.get_active_validator_indices(block_slot.epoch(spec.slots_per_epoch)); + current_state.get_active_validator_indices(block_slot.epoch(E::slots_per_epoch())); for index in active_validator_indices { let balance = std::cmp::min(current_state.balances[index], spec.max_effective_balance) diff --git a/eth2/fork_choice/src/slow_lmd_ghost.rs b/eth2/fork_choice/src/slow_lmd_ghost.rs index 7b5114887..9b7a20400 100644 --- a/eth2/fork_choice/src/slow_lmd_ghost.rs +++ b/eth2/fork_choice/src/slow_lmd_ghost.rs @@ -40,7 +40,7 @@ impl SlowLMDGhost { .ok_or_else(|| ForkChoiceError::MissingBeaconState(*state_root))?; let active_validator_indices = - current_state.get_active_validator_indices(block_slot.epoch(spec.slots_per_epoch)); + current_state.get_active_validator_indices(block_slot.epoch(E::slots_per_epoch())); for index in active_validator_indices { let balance = std::cmp::min(current_state.balances[index], spec.max_effective_balance) diff --git a/eth2/fork_choice/src/test_utils.rs b/eth2/fork_choice/src/test_utils.rs index 76264fcb6..c3bf39930 100644 --- a/eth2/fork_choice/src/test_utils.rs +++ b/eth2/fork_choice/src/test_utils.rs @@ -40,10 +40,10 @@ impl TestingForkChoiceBuilder { } fn get_state(validator_count: usize) -> BeaconState { - let spec = &T::spec(); + let spec = T::default_spec(); let builder: TestingBeaconStateBuilder = - TestingBeaconStateBuilder::from_single_keypair(validator_count, &Keypair::random(), spec); + TestingBeaconStateBuilder::from_single_keypair(validator_count, &Keypair::random(), &spec); let (state, _keypairs) = builder.build(); state } @@ -58,7 +58,7 @@ fn get_chain_of_blocks( validator_count: usize, store: Arc, ) -> Vec<(Hash256, BeaconBlock)> { - let spec = T::spec(); + let spec = T::default_spec(); let mut blocks_and_roots: Vec<(Hash256, BeaconBlock)> = vec![]; let mut unique_hashes = (0..).into_iter().map(|i| Hash256::from(i)); let mut random_block = BeaconBlock::random_for_test(&mut XorShiftRng::from_seed([42; 16])); diff --git a/eth2/fork_choice/tests/tests.rs b/eth2/fork_choice/tests/tests.rs index 9270571ca..59e4e0ee0 100644 --- a/eth2/fork_choice/tests/tests.rs +++ b/eth2/fork_choice/tests/tests.rs @@ -61,7 +61,7 @@ fn test_yaml_vectors>( let test_cases = load_test_cases_from_yaml(yaml_file_path); // default vars - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); let zero_hash = Hash256::zero(); let eth1_data = Eth1Data { deposit_count: 0, @@ -204,7 +204,7 @@ where let store = Arc::new(MemoryStore::open()); let fork_choice = ForkChoice::new(store.clone()); - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); let mut state_builder: TestingBeaconStateBuilder = TestingBeaconStateBuilder::from_single_keypair(num_validators, &Keypair::random(), &spec); diff --git a/eth2/operation_pool/src/lib.rs b/eth2/operation_pool/src/lib.rs index 0affba3f4..0cd46e018 100644 --- a/eth2/operation_pool/src/lib.rs +++ b/eth2/operation_pool/src/lib.rs @@ -676,7 +676,7 @@ mod tests { } fn test_state(rng: &mut XorShiftRng) -> (ChainSpec, BeaconState) { - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); let mut state = BeaconState::random_for_test(rng); @@ -721,21 +721,21 @@ mod tests { fn attestation_test_state( num_committees: usize, ) -> (BeaconState, Vec, ChainSpec) { - let spec = E::spec(); + let spec = E::default_spec(); let num_validators = - num_committees * spec.slots_per_epoch as usize * spec.target_committee_size; + num_committees * T::slots_per_epoch() as usize * spec.target_committee_size; let mut state_builder = TestingBeaconStateBuilder::from_default_keypairs_file_if_exists( num_validators, &spec, ); - let slot_offset = 1000 * spec.slots_per_epoch + spec.slots_per_epoch / 2; + let slot_offset = 1000 * T::slots_per_epoch() + T::slots_per_epoch() / 2; let slot = spec.genesis_slot + slot_offset; state_builder.teleport_to_slot(slot, &spec); state_builder.build_caches(&spec).unwrap(); let (state, keypairs) = state_builder.build(); - (state, keypairs, FoundationEthSpec::spec()) + (state, keypairs, FoundationEthSpec::default_spec()) } #[test] @@ -852,7 +852,7 @@ mod tests { // But once we advance to more than an epoch after the attestation, it should prune it // out of existence. - state.slot += 2 * spec.slots_per_epoch; + state.slot += 2 * T::slots_per_epoch(); op_pool.prune_attestations(state); assert_eq!(op_pool.num_attestations(), 0); } diff --git a/eth2/state_processing/benches/bench_epoch_processing.rs b/eth2/state_processing/benches/bench_epoch_processing.rs index 9bff3a2e3..23e662e09 100644 --- a/eth2/state_processing/benches/bench_epoch_processing.rs +++ b/eth2/state_processing/benches/bench_epoch_processing.rs @@ -23,7 +23,7 @@ pub fn bench_epoch_processing_n_validators(c: &mut Criterion, validator_count: u TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(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); + let target_slot = (spec.genesis_epoch + 4).end_slot(T::slots_per_epoch()); builder.teleport_to_slot(target_slot, &spec); // Builds all caches; benches will not contain shuffling/committee building times. @@ -38,10 +38,10 @@ pub fn bench_epoch_processing_n_validators(c: &mut Criterion, validator_count: u // Assert that the state has an attestations for each committee that is able to include an // attestation in the state. let committees_per_epoch = spec.get_epoch_committee_count(validator_count); - let committees_per_slot = committees_per_epoch / spec.slots_per_epoch; + let committees_per_slot = committees_per_epoch / T::slots_per_epoch(); let previous_epoch_attestations = committees_per_epoch; let current_epoch_attestations = - committees_per_slot * (spec.slots_per_epoch - spec.min_attestation_inclusion_delay); + committees_per_slot * (T::slots_per_epoch() - spec.min_attestation_inclusion_delay); assert_eq!( state.latest_attestations.len() as u64, previous_epoch_attestations + current_epoch_attestations, diff --git a/eth2/state_processing/benches/benches.rs b/eth2/state_processing/benches/benches.rs index 0cf797147..1a153abee 100644 --- a/eth2/state_processing/benches/benches.rs +++ b/eth2/state_processing/benches/benches.rs @@ -34,7 +34,7 @@ pub fn block_processing_worst_case(c: &mut Criterion) { bench_builder.maximize_block_operations(&spec); // Set the state and block to be in the last slot of the 4th epoch. - let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch); + let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(T::slots_per_epoch()); bench_builder.set_slot(last_slot_of_epoch, &spec); // Build all the state caches so the build times aren't included in the benches. @@ -67,13 +67,13 @@ pub fn block_processing_reasonable_case(c: &mut Criterion) { // Set the number of included operations to what we might expect normally. bench_builder.num_proposer_slashings = 0; bench_builder.num_attester_slashings = 0; - bench_builder.num_attestations = (spec.shard_count / spec.slots_per_epoch) as usize; + bench_builder.num_attestations = (spec.shard_count / T::slots_per_epoch()) as usize; bench_builder.num_deposits = 2; bench_builder.num_exits = 2; bench_builder.num_transfers = 2; // Set the state and block to be in the last slot of the 4th epoch. - let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch); + let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(T::slots_per_epoch()); bench_builder.set_slot(last_slot_of_epoch, &spec); // Build all the state caches so the build times aren't included in the benches. diff --git a/eth2/state_processing/src/per_block_processing.rs b/eth2/state_processing/src/per_block_processing.rs index 56238f9c2..437cd459c 100644 --- a/eth2/state_processing/src/per_block_processing.rs +++ b/eth2/state_processing/src/per_block_processing.rs @@ -140,7 +140,7 @@ pub fn verify_block_signature( [state.get_beacon_proposer_index(block.slot, RelativeEpoch::Current, spec)?]; let domain = spec.get_domain( - block.slot.epoch(spec.slots_per_epoch), + block.slot.epoch(T::slots_per_epoch()), Domain::BeaconProposer, &state.fork, ); @@ -172,7 +172,7 @@ pub fn process_randao( block.body.randao_reveal.verify( &state.current_epoch().tree_hash_root()[..], spec.get_domain( - block.slot.epoch(spec.slots_per_epoch), + block.slot.epoch(T::slots_per_epoch()), Domain::Randao, &state.fork ), diff --git a/eth2/state_processing/src/per_block_processing/block_processing_builder.rs b/eth2/state_processing/src/per_block_processing/block_processing_builder.rs index 35e736d5f..5a9d264ce 100644 --- a/eth2/state_processing/src/per_block_processing/block_processing_builder.rs +++ b/eth2/state_processing/src/per_block_processing/block_processing_builder.rs @@ -55,11 +55,13 @@ impl BlockProcessingBuilder { let keypair = &keypairs[proposer_index]; match randao_sk { - Some(sk) => builder.set_randao_reveal(&sk, &state.fork, spec), - None => builder.set_randao_reveal(&keypair.sk, &state.fork, spec), + Some(sk) => builder.set_randao_reveal::(&sk, &state.fork, spec), + None => builder.set_randao_reveal::(&keypair.sk, &state.fork, spec), } - let block = self.block_builder.build(&keypair.sk, &state.fork, spec); + let block = self + .block_builder + .build::(&keypair.sk, &state.fork, spec); (block, state) } diff --git a/eth2/state_processing/src/per_block_processing/tests.rs b/eth2/state_processing/src/per_block_processing/tests.rs index 28ed9c4f0..fe30560c6 100644 --- a/eth2/state_processing/src/per_block_processing/tests.rs +++ b/eth2/state_processing/src/per_block_processing/tests.rs @@ -9,7 +9,7 @@ pub const VALIDATOR_COUNT: usize = 10; #[test] fn valid_block_ok() { - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); let builder = get_builder(&spec); let (block, mut state) = builder.build(None, None, &spec); @@ -20,7 +20,7 @@ fn valid_block_ok() { #[test] fn invalid_block_header_state_slot() { - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); let builder = get_builder(&spec); let (mut block, mut state) = builder.build(None, None, &spec); @@ -39,7 +39,7 @@ fn invalid_block_header_state_slot() { #[test] fn invalid_parent_block_root() { - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); let builder = get_builder(&spec); let invalid_parent_root = Hash256::from([0xAA; 32]); let (block, mut state) = builder.build(None, Some(invalid_parent_root), &spec); @@ -59,14 +59,14 @@ fn invalid_parent_block_root() { #[test] fn invalid_block_signature() { - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); let builder = get_builder(&spec); let (mut block, mut state) = builder.build(None, None, &spec); // sign the block with a keypair that is not the expected proposer let keypair = Keypair::random(); let message = block.signed_root(); - let epoch = block.slot.epoch(spec.slots_per_epoch); + let epoch = block.slot.epoch(FoundationEthSpec::slots_per_epoch()); let domain = spec.get_domain(epoch, Domain::BeaconProposer, &state.fork); block.signature = Signature::new(&message, domain, &keypair.sk); @@ -82,7 +82,7 @@ fn invalid_block_signature() { #[test] fn invalid_randao_reveal_signature() { - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); let builder = get_builder(&spec); // sign randao reveal with random keypair @@ -104,7 +104,8 @@ fn get_builder(spec: &ChainSpec) -> (BlockProcessingBuilder) let mut builder = BlockProcessingBuilder::new(VALIDATOR_COUNT, &spec); // Set the state and block to be in the last slot of the 4th epoch. - let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch); + let last_slot_of_epoch = + (spec.genesis_epoch + 4).end_slot(FoundationEthSpec::slots_per_epoch()); builder.set_slot(last_slot_of_epoch, &spec); builder.build_caches(&spec); diff --git a/eth2/state_processing/src/per_block_processing/validate_attestation.rs b/eth2/state_processing/src/per_block_processing/validate_attestation.rs index 1058c0d21..379b921f4 100644 --- a/eth2/state_processing/src/per_block_processing/validate_attestation.rs +++ b/eth2/state_processing/src/per_block_processing/validate_attestation.rs @@ -68,7 +68,7 @@ fn validate_attestation_parametric( } ); verify!( - state.slot <= attestation_slot + spec.slots_per_epoch, + state.slot <= attestation_slot + T::slots_per_epoch(), Invalid::IncludedTooLate { state: state.slot, attestation: attestation_slot diff --git a/eth2/state_processing/src/per_block_processing/verify_proposer_slashing.rs b/eth2/state_processing/src/per_block_processing/verify_proposer_slashing.rs index 98a9a248c..744427ad9 100644 --- a/eth2/state_processing/src/per_block_processing/verify_proposer_slashing.rs +++ b/eth2/state_processing/src/per_block_processing/verify_proposer_slashing.rs @@ -21,8 +21,8 @@ pub fn verify_proposer_slashing( })?; verify!( - proposer_slashing.header_1.slot.epoch(spec.slots_per_epoch) - == proposer_slashing.header_2.slot.epoch(spec.slots_per_epoch), + proposer_slashing.header_1.slot.epoch(T::slots_per_epoch()) + == proposer_slashing.header_2.slot.epoch(T::slots_per_epoch()), Invalid::ProposalEpochMismatch( proposer_slashing.header_1.slot, proposer_slashing.header_2.slot @@ -40,7 +40,7 @@ pub fn verify_proposer_slashing( ); verify!( - verify_header_signature( + verify_header_signature::( &proposer_slashing.header_1, &proposer.pubkey, &state.fork, @@ -49,7 +49,7 @@ pub fn verify_proposer_slashing( Invalid::BadProposal1Signature ); verify!( - verify_header_signature( + verify_header_signature::( &proposer_slashing.header_2, &proposer.pubkey, &state.fork, @@ -66,7 +66,7 @@ pub fn verify_proposer_slashing( /// Returns `true` if the signature is valid. /// /// Spec v0.6.1 -fn verify_header_signature( +fn verify_header_signature( header: &BeaconBlockHeader, pubkey: &PublicKey, fork: &Fork, @@ -74,7 +74,7 @@ fn verify_header_signature( ) -> bool { let message = header.signed_root(); let domain = spec.get_domain( - header.slot.epoch(spec.slots_per_epoch), + header.slot.epoch(T::slots_per_epoch()), Domain::BeaconProposer, fork, ); diff --git a/eth2/state_processing/src/per_block_processing/verify_transfer.rs b/eth2/state_processing/src/per_block_processing/verify_transfer.rs index 15c142d90..de4cef44f 100644 --- a/eth2/state_processing/src/per_block_processing/verify_transfer.rs +++ b/eth2/state_processing/src/per_block_processing/verify_transfer.rs @@ -101,7 +101,7 @@ fn verify_transfer_parametric( .get(transfer.sender as usize) .ok_or_else(|| Error::Invalid(Invalid::FromValidatorUnknown(transfer.sender)))?; - let epoch = state.slot.epoch(spec.slots_per_epoch); + let epoch = state.slot.epoch(T::slots_per_epoch()); // Ensure one of the following is met: // @@ -136,7 +136,7 @@ fn verify_transfer_parametric( // Verify the transfer signature. let message = transfer.signed_root(); let domain = spec.get_domain( - transfer.slot.epoch(spec.slots_per_epoch), + transfer.slot.epoch(T::slots_per_epoch()), Domain::Transfer, &state.fork, ); diff --git a/eth2/state_processing/src/per_epoch_processing.rs b/eth2/state_processing/src/per_epoch_processing.rs index d261b8b47..290c33804 100644 --- a/eth2/state_processing/src/per_epoch_processing.rs +++ b/eth2/state_processing/src/per_epoch_processing.rs @@ -237,7 +237,7 @@ pub fn process_final_updates( state.slot -= 1; } - if next_epoch.as_u64() % (T::SlotsPerHistoricalRoot::to_u64() / spec.slots_per_epoch) == 0 { + if next_epoch.as_u64() % (T::SlotsPerHistoricalRoot::to_u64() / T::slots_per_epoch()) == 0 { let historical_batch = state.historical_batch(); state .historical_roots diff --git a/eth2/state_processing/src/per_epoch_processing/tests.rs b/eth2/state_processing/src/per_epoch_processing/tests.rs index 9841a5551..0e5a81cce 100644 --- a/eth2/state_processing/src/per_epoch_processing/tests.rs +++ b/eth2/state_processing/src/per_epoch_processing/tests.rs @@ -8,12 +8,12 @@ use types::*; fn runs_without_error() { Builder::from_env(Env::default().default_filter_or("error")).init(); - let spec = FewValidatorsEthSpec::spec(); + let spec = FewValidatorsEthSpec::default_spec(); let mut builder: TestingBeaconStateBuilder = TestingBeaconStateBuilder::from_deterministic_keypairs(8, &spec); - let target_slot = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch); + let target_slot = (spec.genesis_epoch + 4).end_slot(FewValidatorsEthSpec::slots_per_epoch()); builder.teleport_to_slot(target_slot, &spec); let (mut state, _keypairs) = builder.build(); diff --git a/eth2/state_processing/src/per_epoch_processing/validator_statuses.rs b/eth2/state_processing/src/per_epoch_processing/validator_statuses.rs index ed1b968d7..76a485ea7 100644 --- a/eth2/state_processing/src/per_epoch_processing/validator_statuses.rs +++ b/eth2/state_processing/src/per_epoch_processing/validator_statuses.rs @@ -233,7 +233,7 @@ impl ValidatorStatuses { let attestation_slot = state.get_attestation_slot(&a.data)?; let inclusion_slot = attestation_slot + a.inclusion_delay; let relative_epoch = - RelativeEpoch::from_slot(state.slot, inclusion_slot, spec.slots_per_epoch)?; + RelativeEpoch::from_slot(state.slot, inclusion_slot, T::slots_per_epoch())?; status.inclusion_info = Some(InclusionInfo { slot: inclusion_slot, distance: a.inclusion_delay, @@ -297,7 +297,7 @@ impl ValidatorStatuses { spec: &ChainSpec, ) -> Result<(), BeaconStateError> { // Loop through each slot in the previous epoch. - for slot in state.previous_epoch().slot_iter(spec.slots_per_epoch) { + for slot in state.previous_epoch().slot_iter(T::slots_per_epoch()) { let crosslink_committees_at_slot = state.get_crosslink_committees_at_slot(slot)?; // Loop through each committee in the slot. @@ -338,7 +338,7 @@ fn target_matches_epoch_start_block( epoch: Epoch, spec: &ChainSpec, ) -> Result { - let slot = epoch.start_slot(spec.slots_per_epoch); + let slot = epoch.start_slot(T::slots_per_epoch()); let state_boundary_root = *state.get_block_root(slot)?; Ok(a.data.target_root == state_boundary_root) diff --git a/eth2/state_processing/src/per_slot_processing.rs b/eth2/state_processing/src/per_slot_processing.rs index 0fc074262..8adfe988b 100644 --- a/eth2/state_processing/src/per_slot_processing.rs +++ b/eth2/state_processing/src/per_slot_processing.rs @@ -16,7 +16,7 @@ pub fn per_slot_processing( ) -> Result<(), Error> { cache_state(state, spec)?; - if (state.slot > spec.genesis_slot) && ((state.slot + 1) % spec.slots_per_epoch == 0) { + if (state.slot > spec.genesis_slot) && ((state.slot + 1) % T::slots_per_epoch() == 0) { per_epoch_processing(state, spec)?; } diff --git a/eth2/types/src/beacon_state.rs b/eth2/types/src/beacon_state.rs index b93738328..27a2e7a0e 100644 --- a/eth2/types/src/beacon_state.rs +++ b/eth2/types/src/beacon_state.rs @@ -458,7 +458,7 @@ impl BeaconState { epoch: Epoch, spec: &ChainSpec, ) -> Result<&Hash256, BeaconStateError> { - self.get_block_root(epoch.start_slot(spec.slots_per_epoch)) + self.get_block_root(epoch.start_slot(T::slots_per_epoch())) } /// Sets the block root for some given slot. diff --git a/eth2/types/src/beacon_state/beacon_state_types.rs b/eth2/types/src/beacon_state/beacon_state_types.rs index ec6eb68bc..fce0c6dff 100644 --- a/eth2/types/src/beacon_state/beacon_state_types.rs +++ b/eth2/types/src/beacon_state/beacon_state_types.rs @@ -1,5 +1,5 @@ use crate::*; -use fixed_len_vec::typenum::{Unsigned, U1024, U8, U8192}; +use fixed_len_vec::typenum::{Unsigned, U0, U1024, U64, U8, U8192}; use serde_derive::{Deserialize, Serialize}; use std::fmt::Debug; @@ -9,14 +9,24 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq { type LatestRandaoMixesLength: Unsigned + Clone + Sync + Send + Debug + PartialEq; type LatestActiveIndexRootsLength: Unsigned + Clone + Sync + Send + Debug + PartialEq; type LatestSlashedExitLength: Unsigned + Clone + Sync + Send + Debug + PartialEq; + /// Note: `SlotsPerEpoch` is not necessarily required to be a compile-time constant. We include + /// it here just for the convenience of not passing `slots_per_epoch` around all the time. + type SlotsPerEpoch: Unsigned + Clone + Sync + Send + Debug + PartialEq; + type GenesisEpoch: Unsigned + Clone + Sync + Send + Debug + PartialEq; - fn spec() -> ChainSpec; + fn default_spec() -> ChainSpec; + + fn genesis_epoch() -> Epoch { + Epoch::new(Self::GenesisEpoch::to_u64()) + } /// Return the number of committees in one epoch. /// /// Spec v0.6.1 - fn get_epoch_committee_count(active_validator_count: usize) -> usize { - let target_committee_size = Self::spec().target_committee_size; + fn get_epoch_committee_count( + active_validator_count: usize, + target_committee_size: usize, + ) -> usize { let shard_count = Self::shard_count(); let slots_per_epoch = Self::slots_per_epoch() as usize; @@ -35,21 +45,14 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq { /// basic sense. This count is not required to provide any security guarantees regarding /// decentralization, entropy, etc. fn minimum_validator_count() -> usize { - Self::slots_per_epoch() as usize + Self::SlotsPerEpoch::to_usize() } /// Returns the `SLOTS_PER_EPOCH` constant for this specification. /// /// Spec v0.6.1 fn slots_per_epoch() -> u64 { - Self::spec().slots_per_epoch - } - - /// Returns the `SLOTS_PER_EPOCH` constant for this specification. - /// - /// Spec v0.6.1 - fn genesis_epoch() -> Epoch { - Self::spec().genesis_epoch + Self::SlotsPerEpoch::to_u64() } /// Returns the `SHARD_COUNT` constant for this specification. @@ -100,8 +103,10 @@ impl EthSpec for FoundationEthSpec { type LatestRandaoMixesLength = U8192; type LatestActiveIndexRootsLength = U8192; type LatestSlashedExitLength = U8192; + type SlotsPerEpoch = U64; + type GenesisEpoch = U0; - fn spec() -> ChainSpec { + fn default_spec() -> ChainSpec { ChainSpec::foundation() } } @@ -118,9 +123,11 @@ impl EthSpec for FewValidatorsEthSpec { type LatestRandaoMixesLength = U8192; type LatestActiveIndexRootsLength = U8192; type LatestSlashedExitLength = U8192; + type SlotsPerEpoch = U8; + type GenesisEpoch = U0; - fn spec() -> ChainSpec { - ChainSpec::few_validators() + fn default_spec() -> ChainSpec { + ChainSpec::few_validators(Self::slots_per_epoch()) } } @@ -136,9 +143,11 @@ impl EthSpec for LighthouseTestnetEthSpec { type LatestRandaoMixesLength = U8192; type LatestActiveIndexRootsLength = U8192; type LatestSlashedExitLength = U8192; + type SlotsPerEpoch = U8; + type GenesisEpoch = U0; - fn spec() -> ChainSpec { - ChainSpec::lighthouse_testnet() + fn default_spec() -> ChainSpec { + ChainSpec::lighthouse_testnet(Self::slots_per_epoch()) } } diff --git a/eth2/types/src/beacon_state/committee_cache.rs b/eth2/types/src/beacon_state/committee_cache.rs index d1e0e7030..78af72754 100644 --- a/eth2/types/src/beacon_state/committee_cache.rs +++ b/eth2/types/src/beacon_state/committee_cache.rs @@ -45,13 +45,18 @@ impl CommitteeCache { return Err(Error::InsufficientValidators); } - let committee_count = T::get_epoch_committee_count(active_validator_indices.len()) as usize; + let committee_count = T::get_epoch_committee_count( + active_validator_indices.len(), + spec.target_committee_size, + ) as usize; let shuffling_start_shard = match relative_epoch { RelativeEpoch::Current => state.latest_start_shard, RelativeEpoch::Previous => { - let committees_in_previous_epoch = - T::get_epoch_committee_count(active_validator_indices.len()) as u64; + let committees_in_previous_epoch = T::get_epoch_committee_count( + active_validator_indices.len(), + spec.target_committee_size, + ) as u64; (state.latest_start_shard + T::shard_count() as u64 - committees_in_previous_epoch) % T::shard_count() as u64 @@ -59,8 +64,10 @@ impl CommitteeCache { RelativeEpoch::Next => { let current_active_validators = get_active_validator_count(&state.validator_registry, state.current_epoch()); - let committees_in_current_epoch = - T::get_epoch_committee_count(current_active_validators) as u64; + let committees_in_current_epoch = T::get_epoch_committee_count( + current_active_validators, + spec.target_committee_size, + ) as u64; (state.latest_start_shard + committees_in_current_epoch) % T::shard_count() as u64 } diff --git a/eth2/types/src/beacon_state/committee_cache/tests.rs b/eth2/types/src/beacon_state/committee_cache/tests.rs index ecaa3d457..e9b417e3d 100644 --- a/eth2/types/src/beacon_state/committee_cache/tests.rs +++ b/eth2/types/src/beacon_state/committee_cache/tests.rs @@ -20,7 +20,7 @@ fn default_values() { } fn new_state(validator_count: usize, slot: Slot) -> BeaconState { - let spec = &T::spec(); + let spec = &T::default_spec(); let mut builder = TestingBeaconStateBuilder::from_single_keypair(validator_count, &Keypair::random(), spec); @@ -35,7 +35,7 @@ fn new_state(validator_count: usize, slot: Slot) -> BeaconState { #[test] fn fails_without_validators() { let state = new_state::(0, Slot::new(0)); - let spec = &FewValidatorsEthSpec::spec(); + let spec = &FewValidatorsEthSpec::default_spec(); assert_eq!( CommitteeCache::initialized(&state, state.current_epoch(), &spec), @@ -46,7 +46,7 @@ fn fails_without_validators() { #[test] fn initializes_with_the_right_epoch() { let state = new_state::(16, Slot::new(0)); - let spec = &FewValidatorsEthSpec::spec(); + let spec = &FewValidatorsEthSpec::default_spec(); let cache = CommitteeCache::default(); assert_eq!(cache.initialized_epoch, None); @@ -68,7 +68,7 @@ fn shuffles_for_the_right_epoch() { let slot = epoch.start_slot(FewValidatorsEthSpec::slots_per_epoch()); let mut state = new_state::(num_validators, slot); - let spec = &FewValidatorsEthSpec::spec(); + let spec = &FewValidatorsEthSpec::default_spec(); let distinct_hashes: Vec = (0..FewValidatorsEthSpec::latest_randao_mixes_length()) .into_iter() @@ -123,7 +123,7 @@ fn can_start_on_any_shard() { let slot = epoch.start_slot(FewValidatorsEthSpec::slots_per_epoch()); let mut state = new_state::(num_validators, slot); - let spec = &FewValidatorsEthSpec::spec(); + let spec = &FewValidatorsEthSpec::default_spec(); for i in 0..FewValidatorsEthSpec::shard_count() as u64 { state.latest_start_shard = i; @@ -150,15 +150,17 @@ impl EthSpec for ExcessShardsEthSpec { type LatestRandaoMixesLength = U8192; type LatestActiveIndexRootsLength = U8192; type LatestSlashedExitLength = U8192; + type SlotsPerEpoch = U8; + type GenesisEpoch = U0; - fn spec() -> ChainSpec { - ChainSpec::few_validators() + fn default_spec() -> ChainSpec { + ChainSpec::few_validators(Self::slots_per_epoch()) } } #[test] fn starts_on_the_correct_shard() { - let spec = &ExcessShardsEthSpec::spec(); + let spec = &ExcessShardsEthSpec::default_spec(); let num_validators = ExcessShardsEthSpec::shard_count(); @@ -200,14 +202,16 @@ fn starts_on_the_correct_shard() { let previous_shards = ExcessShardsEthSpec::get_epoch_committee_count( get_active_validator_count(&state.validator_registry, previous_epoch), + spec.target_committee_size, ); let current_shards = ExcessShardsEthSpec::get_epoch_committee_count( get_active_validator_count(&state.validator_registry, current_epoch), + spec.target_committee_size, + ); + let next_shards = ExcessShardsEthSpec::get_epoch_committee_count( + get_active_validator_count(&state.validator_registry, next_epoch), + spec.target_committee_size, ); - let next_shards = ExcessShardsEthSpec::get_epoch_committee_count(get_active_validator_count( - &state.validator_registry, - next_epoch, - )); assert_eq!( previous_shards as usize, diff --git a/eth2/types/src/beacon_state/tests.rs b/eth2/types/src/beacon_state/tests.rs index 588d24aa8..581b9662e 100644 --- a/eth2/types/src/beacon_state/tests.rs +++ b/eth2/types/src/beacon_state/tests.rs @@ -7,7 +7,7 @@ ssz_tests!(FoundationBeaconState); cached_tree_hash_tests!(FoundationBeaconState); fn test_beacon_proposer_index() { - let spec = T::spec(); + let spec = T::default_spec(); let relative_epoch = RelativeEpoch::Current; // Build a state for testing. @@ -61,7 +61,7 @@ fn beacon_proposer_index() { /// (current_epoch - LATEST_ACTIVE_INDEX_ROOTS_LENGTH + ACTIVATION_EXIT_DELAY, current_epoch + /// ACTIVATION_EXIT_DELAY] fn active_index_range(current_epoch: Epoch) -> RangeInclusive { - let delay = T::spec().activation_exit_delay; + let delay = T::default_spec().activation_exit_delay; let start: i32 = current_epoch.as_u64() as i32 - T::latest_active_index_roots() as i32 + delay as i32; @@ -79,7 +79,7 @@ fn active_index_range(current_epoch: Epoch) -> RangeInclusive /// Test getting an active index root at the start and end of the valid range, and one either side /// of that range. fn test_active_index(state_slot: Slot) { - let spec = T::spec(); + let spec = T::default_spec(); let builder: TestingBeaconStateBuilder = TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(16, &spec); let (mut state, _keypairs) = builder.build(); @@ -133,8 +133,8 @@ fn test_cache_initialization<'a, T: EthSpec>( spec: &ChainSpec, ) { let slot = relative_epoch - .into_epoch(state.slot.epoch(spec.slots_per_epoch)) - .start_slot(spec.slots_per_epoch); + .into_epoch(state.slot.epoch(T::slots_per_epoch())) + .start_slot(T::slots_per_epoch()); // Assuming the cache isn't already built, assert that a call to a cache-using function fails. assert_eq!( @@ -166,13 +166,13 @@ fn test_cache_initialization<'a, T: EthSpec>( #[test] fn cache_initialization() { - let spec = FewValidatorsEthSpec::spec(); + let spec = FewValidatorsEthSpec::default_spec(); let builder: TestingBeaconStateBuilder = TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(16, &spec); let (mut state, _keypairs) = builder.build(); - state.slot = (spec.genesis_epoch + 1).start_slot(spec.slots_per_epoch); + state.slot = (spec.genesis_epoch + 1).start_slot(FewValidatorsEthSpec::slots_per_epoch()); test_cache_initialization(&mut state, RelativeEpoch::Previous, &spec); test_cache_initialization(&mut state, RelativeEpoch::Current, &spec); @@ -234,7 +234,7 @@ mod committees { (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) { + for slot in epoch.slot_iter(T::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 @@ -290,7 +290,7 @@ mod committees { state_epoch: Epoch, cache_epoch: RelativeEpoch, ) { - let spec = &T::spec(); + let spec = &T::default_spec(); let mut builder = TestingBeaconStateBuilder::from_single_keypair( validator_count, @@ -298,7 +298,7 @@ mod committees { spec, ); - let slot = state_epoch.start_slot(spec.slots_per_epoch); + let slot = state_epoch.start_slot(T::slots_per_epoch()); builder.teleport_to_slot(slot, spec); let (mut state, _keypairs): (BeaconState, _) = builder.build(); @@ -325,7 +325,7 @@ mod committees { } fn committee_consistency_test_suite(cached_epoch: RelativeEpoch) { - let spec = T::spec(); + let spec = T::default_spec(); let validator_count = (T::shard_count() * spec.target_committee_size) + 1; diff --git a/eth2/types/src/chain_spec.rs b/eth2/types/src/chain_spec.rs index 20aa6fcdb..d9a0785a1 100644 --- a/eth2/types/src/chain_spec.rs +++ b/eth2/types/src/chain_spec.rs @@ -1,6 +1,6 @@ use crate::*; use int_to_bytes::int_to_bytes4; -use serde_derive::Deserialize; +use serde_derive::{Deserialize, Serialize}; use test_utils::u8_from_hex_str; /// Each of the BLS signature domains. @@ -18,7 +18,7 @@ pub enum Domain { /// Holds all the "constants" for a BeaconChain. /// /// Spec v0.6.1 -#[derive(PartialEq, Debug, Clone, Deserialize)] +#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] #[serde(default)] pub struct ChainSpec { /* @@ -59,7 +59,7 @@ pub struct ChainSpec { */ pub seconds_per_slot: u64, pub min_attestation_inclusion_delay: u64, - pub slots_per_epoch: u64, + //pub slots_per_epoch: u64, pub min_seed_lookahead: Epoch, pub activation_exit_delay: u64, pub slots_per_eth1_voting_period: u64, @@ -137,7 +137,7 @@ impl ChainSpec { /// Returns a `ChainSpec` compatible with the Ethereum Foundation specification. /// /// Spec v0.6.1 - pub(crate) fn foundation() -> Self { + pub fn foundation() -> Self { Self { /* * Misc @@ -176,7 +176,7 @@ impl ChainSpec { */ seconds_per_slot: 6, min_attestation_inclusion_delay: 4, - slots_per_epoch: 64, + // slots_per_epoch: 64, min_seed_lookahead: Epoch::new(1), activation_exit_delay: 4, slots_per_eth1_voting_period: 1_024, @@ -226,7 +226,7 @@ impl ChainSpec { /// Returns a `ChainSpec` compatible with the Lighthouse testnet specification. /// /// Spec v0.4.0 - pub(crate) fn lighthouse_testnet() -> Self { + pub fn lighthouse_testnet(slots_per_epoch: u64) -> Self { /* * Lighthouse testnet bootnodes */ @@ -237,21 +237,19 @@ impl ChainSpec { Self { boot_nodes, chain_id: 2, // lighthouse testnet chain id - ..ChainSpec::few_validators() + ..ChainSpec::few_validators(slots_per_epoch) } } /// Returns a `ChainSpec` compatible with the specification suitable for 8 validators. - pub(crate) fn few_validators() -> Self { + pub fn few_validators(slots_per_epoch: u64) -> Self { let genesis_slot = Slot::new(0); - let slots_per_epoch = 8; let genesis_epoch = genesis_slot.epoch(slots_per_epoch); Self { target_committee_size: 1, genesis_slot, genesis_epoch, - slots_per_epoch, ..ChainSpec::foundation() } } diff --git a/eth2/types/src/test_utils/builders/testing_attestation_data_builder.rs b/eth2/types/src/test_utils/builders/testing_attestation_data_builder.rs index 2150f5433..0b4aa2987 100644 --- a/eth2/types/src/test_utils/builders/testing_attestation_data_builder.rs +++ b/eth2/types/src/test_utils/builders/testing_attestation_data_builder.rs @@ -21,7 +21,7 @@ impl TestingAttestationDataBuilder { let previous_epoch = state.previous_epoch(); let is_previous_epoch = - state.slot.epoch(spec.slots_per_epoch) != slot.epoch(spec.slots_per_epoch); + state.slot.epoch(T::slots_per_epoch()) != slot.epoch(T::slots_per_epoch()); let source_epoch = if is_previous_epoch { state.previous_justified_epoch @@ -37,11 +37,11 @@ impl TestingAttestationDataBuilder { let target_root = if is_previous_epoch { *state - .get_block_root(previous_epoch.start_slot(spec.slots_per_epoch)) + .get_block_root(previous_epoch.start_slot(T::slots_per_epoch())) .unwrap() } else { *state - .get_block_root(current_epoch.start_slot(spec.slots_per_epoch)) + .get_block_root(current_epoch.start_slot(T::slots_per_epoch())) .unwrap() }; @@ -57,7 +57,7 @@ impl TestingAttestationDataBuilder { }; let source_root = *state - .get_block_root(source_epoch.start_slot(spec.slots_per_epoch)) + .get_block_root(source_epoch.start_slot(T::slots_per_epoch())) .unwrap(); let data = AttestationData { diff --git a/eth2/types/src/test_utils/builders/testing_beacon_block_builder.rs b/eth2/types/src/test_utils/builders/testing_beacon_block_builder.rs index 941ad8fdd..999e88aae 100644 --- a/eth2/types/src/test_utils/builders/testing_beacon_block_builder.rs +++ b/eth2/types/src/test_utils/builders/testing_beacon_block_builder.rs @@ -36,9 +36,9 @@ impl TestingBeaconBlockBuilder { /// Signs the block. /// /// Modifying the block after signing may invalidate the signature. - pub fn sign(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { + pub fn sign(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { let message = self.block.signed_root(); - let epoch = self.block.slot.epoch(spec.slots_per_epoch); + let epoch = self.block.slot.epoch(T::slots_per_epoch()); let domain = spec.get_domain(epoch, Domain::BeaconProposer, fork); self.block.signature = Signature::new(&message, domain, sk); } @@ -46,8 +46,8 @@ impl TestingBeaconBlockBuilder { /// Sets the randao to be a signature across the blocks epoch. /// /// Modifying the block's slot after signing may invalidate the signature. - pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { - let epoch = self.block.slot.epoch(spec.slots_per_epoch); + pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { + let epoch = self.block.slot.epoch(T::slots_per_epoch()); let message = epoch.tree_hash_root(); let domain = spec.get_domain(epoch, Domain::Randao, fork); self.block.body.randao_reveal = Signature::new(&message, domain, sk); @@ -59,14 +59,15 @@ impl TestingBeaconBlockBuilder { } /// Inserts a signed, valid `ProposerSlashing` for the validator. - pub fn insert_proposer_slashing( + pub fn insert_proposer_slashing( &mut self, validator_index: u64, secret_key: &SecretKey, fork: &Fork, spec: &ChainSpec, ) { - let proposer_slashing = build_proposer_slashing(validator_index, secret_key, fork, spec); + let proposer_slashing = + build_proposer_slashing::(validator_index, secret_key, fork, spec); self.block.body.proposer_slashings.push(proposer_slashing); } @@ -115,7 +116,7 @@ impl TestingBeaconBlockBuilder { // - The slot is too old to be included in a block at this slot. // - The `MAX_ATTESTATIONS`. loop { - if state.slot >= slot + spec.slots_per_epoch { + if state.slot >= slot + T::slots_per_epoch() { break; } @@ -194,7 +195,7 @@ impl TestingBeaconBlockBuilder { builder.set_index(index); builder.sign( &keypair, - state.slot.epoch(spec.slots_per_epoch), + state.slot.epoch(T::slots_per_epoch()), &state.fork, spec, ); @@ -211,7 +212,7 @@ impl TestingBeaconBlockBuilder { spec: &ChainSpec, ) { let mut builder = TestingVoluntaryExitBuilder::new( - state.slot.epoch(spec.slots_per_epoch), + state.slot.epoch(T::slots_per_epoch()), validator_index, ); @@ -234,14 +235,19 @@ impl TestingBeaconBlockBuilder { spec: &ChainSpec, ) { let mut builder = TestingTransferBuilder::new(from, to, amount, state.slot); - builder.sign(keypair, &state.fork, spec); + builder.sign::(keypair, &state.fork, spec); self.block.body.transfers.push(builder.build()) } /// 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); + pub fn build( + mut self, + sk: &SecretKey, + fork: &Fork, + spec: &ChainSpec, + ) -> BeaconBlock { + self.sign::(sk, fork, spec); self.block } @@ -254,7 +260,7 @@ impl TestingBeaconBlockBuilder { /// Builds an `ProposerSlashing` for some `validator_index`. /// /// Signs the message using a `BeaconChainHarness`. -fn build_proposer_slashing( +fn build_proposer_slashing( validator_index: u64, secret_key: &SecretKey, fork: &Fork, @@ -265,7 +271,7 @@ fn build_proposer_slashing( Signature::new(message, domain, secret_key) }; - TestingProposerSlashingBuilder::double_vote(validator_index, signer, spec) + TestingProposerSlashingBuilder::double_vote::(validator_index, signer, spec) } /// Builds an `AttesterSlashing` for some `validator_indices`. diff --git a/eth2/types/src/test_utils/builders/testing_beacon_state_builder.rs b/eth2/types/src/test_utils/builders/testing_beacon_state_builder.rs index 20ed8a893..dc2dd0a7c 100644 --- a/eth2/types/src/test_utils/builders/testing_beacon_state_builder.rs +++ b/eth2/types/src/test_utils/builders/testing_beacon_state_builder.rs @@ -173,7 +173,7 @@ impl TestingBeaconStateBuilder { /// 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.teleport_to_epoch(slot.epoch(T::slots_per_epoch()), spec); self.state.slot = slot; } @@ -184,7 +184,7 @@ impl TestingBeaconStateBuilder { fn teleport_to_epoch(&mut self, epoch: Epoch, spec: &ChainSpec) { let state = &mut self.state; - let slot = epoch.start_slot(spec.slots_per_epoch); + let slot = epoch.start_slot(T::slots_per_epoch()); state.slot = slot; @@ -214,8 +214,8 @@ impl TestingBeaconStateBuilder { let current_epoch = state.current_epoch(); let previous_epoch = state.previous_epoch(); - 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() + let first_slot = previous_epoch.start_slot(T::slots_per_epoch()).as_u64(); + let last_slot = current_epoch.end_slot(T::slots_per_epoch()).as_u64() - spec.min_attestation_inclusion_delay; let last_slot = std::cmp::min(state.slot.as_u64(), last_slot); diff --git a/eth2/types/src/test_utils/builders/testing_proposer_slashing_builder.rs b/eth2/types/src/test_utils/builders/testing_proposer_slashing_builder.rs index 458082de2..99c005472 100644 --- a/eth2/types/src/test_utils/builders/testing_proposer_slashing_builder.rs +++ b/eth2/types/src/test_utils/builders/testing_proposer_slashing_builder.rs @@ -17,8 +17,9 @@ impl TestingProposerSlashingBuilder { /// - `domain: Domain` /// /// Where domain is a domain "constant" (e.g., `spec.domain_attestation`). - pub fn double_vote(proposer_index: u64, signer: F, spec: &ChainSpec) -> ProposerSlashing + pub fn double_vote(proposer_index: u64, signer: F, spec: &ChainSpec) -> ProposerSlashing where + T: EthSpec, F: Fn(u64, &[u8], Epoch, Domain) -> Signature, { let slot = Slot::new(0); @@ -40,13 +41,13 @@ impl TestingProposerSlashingBuilder { header_1.signature = { let message = header_1.signed_root(); - let epoch = slot.epoch(spec.slots_per_epoch); + let epoch = slot.epoch(T::slots_per_epoch()); signer(proposer_index, &message[..], epoch, Domain::BeaconProposer) }; header_2.signature = { let message = header_2.signed_root(); - let epoch = slot.epoch(spec.slots_per_epoch); + let epoch = slot.epoch(T::slots_per_epoch()); signer(proposer_index, &message[..], epoch, Domain::BeaconProposer) }; diff --git a/eth2/types/src/test_utils/builders/testing_transfer_builder.rs b/eth2/types/src/test_utils/builders/testing_transfer_builder.rs index 2680f7b66..d3c3da19e 100644 --- a/eth2/types/src/test_utils/builders/testing_transfer_builder.rs +++ b/eth2/types/src/test_utils/builders/testing_transfer_builder.rs @@ -29,10 +29,10 @@ impl TestingTransferBuilder { /// Signs the transfer. /// /// The keypair must match that of the `from` validator index. - pub fn sign(&mut self, keypair: Keypair, fork: &Fork, spec: &ChainSpec) { + pub fn sign(&mut self, keypair: Keypair, fork: &Fork, spec: &ChainSpec) { self.transfer.pubkey = keypair.pk; let message = self.transfer.signed_root(); - let epoch = self.transfer.slot.epoch(spec.slots_per_epoch); + let epoch = self.transfer.slot.epoch(T::slots_per_epoch()); let domain = spec.get_domain(epoch, Domain::Transfer, fork); self.transfer.signature = Signature::new(&message, domain, &keypair.sk); diff --git a/tests/ef_tests/src/cases/epoch_processing_crosslinks.rs b/tests/ef_tests/src/cases/epoch_processing_crosslinks.rs index fa530f9ad..afdb9cc31 100644 --- a/tests/ef_tests/src/cases/epoch_processing_crosslinks.rs +++ b/tests/ef_tests/src/cases/epoch_processing_crosslinks.rs @@ -29,9 +29,9 @@ impl Case for EpochProcessingCrosslinks { let mut expected = self.post.clone(); // Processing requires the epoch cache. - state.build_all_caches(&E::spec()).unwrap(); + state.build_all_caches(&E::default_spec()).unwrap(); - let mut result = process_crosslinks(&mut state, &E::spec()).map(|_| state); + let mut result = process_crosslinks(&mut state, &E::default_spec()).map(|_| state); compare_beacon_state_results_without_caches(&mut result, &mut expected) } diff --git a/tests/ef_tests/src/cases/epoch_processing_registry_updates.rs b/tests/ef_tests/src/cases/epoch_processing_registry_updates.rs index d91a7a4c3..092a8a709 100644 --- a/tests/ef_tests/src/cases/epoch_processing_registry_updates.rs +++ b/tests/ef_tests/src/cases/epoch_processing_registry_updates.rs @@ -27,7 +27,7 @@ impl Case for EpochProcessingRegistryUpdates { fn result(&self, _case_index: usize) -> Result<(), Error> { let mut state = self.pre.clone(); let mut expected = self.post.clone(); - let spec = &E::spec(); + let spec = &E::default_spec(); // Processing requires the epoch cache. state.build_all_caches(spec).unwrap(); diff --git a/tests/ef_tests/src/cases/operations_attester_slashing.rs b/tests/ef_tests/src/cases/operations_attester_slashing.rs index d8f1f06dc..1b95f4359 100644 --- a/tests/ef_tests/src/cases/operations_attester_slashing.rs +++ b/tests/ef_tests/src/cases/operations_attester_slashing.rs @@ -31,9 +31,10 @@ impl Case for OperationsAttesterSlashing { let mut expected = self.post.clone(); // Processing requires the epoch cache. - state.build_all_caches(&E::spec()).unwrap(); + state.build_all_caches(&E::default_spec()).unwrap(); - let result = process_attester_slashings(&mut state, &[attester_slashing], &E::spec()); + let result = + process_attester_slashings(&mut state, &[attester_slashing], &E::default_spec()); let mut result = result.and_then(|_| Ok(state)); diff --git a/tests/ef_tests/src/cases/operations_deposit.rs b/tests/ef_tests/src/cases/operations_deposit.rs index 23b791ba5..8100590fd 100644 --- a/tests/ef_tests/src/cases/operations_deposit.rs +++ b/tests/ef_tests/src/cases/operations_deposit.rs @@ -34,7 +34,7 @@ impl Case for OperationsDeposit { let deposit = self.deposit.clone(); let mut expected = self.post.clone(); - let result = process_deposits(&mut state, &[deposit], &E::spec()); + let result = process_deposits(&mut state, &[deposit], &E::default_spec()); let mut result = result.and_then(|_| Ok(state)); diff --git a/tests/ef_tests/src/cases/operations_exit.rs b/tests/ef_tests/src/cases/operations_exit.rs index 3d0f6b010..cfe20d82b 100644 --- a/tests/ef_tests/src/cases/operations_exit.rs +++ b/tests/ef_tests/src/cases/operations_exit.rs @@ -31,9 +31,9 @@ impl Case for OperationsExit { let mut expected = self.post.clone(); // Exit processing requires the epoch cache. - state.build_all_caches(&E::spec()).unwrap(); + state.build_all_caches(&E::default_spec()).unwrap(); - let result = process_exits(&mut state, &[exit], &E::spec()); + let result = process_exits(&mut state, &[exit], &E::default_spec()); let mut result = result.and_then(|_| Ok(state)); diff --git a/tests/ef_tests/src/cases/operations_proposer_slashing.rs b/tests/ef_tests/src/cases/operations_proposer_slashing.rs index 416a6f7c3..43293dfbc 100644 --- a/tests/ef_tests/src/cases/operations_proposer_slashing.rs +++ b/tests/ef_tests/src/cases/operations_proposer_slashing.rs @@ -31,9 +31,10 @@ impl Case for OperationsProposerSlashing { let mut expected = self.post.clone(); // Processing requires the epoch cache. - state.build_all_caches(&E::spec()).unwrap(); + state.build_all_caches(&E::default_spec()).unwrap(); - let result = process_proposer_slashings(&mut state, &[proposer_slashing], &E::spec()); + let result = + process_proposer_slashings(&mut state, &[proposer_slashing], &E::default_spec()); let mut result = result.and_then(|_| Ok(state)); diff --git a/tests/ef_tests/src/cases/operations_transfer.rs b/tests/ef_tests/src/cases/operations_transfer.rs index 3ec96cd5c..66318e750 100644 --- a/tests/ef_tests/src/cases/operations_transfer.rs +++ b/tests/ef_tests/src/cases/operations_transfer.rs @@ -31,9 +31,9 @@ impl Case for OperationsTransfer { let mut expected = self.post.clone(); // Transfer processing requires the epoch cache. - state.build_all_caches(&E::spec()).unwrap(); + state.build_all_caches(&E::default_spec()).unwrap(); - let mut spec = E::spec(); + let mut spec = E::default_spec(); spec.max_transfers = 1; let result = process_transfers(&mut state, &[transfer], &spec); diff --git a/tests/ef_tests/src/cases/shuffling.rs b/tests/ef_tests/src/cases/shuffling.rs index ef8a1b934..2920840c8 100644 --- a/tests/ef_tests/src/cases/shuffling.rs +++ b/tests/ef_tests/src/cases/shuffling.rs @@ -24,7 +24,7 @@ impl Case for Shuffling { if self.count == 0 { compare_result::<_, Error>(&Ok(vec![]), &Some(self.shuffled.clone()))?; } else { - let spec = T::spec(); + let spec = T::default_spec(); let seed = hex::decode(&self.seed[2..]) .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; diff --git a/tests/ef_tests/src/eth_specs.rs b/tests/ef_tests/src/eth_specs.rs index cdf8b94e8..f0ee1e9f0 100644 --- a/tests/ef_tests/src/eth_specs.rs +++ b/tests/ef_tests/src/eth_specs.rs @@ -1,6 +1,6 @@ use serde_derive::{Deserialize, Serialize}; use types::{ - typenum::{U64, U8}, + typenum::{U0, U64, U8}, ChainSpec, EthSpec, FewValidatorsEthSpec, FoundationEthSpec, }; @@ -18,10 +18,12 @@ impl EthSpec for MinimalEthSpec { type LatestRandaoMixesLength = U64; type LatestActiveIndexRootsLength = U64; type LatestSlashedExitLength = U64; + type SlotsPerEpoch = U8; + type GenesisEpoch = U0; - fn spec() -> ChainSpec { + fn default_spec() -> ChainSpec { // TODO: this spec is likely incorrect! - let mut spec = FewValidatorsEthSpec::spec(); + let mut spec = FewValidatorsEthSpec::default_spec(); spec.shuffle_round_count = 10; spec } diff --git a/validator_client/src/attestation_producer/mod.rs b/validator_client/src/attestation_producer/mod.rs index 0a65c1f1e..d59f383ef 100644 --- a/validator_client/src/attestation_producer/mod.rs +++ b/validator_client/src/attestation_producer/mod.rs @@ -39,6 +39,8 @@ pub struct AttestationProducer<'a, B: BeaconNodeAttestation, S: Signer> { pub beacon_node: Arc, /// The signer to sign the block. pub signer: &'a S, + /// Used for caclulating epoch. + pub slots_per_epoch: u64, } impl<'a, B: BeaconNodeAttestation, S: Signer> AttestationProducer<'a, B, S> { @@ -78,7 +80,7 @@ impl<'a, B: BeaconNodeAttestation, S: Signer> AttestationProducer<'a, B, S> { /// The slash-protection code is not yet implemented. There is zero protection against /// slashing. pub fn produce_attestation(&mut self) -> Result { - let epoch = self.duty.slot.epoch(self.spec.slots_per_epoch); + let epoch = self.duty.slot.epoch(self.slots_per_epoch); let attestation = self .beacon_node diff --git a/validator_client/src/block_producer/mod.rs b/validator_client/src/block_producer/mod.rs index fc01b8126..9c19e3532 100644 --- a/validator_client/src/block_producer/mod.rs +++ b/validator_client/src/block_producer/mod.rs @@ -48,6 +48,8 @@ pub struct BlockProducer<'a, B: BeaconNodeBlock, S: Signer> { pub beacon_node: Arc, /// The signer to sign the block. pub signer: &'a S, + /// Used for caclulating epoch. + pub slots_per_epoch: u64, } impl<'a, B: BeaconNodeBlock, S: Signer> BlockProducer<'a, B, S> { @@ -84,7 +86,7 @@ impl<'a, B: BeaconNodeBlock, S: Signer> BlockProducer<'a, B, S> { /// The slash-protection code is not yet implemented. There is zero protection against /// slashing. pub fn produce_block(&mut self) -> Result { - let epoch = self.slot.epoch(self.spec.slots_per_epoch); + let epoch = self.slot.epoch(self.slots_per_epoch); let message = epoch.tree_hash_root(); let randao_reveal = match self.signer.sign_message( @@ -186,9 +188,9 @@ mod tests { let beacon_node = Arc::new(SimulatedBeaconNode::default()); let signer = Arc::new(LocalSigner::new(Keypair::random())); - let mut epoch_map = EpochMap::new(spec.slots_per_epoch); + let mut epoch_map = EpochMap::new(T::slots_per_epoch()); let produce_slot = Slot::new(100); - let produce_epoch = produce_slot.epoch(spec.slots_per_epoch); + let produce_epoch = produce_slot.epoch(T::slots_per_epoch()); epoch_map.map.insert(produce_epoch, produce_slot); let epoch_map = Arc::new(epoch_map); @@ -233,7 +235,7 @@ mod tests { ); // In an epoch without known duties... - let slot = (produce_epoch.as_u64() + 1) * spec.slots_per_epoch; + let slot = (produce_epoch.as_u64() + 1) * T::slots_per_epoch(); slot_clock.set_slot(slot); assert_eq!( block_proposer.poll(), diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 1e9450d59..f5d795ede 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -19,6 +19,7 @@ pub struct Config { pub server: String, /// The chain specification that we are connecting to pub spec: ChainSpec, + pub slots_per_epoch: u64, } const DEFAULT_PRIVATE_KEY_FILENAME: &str = "private.key"; @@ -33,12 +34,13 @@ impl Default for Config { let server = "localhost:5051".to_string(); - let spec = FoundationEthSpec::spec(); + let spec = FoundationEthSpec::default_spec(); Self { data_dir, server, spec, + slots_per_epoch: FoundationEthSpec::slots_per_epoch(), } } } @@ -67,9 +69,9 @@ impl Config { if let Some(spec_str) = args.value_of("spec") { info!(log, "Using custom spec: {:?}", spec_str); config.spec = match spec_str { - "foundation" => FoundationEthSpec::spec(), - "few_validators" => FewValidatorsEthSpec::spec(), - "lighthouse_testnet" => LighthouseTestnetEthSpec::spec(), + "foundation" => FoundationEthSpec::default_spec(), + "few_validators" => FewValidatorsEthSpec::default_spec(), + "lighthouse_testnet" => LighthouseTestnetEthSpec::default_spec(), // Should be impossible due to clap's `possible_values(..)` function. _ => unreachable!(), }; diff --git a/validator_client/src/duties/mod.rs b/validator_client/src/duties/mod.rs index b2ddfd0b0..3f75c937d 100644 --- a/validator_client/src/duties/mod.rs +++ b/validator_client/src/duties/mod.rs @@ -164,7 +164,7 @@ mod tests { #[test] pub fn polling() { let spec = Arc::new(ChainSpec::foundation()); - let duties_map = Arc::new(EpochDutiesMap::new(spec.slots_per_epoch)); + let duties_map = Arc::new(EpochDutiesMap::new(T::slots_per_epoch())); let keypair = Keypair::random(); let slot_clock = Arc::new(TestingSlotClock::new(0)); let beacon_node = Arc::new(TestBeaconNode::default()); diff --git a/validator_client/src/service.rs b/validator_client/src/service.rs index 033394a0d..99455808c 100644 --- a/validator_client/src/service.rs +++ b/validator_client/src/service.rs @@ -47,6 +47,7 @@ pub struct Service { slot_clock: SystemTimeSlotClock, /// The current slot we are processing. current_slot: Slot, + slots_per_epoch: u64, /// The chain specification for this clients instance. spec: Arc, /// The duties manager which maintains the state of when to perform actions. @@ -177,7 +178,7 @@ impl Service { // Builds a mapping of Epoch -> Map(PublicKey, EpochDuty) // where EpochDuty contains slot numbers and attestation data that each validator needs to // produce work on. - let duties_map = RwLock::new(EpochDutiesMap::new(config.spec.slots_per_epoch)); + let duties_map = RwLock::new(EpochDutiesMap::new(config.slots_per_epoch)); // builds a manager which maintains the list of current duties for all known validators // and can check when a validator needs to perform a task. @@ -194,6 +195,7 @@ impl Service { fork, slot_clock, current_slot, + slots_per_epoch: config.slots_per_epoch, spec, duties_manager, beacon_block_client, @@ -204,7 +206,10 @@ impl Service { /// Initialise the service then run the core thread. // TODO: Improve handling of generic BeaconNode types, to stub grpcClient - pub fn start(config: ValidatorConfig, log: slog::Logger) -> error_chain::Result<()> { + pub fn start( + config: ValidatorConfig, + log: slog::Logger, + ) -> error_chain::Result<()> { // connect to the node and retrieve its properties and initialize the gRPC clients let mut service = Service::::initialize_service(config, log)?; @@ -274,7 +279,7 @@ impl Service { Ok(slot) => slot.expect("Genesis is in the future"), }; - let current_epoch = current_slot.epoch(self.spec.slots_per_epoch); + let current_epoch = current_slot.epoch(self.slots_per_epoch); // this is a fatal error. If the slot clock repeats, there is something wrong with // the timer, terminate immediately. @@ -291,7 +296,7 @@ impl Service { fn check_for_duties(&mut self) { let cloned_manager = self.duties_manager.clone(); let cloned_log = self.log.clone(); - let current_epoch = self.current_slot.epoch(self.spec.slots_per_epoch); + let current_epoch = self.current_slot.epoch(self.slots_per_epoch); // spawn a new thread separate to the runtime // TODO: Handle thread termination/timeout // TODO: Add duties thread back in, with channel to process duties in duty change. @@ -316,6 +321,7 @@ impl Service { let spec = self.spec.clone(); let beacon_node = self.beacon_block_client.clone(); let log = self.log.clone(); + let slots_per_epoch = self.slots_per_epoch; std::thread::spawn(move || { info!(log, "Producing a block"; "Validator"=> format!("{}", signers[signer_index])); let signer = &signers[signer_index]; @@ -325,6 +331,7 @@ impl Service { spec, beacon_node, signer, + slots_per_epoch, }; block_producer.handle_produce_block(log); }); @@ -337,6 +344,7 @@ impl Service { let spec = self.spec.clone(); let beacon_node = self.attestation_client.clone(); let log = self.log.clone(); + let slots_per_epoch = self.slots_per_epoch; std::thread::spawn(move || { info!(log, "Producing an attestation"; "Validator"=> format!("{}", signers[signer_index])); let signer = &signers[signer_index]; @@ -346,6 +354,7 @@ impl Service { spec, beacon_node, signer, + slots_per_epoch, }; attestation_producer.handle_produce_attestation(log); });