state_processing: IndexedAttestation rename
This commit is contained in:
parent
bc03e14943
commit
4f138fa3fe
@ -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)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user