mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 04:37:13 +00:00
Merge remote-tracking branch 'origin/master' into spec-0.6
This commit is contained in:
@@ -14,7 +14,6 @@ env_logger = "0.6.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_yaml = "0.8"
|
||||
yaml-utils = { path = "yaml_utils" }
|
||||
|
||||
[dependencies]
|
||||
bls = { path = "../utils/bls" }
|
||||
@@ -31,6 +30,3 @@ tree_hash = { path = "../utils/tree_hash" }
|
||||
tree_hash_derive = { path = "../utils/tree_hash_derive" }
|
||||
types = { path = "../types" }
|
||||
rayon = "1.0"
|
||||
|
||||
[features]
|
||||
fake_crypto = ["bls/fake_crypto"]
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../utils/bls/build.rs
|
||||
@@ -4,8 +4,8 @@ use types::{BeaconStateError as Error, *};
|
||||
/// Initiate the exit of the validator of the given `index`.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn initiate_validator_exit(
|
||||
state: &mut BeaconState,
|
||||
pub fn initiate_validator_exit<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
index: usize,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
22
eth2/state_processing/src/common/exit_validator.rs
Normal file
22
eth2/state_processing/src/common/exit_validator.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Exit the validator of the given `index`.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn exit_validator<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
if validator_index >= state.validator_registry.len() {
|
||||
return Err(Error::UnknownValidator);
|
||||
}
|
||||
|
||||
let delayed_epoch = state.get_delayed_activation_exit_epoch(state.current_epoch(spec), spec);
|
||||
|
||||
if state.validator_registry[validator_index].exit_epoch > delayed_epoch {
|
||||
state.validator_registry[validator_index].exit_epoch = delayed_epoch;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -4,8 +4,8 @@ use types::{BeaconStateError as Error, *};
|
||||
/// Slash the validator with index ``index``.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn slash_validator(
|
||||
state: &mut BeaconState,
|
||||
pub fn slash_validator<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
slashed_index: usize,
|
||||
opt_whistleblower_index: Option<usize>,
|
||||
spec: &ChainSpec,
|
||||
@@ -20,13 +20,12 @@ pub fn slash_validator(
|
||||
|
||||
state.validator_registry[slashed_index].slashed = true;
|
||||
state.validator_registry[slashed_index].withdrawable_epoch =
|
||||
current_epoch + Epoch::from(spec.latest_slashed_exit_length);
|
||||
current_epoch + Epoch::from(T::latest_slashed_exit_length());
|
||||
let slashed_balance = state.get_effective_balance(slashed_index, spec)?;
|
||||
|
||||
state.set_slashed_balance(
|
||||
current_epoch,
|
||||
state.get_slashed_balance(current_epoch, spec)? + slashed_balance,
|
||||
spec,
|
||||
state.get_slashed_balance(current_epoch)? + slashed_balance,
|
||||
)?;
|
||||
|
||||
let proposer_index =
|
||||
|
||||
@@ -10,12 +10,12 @@ pub enum GenesisError {
|
||||
/// Returns the genesis `BeaconState`
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn get_genesis_state(
|
||||
pub fn get_genesis_state<T: EthSpec>(
|
||||
genesis_validator_deposits: &[Deposit],
|
||||
genesis_time: u64,
|
||||
genesis_eth1_data: Eth1Data,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<BeaconState, BlockProcessingError> {
|
||||
) -> Result<BeaconState<T>, BlockProcessingError> {
|
||||
// Get the genesis `BeaconState`
|
||||
let mut state = BeaconState::genesis(genesis_time, genesis_eth1_data, spec);
|
||||
|
||||
@@ -37,7 +37,7 @@ pub fn get_genesis_state(
|
||||
.get_cached_active_validator_indices(RelativeEpoch::Current, spec)?
|
||||
.to_vec();
|
||||
let genesis_active_index_root = Hash256::from_slice(&active_validator_indices.tree_hash_root());
|
||||
state.fill_active_index_roots_with(genesis_active_index_root, spec);
|
||||
state.fill_active_index_roots_with(genesis_active_index_root);
|
||||
|
||||
// Generate the current shuffling seed.
|
||||
state.current_shuffling_seed = state.generate_seed(spec.genesis_epoch, spec)?;
|
||||
|
||||
@@ -40,8 +40,8 @@ const VERIFY_DEPOSIT_MERKLE_PROOFS: bool = false;
|
||||
/// returns an error describing why the block was invalid or how the function failed to execute.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn per_block_processing(
|
||||
state: &mut BeaconState,
|
||||
pub fn per_block_processing<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
block: &BeaconBlock,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -55,8 +55,8 @@ pub fn per_block_processing(
|
||||
/// returns an error describing why the block was invalid or how the function failed to execute.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn per_block_processing_without_verifying_block_signature(
|
||||
state: &mut BeaconState,
|
||||
pub fn per_block_processing_without_verifying_block_signature<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
block: &BeaconBlock,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -70,8 +70,8 @@ pub fn per_block_processing_without_verifying_block_signature(
|
||||
/// returns an error describing why the block was invalid or how the function failed to execute.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
fn per_block_processing_signature_optional(
|
||||
mut state: &mut BeaconState,
|
||||
fn per_block_processing_signature_optional<T: EthSpec>(
|
||||
mut state: &mut BeaconState<T>,
|
||||
block: &BeaconBlock,
|
||||
should_verify_block_signature: bool,
|
||||
spec: &ChainSpec,
|
||||
@@ -100,8 +100,8 @@ fn per_block_processing_signature_optional(
|
||||
/// Processes the block header.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_block_header(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_block_header<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
block: &BeaconBlock,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -125,8 +125,8 @@ pub fn process_block_header(
|
||||
/// Verifies the signature of a block.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn verify_block_signature(
|
||||
state: &BeaconState,
|
||||
pub fn verify_block_signature<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
block: &BeaconBlock,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -153,8 +153,8 @@ pub fn verify_block_signature(
|
||||
/// `state.latest_randao_mixes`.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_randao(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_randao<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
block: &BeaconBlock,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -184,7 +184,10 @@ pub fn process_randao(
|
||||
/// Update the `state.eth1_data_votes` based upon the `eth1_data` provided.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_eth1_data(state: &mut BeaconState, eth1_data: &Eth1Data) -> Result<(), Error> {
|
||||
pub fn process_eth1_data<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
eth1_data: &Eth1Data,
|
||||
) -> Result<(), Error> {
|
||||
// Attempt to find a `Eth1DataVote` with matching `Eth1Data`.
|
||||
let matching_eth1_vote_index = state
|
||||
.eth1_data_votes
|
||||
@@ -210,8 +213,8 @@ pub fn process_eth1_data(state: &mut BeaconState, eth1_data: &Eth1Data) -> Resul
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_proposer_slashings(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_proposer_slashings<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
proposer_slashings: &[ProposerSlashing],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -243,8 +246,8 @@ pub fn process_proposer_slashings(
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_attester_slashings(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_attester_slashings<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
attester_slashings: &[AttesterSlashing],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -301,8 +304,8 @@ pub fn process_attester_slashings(
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_attestations(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_attestations<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
attestations: &[Attestation],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -343,8 +346,8 @@ pub fn process_attestations(
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_deposits(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_deposits<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
deposits: &[Deposit],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -413,8 +416,8 @@ pub fn process_deposits(
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_exits(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_exits<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
voluntary_exits: &[VoluntaryExit],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -445,8 +448,8 @@ pub fn process_exits(
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_transfers(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_transfers<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
transfers: &[Transfer],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
@@ -9,8 +9,8 @@ use types::*;
|
||||
/// Returns `Ok(())` if the `Attestation` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn validate_attestation(
|
||||
state: &BeaconState,
|
||||
pub fn validate_attestation<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation: &Attestation,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -18,8 +18,8 @@ pub fn validate_attestation(
|
||||
}
|
||||
|
||||
/// Like `validate_attestation` but doesn't run checks which may become true in future states.
|
||||
pub fn validate_attestation_time_independent_only(
|
||||
state: &BeaconState,
|
||||
pub fn validate_attestation_time_independent_only<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation: &Attestation,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -32,8 +32,8 @@ pub fn validate_attestation_time_independent_only(
|
||||
/// Returns `Ok(())` if the `Attestation` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn validate_attestation_without_signature(
|
||||
state: &BeaconState,
|
||||
pub fn validate_attestation_without_signature<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation: &Attestation,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -45,8 +45,8 @@ pub fn validate_attestation_without_signature(
|
||||
///
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
fn validate_attestation_parametric(
|
||||
state: &BeaconState,
|
||||
fn validate_attestation_parametric<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation: &Attestation,
|
||||
spec: &ChainSpec,
|
||||
verify_signature: bool,
|
||||
@@ -168,9 +168,9 @@ fn validate_attestation_parametric(
|
||||
/// match the current (or previous) justified epoch and root from the state.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
fn verify_justified_epoch_and_root(
|
||||
fn verify_justified_epoch_and_root<T: EthSpec>(
|
||||
attestation: &Attestation,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let state_epoch = state.slot.epoch(spec.slots_per_epoch);
|
||||
@@ -223,8 +223,8 @@ fn verify_justified_epoch_and_root(
|
||||
/// - A `validator_index` in `committee` is not in `state.validator_registry`.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
fn verify_attestation_signature(
|
||||
state: &BeaconState,
|
||||
fn verify_attestation_signature<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
committee: &[usize],
|
||||
a: &Attestation,
|
||||
spec: &ChainSpec,
|
||||
|
||||
@@ -8,8 +8,8 @@ use types::*;
|
||||
/// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn verify_attester_slashing(
|
||||
state: &BeaconState,
|
||||
pub fn verify_attester_slashing<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attester_slashing: &AttesterSlashing,
|
||||
should_verify_indexed_attestations: bool,
|
||||
spec: &ChainSpec,
|
||||
@@ -42,8 +42,8 @@ pub fn verify_attester_slashing(
|
||||
/// Returns Ok(indices) if `indices.len() > 0`.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn gather_attester_slashing_indices(
|
||||
state: &BeaconState,
|
||||
pub fn gather_attester_slashing_indices<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attester_slashing: &AttesterSlashing,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<u64>, Error> {
|
||||
@@ -57,8 +57,8 @@ pub fn gather_attester_slashing_indices(
|
||||
|
||||
/// Same as `gather_attester_slashing_indices` but allows the caller to specify the criteria
|
||||
/// for determining whether a given validator should be considered slashed.
|
||||
pub fn gather_attester_slashing_indices_modular<F>(
|
||||
state: &BeaconState,
|
||||
pub fn gather_attester_slashing_indices_modular<F, T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attester_slashing: &AttesterSlashing,
|
||||
is_slashed: F,
|
||||
spec: &ChainSpec,
|
||||
|
||||
@@ -16,8 +16,8 @@ use types::*;
|
||||
/// Note: this function is incomplete.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn verify_deposit(
|
||||
state: &BeaconState,
|
||||
pub fn verify_deposit<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
deposit: &Deposit,
|
||||
verify_merkle_branch: bool,
|
||||
spec: &ChainSpec,
|
||||
@@ -47,7 +47,10 @@ pub fn verify_deposit(
|
||||
/// Verify that the `Deposit` index is correct.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn verify_deposit_index(state: &BeaconState, deposit: &Deposit) -> Result<(), Error> {
|
||||
pub fn verify_deposit_index<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
deposit: &Deposit,
|
||||
) -> Result<(), Error> {
|
||||
verify!(
|
||||
deposit.index == state.deposit_index,
|
||||
Invalid::BadIndex {
|
||||
@@ -65,8 +68,8 @@ pub fn verify_deposit_index(state: &BeaconState, deposit: &Deposit) -> Result<()
|
||||
/// ## Errors
|
||||
///
|
||||
/// Errors if the state's `pubkey_cache` is not current.
|
||||
pub fn get_existing_validator_index(
|
||||
state: &BeaconState,
|
||||
pub fn get_existing_validator_index<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
deposit: &Deposit,
|
||||
) -> Result<Option<u64>, Error> {
|
||||
let deposit_input = &deposit.deposit_data.deposit_input;
|
||||
@@ -89,11 +92,15 @@ pub fn get_existing_validator_index(
|
||||
/// Verify that a deposit is included in the state's eth1 deposit root.
|
||||
///
|
||||
/// Spec v0.6.0
|
||||
fn verify_deposit_merkle_proof(state: &BeaconState, deposit: &Deposit, spec: &ChainSpec) -> bool {
|
||||
fn verify_deposit_merkle_proof<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
deposit: &Deposit,
|
||||
spec: &ChainSpec,
|
||||
) -> bool {
|
||||
let leaf = deposit.data.tree_hash_root();
|
||||
verify_merkle_proof(
|
||||
Hash256::from_slice(&leaf),
|
||||
&deposit.proof,
|
||||
&deposit.proof[..],
|
||||
spec.deposit_contract_tree_depth as usize,
|
||||
deposit.index as usize,
|
||||
state.latest_eth1_data.deposit_root,
|
||||
|
||||
@@ -8,8 +8,8 @@ use types::*;
|
||||
/// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn verify_exit(
|
||||
state: &BeaconState,
|
||||
pub fn verify_exit<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
exit: &VoluntaryExit,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -17,8 +17,8 @@ pub fn verify_exit(
|
||||
}
|
||||
|
||||
/// Like `verify_exit` but doesn't run checks which may become true in future states.
|
||||
pub fn verify_exit_time_independent_only(
|
||||
state: &BeaconState,
|
||||
pub fn verify_exit_time_independent_only<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
exit: &VoluntaryExit,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -26,8 +26,8 @@ pub fn verify_exit_time_independent_only(
|
||||
}
|
||||
|
||||
/// Parametric version of `verify_exit` that skips some checks if `time_independent_only` is true.
|
||||
fn verify_exit_parametric(
|
||||
state: &BeaconState,
|
||||
fn verify_exit_parametric<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
exit: &VoluntaryExit,
|
||||
spec: &ChainSpec,
|
||||
time_independent_only: bool,
|
||||
|
||||
@@ -11,8 +11,8 @@ use types::*;
|
||||
/// Returns `Ok(())` if the `IndexedAttestation` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn verify_indexed_attestation(
|
||||
state: &BeaconState,
|
||||
pub fn verify_indexed_attestation<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
indexed_attestation: &IndexedAttestation,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
@@ -8,9 +8,9 @@ use types::*;
|
||||
/// Returns `Ok(())` if the `ProposerSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn verify_proposer_slashing(
|
||||
pub fn verify_proposer_slashing<T: EthSpec>(
|
||||
proposer_slashing: &ProposerSlashing,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let proposer = state
|
||||
|
||||
@@ -11,8 +11,8 @@ use types::*;
|
||||
/// Note: this function is incomplete.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn verify_transfer(
|
||||
state: &BeaconState,
|
||||
pub fn verify_transfer<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
transfer: &Transfer,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -20,8 +20,8 @@ pub fn verify_transfer(
|
||||
}
|
||||
|
||||
/// Like `verify_transfer` but doesn't run checks which may become true in future states.
|
||||
pub fn verify_transfer_time_independent_only(
|
||||
state: &BeaconState,
|
||||
pub fn verify_transfer_time_independent_only<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
transfer: &Transfer,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -29,8 +29,8 @@ pub fn verify_transfer_time_independent_only(
|
||||
}
|
||||
|
||||
/// Parametric version of `verify_transfer` that allows some checks to be skipped.
|
||||
fn verify_transfer_parametric(
|
||||
state: &BeaconState,
|
||||
fn verify_transfer_parametric<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
transfer: &Transfer,
|
||||
spec: &ChainSpec,
|
||||
time_independent_only: bool,
|
||||
@@ -123,8 +123,8 @@ fn verify_transfer_parametric(
|
||||
/// Does not check that the transfer is valid, however checks for overflow in all actions.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn execute_transfer(
|
||||
state: &mut BeaconState,
|
||||
pub fn execute_transfer<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
transfer: &Transfer,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
@@ -33,7 +33,10 @@ pub type WinningRootHashSet = HashMap<u64, WinningRoot>;
|
||||
/// returned, a state might be "half-processed" and therefore in an invalid state.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
|
||||
pub fn per_epoch_processing<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
// Ensure the previous and next epoch caches are built.
|
||||
state.build_epoch_cache(RelativeEpoch::Previous, spec)?;
|
||||
state.build_epoch_cache(RelativeEpoch::Current, spec)?;
|
||||
@@ -83,7 +86,7 @@ pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result
|
||||
/// Maybe resets the eth1 period.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn maybe_reset_eth1_period(state: &mut BeaconState, spec: &ChainSpec) {
|
||||
pub fn maybe_reset_eth1_period<T: EthSpec>(state: &mut BeaconState<T>, spec: &ChainSpec) {
|
||||
/* FIXME(sproul)
|
||||
let next_epoch = state.next_epoch(spec);
|
||||
let voting_period = spec.epochs_per_eth1_voting_period;
|
||||
@@ -110,8 +113,8 @@ pub fn maybe_reset_eth1_period(state: &mut BeaconState, spec: &ChainSpec) {
|
||||
/// - `finalized_root`
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn process_justification_and_finalization(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_justification_and_finalization<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
total_balances: &TotalBalances,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -178,8 +181,8 @@ pub fn process_justification_and_finalization(
|
||||
/// Also returns a `WinningRootHashSet` for later use during epoch processing.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn process_crosslinks(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_crosslinks<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<WinningRootHashSet, Error> {
|
||||
let mut winning_root_for_shards: WinningRootHashSet = HashMap::new();
|
||||
@@ -211,7 +214,10 @@ pub fn process_crosslinks(
|
||||
/// Finish up an epoch update.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
|
||||
pub fn finish_epoch_update<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
let next_epoch = state.next_epoch(spec);
|
||||
|
||||
@@ -230,11 +236,7 @@ pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result<
|
||||
state.set_active_index_root(next_epoch, active_index_root, spec)?;
|
||||
|
||||
// Set total slashed balances
|
||||
state.set_slashed_balance(
|
||||
next_epoch,
|
||||
state.get_slashed_balance(current_epoch, spec)?,
|
||||
spec,
|
||||
)?;
|
||||
state.set_slashed_balance(next_epoch, state.get_slashed_balance(current_epoch)?)?;
|
||||
|
||||
// Set randao mix
|
||||
state.set_randao_mix(
|
||||
@@ -246,8 +248,8 @@ pub fn finish_epoch_update(state: &mut BeaconState, spec: &ChainSpec) -> Result<
|
||||
state.slot -= 1;
|
||||
}
|
||||
|
||||
if next_epoch.as_u64() % (spec.slots_per_historical_root as u64 / spec.slots_per_epoch) == 0 {
|
||||
let historical_batch: HistoricalBatch = state.historical_batch();
|
||||
if next_epoch.as_u64() % (T::SlotsPerHistoricalRoot::to_u64() / spec.slots_per_epoch) == 0 {
|
||||
let historical_batch = state.historical_batch();
|
||||
state
|
||||
.historical_roots
|
||||
.push(Hash256::from_slice(&historical_batch.tree_hash_root()[..]));
|
||||
|
||||
@@ -33,8 +33,8 @@ impl std::ops::AddAssign for Delta {
|
||||
/// Apply attester and proposer rewards.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn process_rewards_and_penalties(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_rewards_and_penalties<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
validator_statuses: &mut ValidatorStatuses,
|
||||
winning_root_for_shards: &WinningRootHashSet,
|
||||
spec: &ChainSpec,
|
||||
@@ -75,9 +75,9 @@ pub fn process_rewards_and_penalties(
|
||||
/// For each attesting validator, reward the proposer who was first to include their attestation.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
fn get_proposer_deltas(
|
||||
fn get_proposer_deltas<T: EthSpec>(
|
||||
deltas: &mut Vec<Delta>,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
validator_statuses: &mut ValidatorStatuses,
|
||||
winning_root_for_shards: &WinningRootHashSet,
|
||||
spec: &ChainSpec,
|
||||
@@ -112,9 +112,9 @@ fn get_proposer_deltas(
|
||||
/// Apply rewards for participation in attestations during the previous epoch.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
fn get_attestation_deltas(
|
||||
fn get_attestation_deltas<T: EthSpec>(
|
||||
deltas: &mut Vec<Delta>,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
validator_statuses: &ValidatorStatuses,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -225,9 +225,9 @@ fn get_attestation_delta(
|
||||
/// Calculate the deltas based upon the winning roots for attestations during the previous epoch.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
fn get_crosslink_deltas(
|
||||
fn get_crosslink_deltas<T: EthSpec>(
|
||||
deltas: &mut Vec<Delta>,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
validator_statuses: &ValidatorStatuses,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
@@ -259,8 +259,8 @@ fn get_crosslink_deltas(
|
||||
/// Returns the base reward for some validator.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
fn get_base_reward(
|
||||
state: &BeaconState,
|
||||
fn get_base_reward<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
index: usize,
|
||||
// Should be == get_total_active_balance(state, spec)
|
||||
total_active_balance: u64,
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
use crate::common::verify_bitfield_length;
|
||||
use types::*;
|
||||
|
||||
/// Returns validator indices which participated in the attestation.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn get_attestation_participants<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation_data: &AttestationData,
|
||||
bitfield: &Bitfield,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<usize>, BeaconStateError> {
|
||||
let epoch = attestation_data.slot.epoch(spec.slots_per_epoch);
|
||||
|
||||
let crosslink_committee =
|
||||
state.get_crosslink_committee_for_shard(epoch, attestation_data.shard, spec)?;
|
||||
|
||||
if crosslink_committee.slot != attestation_data.slot {
|
||||
return Err(BeaconStateError::NoCommitteeForShard);
|
||||
}
|
||||
|
||||
let committee = &crosslink_committee.committee;
|
||||
|
||||
if !verify_bitfield_length(&bitfield, committee.len()) {
|
||||
return Err(BeaconStateError::InvalidBitfield);
|
||||
}
|
||||
|
||||
let mut participants = Vec::with_capacity(committee.len());
|
||||
for (i, validator_index) in committee.iter().enumerate() {
|
||||
match bitfield.get(i) {
|
||||
Ok(bit) if bit => participants.push(*validator_index),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
participants.shrink_to_fit();
|
||||
|
||||
Ok(participants)
|
||||
}
|
||||
@@ -4,8 +4,8 @@ use types::*;
|
||||
/// Returns validator indices which participated in the attestation.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn get_attesting_indices_unsorted(
|
||||
state: &BeaconState,
|
||||
pub fn get_attesting_indices_unsorted<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation_data: &AttestationData,
|
||||
bitfield: &Bitfield,
|
||||
spec: &ChainSpec,
|
||||
|
||||
@@ -5,8 +5,8 @@ use types::*;
|
||||
/// slot.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn inclusion_distance(
|
||||
state: &BeaconState,
|
||||
pub fn inclusion_distance<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestations: &[&PendingAttestation],
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
@@ -20,8 +20,8 @@ pub fn inclusion_distance(
|
||||
/// Returns the slot of the earliest included attestation for some validator.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn inclusion_slot(
|
||||
state: &BeaconState,
|
||||
pub fn inclusion_slot<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestations: &[&PendingAttestation],
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
@@ -36,8 +36,8 @@ pub fn inclusion_slot(
|
||||
/// Finds the earliest included attestation for some validator.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
fn earliest_included_attestation(
|
||||
state: &BeaconState,
|
||||
fn earliest_included_attestation<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestations: &[&PendingAttestation],
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
|
||||
@@ -5,7 +5,10 @@ use types::{BeaconStateError as Error, *};
|
||||
/// ``EJECTION_BALANCE``.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_ejections(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
|
||||
pub fn process_ejections<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
// There is an awkward double (triple?) loop here because we can't loop across the borrowed
|
||||
// active validator indices and mutate state in the one loop.
|
||||
let exitable: Vec<usize> = state
|
||||
|
||||
@@ -3,7 +3,7 @@ use types::*;
|
||||
/// Process the exit queue.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) {
|
||||
pub fn process_exit_queue<T: EthSpec>(state: &mut BeaconState<T>, spec: &ChainSpec) {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
|
||||
let eligible = |index: usize| {
|
||||
@@ -34,8 +34,8 @@ pub fn process_exit_queue(state: &mut BeaconState, spec: &ChainSpec) {
|
||||
/// Initiate an exit for the validator of the given `index`.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
fn prepare_validator_for_withdrawal(
|
||||
state: &mut BeaconState,
|
||||
fn prepare_validator_for_withdrawal<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
validator_index: usize,
|
||||
spec: &ChainSpec,
|
||||
) {
|
||||
|
||||
@@ -3,20 +3,20 @@ use types::{BeaconStateError as Error, *};
|
||||
/// Process slashings.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn process_slashings(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_slashings<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
current_total_balance: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
|
||||
let total_at_start = state.get_slashed_balance(current_epoch + 1, spec)?;
|
||||
let total_at_end = state.get_slashed_balance(current_epoch, spec)?;
|
||||
let total_at_start = state.get_slashed_balance(current_epoch + 1)?;
|
||||
let total_at_end = state.get_slashed_balance(current_epoch)?;
|
||||
let total_penalities = total_at_end - total_at_start;
|
||||
|
||||
for (index, validator) in state.validator_registry.iter().enumerate() {
|
||||
let should_penalize = current_epoch.as_usize()
|
||||
== validator.withdrawable_epoch.as_usize() - spec.latest_slashed_exit_length / 2;
|
||||
== validator.withdrawable_epoch.as_usize() - T::LatestSlashedExitLength::to_usize() / 2;
|
||||
|
||||
if validator.slashed && should_penalize {
|
||||
let effective_balance = state.get_effective_balance(index, spec)?;
|
||||
|
||||
@@ -6,8 +6,8 @@ use types::*;
|
||||
/// Peforms a validator registry update, if required.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn process_registry_updates(
|
||||
state: &mut BeaconState,
|
||||
pub fn process_registry_updates<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
current_total_balance: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
@@ -8,9 +8,10 @@ use types::*;
|
||||
fn runs_without_error() {
|
||||
Builder::from_env(Env::default().default_filter_or("error")).init();
|
||||
|
||||
let spec = ChainSpec::few_validators();
|
||||
let spec = FewValidatorsEthSpec::spec();
|
||||
|
||||
let mut builder = TestingBeaconStateBuilder::from_deterministic_keypairs(8, &spec);
|
||||
let mut builder: TestingBeaconStateBuilder<FewValidatorsEthSpec> =
|
||||
TestingBeaconStateBuilder::from_deterministic_keypairs(8, &spec);
|
||||
|
||||
let target_slot = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
|
||||
builder.teleport_to_slot(target_slot, &spec);
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
use super::super::common::exit_validator;
|
||||
use super::Error;
|
||||
use types::*;
|
||||
|
||||
/// Peforms a validator registry update, if required.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn update_registry_and_shuffling_data<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
current_total_balance: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
// First set previous shuffling data to current shuffling data.
|
||||
state.previous_shuffling_epoch = state.current_shuffling_epoch;
|
||||
state.previous_shuffling_start_shard = state.previous_shuffling_start_shard;
|
||||
state.previous_shuffling_seed = state.previous_shuffling_seed;
|
||||
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
let next_epoch = current_epoch + 1;
|
||||
|
||||
// Check we should update, and if so, update.
|
||||
if should_update_validator_registry(state, spec)? {
|
||||
update_validator_registry(state, current_total_balance, spec)?;
|
||||
|
||||
// If we update the registry, update the shuffling data and shards as well.
|
||||
state.current_shuffling_epoch = next_epoch;
|
||||
state.current_shuffling_start_shard = {
|
||||
let active_validators =
|
||||
state.get_cached_active_validator_indices(RelativeEpoch::Current, spec)?;
|
||||
let epoch_committee_count = spec.get_epoch_committee_count(active_validators.len());
|
||||
|
||||
(state.current_shuffling_start_shard + epoch_committee_count) % spec.shard_count
|
||||
};
|
||||
state.current_shuffling_seed = state.generate_seed(state.current_shuffling_epoch, spec)?;
|
||||
} else {
|
||||
// If processing at least on crosslink keeps failing, the reshuffle every power of two, but
|
||||
// don't update the current_shuffling_start_shard.
|
||||
let epochs_since_last_update = current_epoch - state.validator_registry_update_epoch;
|
||||
|
||||
if epochs_since_last_update > 1 && epochs_since_last_update.is_power_of_two() {
|
||||
state.current_shuffling_epoch = next_epoch;
|
||||
state.current_shuffling_seed =
|
||||
state.generate_seed(state.current_shuffling_epoch, spec)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns `true` if the validator registry should be updated during an epoch processing.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn should_update_validator_registry<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<bool, BeaconStateError> {
|
||||
if state.finalized_epoch <= state.validator_registry_update_epoch {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let num_active_validators = state
|
||||
.get_cached_active_validator_indices(RelativeEpoch::Current, spec)?
|
||||
.len();
|
||||
let current_epoch_committee_count = spec.get_epoch_committee_count(num_active_validators);
|
||||
|
||||
for shard in (0..current_epoch_committee_count)
|
||||
.map(|i| (state.current_shuffling_start_shard + i as u64) % spec.shard_count)
|
||||
{
|
||||
if state.latest_crosslinks[shard as usize].epoch <= state.validator_registry_update_epoch {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Update validator registry, activating/exiting validators if possible.
|
||||
///
|
||||
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn update_validator_registry<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
current_total_balance: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
|
||||
let max_balance_churn = std::cmp::max(
|
||||
spec.max_deposit_amount,
|
||||
current_total_balance / (2 * spec.max_balance_churn_quotient),
|
||||
);
|
||||
|
||||
// Activate validators within the allowable balance churn.
|
||||
let mut balance_churn = 0;
|
||||
for index in 0..state.validator_registry.len() {
|
||||
let not_activated =
|
||||
state.validator_registry[index].activation_epoch == spec.far_future_epoch;
|
||||
let has_enough_balance = state.validator_balances[index] >= spec.max_deposit_amount;
|
||||
|
||||
if not_activated && has_enough_balance {
|
||||
// Check the balance churn would be within the allowance.
|
||||
balance_churn += state.get_effective_balance(index, spec)?;
|
||||
if balance_churn > max_balance_churn {
|
||||
break;
|
||||
}
|
||||
|
||||
activate_validator(state, index, false, spec);
|
||||
}
|
||||
}
|
||||
|
||||
// Exit validators within the allowable balance churn.
|
||||
let mut balance_churn = 0;
|
||||
for index in 0..state.validator_registry.len() {
|
||||
let not_exited = state.validator_registry[index].exit_epoch == spec.far_future_epoch;
|
||||
let has_initiated_exit = state.validator_registry[index].initiated_exit;
|
||||
|
||||
if not_exited && has_initiated_exit {
|
||||
// Check the balance churn would be within the allowance.
|
||||
balance_churn += state.get_effective_balance(index, spec)?;
|
||||
if balance_churn > max_balance_churn {
|
||||
break;
|
||||
}
|
||||
|
||||
exit_validator(state, index, spec)?;
|
||||
}
|
||||
}
|
||||
|
||||
state.validator_registry_update_epoch = current_epoch;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Activate the validator of the given ``index``.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn activate_validator<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
validator_index: usize,
|
||||
is_genesis: bool,
|
||||
spec: &ChainSpec,
|
||||
) {
|
||||
let current_epoch = state.current_epoch(spec);
|
||||
|
||||
state.validator_registry[validator_index].activation_epoch = if is_genesis {
|
||||
spec.genesis_epoch
|
||||
} else {
|
||||
state.get_delayed_activation_exit_epoch(current_epoch, spec)
|
||||
}
|
||||
}
|
||||
@@ -163,7 +163,10 @@ impl ValidatorStatuses {
|
||||
/// - Total balances for the current and previous epochs.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn new(state: &BeaconState, spec: &ChainSpec) -> Result<Self, BeaconStateError> {
|
||||
pub fn new<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Self, BeaconStateError> {
|
||||
let mut statuses = Vec::with_capacity(state.validator_registry.len());
|
||||
let mut total_balances = TotalBalances::default();
|
||||
|
||||
@@ -200,9 +203,9 @@ impl ValidatorStatuses {
|
||||
/// `total_balances` fields.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn process_attestations(
|
||||
pub fn process_attestations<T: EthSpec>(
|
||||
&mut self,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BeaconStateError> {
|
||||
for a in state
|
||||
@@ -286,9 +289,9 @@ impl ValidatorStatuses {
|
||||
/// "winning" shard block root for the previous epoch.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn process_winning_roots(
|
||||
pub fn process_winning_roots<T: EthSpec>(
|
||||
&mut self,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
winning_roots: &WinningRootHashSet,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BeaconStateError> {
|
||||
@@ -329,14 +332,14 @@ fn is_from_epoch(a: &PendingAttestation, epoch: Epoch) -> bool {
|
||||
/// beacon block in the given `epoch`.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
fn target_matches_epoch_start_block(
|
||||
fn target_matches_epoch_start_block<T: EthSpec>(
|
||||
a: &PendingAttestation,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
epoch: Epoch,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<bool, BeaconStateError> {
|
||||
let slot = epoch.start_slot(spec.slots_per_epoch);
|
||||
let state_boundary_root = *state.get_block_root(slot, spec)?;
|
||||
let state_boundary_root = *state.get_block_root(slot)?;
|
||||
|
||||
Ok(a.data.target_root == state_boundary_root)
|
||||
}
|
||||
@@ -345,13 +348,13 @@ fn target_matches_epoch_start_block(
|
||||
/// the current slot of the `PendingAttestation`.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
fn has_common_beacon_block_root(
|
||||
fn has_common_beacon_block_root<T: EthSpec>(
|
||||
a: &PendingAttestation,
|
||||
state: &BeaconState,
|
||||
state: &BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<bool, BeaconStateError> {
|
||||
let attestation_slot = state.get_attestation_slot(&a.data, spec)?;
|
||||
let state_block_root = *state.get_block_root(attestation_slot, spec)?;
|
||||
let state_block_root = *state.get_block_root(attestation_slot)?;
|
||||
|
||||
Ok(a.data.beacon_block_root == state_block_root)
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ impl WinningRoot {
|
||||
/// per-epoch processing.
|
||||
///
|
||||
/// Spec v0.6.1
|
||||
pub fn winning_root(
|
||||
state: &BeaconState,
|
||||
pub fn winning_root<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
shard: u64,
|
||||
epoch: Epoch,
|
||||
spec: &ChainSpec,
|
||||
@@ -99,8 +99,8 @@ pub fn winning_root(
|
||||
Ok(winning_root)
|
||||
}
|
||||
|
||||
pub fn get_unslashed_attesting_indices_unsorted(
|
||||
state: &BeaconState,
|
||||
pub fn get_unslashed_attesting_indices_unsorted<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestations: &[&PendingAttestation],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<usize>, BeaconStateError> {
|
||||
|
||||
@@ -11,7 +11,10 @@ pub enum Error {
|
||||
/// Advances a state forward by one slot, performing per-epoch processing if required.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn per_slot_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
|
||||
pub fn per_slot_processing<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
cache_state(state, spec)?;
|
||||
|
||||
if (state.slot + 1) % spec.slots_per_epoch == 0 {
|
||||
@@ -23,7 +26,7 @@ pub fn per_slot_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result<
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cache_state(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
|
||||
fn cache_state<T: EthSpec>(state: &mut BeaconState<T>, spec: &ChainSpec) -> Result<(), Error> {
|
||||
let previous_slot_state_root = state.update_tree_hash_cache()?;
|
||||
|
||||
// Note: increment the state slot here to allow use of our `state_root` and `block_root`
|
||||
@@ -39,10 +42,10 @@ fn cache_state(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
// Store the previous slot's post state transition root.
|
||||
state.set_state_root(previous_slot, previous_slot_state_root, spec)?;
|
||||
state.set_state_root(previous_slot, previous_slot_state_root)?;
|
||||
|
||||
let latest_block_root = Hash256::from_slice(&state.latest_block_header.signed_root()[..]);
|
||||
state.set_block_root(previous_slot, latest_block_root, spec)?;
|
||||
state.set_block_root(previous_slot, latest_block_root)?;
|
||||
|
||||
// Set the state slot back to what it should be.
|
||||
state.slot -= 1;
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
#![cfg(not(debug_assertions))]
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
use serde_yaml;
|
||||
use state_processing::{per_block_processing, per_slot_processing};
|
||||
use std::{fs::File, io::prelude::*, path::PathBuf};
|
||||
use types::*;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ExpectedState {
|
||||
pub slot: Option<Slot>,
|
||||
pub genesis_time: Option<u64>,
|
||||
pub fork: Option<Fork>,
|
||||
pub validator_registry: Option<Vec<Validator>>,
|
||||
pub validator_balances: Option<Vec<u64>>,
|
||||
pub previous_epoch_attestations: Option<Vec<PendingAttestation>>,
|
||||
pub current_epoch_attestations: Option<Vec<PendingAttestation>>,
|
||||
pub historical_roots: Option<Vec<Hash256>>,
|
||||
pub finalized_epoch: Option<Epoch>,
|
||||
pub latest_block_roots: Option<TreeHashVector<Hash256>>,
|
||||
}
|
||||
|
||||
impl ExpectedState {
|
||||
// Return a list of fields that differ, and a string representation of the beacon state's field.
|
||||
fn check(&self, state: &BeaconState) -> Vec<(&str, String)> {
|
||||
// Check field equality
|
||||
macro_rules! cfe {
|
||||
($field_name:ident) => {
|
||||
if self.$field_name.as_ref().map_or(true, |$field_name| {
|
||||
println!(" > Checking {}", stringify!($field_name));
|
||||
$field_name == &state.$field_name
|
||||
}) {
|
||||
vec![]
|
||||
} else {
|
||||
vec![(stringify!($field_name), format!("{:#?}", state.$field_name))]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
vec![
|
||||
cfe!(slot),
|
||||
cfe!(genesis_time),
|
||||
cfe!(fork),
|
||||
cfe!(validator_registry),
|
||||
cfe!(validator_balances),
|
||||
cfe!(previous_epoch_attestations),
|
||||
cfe!(current_epoch_attestations),
|
||||
cfe!(historical_roots),
|
||||
cfe!(finalized_epoch),
|
||||
cfe!(latest_block_roots),
|
||||
]
|
||||
.into_iter()
|
||||
.flat_map(|x| x)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct TestCase {
|
||||
pub name: String,
|
||||
pub config: ChainSpec,
|
||||
pub verify_signatures: bool,
|
||||
pub initial_state: BeaconState,
|
||||
pub blocks: Vec<BeaconBlock>,
|
||||
pub expected_state: ExpectedState,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct TestDoc {
|
||||
pub title: String,
|
||||
pub summary: String,
|
||||
pub fork: String,
|
||||
pub test_cases: Vec<TestCase>,
|
||||
}
|
||||
|
||||
fn load_test_case(test_name: &str) -> TestDoc {
|
||||
let mut file = {
|
||||
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
file_path_buf.push(format!("yaml_utils/specs/{}", test_name));
|
||||
|
||||
File::open(file_path_buf).unwrap()
|
||||
};
|
||||
let mut yaml_str = String::new();
|
||||
file.read_to_string(&mut yaml_str).unwrap();
|
||||
yaml_str = yaml_str.to_lowercase();
|
||||
|
||||
serde_yaml::from_str(&yaml_str.as_str()).unwrap()
|
||||
}
|
||||
|
||||
fn run_state_transition_test(test_name: &str) {
|
||||
let doc = load_test_case(test_name);
|
||||
|
||||
// Run Tests
|
||||
let mut ok = true;
|
||||
for (i, test_case) in doc.test_cases.iter().enumerate() {
|
||||
let fake_crypto = cfg!(feature = "fake_crypto");
|
||||
if !test_case.verify_signatures == fake_crypto {
|
||||
println!("Running {}", test_case.name);
|
||||
} else {
|
||||
println!(
|
||||
"Skipping {} (fake_crypto: {}, need fake: {})",
|
||||
test_case.name, fake_crypto, !test_case.verify_signatures
|
||||
);
|
||||
continue;
|
||||
}
|
||||
let mut state = test_case.initial_state.clone();
|
||||
for (j, block) in test_case.blocks.iter().enumerate() {
|
||||
while block.slot > state.slot {
|
||||
per_slot_processing(&mut state, &test_case.config).unwrap();
|
||||
}
|
||||
let res = per_block_processing(&mut state, &block, &test_case.config);
|
||||
if res.is_err() {
|
||||
println!("Error in {} (#{}), on block {}", test_case.name, i, j);
|
||||
println!("{:?}", res);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
let mismatched_fields = test_case.expected_state.check(&state);
|
||||
if !mismatched_fields.is_empty() {
|
||||
println!(
|
||||
"Error in expected state, these fields didn't match: {:?}",
|
||||
mismatched_fields.iter().map(|(f, _)| f).collect::<Vec<_>>()
|
||||
);
|
||||
for (field_name, state_val) in mismatched_fields {
|
||||
println!("state.{} was: {}", field_name, state_val);
|
||||
}
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(ok, "one or more tests failed, see above");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn test_read_yaml() {
|
||||
load_test_case("sanity-check_small-config_32-vals.yaml");
|
||||
load_test_case("sanity-check_default-config_100-vals.yaml");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn run_state_transition_tests_small() {
|
||||
run_state_transition_test("sanity-check_small-config_32-vals.yaml");
|
||||
}
|
||||
|
||||
// Run with --ignored to run this test
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn run_state_transition_tests_large() {
|
||||
run_state_transition_test("sanity-check_default-config_100-vals.yaml");
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "yaml-utils"
|
||||
version = "0.1.0"
|
||||
authors = ["Kirk Baird <baird.k@outlook.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[build-dependencies]
|
||||
reqwest = "0.9"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[lib]
|
||||
name = "yaml_utils"
|
||||
path = "src/lib.rs"
|
||||
@@ -1,27 +0,0 @@
|
||||
extern crate reqwest;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::copy;
|
||||
|
||||
fn main() {
|
||||
// These test files are not to be stored in the lighthouse repo as they are quite large (32MB).
|
||||
// They will be downloaded at build time by yaml-utils crate (in build.rs)
|
||||
let git_path = "https://raw.githubusercontent.com/ethereum/eth2.0-tests/master/state/";
|
||||
let test_names = vec![
|
||||
"sanity-check_default-config_100-vals.yaml",
|
||||
"sanity-check_small-config_32-vals.yaml",
|
||||
];
|
||||
|
||||
for test in test_names {
|
||||
let mut target = String::from(git_path);
|
||||
target.push_str(test);
|
||||
let mut response = reqwest::get(target.as_str()).unwrap();
|
||||
|
||||
let mut dest = {
|
||||
let mut file_name = String::from("specs/");
|
||||
file_name.push_str(test);
|
||||
File::create(file_name).unwrap()
|
||||
};
|
||||
copy(&mut response, &mut dest).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Script to extract all the fields of the state mentioned in `expected_state` fields of tests
|
||||
# in the `spec` directory. These fields can then be added to the `ExpectedState` struct.
|
||||
# Might take a while to run.
|
||||
|
||||
import os, yaml
|
||||
|
||||
if __name__ == "__main__":
|
||||
yaml_files = (filename for filename in os.listdir("specs") if filename.endswith(".yaml"))
|
||||
parsed_yaml = (yaml.load(open("specs/" + filename, "r")) for filename in yaml_files)
|
||||
all_fields = set()
|
||||
for y in parsed_yaml:
|
||||
all_fields.update(*({key for key in case["expected_state"]} for case in y["test_cases"]))
|
||||
print(all_fields)
|
||||
@@ -1 +0,0 @@
|
||||
*.yaml
|
||||
@@ -1 +0,0 @@
|
||||
// This is a place holder such that yaml-utils is now a crate hence build.rs will be run when 'cargo test' is called
|
||||
Reference in New Issue
Block a user