mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 13:24:44 +00:00
Update to spec v0.11 (#959)
* Update process_final_updates() hysteresis computation * Update core to v0.11.1 * Bump tags to v0.11.1 * Update docs and deposit contract * Add compute_fork_digest * Address review comments Co-authored-by: Herman Alonso Junge <alonso.junge@gmail.com>
This commit is contained in:
@@ -3,7 +3,7 @@ use types::*;
|
||||
|
||||
/// Returns validator indices which participated in the attestation, sorted by increasing index.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn get_attesting_indices<T: EthSpec>(
|
||||
committee: &[usize],
|
||||
bitlist: &BitList<T::MaxValidatorsPerCommittee>,
|
||||
|
||||
@@ -3,7 +3,7 @@ use types::*;
|
||||
|
||||
/// Returns the base reward for some validator.
|
||||
///
|
||||
/// Spec v0.9.1
|
||||
/// Spec v0.11.1
|
||||
pub fn get_base_reward<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
index: usize,
|
||||
|
||||
@@ -6,7 +6,7 @@ type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;
|
||||
|
||||
/// Convert `attestation` to (almost) indexed-verifiable form.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn get_indexed_attestation<T: EthSpec>(
|
||||
committee: &[usize],
|
||||
attestation: &Attestation<T>,
|
||||
|
||||
@@ -3,7 +3,7 @@ use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Initiate the exit of the validator of the given `index`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn initiate_validator_exit<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
index: usize,
|
||||
|
||||
@@ -4,7 +4,7 @@ use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Slash the validator with index ``index``.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn slash_validator<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
slashed_index: usize,
|
||||
|
||||
@@ -6,7 +6,7 @@ use types::*;
|
||||
|
||||
/// Initialize a `BeaconState` from genesis data.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
// TODO: this is quite inefficient and we probably want to rethink how we do this
|
||||
pub fn initialize_beacon_state_from_eth1<T: EthSpec>(
|
||||
eth1_block_hash: Hash256,
|
||||
@@ -42,12 +42,15 @@ pub fn initialize_beacon_state_from_eth1<T: EthSpec>(
|
||||
// Now that we have our validators, initialize the caches (including the committees)
|
||||
state.build_all_caches(spec)?;
|
||||
|
||||
// Set genesis validators root for domain separation and chain versioning
|
||||
state.genesis_validators_root = state.update_validators_tree_hash_cache()?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
/// Determine whether a candidate genesis state is suitable for starting the chain.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn is_valid_genesis_state<T: EthSpec>(state: &BeaconState<T>, spec: &ChainSpec) -> bool {
|
||||
state.genesis_time >= spec.min_genesis_time
|
||||
&& state.get_active_validator_indices(T::genesis_epoch()).len() as u64
|
||||
@@ -56,7 +59,7 @@ pub fn is_valid_genesis_state<T: EthSpec>(state: &BeaconState<T>, spec: &ChainSp
|
||||
|
||||
/// Activate genesis validators, if their balance is acceptable.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_activations<T: EthSpec>(state: &mut BeaconState<T>, spec: &ChainSpec) {
|
||||
for (index, validator) in state.validators.iter_mut().enumerate() {
|
||||
let balance = state.balances[index];
|
||||
|
||||
@@ -70,7 +70,7 @@ impl VerifySignatures {
|
||||
/// tree hash root of the block, NOT the signing root of the block. This function takes
|
||||
/// care of mixing in the domain.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn per_block_processing<T: EthSpec>(
|
||||
mut state: &mut BeaconState<T>,
|
||||
signed_block: &SignedBeaconBlock<T>,
|
||||
@@ -136,14 +136,26 @@ pub fn per_block_processing<T: EthSpec>(
|
||||
|
||||
/// Processes the block header.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_block_header<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
block: &BeaconBlock<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockOperationError<HeaderInvalid>> {
|
||||
// Verify that the slots match
|
||||
verify!(block.slot == state.slot, HeaderInvalid::StateSlotMismatch);
|
||||
|
||||
// Verify that proposer index is the correct index
|
||||
let proposer_index = block.proposer_index as usize;
|
||||
let state_proposer_index = state.get_beacon_proposer_index(block.slot, spec)?;
|
||||
verify!(
|
||||
proposer_index == state_proposer_index,
|
||||
HeaderInvalid::ProposerIndexMismatch {
|
||||
block_proposer_index: proposer_index,
|
||||
state_proposer_index,
|
||||
}
|
||||
);
|
||||
|
||||
let expected_previous_block_root = state.latest_block_header.tree_hash_root();
|
||||
verify!(
|
||||
block.parent_root == expected_previous_block_root,
|
||||
@@ -156,11 +168,10 @@ pub fn process_block_header<T: EthSpec>(
|
||||
state.latest_block_header = block.temporary_block_header();
|
||||
|
||||
// Verify proposer is not slashed
|
||||
let proposer_idx = state.get_beacon_proposer_index(block.slot, spec)?;
|
||||
let proposer = &state.validators[proposer_idx];
|
||||
let proposer = &state.validators[proposer_index];
|
||||
verify!(
|
||||
!proposer.slashed,
|
||||
HeaderInvalid::ProposerSlashed(proposer_idx)
|
||||
HeaderInvalid::ProposerSlashed(proposer_index)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -168,7 +179,7 @@ pub fn process_block_header<T: EthSpec>(
|
||||
|
||||
/// Verifies the signature of a block.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_block_signature<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
block: &SignedBeaconBlock<T>,
|
||||
@@ -186,7 +197,7 @@ pub fn verify_block_signature<T: EthSpec>(
|
||||
/// Verifies the `randao_reveal` against the block's proposer pubkey and updates
|
||||
/// `state.latest_randao_mixes`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_randao<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
block: &BeaconBlock<T>,
|
||||
@@ -209,7 +220,7 @@ pub fn process_randao<T: EthSpec>(
|
||||
|
||||
/// Update the `state.eth1_data_votes` based upon the `eth1_data` provided.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_eth1_data<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
eth1_data: &Eth1Data,
|
||||
@@ -226,7 +237,7 @@ pub fn process_eth1_data<T: EthSpec>(
|
||||
/// Returns `Some(eth1_data)` if adding the given `eth1_data` to `state.eth1_data_votes` would
|
||||
/// result in a change to `state.eth1_data`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn get_new_eth1_data<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
eth1_data: &Eth1Data,
|
||||
@@ -250,7 +261,7 @@ pub fn get_new_eth1_data<T: EthSpec>(
|
||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_proposer_slashings<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
proposer_slashings: &[ProposerSlashing],
|
||||
@@ -268,7 +279,12 @@ pub fn process_proposer_slashings<T: EthSpec>(
|
||||
|
||||
// Update the state.
|
||||
for proposer_slashing in proposer_slashings {
|
||||
slash_validator(state, proposer_slashing.proposer_index as usize, None, spec)?;
|
||||
slash_validator(
|
||||
state,
|
||||
proposer_slashing.signed_header_1.message.proposer_index as usize,
|
||||
None,
|
||||
spec,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -279,7 +295,7 @@ pub fn process_proposer_slashings<T: EthSpec>(
|
||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_attester_slashings<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
attester_slashings: &[AttesterSlashing<T>],
|
||||
@@ -333,7 +349,7 @@ pub fn process_attester_slashings<T: EthSpec>(
|
||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_attestations<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
attestations: &[Attestation<T>],
|
||||
@@ -379,7 +395,7 @@ pub fn process_attestations<T: EthSpec>(
|
||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_deposits<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
deposits: &[Deposit],
|
||||
@@ -416,7 +432,7 @@ pub fn process_deposits<T: EthSpec>(
|
||||
|
||||
/// Process a single deposit, optionally verifying its merkle proof.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_deposit<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
deposit: &Deposit,
|
||||
@@ -482,7 +498,7 @@ pub fn process_deposit<T: EthSpec>(
|
||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||
/// an `Err` describing the invalid object or cause of failure.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_exits<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
voluntary_exits: &[SignedVoluntaryExit],
|
||||
|
||||
@@ -56,9 +56,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||
let keypair = &keypairs[proposer_index];
|
||||
|
||||
builder.set_proposer_index(proposer_index as u64);
|
||||
|
||||
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, state.genesis_validators_root, spec)
|
||||
}
|
||||
None => builder.set_randao_reveal(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
),
|
||||
}
|
||||
|
||||
self.block_builder.insert_deposits(
|
||||
@@ -70,7 +79,12 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
spec,
|
||||
);
|
||||
|
||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
||||
let block = self.block_builder.build(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
|
||||
(block, state)
|
||||
}
|
||||
@@ -96,9 +110,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||
let keypair = &keypairs[proposer_index];
|
||||
|
||||
builder.set_proposer_index(proposer_index as u64);
|
||||
|
||||
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, state.genesis_validators_root, spec)
|
||||
}
|
||||
None => builder.set_randao_reveal(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
),
|
||||
}
|
||||
match test_task {
|
||||
ExitTestTask::AlreadyInitiated => {
|
||||
@@ -125,7 +148,12 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
||||
let block = self.block_builder.build(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
|
||||
(block, state)
|
||||
}
|
||||
@@ -151,9 +179,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||
let keypair = &keypairs[proposer_index];
|
||||
|
||||
builder.set_proposer_index(proposer_index as u64);
|
||||
|
||||
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, state.genesis_validators_root, spec)
|
||||
}
|
||||
None => builder.set_randao_reveal(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
),
|
||||
}
|
||||
|
||||
let all_secret_keys: Vec<&SecretKey> = keypairs.iter().map(|keypair| &keypair.sk).collect();
|
||||
@@ -166,7 +203,12 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
spec,
|
||||
)
|
||||
.unwrap();
|
||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
||||
let block = self.block_builder.build(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
|
||||
(block, state)
|
||||
}
|
||||
@@ -192,9 +234,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||
let keypair = &keypairs[proposer_index];
|
||||
|
||||
builder.set_proposer_index(proposer_index as u64);
|
||||
|
||||
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, state.genesis_validators_root, spec)
|
||||
}
|
||||
None => builder.set_randao_reveal(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
),
|
||||
}
|
||||
|
||||
let mut validator_indices = vec![];
|
||||
@@ -210,10 +261,16 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
&validator_indices,
|
||||
&secret_keys,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
}
|
||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
||||
let block = self.block_builder.build(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
|
||||
(block, state)
|
||||
}
|
||||
@@ -239,9 +296,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||
let keypair = &keypairs[proposer_index];
|
||||
|
||||
builder.set_proposer_index(proposer_index as u64);
|
||||
|
||||
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, state.genesis_validators_root, spec)
|
||||
}
|
||||
None => builder.set_randao_reveal(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
),
|
||||
}
|
||||
|
||||
for i in 0..num_proposer_slashings {
|
||||
@@ -252,10 +318,16 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
validator_indices,
|
||||
&secret_keys,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
}
|
||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
||||
let block = self.block_builder.build(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
|
||||
(block, state)
|
||||
}
|
||||
@@ -279,12 +351,26 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||
let keypair = &keypairs[proposer_index];
|
||||
|
||||
builder.set_proposer_index(proposer_index as u64);
|
||||
|
||||
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, state.genesis_validators_root, spec)
|
||||
}
|
||||
None => builder.set_randao_reveal(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
),
|
||||
}
|
||||
|
||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
||||
let block = self.block_builder.build(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
|
||||
(block, state)
|
||||
}
|
||||
|
||||
@@ -159,7 +159,14 @@ impl<T> From<ssz_types::Error> for BlockOperationError<T> {
|
||||
pub enum HeaderInvalid {
|
||||
ProposalSignatureInvalid,
|
||||
StateSlotMismatch,
|
||||
ParentBlockRootMismatch { state: Hash256, block: Hash256 },
|
||||
ProposerIndexMismatch {
|
||||
block_proposer_index: usize,
|
||||
state_proposer_index: usize,
|
||||
},
|
||||
ParentBlockRootMismatch {
|
||||
state: Hash256,
|
||||
block: Hash256,
|
||||
},
|
||||
ProposerSlashed(usize),
|
||||
}
|
||||
|
||||
@@ -171,6 +178,10 @@ pub enum ProposerSlashingInvalid {
|
||||
///
|
||||
/// (proposal_1_slot, proposal_2_slot)
|
||||
ProposalSlotMismatch(Slot, Slot),
|
||||
/// The two proposals have different proposer indices.
|
||||
///
|
||||
/// (proposer_index_1, proposer_index_2)
|
||||
ProposerIndexMismatch(u64, u64),
|
||||
/// The proposals are identical and therefore not slashable.
|
||||
ProposalsIdentical,
|
||||
/// The specified proposer cannot be slashed because they are already slashed, or not active.
|
||||
|
||||
@@ -11,7 +11,7 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
||||
|
||||
/// Verify an `IndexedAttestation`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn is_valid_indexed_attestation<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
indexed_attestation: &IndexedAttestation<T>,
|
||||
|
||||
@@ -53,6 +53,7 @@ pub fn block_proposal_signature_set<'a, T: EthSpec>(
|
||||
block.slot.epoch(T::slots_per_epoch()),
|
||||
Domain::BeaconProposer,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = if let Some(root) = block_root {
|
||||
@@ -84,6 +85,7 @@ pub fn randao_signature_set<'a, T: EthSpec>(
|
||||
block.slot.epoch(T::slots_per_epoch()),
|
||||
Domain::Randao,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = state.current_epoch().signing_root(domain);
|
||||
@@ -101,7 +103,7 @@ pub fn proposer_slashing_signature_set<'a, T: EthSpec>(
|
||||
proposer_slashing: &'a ProposerSlashing,
|
||||
spec: &'a ChainSpec,
|
||||
) -> Result<(SignatureSet<'a>, SignatureSet<'a>)> {
|
||||
let proposer_index = proposer_slashing.proposer_index as usize;
|
||||
let proposer_index = proposer_slashing.signed_header_1.message.proposer_index as usize;
|
||||
|
||||
Ok((
|
||||
block_header_signature_set(
|
||||
@@ -130,6 +132,7 @@ fn block_header_signature_set<'a, T: EthSpec>(
|
||||
signed_header.message.slot.epoch(T::slots_per_epoch()),
|
||||
Domain::BeaconProposer,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = signed_header
|
||||
@@ -162,6 +165,7 @@ pub fn indexed_attestation_signature_set<'a, 'b, T: EthSpec>(
|
||||
indexed_attestation.data.target.epoch,
|
||||
Domain::BeaconAttester,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = indexed_attestation.data.signing_root(domain);
|
||||
@@ -177,6 +181,7 @@ pub fn indexed_attestation_signature_set_from_pubkeys<'a, 'b, T: EthSpec>(
|
||||
signature: &'a AggregateSignature,
|
||||
indexed_attestation: &'b IndexedAttestation<T>,
|
||||
fork: &Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
spec: &'a ChainSpec,
|
||||
) -> Result<SignatureSet<'a>> {
|
||||
let pubkeys = pubkeys
|
||||
@@ -188,6 +193,7 @@ pub fn indexed_attestation_signature_set_from_pubkeys<'a, 'b, T: EthSpec>(
|
||||
indexed_attestation.data.target.epoch,
|
||||
Domain::BeaconAttester,
|
||||
&fork,
|
||||
genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = indexed_attestation.data.signing_root(domain);
|
||||
@@ -258,7 +264,12 @@ pub fn exit_signature_set<'a, T: EthSpec>(
|
||||
let exit = &signed_exit.message;
|
||||
let proposer_index = exit.validator_index as usize;
|
||||
|
||||
let domain = spec.get_domain(exit.epoch, Domain::VoluntaryExit, &state.fork);
|
||||
let domain = spec.get_domain(
|
||||
exit.epoch,
|
||||
Domain::VoluntaryExit,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = exit.signing_root(domain).as_bytes().to_vec();
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use types::test_utils::{
|
||||
use types::*;
|
||||
|
||||
pub const NUM_DEPOSITS: u64 = 1;
|
||||
pub const VALIDATOR_COUNT: usize = 10;
|
||||
pub const VALIDATOR_COUNT: usize = 64;
|
||||
pub const SLOT_OFFSET: u64 = 4;
|
||||
pub const EXIT_SLOT_OFFSET: u64 = 2048;
|
||||
pub const NUM_ATTESTATIONS: u64 = 1;
|
||||
@@ -93,7 +93,12 @@ fn invalid_block_signature() {
|
||||
|
||||
// sign the block with a keypair that is not the expected proposer
|
||||
let keypair = Keypair::random();
|
||||
let block = block.message.sign(&keypair.sk, &state.fork, &spec);
|
||||
let block = block.message.sign(
|
||||
&keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
&spec,
|
||||
);
|
||||
|
||||
// process block with invalid block signature
|
||||
let result = per_block_processing(
|
||||
@@ -630,7 +635,7 @@ fn invalid_attestation_wrong_justified_checkpoint() {
|
||||
#[test]
|
||||
fn invalid_attestation_bad_indexed_attestation_bad_signature() {
|
||||
let spec = MainnetEthSpec::default_spec();
|
||||
let builder = get_builder(&spec, SLOT_OFFSET, 33); // minmium number of validators required for this test
|
||||
let builder = get_builder(&spec, SLOT_OFFSET, VALIDATOR_COUNT);
|
||||
let test_task = AttestationTestTask::BadIndexedAttestationBadSignature;
|
||||
let (block, mut state) =
|
||||
builder.build_with_n_attestations(test_task, NUM_ATTESTATIONS, None, None, &spec);
|
||||
|
||||
@@ -15,7 +15,7 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
||||
///
|
||||
/// Optionally verifies the aggregate signature, depending on `verify_signatures`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_attestation_for_block_inclusion<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation: &Attestation<T>,
|
||||
@@ -49,7 +49,7 @@ pub fn verify_attestation_for_block_inclusion<T: EthSpec>(
|
||||
/// Returns a descriptive `Err` if the attestation is malformed or does not accurately reflect the
|
||||
/// prior blocks in `state`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_attestation_for_state<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation: &Attestation<T>,
|
||||
@@ -58,6 +58,13 @@ pub fn verify_attestation_for_state<T: EthSpec>(
|
||||
) -> Result<()> {
|
||||
let data = &attestation.data;
|
||||
|
||||
// This emptiness check is required *in addition* to the length check in `get_attesting_indices`
|
||||
// because we can parse a bitfield and know its length, even if it has no bits set.
|
||||
verify!(
|
||||
!attestation.aggregation_bits.is_zero(),
|
||||
Invalid::AggregationBitfieldIsEmpty
|
||||
);
|
||||
|
||||
verify!(
|
||||
data.index < state.get_committee_count_at_slot(data.slot)?,
|
||||
Invalid::BadCommitteeIndex
|
||||
@@ -76,7 +83,7 @@ pub fn verify_attestation_for_state<T: EthSpec>(
|
||||
|
||||
/// Check target epoch and source checkpoint.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
fn verify_casper_ffg_vote<T: EthSpec>(
|
||||
attestation: &Attestation<T>,
|
||||
state: &BeaconState<T>,
|
||||
|
||||
@@ -15,7 +15,7 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
||||
///
|
||||
/// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_attester_slashing<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attester_slashing: &AttesterSlashing<T>,
|
||||
@@ -47,7 +47,7 @@ pub fn verify_attester_slashing<T: EthSpec>(
|
||||
///
|
||||
/// Returns Ok(indices) if `indices.len() > 0`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn get_slashable_indices<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attester_slashing: &AttesterSlashing<T>,
|
||||
|
||||
@@ -14,7 +14,7 @@ fn error(reason: DepositInvalid) -> BlockOperationError<DepositInvalid> {
|
||||
|
||||
/// Verify `Deposit.pubkey` signed `Deposit.signature`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_deposit_signature(deposit_data: &DepositData, spec: &ChainSpec) -> Result<()> {
|
||||
let deposit_signature_message = deposit_pubkey_signature_message(&deposit_data, spec)
|
||||
.ok_or_else(|| error(DepositInvalid::BadBlsBytes))?;
|
||||
@@ -46,7 +46,7 @@ pub fn get_existing_validator_index<T: EthSpec>(
|
||||
/// The deposit index is provided as a parameter so we can check proofs
|
||||
/// before they're due to be processed, and in parallel.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_deposit_merkle_proof<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
deposit: &Deposit,
|
||||
|
||||
@@ -13,7 +13,7 @@ fn error(reason: ExitInvalid) -> BlockOperationError<ExitInvalid> {
|
||||
///
|
||||
/// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_exit<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
exit: &SignedVoluntaryExit,
|
||||
@@ -25,7 +25,7 @@ pub fn verify_exit<T: EthSpec>(
|
||||
|
||||
/// Like `verify_exit` but doesn't run checks which may become true in future states.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_exit_time_independent_only<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
exit: &SignedVoluntaryExit,
|
||||
@@ -37,7 +37,7 @@ pub fn verify_exit_time_independent_only<T: EthSpec>(
|
||||
|
||||
/// Parametric version of `verify_exit` that skips some checks if `time_independent_only` is true.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
fn verify_exit_parametric<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
signed_exit: &SignedVoluntaryExit,
|
||||
|
||||
@@ -14,38 +14,40 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
||||
///
|
||||
/// Returns `Ok(())` if the `ProposerSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn verify_proposer_slashing<T: EthSpec>(
|
||||
proposer_slashing: &ProposerSlashing,
|
||||
state: &BeaconState<T>,
|
||||
verify_signatures: VerifySignatures,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<()> {
|
||||
let proposer = state
|
||||
.validators
|
||||
.get(proposer_slashing.proposer_index as usize)
|
||||
.ok_or_else(|| error(Invalid::ProposerUnknown(proposer_slashing.proposer_index)))?;
|
||||
let header_1 = &proposer_slashing.signed_header_1.message;
|
||||
let header_2 = &proposer_slashing.signed_header_2.message;
|
||||
|
||||
// Verify slots match
|
||||
verify!(
|
||||
proposer_slashing.signed_header_1.message.slot
|
||||
== proposer_slashing.signed_header_2.message.slot,
|
||||
Invalid::ProposalSlotMismatch(
|
||||
proposer_slashing.signed_header_1.message.slot,
|
||||
proposer_slashing.signed_header_2.message.slot
|
||||
)
|
||||
header_1.slot == header_2.slot,
|
||||
Invalid::ProposalSlotMismatch(header_1.slot, header_2.slot)
|
||||
);
|
||||
|
||||
// Verify header proposer indices match
|
||||
verify!(
|
||||
header_1.proposer_index == header_2.proposer_index,
|
||||
Invalid::ProposerIndexMismatch(header_1.proposer_index, header_2.proposer_index)
|
||||
);
|
||||
|
||||
// But the headers are different
|
||||
verify!(
|
||||
proposer_slashing.signed_header_1 != proposer_slashing.signed_header_2,
|
||||
Invalid::ProposalsIdentical
|
||||
);
|
||||
verify!(header_1 != header_2, Invalid::ProposalsIdentical);
|
||||
|
||||
// Check proposer is slashable
|
||||
let proposer = state
|
||||
.validators
|
||||
.get(header_1.proposer_index as usize)
|
||||
.ok_or_else(|| error(Invalid::ProposerUnknown(header_1.proposer_index)))?;
|
||||
|
||||
verify!(
|
||||
proposer.is_slashable_at(state.current_epoch()),
|
||||
Invalid::ProposerNotSlashable(proposer_slashing.proposer_index)
|
||||
Invalid::ProposerNotSlashable(header_1.proposer_index)
|
||||
);
|
||||
|
||||
if verify_signatures.is_true() {
|
||||
|
||||
@@ -19,7 +19,7 @@ pub use validator_statuses::{TotalBalances, ValidatorStatus, ValidatorStatuses};
|
||||
/// Mutates the given `BeaconState`, returning early if an error is encountered. If an error is
|
||||
/// returned, a state might be "half-processed" and therefore in an invalid state.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn per_epoch_processing<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
@@ -45,7 +45,11 @@ pub fn per_epoch_processing<T: EthSpec>(
|
||||
process_registry_updates(state, spec)?;
|
||||
|
||||
// Slashings.
|
||||
process_slashings(state, validator_statuses.total_balances.current_epoch, spec)?;
|
||||
process_slashings(
|
||||
state,
|
||||
validator_statuses.total_balances.current_epoch(),
|
||||
spec,
|
||||
)?;
|
||||
|
||||
// Final updates.
|
||||
process_final_updates(state, spec)?;
|
||||
@@ -66,7 +70,7 @@ pub fn per_epoch_processing<T: EthSpec>(
|
||||
/// - `finalized_epoch`
|
||||
/// - `finalized_root`
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
#[allow(clippy::if_same_then_else)] // For readability and consistency with spec.
|
||||
pub fn process_justification_and_finalization<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
@@ -86,7 +90,7 @@ pub fn process_justification_and_finalization<T: EthSpec>(
|
||||
state.previous_justified_checkpoint = state.current_justified_checkpoint.clone();
|
||||
state.justification_bits.shift_up(1)?;
|
||||
|
||||
if total_balances.previous_epoch_target_attesters * 3 >= total_balances.current_epoch * 2 {
|
||||
if total_balances.previous_epoch_target_attesters() * 3 >= total_balances.current_epoch() * 2 {
|
||||
state.current_justified_checkpoint = Checkpoint {
|
||||
epoch: previous_epoch,
|
||||
root: *state.get_block_root_at_epoch(previous_epoch)?,
|
||||
@@ -94,7 +98,7 @@ pub fn process_justification_and_finalization<T: EthSpec>(
|
||||
state.justification_bits.set(1, true)?;
|
||||
}
|
||||
// If the current epoch gets justified, fill the last bit.
|
||||
if total_balances.current_epoch_target_attesters * 3 >= total_balances.current_epoch * 2 {
|
||||
if total_balances.current_epoch_target_attesters() * 3 >= total_balances.current_epoch() * 2 {
|
||||
state.current_justified_checkpoint = Checkpoint {
|
||||
epoch: current_epoch,
|
||||
root: *state.get_block_root_at_epoch(current_epoch)?,
|
||||
@@ -134,7 +138,7 @@ pub fn process_justification_and_finalization<T: EthSpec>(
|
||||
|
||||
/// Finish up an epoch update.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_final_updates<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
@@ -148,11 +152,14 @@ pub fn process_final_updates<T: EthSpec>(
|
||||
}
|
||||
|
||||
// Update effective balances with hysteresis (lag).
|
||||
let hysteresis_increment = spec.effective_balance_increment / spec.hysteresis_quotient;
|
||||
let downward_threshold = hysteresis_increment * spec.hysteresis_downward_multiplier;
|
||||
let upward_threshold = hysteresis_increment * spec.hysteresis_upward_multiplier;
|
||||
for (index, validator) in state.validators.iter_mut().enumerate() {
|
||||
let balance = state.balances[index];
|
||||
let half_increment = spec.effective_balance_increment / 2;
|
||||
if balance < validator.effective_balance
|
||||
|| validator.effective_balance + 3 * half_increment < balance
|
||||
|
||||
if balance + downward_threshold < validator.effective_balance
|
||||
|| validator.effective_balance + upward_threshold < balance
|
||||
{
|
||||
validator.effective_balance = std::cmp::min(
|
||||
balance - balance % spec.effective_balance_increment,
|
||||
|
||||
@@ -33,7 +33,7 @@ impl std::ops::AddAssign for Delta {
|
||||
|
||||
/// Apply attester and proposer rewards.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_rewards_and_penalties<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
validator_statuses: &mut ValidatorStatuses,
|
||||
@@ -67,7 +67,7 @@ pub fn process_rewards_and_penalties<T: EthSpec>(
|
||||
|
||||
/// For each attesting validator, reward the proposer who was first to include their attestation.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
fn get_proposer_deltas<T: EthSpec>(
|
||||
deltas: &mut Vec<Delta>,
|
||||
state: &BeaconState<T>,
|
||||
@@ -83,7 +83,7 @@ fn get_proposer_deltas<T: EthSpec>(
|
||||
let base_reward = get_base_reward(
|
||||
state,
|
||||
index,
|
||||
validator_statuses.total_balances.current_epoch,
|
||||
validator_statuses.total_balances.current_epoch(),
|
||||
spec,
|
||||
)?;
|
||||
|
||||
@@ -100,7 +100,7 @@ fn get_proposer_deltas<T: EthSpec>(
|
||||
|
||||
/// Apply rewards for participation in attestations during the previous epoch.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
fn get_attestation_deltas<T: EthSpec>(
|
||||
deltas: &mut Vec<Delta>,
|
||||
state: &BeaconState<T>,
|
||||
@@ -113,7 +113,7 @@ fn get_attestation_deltas<T: EthSpec>(
|
||||
let base_reward = get_base_reward(
|
||||
state,
|
||||
index,
|
||||
validator_statuses.total_balances.current_epoch,
|
||||
validator_statuses.total_balances.current_epoch(),
|
||||
spec,
|
||||
)?;
|
||||
|
||||
@@ -133,7 +133,7 @@ fn get_attestation_deltas<T: EthSpec>(
|
||||
|
||||
/// Determine the delta for a single validator, sans proposer rewards.
|
||||
///
|
||||
/// Spec v0.11.0
|
||||
/// Spec v0.11.1
|
||||
fn get_attestation_delta<T: EthSpec>(
|
||||
validator: &ValidatorStatus,
|
||||
total_balances: &TotalBalances,
|
||||
@@ -157,13 +157,13 @@ fn get_attestation_delta<T: EthSpec>(
|
||||
// - increment = EFFECTIVE_BALANCE_INCREMENT
|
||||
// - reward_numerator = get_base_reward(state, index) * (attesting_balance // increment)
|
||||
// - rewards[index] = reward_numerator // (total_balance // increment)
|
||||
let total_balance_ebi = total_balances.current_epoch / spec.effective_balance_increment;
|
||||
let total_balance_ebi = total_balances.current_epoch() / spec.effective_balance_increment;
|
||||
let total_attesting_balance_ebi =
|
||||
total_balances.previous_epoch_attesters / spec.effective_balance_increment;
|
||||
total_balances.previous_epoch_attesters() / spec.effective_balance_increment;
|
||||
let matching_target_balance_ebi =
|
||||
total_balances.previous_epoch_target_attesters / spec.effective_balance_increment;
|
||||
total_balances.previous_epoch_target_attesters() / spec.effective_balance_increment;
|
||||
let matching_head_balance_ebi =
|
||||
total_balances.previous_epoch_head_attesters / spec.effective_balance_increment;
|
||||
total_balances.previous_epoch_head_attesters() / spec.effective_balance_increment;
|
||||
|
||||
// Expected FFG source.
|
||||
// Spec:
|
||||
|
||||
@@ -2,7 +2,7 @@ use types::{BeaconStateError as Error, *};
|
||||
|
||||
/// Process slashings.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_slashings<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
total_balance: u64,
|
||||
|
||||
@@ -5,7 +5,7 @@ use types::*;
|
||||
|
||||
/// Performs a validator registry update, if required.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_registry_updates<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
|
||||
@@ -12,7 +12,7 @@ macro_rules! set_self_if_other_is_true {
|
||||
}
|
||||
|
||||
/// The information required to reward a block producer for including an attestation in a block.
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct InclusionInfo {
|
||||
/// The distance between the attestation slot and the slot that attestation was included in a
|
||||
/// block.
|
||||
@@ -43,7 +43,7 @@ impl InclusionInfo {
|
||||
}
|
||||
|
||||
/// Information required to reward some validator during the current and previous epoch.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ValidatorStatus {
|
||||
/// True if the validator has been slashed, ever.
|
||||
pub is_slashed: bool,
|
||||
@@ -107,30 +107,64 @@ impl ValidatorStatus {
|
||||
|
||||
/// The total effective balances for different sets of validators during the previous and current
|
||||
/// epochs.
|
||||
#[derive(Default, Clone, Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TotalBalances {
|
||||
/// The effective balance increment from the spec.
|
||||
effective_balance_increment: u64,
|
||||
/// The total effective balance of all active validators during the _current_ epoch.
|
||||
pub current_epoch: u64,
|
||||
current_epoch: u64,
|
||||
/// The total effective balance of all active validators during the _previous_ epoch.
|
||||
pub previous_epoch: u64,
|
||||
previous_epoch: u64,
|
||||
/// The total effective balance of all validators who attested during the _current_ epoch.
|
||||
pub current_epoch_attesters: u64,
|
||||
current_epoch_attesters: u64,
|
||||
/// The total effective balance of all validators who attested during the _current_ epoch and
|
||||
/// agreed with the state about the beacon block at the first slot of the _current_ epoch.
|
||||
pub current_epoch_target_attesters: u64,
|
||||
current_epoch_target_attesters: u64,
|
||||
/// The total effective balance of all validators who attested during the _previous_ epoch.
|
||||
pub previous_epoch_attesters: u64,
|
||||
previous_epoch_attesters: u64,
|
||||
/// The total effective balance of all validators who attested during the _previous_ epoch and
|
||||
/// agreed with the state about the beacon block at the first slot of the _previous_ epoch.
|
||||
pub previous_epoch_target_attesters: u64,
|
||||
previous_epoch_target_attesters: u64,
|
||||
/// The total effective balance of all validators who attested during the _previous_ epoch and
|
||||
/// agreed with the state about the beacon block at the time of attestation.
|
||||
pub previous_epoch_head_attesters: u64,
|
||||
previous_epoch_head_attesters: u64,
|
||||
}
|
||||
|
||||
// Generate a safe accessor for a balance in `TotalBalances`, as per spec `get_total_balance`.
|
||||
macro_rules! balance_accessor {
|
||||
($field_name:ident) => {
|
||||
pub fn $field_name(&self) -> u64 {
|
||||
std::cmp::max(self.effective_balance_increment, self.$field_name)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl TotalBalances {
|
||||
pub fn new(spec: &ChainSpec) -> Self {
|
||||
Self {
|
||||
effective_balance_increment: spec.effective_balance_increment,
|
||||
current_epoch: 0,
|
||||
previous_epoch: 0,
|
||||
current_epoch_attesters: 0,
|
||||
current_epoch_target_attesters: 0,
|
||||
previous_epoch_attesters: 0,
|
||||
previous_epoch_target_attesters: 0,
|
||||
previous_epoch_head_attesters: 0,
|
||||
}
|
||||
}
|
||||
|
||||
balance_accessor!(current_epoch);
|
||||
balance_accessor!(previous_epoch);
|
||||
balance_accessor!(current_epoch_attesters);
|
||||
balance_accessor!(current_epoch_target_attesters);
|
||||
balance_accessor!(previous_epoch_attesters);
|
||||
balance_accessor!(previous_epoch_target_attesters);
|
||||
balance_accessor!(previous_epoch_head_attesters);
|
||||
}
|
||||
|
||||
/// Summarised information about validator participation in the _previous and _current_ epochs of
|
||||
/// some `BeaconState`.
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValidatorStatuses {
|
||||
/// Information about each individual validator from the state's validator registry.
|
||||
pub statuses: Vec<ValidatorStatus>,
|
||||
@@ -144,13 +178,13 @@ impl ValidatorStatuses {
|
||||
/// - Active validators
|
||||
/// - Total balances for the current and previous epochs.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn new<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Self, BeaconStateError> {
|
||||
let mut statuses = Vec::with_capacity(state.validators.len());
|
||||
let mut total_balances = TotalBalances::default();
|
||||
let mut total_balances = TotalBalances::new(spec);
|
||||
|
||||
for (i, validator) in state.validators.iter().enumerate() {
|
||||
let effective_balance = state.get_effective_balance(i, spec)?;
|
||||
@@ -184,7 +218,7 @@ impl ValidatorStatuses {
|
||||
/// Process some attestations from the given `state` updating the `statuses` and
|
||||
/// `total_balances` fields.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn process_attestations<T: EthSpec>(
|
||||
&mut self,
|
||||
state: &BeaconState<T>,
|
||||
@@ -221,10 +255,10 @@ impl ValidatorStatuses {
|
||||
|
||||
if target_matches_epoch_start_block(a, state, state.previous_epoch())? {
|
||||
status.is_previous_epoch_target_attester = true;
|
||||
}
|
||||
|
||||
if has_common_beacon_block_root(a, state)? {
|
||||
status.is_previous_epoch_head_attester = true;
|
||||
if has_common_beacon_block_root(a, state)? {
|
||||
status.is_previous_epoch_head_attester = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +299,7 @@ impl ValidatorStatuses {
|
||||
/// Returns `true` if the attestation's FFG target is equal to the hash of the `state`'s first
|
||||
/// beacon block in the given `epoch`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
fn target_matches_epoch_start_block<T: EthSpec>(
|
||||
a: &PendingAttestation<T>,
|
||||
state: &BeaconState<T>,
|
||||
@@ -280,7 +314,7 @@ fn target_matches_epoch_start_block<T: EthSpec>(
|
||||
/// Returns `true` if a `PendingAttestation` and `BeaconState` share the same beacon block hash for
|
||||
/// the current slot of the `PendingAttestation`.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
fn has_common_beacon_block_root<T: EthSpec>(
|
||||
a: &PendingAttestation<T>,
|
||||
state: &BeaconState<T>,
|
||||
|
||||
@@ -13,7 +13,7 @@ pub enum Error {
|
||||
/// `state_root` is `None`, the root of `state` will be computed using a cached tree hash.
|
||||
/// Providing the `state_root` makes this function several orders of magniude faster.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
/// Spec v0.11.1
|
||||
pub fn per_slot_processing<T: EthSpec>(
|
||||
state: &mut BeaconState<T>,
|
||||
state_root: Option<Hash256>,
|
||||
|
||||
@@ -62,7 +62,14 @@ impl<T: EthSpec> BlockBuilder<T> {
|
||||
|
||||
let proposer_keypair = &keypairs[proposer_index];
|
||||
|
||||
builder.set_randao_reveal(&proposer_keypair.sk, &state.fork, spec);
|
||||
builder.set_proposer_index(proposer_index as u64);
|
||||
|
||||
builder.set_randao_reveal(
|
||||
&proposer_keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
|
||||
let parent_root = state.latest_block_header.canonical_root();
|
||||
builder.set_parent_root(parent_root);
|
||||
@@ -79,6 +86,7 @@ impl<T: EthSpec> BlockBuilder<T> {
|
||||
validator_index,
|
||||
&keypairs[validator_index as usize].sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
}
|
||||
@@ -106,6 +114,7 @@ impl<T: EthSpec> BlockBuilder<T> {
|
||||
&attesters,
|
||||
&secret_keys,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
}
|
||||
@@ -161,9 +170,12 @@ impl<T: EthSpec> BlockBuilder<T> {
|
||||
// Set the eth1 data to be different from the state.
|
||||
self.block_builder.block.body.eth1_data.block_hash = Hash256::from_slice(&[42; 32]);
|
||||
|
||||
let block = self
|
||||
.block_builder
|
||||
.build(&proposer_keypair.sk, &state.fork, spec);
|
||||
let block = self.block_builder.build(
|
||||
&proposer_keypair.sk,
|
||||
&state.fork,
|
||||
state.genesis_validators_root,
|
||||
spec,
|
||||
);
|
||||
|
||||
(block, state)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user