state_processing: IndexedAttestation rename

This commit is contained in:
Michael Sproul 2019-05-13 17:28:04 +10:00
parent bc03e14943
commit 4f138fa3fe
No known key found for this signature in database
GPG Key ID: 77B1309D2E54E914
4 changed files with 75 additions and 77 deletions

View File

@ -15,7 +15,7 @@ pub use validate_attestation::{
}; };
pub use verify_deposit::{get_existing_validator_index, verify_deposit, verify_deposit_index}; pub use verify_deposit::{get_existing_validator_index, verify_deposit, verify_deposit_index};
pub use verify_exit::{verify_exit, verify_exit_time_independent_only}; pub use verify_exit::{verify_exit, verify_exit_time_independent_only};
pub use verify_slashable_attestation::verify_slashable_attestation; pub use verify_indexed_attestation::verify_indexed_attestation;
pub use verify_transfer::{ pub use verify_transfer::{
execute_transfer, verify_transfer, verify_transfer_time_independent_only, execute_transfer, verify_transfer, verify_transfer_time_independent_only,
}; };
@ -25,8 +25,8 @@ mod validate_attestation;
mod verify_attester_slashing; mod verify_attester_slashing;
mod verify_deposit; mod verify_deposit;
mod verify_exit; mod verify_exit;
mod verify_indexed_attestation;
mod verify_proposer_slashing; mod verify_proposer_slashing;
mod verify_slashable_attestation;
mod verify_transfer; mod verify_transfer;
// Set to `true` to check the merkle proof that a deposit is in the eth1 deposit root. // Set to `true` to check the merkle proof that a deposit is in the eth1 deposit root.
@ -253,41 +253,41 @@ pub fn process_attester_slashings(
Invalid::MaxAttesterSlashingsExceed Invalid::MaxAttesterSlashingsExceed
); );
// Verify the `SlashableAttestation`s in parallel (these are the resource-consuming objects, not // Verify the `IndexedAttestation`s in parallel (these are the resource-consuming objects, not
// the `AttesterSlashing`s themselves). // the `AttesterSlashing`s themselves).
let mut slashable_attestations: Vec<&SlashableAttestation> = let mut indexed_attestations: Vec<&IndexedAttestation> =
Vec::with_capacity(attester_slashings.len() * 2); Vec::with_capacity(attester_slashings.len() * 2);
for attester_slashing in attester_slashings { for attester_slashing in attester_slashings {
slashable_attestations.push(&attester_slashing.slashable_attestation_1); indexed_attestations.push(&attester_slashing.attestation_1);
slashable_attestations.push(&attester_slashing.slashable_attestation_2); indexed_attestations.push(&attester_slashing.attestation_2);
} }
// Verify slashable attestations in parallel. // Verify indexed attestations in parallel.
slashable_attestations indexed_attestations
.par_iter() .par_iter()
.enumerate() .enumerate()
.try_for_each(|(i, slashable_attestation)| { .try_for_each(|(i, indexed_attestation)| {
verify_slashable_attestation(&state, slashable_attestation, spec) verify_indexed_attestation(&state, indexed_attestation, spec)
.map_err(|e| e.into_with_index(i)) .map_err(|e| e.into_with_index(i))
})?; })?;
let all_slashable_attestations_have_been_checked = true; let all_indexed_attestations_have_been_checked = true;
// Gather the slashable indices and preform the final verification and update the state in series. // Gather the indexed indices and preform the final verification and update the state in series.
for (i, attester_slashing) in attester_slashings.iter().enumerate() { for (i, attester_slashing) in attester_slashings.iter().enumerate() {
let should_verify_slashable_attestations = !all_slashable_attestations_have_been_checked; let should_verify_indexed_attestations = !all_indexed_attestations_have_been_checked;
verify_attester_slashing( verify_attester_slashing(
&state, &state,
&attester_slashing, &attester_slashing,
should_verify_slashable_attestations, should_verify_indexed_attestations,
spec, spec,
) )
.map_err(|e| e.into_with_index(i))?; .map_err(|e| e.into_with_index(i))?;
let slashable_indices = gather_attester_slashing_indices(&state, &attester_slashing, spec) let indexed_indices = gather_attester_slashing_indices(&state, &attester_slashing, spec)
.map_err(|e| e.into_with_index(i))?; .map_err(|e| e.into_with_index(i))?;
for i in slashable_indices { for i in indexed_indices {
slash_validator(state, i as usize, spec)?; slash_validator(state, i as usize, spec)?;
} }
} }

View File

