* Start updating types * WIP * Signature hacking * Existing EF tests passing with fake_crypto * Updates * Delete outdated API spec * The refactor continues * It compiles * WIP test fixes * All release tests passing bar genesis state parsing * Update and test YamlConfig * Update to spec v0.10 compatible BLS * Updates to BLS EF tests * Add EF test for AggregateVerify And delete unused hash2curve tests for uncompressed points * Update EF tests to v0.10.1 * Use optional block root correctly in block proc * Use genesis fork in deposit domain. All tests pass * Cargo fmt * Fast aggregate verify test * Update REST API docs * Cargo fmt * Fix unused import * Bump spec tags to v0.10.1 * Add `seconds_per_eth1_block` to chainspec * Update to timestamp based eth1 voting scheme * Return None from `get_votes_to_consider` if block cache is empty * Handle overflows in `is_candidate_block` * Revert to failing tests * Fix eth1 data sets test * Choose default vote according to spec * Fix collect_valid_votes tests * Fix `get_votes_to_consider` to choose all eligible blocks * Uncomment winning_vote tests * Add comments; remove unused code * Reduce seconds_per_eth1_block for simulation * Addressed review comments * Add test for default vote case * Fix logs * Remove unused functions * Meter default eth1 votes * Fix comments * Address review comments; remove unused dependency * Add first attempt at attestation proc. re-write * Add version 2 of attestation processing * Minor fixes * Add validator pubkey cache * Make get_indexed_attestation take a committee * Link signature processing into new attn verification * First working version * Ensure pubkey cache is updated * Add more metrics, slight optimizations * Clone committee cache during attestation processing * Update shuffling cache during block processing * Remove old commented-out code * Fix shuffling cache insert bug * Used indexed attestation in fork choice * Restructure attn processing, add metrics * Add more detailed metrics * Tidy, fix failing tests * Fix failing tests, tidy * Disable/delete two outdated tests * Tidy * Add pubkey cache persistence file * Add more comments * Integrate persistence file into builder * Add pubkey cache tests * Add data_dir to beacon chain builder * Remove Option in pubkey cache persistence file * Ensure consistency between datadir/data_dir * Fix failing network test * Tidy * Fix todos * Add attestation processing tests * Add another test * Only run attestation tests in release * Make attestation tests MainnetEthSpec * Address Michael's comments * Remove redundant check * Fix warning * Fix failing test Co-authored-by: Michael Sproul <micsproul@gmail.com> Co-authored-by: Pawan Dhananjay <pawandhananjay@gmail.com>
116 lines
3.7 KiB
Rust
116 lines
3.7 KiB
Rust
use super::errors::{AttestationInvalid as Invalid, BlockOperationError};
|
|
use super::VerifySignatures;
|
|
use crate::common::get_indexed_attestation;
|
|
use crate::per_block_processing::is_valid_indexed_attestation;
|
|
use types::*;
|
|
|
|
type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;
|
|
|
|
fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
|
BlockOperationError::invalid(reason)
|
|
}
|
|
|
|
/// Returns `Ok(())` if the given `attestation` is valid to be included in a block that is applied
|
|
/// to `state`. Otherwise, returns a descriptive `Err`.
|
|
///
|
|
/// Optionally verifies the aggregate signature, depending on `verify_signatures`.
|
|
///
|
|
/// Spec v0.10.1
|
|
pub fn verify_attestation_for_block_inclusion<T: EthSpec>(
|
|
state: &BeaconState<T>,
|
|
attestation: &Attestation<T>,
|
|
verify_signatures: VerifySignatures,
|
|
spec: &ChainSpec,
|
|
) -> Result<()> {
|
|
let data = &attestation.data;
|
|
|
|
verify!(
|
|
data.slot + spec.min_attestation_inclusion_delay <= state.slot,
|
|
Invalid::IncludedTooEarly {
|
|
state: state.slot,
|
|
delay: spec.min_attestation_inclusion_delay,
|
|
attestation: data.slot,
|
|
}
|
|
);
|
|
verify!(
|
|
state.slot <= data.slot + T::slots_per_epoch(),
|
|
Invalid::IncludedTooLate {
|
|
state: state.slot,
|
|
attestation: data.slot,
|
|
}
|
|
);
|
|
|
|
verify_attestation_for_state(state, attestation, verify_signatures, spec)
|
|
}
|
|
|
|
/// Returns `Ok(())` if `attestation` is a valid attestation to the chain that precedes the given
|
|
/// `state`.
|
|
///
|
|
/// Returns a descriptive `Err` if the attestation is malformed or does not accurately reflect the
|
|
/// prior blocks in `state`.
|
|
///
|
|
/// Spec v0.10.1
|
|
pub fn verify_attestation_for_state<T: EthSpec>(
|
|
state: &BeaconState<T>,
|
|
attestation: &Attestation<T>,
|
|
verify_signatures: VerifySignatures,
|
|
spec: &ChainSpec,
|
|
) -> Result<()> {
|
|
let data = &attestation.data;
|
|
|
|
verify!(
|
|
data.index < state.get_committee_count_at_slot(data.slot)?,
|
|
Invalid::BadCommitteeIndex
|
|
);
|
|
|
|
// Verify the Casper FFG vote.
|
|
verify_casper_ffg_vote(attestation, state)?;
|
|
|
|
// Check signature and bitfields
|
|
let committee = state.get_beacon_committee(attestation.data.slot, attestation.data.index)?;
|
|
let indexed_attestation = get_indexed_attestation(committee.committee, attestation)?;
|
|
is_valid_indexed_attestation(state, &indexed_attestation, verify_signatures, spec)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Check target epoch and source checkpoint.
|
|
///
|
|
/// Spec v0.10.1
|
|
fn verify_casper_ffg_vote<T: EthSpec>(
|
|
attestation: &Attestation<T>,
|
|
state: &BeaconState<T>,
|
|
) -> Result<()> {
|
|
let data = &attestation.data;
|
|
verify!(
|
|
data.target.epoch == data.slot.epoch(T::slots_per_epoch()),
|
|
Invalid::TargetEpochSlotMismatch {
|
|
target_epoch: data.target.epoch,
|
|
slot_epoch: data.slot.epoch(T::slots_per_epoch()),
|
|
}
|
|
);
|
|
if data.target.epoch == state.current_epoch() {
|
|
verify!(
|
|
data.source == state.current_justified_checkpoint,
|
|
Invalid::WrongJustifiedCheckpoint {
|
|
state: state.current_justified_checkpoint.clone(),
|
|
attestation: data.source.clone(),
|
|
is_current: true,
|
|
}
|
|
);
|
|
Ok(())
|
|
} else if data.target.epoch == state.previous_epoch() {
|
|
verify!(
|
|
data.source == state.previous_justified_checkpoint,
|
|
Invalid::WrongJustifiedCheckpoint {
|
|
state: state.previous_justified_checkpoint.clone(),
|
|
attestation: data.source.clone(),
|
|
is_current: false,
|
|
}
|
|
);
|
|
Ok(())
|
|
} else {
|
|
Err(error(Invalid::BadTargetEpoch))
|
|
}
|
|
}
|