@ -80,10 +80,10 @@ pub enum BlockInvalid {
MaxExitsExceeded, MaxExitsExceeded,
MaxTransfersExceed, MaxTransfersExceed,
AttestationInvalid(usize, AttestationInvalid), AttestationInvalid(usize, AttestationInvalid),
/// A `SlashableAttestation` inside an `AttesterSlashing` was invalid. /// A `IndexedAttestation` inside an `AttesterSlashing` was invalid.
/// ///
/// To determine the offending `AttesterSlashing` index, divide the error message `usize` by two. /// To determine the offending `AttesterSlashing` index, divide the error message `usize` by two.
SlashableAttestationInvalid(usize, SlashableAttestationInvalid), IndexedAttestationInvalid(usize, IndexedAttestationInvalid),
AttesterSlashingInvalid(usize, AttesterSlashingInvalid), AttesterSlashingInvalid(usize, AttesterSlashingInvalid),
ProposerSlashingInvalid(usize, ProposerSlashingInvalid), ProposerSlashingInvalid(usize, ProposerSlashingInvalid),
DepositInvalid(usize, DepositInvalid), DepositInvalid(usize, DepositInvalid),
@ -194,10 +194,10 @@ pub enum AttesterSlashingInvalid {
AttestationDataIdentical, AttestationDataIdentical,
/// The attestations were not in conflict. /// The attestations were not in conflict.
NotSlashable, NotSlashable,
/// The first `SlashableAttestation` was invalid. /// The first `IndexedAttestation` was invalid.
SlashableAttestation1Invalid(SlashableAttestationInvalid), IndexedAttestation1Invalid(IndexedAttestationInvalid),
/// The second `SlashableAttestation` was invalid. /// The second `IndexedAttestation` was invalid.
SlashableAttestation2Invalid(SlashableAttestationInvalid), IndexedAttestation2Invalid(IndexedAttestationInvalid),
/// The validator index is unknown. One cannot slash one who does not exist. /// The validator index is unknown. One cannot slash one who does not exist.
UnknownValidator(u64), UnknownValidator(u64),
/// The specified validator has already been withdrawn. /// The specified validator has already been withdrawn.
@ -210,19 +210,19 @@ impl_from_beacon_state_error!(AttesterSlashingValidationError);
impl_into_with_index_with_beacon_error!(AttesterSlashingValidationError, AttesterSlashingInvalid); impl_into_with_index_with_beacon_error!(AttesterSlashingValidationError, AttesterSlashingInvalid);
/* /*
* `SlashableAttestation` Validation * `IndexedAttestation` Validation
*/ */
/// The object is invalid or validation failed. /// The object is invalid or validation failed.
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum SlashableAttestationValidationError { pub enum IndexedAttestationValidationError {
/// Validation completed successfully and the object is invalid. /// Validation completed successfully and the object is invalid.
Invalid(SlashableAttestationInvalid), Invalid(IndexedAttestationInvalid),
} }
/// Describes why an object is invalid. /// Describes why an object is invalid.
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum SlashableAttestationInvalid { pub enum IndexedAttestationInvalid {
/// The custody bitfield has some bits set `true`. This is not allowed in phase 0. /// The custody bitfield has some bits set `true`. This is not allowed in phase 0.
CustodyBitfieldHasSetBits, CustodyBitfieldHasSetBits,
/// No validator indices were specified. /// No validator indices were specified.
@ -245,17 +245,17 @@ pub enum SlashableAttestationInvalid {
BadSignature, BadSignature,
} }
impl Into<SlashableAttestationInvalid> for SlashableAttestationValidationError { impl Into<IndexedAttestationInvalid> for IndexedAttestationValidationError {
fn into(self) -> SlashableAttestationInvalid { fn into(self) -> IndexedAttestationInvalid {
match self { match self {
SlashableAttestationValidationError::Invalid(e) => e, IndexedAttestationValidationError::Invalid(e) => e,
} }
} }
} }
impl_into_with_index_without_beacon_error!( impl_into_with_index_without_beacon_error!(
SlashableAttestationValidationError, IndexedAttestationValidationError,
SlashableAttestationInvalid IndexedAttestationInvalid
); );
/* /*

View File

@ -1,5 +1,5 @@
use super::errors::{AttesterSlashingInvalid as Invalid, AttesterSlashingValidationError as Error}; use super::errors::{AttesterSlashingInvalid as Invalid, AttesterSlashingValidationError as Error};
use super::verify_slashable_attestation::verify_slashable_attestation; use super::verify_indexed_attestation::verify_indexed_attestation;
use types::*; use types::*;
/// Indicates if an `AttesterSlashing` is valid to be included in a block in the current epoch of the given /// Indicates if an `AttesterSlashing` is valid to be included in a block in the current epoch of the given
@ -11,27 +11,27 @@ use types::*;
pub fn verify_attester_slashing( pub fn verify_attester_slashing(
state: &BeaconState, state: &BeaconState,
attester_slashing: &AttesterSlashing, attester_slashing: &AttesterSlashing,
should_verify_slashable_attestations: bool, should_verify_indexed_attestations: bool,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<(), Error> { ) -> Result<(), Error> {
let slashable_attestation_1 = &attester_slashing.slashable_attestation_1; let indexed_attestation_1 = &attester_slashing.indexed_attestation_1;
let slashable_attestation_2 = &attester_slashing.slashable_attestation_2; let indexed_attestation_2 = &attester_slashing.indexed_attestation_2;
verify!( verify!(
slashable_attestation_1.data != slashable_attestation_2.data, indexed_attestation_1.data != indexed_attestation_2.data,
Invalid::AttestationDataIdentical Invalid::AttestationDataIdentical
); );
verify!( verify!(
slashable_attestation_1.is_double_vote(slashable_attestation_2, spec) indexed_attestation_1.is_double_vote(indexed_attestation_2, spec)
| slashable_attestation_1.is_surround_vote(slashable_attestation_2, spec), | indexed_attestation_1.is_surround_vote(indexed_attestation_2, spec),
Invalid::NotSlashable Invalid::NotSlashable
); );
if should_verify_slashable_attestations { if should_verify_indexed_attestations {
verify_slashable_attestation(state, &slashable_attestation_1, spec) verify_indexed_attestation(state, &indexed_attestation_1, spec)
.map_err(|e| Error::Invalid(Invalid::SlashableAttestation1Invalid(e.into())))?; .map_err(|e| Error::Invalid(Invalid::IndexedAttestation1Invalid(e.into())))?;
verify_slashable_attestation(state, &slashable_attestation_2, spec) verify_indexed_attestation(state, &indexed_attestation_2, spec)
.map_err(|e| Error::Invalid(Invalid::SlashableAttestation2Invalid(e.into())))?; .map_err(|e| Error::Invalid(Invalid::IndexedAttestation2Invalid(e.into())))?;
} }
Ok(()) Ok(())
@ -66,31 +66,31 @@ pub fn gather_attester_slashing_indices_modular<F>(
where where
F: Fn(u64, &Validator) -> bool, F: Fn(u64, &Validator) -> bool,
{ {
let slashable_attestation_1 = &attester_slashing.slashable_attestation_1; let indexed_attestation_1 = &attester_slashing.indexed_attestation_1;
let slashable_attestation_2 = &attester_slashing.slashable_attestation_2; let indexed_attestation_2 = &attester_slashing.indexed_attestation_2;
let mut slashable_indices = Vec::with_capacity(spec.max_indices_per_slashable_vote); let mut indexed_indices = Vec::with_capacity(spec.max_indices_per_indexed_vote);
for i in &slashable_attestation_1.validator_indices { for i in &indexed_attestation_1.validator_indices {
let validator = state let validator = state
.validator_registry .validator_registry
.get(*i as usize) .get(*i as usize)
.ok_or_else(|| Error::Invalid(Invalid::UnknownValidator(*i)))?; .ok_or_else(|| Error::Invalid(Invalid::UnknownValidator(*i)))?;
if slashable_attestation_2.validator_indices.contains(&i) & !is_slashed(*i, validator) { if indexed_attestation_2.validator_indices.contains(&i) & !is_slashed(*i, validator) {
// TODO: verify that we should reject any slashable attestation which includes a // TODO: verify that we should reject any indexed attestation which includes a
// withdrawn validator. PH has asked the question on gitter, awaiting response. // withdrawn validator. PH has asked the question on gitter, awaiting response.
verify!( verify!(
validator.withdrawable_epoch > state.slot.epoch(spec.slots_per_epoch), validator.withdrawable_epoch > state.slot.epoch(spec.slots_per_epoch),
Invalid::ValidatorAlreadyWithdrawn(*i) Invalid::ValidatorAlreadyWithdrawn(*i)
); );
slashable_indices.push(*i); indexed_indices.push(*i);
} }
} }
verify!(!slashable_indices.is_empty(), Invalid::NoSlashableIndices); verify!(!indexed_indices.is_empty(), Invalid::NoSlashableIndices);
slashable_indices.shrink_to_fit(); indexed_indices.shrink_to_fit();
Ok(slashable_indices) Ok(indexed_indices)
} }

View File

@ -1,52 +1,50 @@
use super::errors::{ use super::errors::{
SlashableAttestationInvalid as Invalid, SlashableAttestationValidationError as Error, IndexedAttestationInvalid as Invalid, IndexedAttestationValidationError as Error,
}; };
use crate::common::verify_bitfield_length; use crate::common::verify_bitfield_length;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use types::*; use types::*;
/// Indicates if a `SlashableAttestation` is valid to be included in a block in the current epoch of the given /// Indicates if a `IndexedAttestation` is valid to be included in a block in the current epoch of the given
/// state. /// state.
/// ///
/// Returns `Ok(())` if the `SlashableAttestation` is valid, otherwise indicates the reason for invalidity. /// Returns `Ok(())` if the `IndexedAttestation` is valid, otherwise indicates the reason for invalidity.
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
pub fn verify_slashable_attestation( pub fn verify_indexed_attestation(
state: &BeaconState, state: &BeaconState,
slashable_attestation: &SlashableAttestation, indexed_attestation: &IndexedAttestation,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<(), Error> { ) -> Result<(), Error> {
if slashable_attestation.custody_bitfield.num_set_bits() > 0 { if indexed_attestation.custody_bitfield.num_set_bits() > 0 {
invalid!(Invalid::CustodyBitfieldHasSetBits); invalid!(Invalid::CustodyBitfieldHasSetBits);
} }
if slashable_attestation.validator_indices.is_empty() { if indexed_attestation.validator_indices.is_empty() {
invalid!(Invalid::NoValidatorIndices); invalid!(Invalid::NoValidatorIndices);
} }
for i in 0..(slashable_attestation.validator_indices.len() - 1) { for i in 0..(indexed_attestation.validator_indices.len() - 1) {
if slashable_attestation.validator_indices[i] if indexed_attestation.validator_indices[i] >= indexed_attestation.validator_indices[i + 1]
>= slashable_attestation.validator_indices[i + 1]
{ {
invalid!(Invalid::BadValidatorIndicesOrdering(i)); invalid!(Invalid::BadValidatorIndicesOrdering(i));
} }
} }
if !verify_bitfield_length( if !verify_bitfield_length(
&slashable_attestation.custody_bitfield, &indexed_attestation.custody_bitfield,
slashable_attestation.validator_indices.len(), indexed_attestation.validator_indices.len(),
) { ) {
invalid!(Invalid::BadCustodyBitfieldLength( invalid!(Invalid::BadCustodyBitfieldLength(
slashable_attestation.validator_indices.len(), indexed_attestation.validator_indices.len(),
slashable_attestation.custody_bitfield.len() indexed_attestation.custody_bitfield.len()
)); ));
} }
if slashable_attestation.validator_indices.len() > spec.max_indices_per_slashable_vote as usize if indexed_attestation.validator_indices.len() > spec.max_indices_per_indexed_vote as usize {
{
invalid!(Invalid::MaxIndicesExceed( invalid!(Invalid::MaxIndicesExceed(
spec.max_indices_per_slashable_vote as usize, spec.max_indices_per_indexed_vote as usize,
slashable_attestation.validator_indices.len() indexed_attestation.validator_indices.len()
)); ));
} }
@ -57,8 +55,8 @@ pub fn verify_slashable_attestation(
let mut aggregate_pubs = vec![AggregatePublicKey::new(); 2]; let mut aggregate_pubs = vec![AggregatePublicKey::new(); 2];
let mut message_exists = vec![false; 2]; let mut message_exists = vec![false; 2];
for (i, v) in slashable_attestation.validator_indices.iter().enumerate() { for (i, v) in indexed_attestation.validator_indices.iter().enumerate() {
let custody_bit = match slashable_attestation.custody_bitfield.get(i) { let custody_bit = match indexed_attestation.custody_bitfield.get(i) {
Ok(bit) => bit, Ok(bit) => bit,
Err(_) => unreachable!(), Err(_) => unreachable!(),
}; };
@ -74,12 +72,12 @@ pub fn verify_slashable_attestation(
} }
let message_0 = AttestationDataAndCustodyBit { let message_0 = AttestationDataAndCustodyBit {
data: slashable_attestation.data.clone(), data: indexed_attestation.data.clone(),
custody_bit: false, custody_bit: false,
} }
.tree_hash_root(); .tree_hash_root();
let message_1 = AttestationDataAndCustodyBit { let message_1 = AttestationDataAndCustodyBit {
data: slashable_attestation.data.clone(), data: indexed_attestation.data.clone(),
custody_bit: true, custody_bit: true,
} }
.tree_hash_root(); .tree_hash_root();
@ -97,12 +95,12 @@ pub fn verify_slashable_attestation(
} }
let domain = { let domain = {
let epoch = slashable_attestation.data.slot.epoch(spec.slots_per_epoch); let epoch = indexed_attestation.data.slot.epoch(spec.slots_per_epoch);
spec.get_domain(epoch, Domain::Attestation, &state.fork) spec.get_domain(epoch, Domain::Attestation, &state.fork)
}; };
verify!( verify!(
slashable_attestation indexed_attestation
.aggregate_signature .aggregate_signature
.verify_multiple(&messages[..], domain, &keys[..]), .verify_multiple(&messages[..], domain, &keys[..]),
Invalid::BadSignature Invalid::BadSignature