Add comments to block_processing code
This commit is contained in:
parent
40f74c9b26
commit
599948b26b
@ -1,4 +1,4 @@
|
|||||||
use types::BeaconStateError;
|
use types::*;
|
||||||
|
|
||||||
macro_rules! impl_from_beacon_state_error {
|
macro_rules! impl_from_beacon_state_error {
|
||||||
($type: ident) => {
|
($type: ident) => {
|
||||||
@ -39,23 +39,31 @@ macro_rules! impl_into_with_index_without_beacon_error {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A conversion that consumes `self` and adds an `index` variable to resulting struct.
|
||||||
|
///
|
||||||
|
/// Used here to allow converting an error into an upstream error that points to the object that
|
||||||
|
/// caused the error. For example, pointing to the index of an attestation that caused the
|
||||||
|
/// `AttestationInvalid` error.
|
||||||
pub trait IntoWithIndex<T>: Sized {
|
pub trait IntoWithIndex<T>: Sized {
|
||||||
fn into_with_index(self, i: usize) -> T;
|
fn into_with_index(self, index: usize) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Block Validation
|
* Block Validation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// The object is invalid or validation failed.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum BlockProcessingError {
|
pub enum BlockProcessingError {
|
||||||
/// The `BeaconBlock` is invalid.
|
/// Validation completed successfully and the object is invalid.
|
||||||
Invalid(BlockInvalid),
|
Invalid(BlockInvalid),
|
||||||
|
/// Encountered a `BeaconStateError` whilst attempting to determine validity.
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_from_beacon_state_error!(BlockProcessingError);
|
impl_from_beacon_state_error!(BlockProcessingError);
|
||||||
|
|
||||||
|
/// Describes why an object is invalid.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum BlockInvalid {
|
pub enum BlockInvalid {
|
||||||
StateSlotMismatch,
|
StateSlotMismatch,
|
||||||
@ -87,28 +95,61 @@ impl Into<BlockProcessingError> for BlockInvalid {
|
|||||||
* Attestation Validation
|
* Attestation Validation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// The object is invalid or validation failed.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum AttestationValidationError {
|
pub enum AttestationValidationError {
|
||||||
/// The `Attestation` is invalid.
|
/// Validation completed successfully and the object is invalid.
|
||||||
Invalid(AttestationInvalid),
|
Invalid(AttestationInvalid),
|
||||||
/// Encountered a `BeaconStateError` whilst attempting to determine validity.
|
/// Encountered a `BeaconStateError` whilst attempting to determine validity.
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes why an object is invalid.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum AttestationInvalid {
|
pub enum AttestationInvalid {
|
||||||
PreGenesis,
|
/// Attestation references a pre-genesis slot.
|
||||||
IncludedTooEarly,
|
///
|
||||||
IncludedTooLate,
|
/// (genesis_slot, attestation_slot)
|
||||||
WrongJustifiedSlot,
|
PreGenesis(Slot, Slot),
|
||||||
WrongJustifiedRoot,
|
/// Attestation included before the inclusion delay.
|
||||||
|
///
|
||||||
|
/// (state_slot, inclusion_delay, attestation_slot)
|
||||||
|
IncludedTooEarly(Slot, u64, Slot),
|
||||||
|
/// Attestation slot is too far in the past to be included in a block.
|
||||||
|
///
|
||||||
|
/// (state_slot, attestation_slot)
|
||||||
|
IncludedTooLate(Slot, Slot),
|
||||||
|
/// Attestation justified epoch does not match the states current or previous justified epoch.
|
||||||
|
///
|
||||||
|
/// (attestation_justified_epoch, state_epoch, used_previous_epoch)
|
||||||
|
WrongJustifiedEpoch(Epoch, Epoch, bool),
|
||||||
|
/// Attestation justified epoch root does not match root known to the state.
|
||||||
|
///
|
||||||
|
/// (state_justified_root, attestation_justified_root)
|
||||||
|
WrongJustifiedRoot(Hash256, Hash256),
|
||||||
|
/// Attestation crosslink root does not match the state crosslink root for the attestations
|
||||||
|
/// slot.
|
||||||
BadLatestCrosslinkRoot,
|
BadLatestCrosslinkRoot,
|
||||||
|
/// The custody bitfield has some bits set `true`. This is not allowed in phase 0.
|
||||||
CustodyBitfieldHasSetBits,
|
CustodyBitfieldHasSetBits,
|
||||||
|
/// There are no set bits on the attestation -- an attestation must be signed by at least one
|
||||||
|
/// validator.
|
||||||
AggregationBitfieldIsEmpty,
|
AggregationBitfieldIsEmpty,
|
||||||
BadAggregationBitfieldLength,
|
/// The custody bitfield length is not the smallest possible size to represent the committee.
|
||||||
BadCustodyBitfieldLength,
|
///
|
||||||
NoCommitteeForShard,
|
/// (committee_len, bitfield_len)
|
||||||
|
BadCustodyBitfieldLength(usize, usize),
|
||||||
|
/// The aggregation bitfield length is not the smallest possible size to represent the committee.
|
||||||
|
///
|
||||||
|
/// (committee_len, bitfield_len)
|
||||||
|
BadAggregationBitfieldLength(usize, usize),
|
||||||
|
/// There was no known committee for the given shard in the given slot.
|
||||||
|
///
|
||||||
|
/// (attestation_data_shard, attestation_data_slot)
|
||||||
|
NoCommitteeForShard(u64, Slot),
|
||||||
|
/// The attestation signature verification failed.
|
||||||
BadSignature,
|
BadSignature,
|
||||||
|
/// The shard block root was not set to zero. This is a phase 0 requirement.
|
||||||
ShardBlockRootNotZero,
|
ShardBlockRootNotZero,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,21 +160,29 @@ impl_into_with_index_with_beacon_error!(AttestationValidationError, AttestationI
|
|||||||
* `AttesterSlashing` Validation
|
* `AttesterSlashing` Validation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// The object is invalid or validation failed.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum AttesterSlashingValidationError {
|
pub enum AttesterSlashingValidationError {
|
||||||
/// The `SlashableAttestation` is invalid.
|
/// Validation completed successfully and the object is invalid.
|
||||||
Invalid(AttesterSlashingInvalid),
|
Invalid(AttesterSlashingInvalid),
|
||||||
/// Encountered a `BeaconStateError` whilst attempting to determine validity.
|
/// Encountered a `BeaconStateError` whilst attempting to determine validity.
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes why an object is invalid.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum AttesterSlashingInvalid {
|
pub enum AttesterSlashingInvalid {
|
||||||
|
/// The attestation data is identical, an attestation cannot conflict with itself.
|
||||||
AttestationDataIdentical,
|
AttestationDataIdentical,
|
||||||
|
/// The attestations were not in conflict.
|
||||||
NotSlashable,
|
NotSlashable,
|
||||||
|
/// The first `SlashableAttestation` was invalid.
|
||||||
SlashableAttestation1Invalid(SlashableAttestationInvalid),
|
SlashableAttestation1Invalid(SlashableAttestationInvalid),
|
||||||
|
/// The second `SlashableAttestation` was invalid.
|
||||||
SlashableAttestation2Invalid(SlashableAttestationInvalid),
|
SlashableAttestation2Invalid(SlashableAttestationInvalid),
|
||||||
UnknownValidator,
|
/// The validator index is unknown. One cannot slash one who does not exist.
|
||||||
|
UnknownValidator(u64),
|
||||||
|
/// There were no indices able to be slashed.
|
||||||
NoSlashableIndices,
|
NoSlashableIndices,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,19 +193,35 @@ impl_into_with_index_with_beacon_error!(AttesterSlashingValidationError, Atteste
|
|||||||
* `SlashableAttestation` Validation
|
* `SlashableAttestation` Validation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// The object is invalid or validation failed.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum SlashableAttestationValidationError {
|
pub enum SlashableAttestationValidationError {
|
||||||
|
/// Validation completed successfully and the object is invalid.
|
||||||
Invalid(SlashableAttestationInvalid),
|
Invalid(SlashableAttestationInvalid),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes why an object is invalid.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum SlashableAttestationInvalid {
|
pub enum SlashableAttestationInvalid {
|
||||||
|
/// The custody bitfield has some bits set `true`. This is not allowed in phase 0.
|
||||||
CustodyBitfieldHasSetBits,
|
CustodyBitfieldHasSetBits,
|
||||||
|
/// No validator indices were specified.
|
||||||
NoValidatorIndices,
|
NoValidatorIndices,
|
||||||
BadValidatorIndicesOrdering,
|
/// The validator indices were not in increasing order.
|
||||||
BadCustodyBitfieldLength,
|
///
|
||||||
MaxIndicesExceed,
|
/// The error occured between the given `index` and `index + 1`
|
||||||
UnknownValidator,
|
BadValidatorIndicesOrdering(usize),
|
||||||
|
/// The custody bitfield length is not the smallest possible size to represent the validators.
|
||||||
|
///
|
||||||
|
/// (validators_len, bitfield_len)
|
||||||
|
BadCustodyBitfieldLength(usize, usize),
|
||||||
|
/// The number of slashable indices exceed the global maximum.
|
||||||
|
///
|
||||||
|
/// (max_indices, indices_given)
|
||||||
|
MaxIndicesExceed(usize, usize),
|
||||||
|
/// The validator index is unknown. One cannot slash one who does not exist.
|
||||||
|
UnknownValidator(u64),
|
||||||
|
/// The slashable attestation aggregate signature was not valid.
|
||||||
BadSignature,
|
BadSignature,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,19 +237,35 @@ impl Into<SlashableAttestationInvalid> for SlashableAttestationValidationError {
|
|||||||
* `ProposerSlashing` Validation
|
* `ProposerSlashing` Validation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// The object is invalid or validation failed.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ProposerSlashingValidationError {
|
pub enum ProposerSlashingValidationError {
|
||||||
|
/// Validation completed successfully and the object is invalid.
|
||||||
Invalid(ProposerSlashingInvalid),
|
Invalid(ProposerSlashingInvalid),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes why an object is invalid.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ProposerSlashingInvalid {
|
pub enum ProposerSlashingInvalid {
|
||||||
ProposerUnknown,
|
/// The proposer index is not a known validator.
|
||||||
ProposalSlotMismatch,
|
ProposerUnknown(u64),
|
||||||
ProposalShardMismatch,
|
/// The two proposal have different slots.
|
||||||
ProposalBlockRootMismatch,
|
///
|
||||||
|
/// (proposal_1_slot, proposal_2_slot)
|
||||||
|
ProposalSlotMismatch(Slot, Slot),
|
||||||
|
/// The two proposal have different shards.
|
||||||
|
///
|
||||||
|
/// (proposal_1_shard, proposal_2_shard)
|
||||||
|
ProposalShardMismatch(u64, u64),
|
||||||
|
/// The two proposal have different block roots.
|
||||||
|
///
|
||||||
|
/// (proposal_1_root, proposal_2_root)
|
||||||
|
ProposalBlockRootMismatch(Hash256, Hash256),
|
||||||
|
/// The specified proposer has already been slashed.
|
||||||
ProposerAlreadySlashed,
|
ProposerAlreadySlashed,
|
||||||
|
/// The first proposal signature was invalid.
|
||||||
BadProposal1Signature,
|
BadProposal1Signature,
|
||||||
|
/// The second proposal signature was invalid.
|
||||||
BadProposal2Signature,
|
BadProposal2Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,14 +278,20 @@ impl_into_with_index_without_beacon_error!(
|
|||||||
* `Deposit` Validation
|
* `Deposit` Validation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// The object is invalid or validation failed.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum DepositValidationError {
|
pub enum DepositValidationError {
|
||||||
|
/// Validation completed successfully and the object is invalid.
|
||||||
Invalid(DepositInvalid),
|
Invalid(DepositInvalid),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes why an object is invalid.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum DepositInvalid {
|
pub enum DepositInvalid {
|
||||||
BadIndex,
|
/// The deposit index does not match the state index.
|
||||||
|
///
|
||||||
|
/// (state_index, deposit_index)
|
||||||
|
BadIndex(u64, u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_into_with_index_without_beacon_error!(DepositValidationError, DepositInvalid);
|
impl_into_with_index_without_beacon_error!(DepositValidationError, DepositInvalid);
|
||||||
@ -213,16 +300,24 @@ impl_into_with_index_without_beacon_error!(DepositValidationError, DepositInvali
|
|||||||
* `Exit` Validation
|
* `Exit` Validation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// The object is invalid or validation failed.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ExitValidationError {
|
pub enum ExitValidationError {
|
||||||
|
/// Validation completed successfully and the object is invalid.
|
||||||
Invalid(ExitInvalid),
|
Invalid(ExitInvalid),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes why an object is invalid.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ExitInvalid {
|
pub enum ExitInvalid {
|
||||||
ValidatorUnknown,
|
/// The specified validator is not in the state's validator registry.
|
||||||
|
ValidatorUnknown(u64),
|
||||||
AlreadyExited,
|
AlreadyExited,
|
||||||
FutureEpoch,
|
/// The exit is for a future epoch.
|
||||||
|
///
|
||||||
|
/// (state_epoch, exit_epoch)
|
||||||
|
FutureEpoch(Epoch, Epoch),
|
||||||
|
/// The exit signature was not signed by the validator.
|
||||||
BadSignature,
|
BadSignature,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,11 +327,14 @@ impl_into_with_index_without_beacon_error!(ExitValidationError, ExitInvalid);
|
|||||||
* `Transfer` Validation
|
* `Transfer` Validation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// The object is invalid or validation failed.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum TransferValidationError {
|
pub enum TransferValidationError {
|
||||||
|
/// Validation completed successfully and the object is invalid.
|
||||||
Invalid(TransferInvalid),
|
Invalid(TransferInvalid),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes why an object is invalid.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum TransferInvalid {}
|
pub enum TransferInvalid {}
|
||||||
|
|
||||||
|
@ -19,6 +19,12 @@ mod verify_proposer_slashing;
|
|||||||
mod verify_slashable_attestation;
|
mod verify_slashable_attestation;
|
||||||
mod verify_transfer;
|
mod verify_transfer;
|
||||||
|
|
||||||
|
/// Updates the state for a new block, whilst validating that the block is valid.
|
||||||
|
///
|
||||||
|
/// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise
|
||||||
|
/// returns an error describing why the block was invalid or how the function failed to execute.
|
||||||
|
///
|
||||||
|
/// Spec v0.4.0
|
||||||
pub fn per_block_processing(
|
pub fn per_block_processing(
|
||||||
state: &mut BeaconState,
|
state: &mut BeaconState,
|
||||||
block: &BeaconBlock,
|
block: &BeaconBlock,
|
||||||
@ -27,6 +33,13 @@ pub fn per_block_processing(
|
|||||||
per_block_processing_signature_optional(state, block, true, spec)
|
per_block_processing_signature_optional(state, block, true, spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the state for a new block, whilst validating that the block is valid, without actually
|
||||||
|
/// checking the block proposer signature.
|
||||||
|
///
|
||||||
|
/// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise
|
||||||
|
/// returns an error describing why the block was invalid or how the function failed to execute.
|
||||||
|
///
|
||||||
|
/// Spec v0.4.0
|
||||||
pub fn per_block_processing_without_verifying_block_signature(
|
pub fn per_block_processing_without_verifying_block_signature(
|
||||||
state: &mut BeaconState,
|
state: &mut BeaconState,
|
||||||
block: &BeaconBlock,
|
block: &BeaconBlock,
|
||||||
@ -35,6 +48,13 @@ pub fn per_block_processing_without_verifying_block_signature(
|
|||||||
per_block_processing_signature_optional(state, block, false, spec)
|
per_block_processing_signature_optional(state, block, false, spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the state for a new block, whilst validating that the block is valid, optionally
|
||||||
|
/// checking the block proposer signature.
|
||||||
|
///
|
||||||
|
/// Returns `Ok(())` if the block is valid and the state was successfully updated. Otherwise
|
||||||
|
/// returns an error describing why the block was invalid or how the function failed to execute.
|
||||||
|
///
|
||||||
|
/// Spec v0.4.0
|
||||||
fn per_block_processing_signature_optional(
|
fn per_block_processing_signature_optional(
|
||||||
mut state: &mut BeaconState,
|
mut state: &mut BeaconState,
|
||||||
block: &BeaconBlock,
|
block: &BeaconBlock,
|
||||||
|
@ -3,7 +3,10 @@ use ssz::TreeHash;
|
|||||||
use types::beacon_state::helpers::*;
|
use types::beacon_state::helpers::*;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Validate an attestation, checking the aggregate signature.
|
/// Indicates if an `Attestation` is valid to be included in a block in the current epoch of the
|
||||||
|
/// given state.
|
||||||
|
///
|
||||||
|
/// Returns `Ok(())` if the `Attestation` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
pub fn validate_attestation(
|
pub fn validate_attestation(
|
||||||
@ -14,7 +17,10 @@ pub fn validate_attestation(
|
|||||||
validate_attestation_signature_optional(state, attestation, spec, true)
|
validate_attestation_signature_optional(state, attestation, spec, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validate an attestation, without checking the aggregate signature.
|
/// Indicates if an `Attestation` is valid to be included in a block in the current epoch of the
|
||||||
|
/// given state, without validating the aggregate signature.
|
||||||
|
///
|
||||||
|
/// Returns `Ok(())` if the `Attestation` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
pub fn validate_attestation_without_signature(
|
pub fn validate_attestation_without_signature(
|
||||||
@ -25,7 +31,9 @@ pub fn validate_attestation_without_signature(
|
|||||||
validate_attestation_signature_optional(state, attestation, spec, false)
|
validate_attestation_signature_optional(state, attestation, spec, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validate an attestation, optionally checking the aggregate signature.
|
/// Indicates if an `Attestation` is valid to be included in a block in the current epoch of the
|
||||||
|
/// given state, optionally validating the aggregate signature.
|
||||||
|
///
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
fn validate_attestation_signature_optional(
|
fn validate_attestation_signature_optional(
|
||||||
@ -37,19 +45,23 @@ fn validate_attestation_signature_optional(
|
|||||||
// Verify that `attestation.data.slot >= GENESIS_SLOT`.
|
// Verify that `attestation.data.slot >= GENESIS_SLOT`.
|
||||||
verify!(
|
verify!(
|
||||||
attestation.data.slot >= spec.genesis_slot,
|
attestation.data.slot >= spec.genesis_slot,
|
||||||
Invalid::PreGenesis
|
Invalid::PreGenesis(spec.genesis_slot, attestation.data.slot)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify that `attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot`.
|
// Verify that `attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot`.
|
||||||
verify!(
|
verify!(
|
||||||
attestation.data.slot + spec.min_attestation_inclusion_delay <= state.slot,
|
attestation.data.slot + spec.min_attestation_inclusion_delay <= state.slot,
|
||||||
Invalid::IncludedTooEarly
|
Invalid::IncludedTooEarly(
|
||||||
|
state.slot,
|
||||||
|
spec.min_attestation_inclusion_delay,
|
||||||
|
attestation.data.slot
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify that `state.slot < attestation.data.slot + SLOTS_PER_EPOCH`.
|
// Verify that `state.slot < attestation.data.slot + SLOTS_PER_EPOCH`.
|
||||||
verify!(
|
verify!(
|
||||||
state.slot < attestation.data.slot + spec.slots_per_epoch,
|
state.slot < attestation.data.slot + spec.slots_per_epoch,
|
||||||
Invalid::IncludedTooLate
|
Invalid::IncludedTooLate(state.slot, attestation.data.slot)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify that `attestation.data.justified_epoch` is equal to `state.justified_epoch` if
|
// Verify that `attestation.data.justified_epoch` is equal to `state.justified_epoch` if
|
||||||
@ -58,29 +70,37 @@ fn validate_attestation_signature_optional(
|
|||||||
if (attestation.data.slot + 1).epoch(spec.slots_per_epoch) >= state.current_epoch(spec) {
|
if (attestation.data.slot + 1).epoch(spec.slots_per_epoch) >= state.current_epoch(spec) {
|
||||||
verify!(
|
verify!(
|
||||||
attestation.data.justified_epoch == state.justified_epoch,
|
attestation.data.justified_epoch == state.justified_epoch,
|
||||||
Invalid::WrongJustifiedSlot
|
Invalid::WrongJustifiedEpoch(
|
||||||
|
attestation.data.justified_epoch,
|
||||||
|
state.justified_epoch,
|
||||||
|
false
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
verify!(
|
verify!(
|
||||||
attestation.data.justified_epoch == state.previous_justified_epoch,
|
attestation.data.justified_epoch == state.previous_justified_epoch,
|
||||||
Invalid::WrongJustifiedSlot
|
Invalid::WrongJustifiedEpoch(
|
||||||
|
attestation.data.justified_epoch,
|
||||||
|
state.previous_justified_epoch,
|
||||||
|
true
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that `attestation.data.justified_block_root` is equal to `get_block_root(state,
|
// Verify that `attestation.data.justified_block_root` is equal to `get_block_root(state,
|
||||||
// get_epoch_start_slot(attestation.data.justified_epoch))`.
|
// get_epoch_start_slot(attestation.data.justified_epoch))`.
|
||||||
verify!(
|
let justified_block_root = *state
|
||||||
attestation.data.justified_block_root
|
|
||||||
== *state
|
|
||||||
.get_block_root(
|
.get_block_root(
|
||||||
attestation
|
attestation
|
||||||
.data
|
.data
|
||||||
.justified_epoch
|
.justified_epoch
|
||||||
.start_slot(spec.slots_per_epoch),
|
.start_slot(spec.slots_per_epoch),
|
||||||
&spec
|
&spec,
|
||||||
)
|
)
|
||||||
.ok_or(BeaconStateError::InsufficientBlockRoots)?,
|
.ok_or(BeaconStateError::InsufficientBlockRoots)?;
|
||||||
Invalid::WrongJustifiedRoot
|
verify!(
|
||||||
|
attestation.data.justified_block_root == justified_block_root,
|
||||||
|
Invalid::WrongJustifiedRoot(justified_block_root, attestation.data.justified_block_root)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify that either:
|
// Verify that either:
|
||||||
@ -106,7 +126,12 @@ fn validate_attestation_signature_optional(
|
|||||||
.get_crosslink_committees_at_slot(attestation.data.slot, spec)?
|
.get_crosslink_committees_at_slot(attestation.data.slot, spec)?
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(_committee, shard)| *shard == attestation.data.shard)
|
.find(|(_committee, shard)| *shard == attestation.data.shard)
|
||||||
.ok_or_else(|| Error::Invalid(Invalid::NoCommitteeForShard))?;
|
.ok_or_else(|| {
|
||||||
|
Error::Invalid(Invalid::NoCommitteeForShard(
|
||||||
|
attestation.data.shard,
|
||||||
|
attestation.data.slot,
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
// Custody bitfield is all zeros (phase 0 requirement).
|
// Custody bitfield is all zeros (phase 0 requirement).
|
||||||
verify!(
|
verify!(
|
||||||
@ -115,8 +140,8 @@ fn validate_attestation_signature_optional(
|
|||||||
);
|
);
|
||||||
// Custody bitfield length is correct.
|
// Custody bitfield length is correct.
|
||||||
verify!(
|
verify!(
|
||||||
verify_bitfield_length(&attestation.aggregation_bitfield, committee.len()),
|
verify_bitfield_length(&attestation.custody_bitfield, committee.len()),
|
||||||
Invalid::BadCustodyBitfieldLength
|
Invalid::BadCustodyBitfieldLength(committee.len(), attestation.custody_bitfield.len())
|
||||||
);
|
);
|
||||||
// Aggregation bitfield isn't empty.
|
// Aggregation bitfield isn't empty.
|
||||||
verify!(
|
verify!(
|
||||||
@ -126,7 +151,10 @@ fn validate_attestation_signature_optional(
|
|||||||
// Aggregation bitfield length is correct.
|
// Aggregation bitfield length is correct.
|
||||||
verify!(
|
verify!(
|
||||||
verify_bitfield_length(&attestation.aggregation_bitfield, committee.len()),
|
verify_bitfield_length(&attestation.aggregation_bitfield, committee.len()),
|
||||||
Invalid::BadAggregationBitfieldLength
|
Invalid::BadAggregationBitfieldLength(
|
||||||
|
committee.len(),
|
||||||
|
attestation.aggregation_bitfield.len()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if verify_signature {
|
if verify_signature {
|
||||||
|
@ -2,10 +2,10 @@ use super::verify_slashable_attestation::verify_slashable_attestation;
|
|||||||
use crate::errors::{AttesterSlashingInvalid as Invalid, AttesterSlashingValidationError as Error};
|
use crate::errors::{AttesterSlashingInvalid as Invalid, AttesterSlashingValidationError as Error};
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Returns `Ok(())` if some `AttesterSlashing` is valid to be included in some `BeaconState`,
|
/// Indicates if an `AttesterSlashing` is valid to be included in a block in the current epoch of the given
|
||||||
/// otherwise returns an `Err`.
|
/// state.
|
||||||
///
|
///
|
||||||
/// Returns the slashable indices from the `AttesterSlashing`.
|
/// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
pub fn verify_attester_slashing(
|
pub fn verify_attester_slashing(
|
||||||
@ -36,7 +36,7 @@ pub fn verify_attester_slashing(
|
|||||||
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))?;
|
.ok_or_else(|| Error::Invalid(Invalid::UnknownValidator(*i)))?;
|
||||||
|
|
||||||
if slashable_attestation_1.validator_indices.contains(&i) & !validator.slashed {
|
if slashable_attestation_1.validator_indices.contains(&i) & !validator.slashed {
|
||||||
slashable_indices.push(*i);
|
slashable_indices.push(*i);
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
use crate::errors::{DepositInvalid as Invalid, DepositValidationError as Error};
|
use crate::errors::{DepositInvalid as Invalid, DepositValidationError as Error};
|
||||||
use ssz::TreeHash;
|
|
||||||
use types::beacon_state::helpers::verify_bitfield_length;
|
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Verify validity of ``slashable_attestation`` fields.
|
/// Indicates if a `Deposit` is valid to be included in a block in the current epoch of the given
|
||||||
|
/// state.
|
||||||
///
|
///
|
||||||
/// Returns `Ok(())` if all fields are valid.
|
/// Returns `Ok(())` if the `Deposit` is valid, otherwise indicates the reason for invalidity.
|
||||||
|
///
|
||||||
|
/// Note: this function is incomplete.
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
pub fn verify_deposit(
|
pub fn verify_deposit(
|
||||||
state: &BeaconState,
|
state: &BeaconState,
|
||||||
deposit: &Deposit,
|
deposit: &Deposit,
|
||||||
spec: &ChainSpec,
|
_spec: &ChainSpec,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// TODO: verify serialized deposit data.
|
// TODO: verify serialized deposit data.
|
||||||
|
|
||||||
// TODO: verify deposit index.
|
// TODO: verify deposit index.
|
||||||
verify!(deposit.index == state.deposit_index, Invalid::BadIndex);
|
verify!(
|
||||||
|
deposit.index == state.deposit_index,
|
||||||
|
Invalid::BadIndex(state.deposit_index, deposit.index)
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: verify merkle branch.
|
// TODO: verify merkle branch.
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@ use crate::errors::{ExitInvalid as Invalid, ExitValidationError as Error};
|
|||||||
use ssz::SignedRoot;
|
use ssz::SignedRoot;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Verify validity of ``slashable_attestation`` fields.
|
/// Indicates if an `Exit` is valid to be included in a block in the current epoch of the given
|
||||||
|
/// state.
|
||||||
///
|
///
|
||||||
/// Returns `Ok(())` if all fields are valid.
|
/// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
pub fn verify_exit(
|
pub fn verify_exit(
|
||||||
@ -15,7 +16,9 @@ pub fn verify_exit(
|
|||||||
let validator = state
|
let validator = state
|
||||||
.validator_registry
|
.validator_registry
|
||||||
.get(exit.validator_index as usize)
|
.get(exit.validator_index as usize)
|
||||||
.ok_or(Error::Invalid(Invalid::ValidatorUnknown))?;
|
.ok_or(Error::Invalid(Invalid::ValidatorUnknown(
|
||||||
|
exit.validator_index,
|
||||||
|
)))?;
|
||||||
|
|
||||||
verify!(
|
verify!(
|
||||||
validator.exit_epoch
|
validator.exit_epoch
|
||||||
@ -25,7 +28,7 @@ pub fn verify_exit(
|
|||||||
|
|
||||||
verify!(
|
verify!(
|
||||||
state.current_epoch(spec) >= exit.epoch,
|
state.current_epoch(spec) >= exit.epoch,
|
||||||
Invalid::FutureEpoch
|
Invalid::FutureEpoch(state.current_epoch(spec), exit.epoch)
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = exit.signed_root();
|
let message = exit.signed_root();
|
||||||
|
@ -2,8 +2,10 @@ use crate::errors::{ProposerSlashingInvalid as Invalid, ProposerSlashingValidati
|
|||||||
use ssz::SignedRoot;
|
use ssz::SignedRoot;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Returns `Ok(())` if some `ProposerSlashing` is valid to be included in some `BeaconState`,
|
/// Indicates if a `ProposerSlashing` is valid to be included in a block in the current epoch of the given
|
||||||
/// otherwise returns an `Err`.
|
/// state.
|
||||||
|
///
|
||||||
|
/// Returns `Ok(())` if the `ProposerSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
pub fn verify_proposer_slashing(
|
pub fn verify_proposer_slashing(
|
||||||
@ -14,21 +16,32 @@ pub fn verify_proposer_slashing(
|
|||||||
let proposer = state
|
let proposer = state
|
||||||
.validator_registry
|
.validator_registry
|
||||||
.get(proposer_slashing.proposer_index as usize)
|
.get(proposer_slashing.proposer_index as usize)
|
||||||
.ok_or(Error::Invalid(Invalid::ProposerUnknown))?;
|
.ok_or(Error::Invalid(Invalid::ProposerUnknown(
|
||||||
|
proposer_slashing.proposer_index,
|
||||||
|
)))?;
|
||||||
|
|
||||||
verify!(
|
verify!(
|
||||||
proposer_slashing.proposal_1.slot == proposer_slashing.proposal_2.slot,
|
proposer_slashing.proposal_1.slot == proposer_slashing.proposal_2.slot,
|
||||||
Invalid::ProposalSlotMismatch
|
Invalid::ProposalSlotMismatch(
|
||||||
|
proposer_slashing.proposal_1.slot,
|
||||||
|
proposer_slashing.proposal_2.slot
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
verify!(
|
verify!(
|
||||||
proposer_slashing.proposal_1.shard == proposer_slashing.proposal_2.shard,
|
proposer_slashing.proposal_1.shard == proposer_slashing.proposal_2.shard,
|
||||||
Invalid::ProposalShardMismatch
|
Invalid::ProposalShardMismatch(
|
||||||
|
proposer_slashing.proposal_1.shard,
|
||||||
|
proposer_slashing.proposal_2.shard
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
verify!(
|
verify!(
|
||||||
proposer_slashing.proposal_1.block_root != proposer_slashing.proposal_2.block_root,
|
proposer_slashing.proposal_1.block_root != proposer_slashing.proposal_2.block_root,
|
||||||
Invalid::ProposalBlockRootMismatch
|
Invalid::ProposalBlockRootMismatch(
|
||||||
|
proposer_slashing.proposal_1.block_root,
|
||||||
|
proposer_slashing.proposal_2.block_root
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
verify!(!proposer.slashed, Invalid::ProposerAlreadySlashed);
|
verify!(!proposer.slashed, Invalid::ProposerAlreadySlashed);
|
||||||
@ -55,6 +68,9 @@ pub fn verify_proposer_slashing(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verifies the signature of a proposal.
|
||||||
|
///
|
||||||
|
/// Returns `true` if the signature is valid.
|
||||||
fn verify_proposal_signature(
|
fn verify_proposal_signature(
|
||||||
proposal: &Proposal,
|
proposal: &Proposal,
|
||||||
pubkey: &PublicKey,
|
pubkey: &PublicKey,
|
||||||
|
@ -5,9 +5,10 @@ use ssz::TreeHash;
|
|||||||
use types::beacon_state::helpers::verify_bitfield_length;
|
use types::beacon_state::helpers::verify_bitfield_length;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Verify validity of ``slashable_attestation`` fields.
|
/// Indicates if a `SlashableAttestation` is valid to be included in a block in the current epoch of the given
|
||||||
|
/// state.
|
||||||
///
|
///
|
||||||
/// Returns `Ok(())` if all fields are valid.
|
/// Returns `Ok(())` if the `SlashableAttestation` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
pub fn verify_slashable_attestation(
|
pub fn verify_slashable_attestation(
|
||||||
@ -27,7 +28,7 @@ pub fn verify_slashable_attestation(
|
|||||||
if slashable_attestation.validator_indices[i]
|
if slashable_attestation.validator_indices[i]
|
||||||
>= slashable_attestation.validator_indices[i + 1]
|
>= slashable_attestation.validator_indices[i + 1]
|
||||||
{
|
{
|
||||||
invalid!(Invalid::BadValidatorIndicesOrdering);
|
invalid!(Invalid::BadValidatorIndicesOrdering(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,12 +36,18 @@ pub fn verify_slashable_attestation(
|
|||||||
&slashable_attestation.custody_bitfield,
|
&slashable_attestation.custody_bitfield,
|
||||||
slashable_attestation.validator_indices.len(),
|
slashable_attestation.validator_indices.len(),
|
||||||
) {
|
) {
|
||||||
invalid!(Invalid::BadCustodyBitfieldLength);
|
invalid!(Invalid::BadCustodyBitfieldLength(
|
||||||
|
slashable_attestation.validator_indices.len(),
|
||||||
|
slashable_attestation.custody_bitfield.len()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if slashable_attestation.validator_indices.len() > spec.max_indices_per_slashable_vote as usize
|
if slashable_attestation.validator_indices.len() > spec.max_indices_per_slashable_vote as usize
|
||||||
{
|
{
|
||||||
invalid!(Invalid::MaxIndicesExceed);
|
invalid!(Invalid::MaxIndicesExceed(
|
||||||
|
spec.max_indices_per_slashable_vote as usize,
|
||||||
|
slashable_attestation.validator_indices.len()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this signature verification could likely be replaced with:
|
// TODO: this signature verification could likely be replaced with:
|
||||||
@ -62,7 +69,7 @@ pub fn verify_slashable_attestation(
|
|||||||
Some(validator) => {
|
Some(validator) => {
|
||||||
aggregate_pubs[custody_bit as usize].add(&validator.pubkey);
|
aggregate_pubs[custody_bit as usize].add(&validator.pubkey);
|
||||||
}
|
}
|
||||||
None => invalid!(Invalid::UnknownValidator),
|
None => invalid!(Invalid::UnknownValidator(*v)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
use crate::errors::{TransferInvalid as Invalid, TransferValidationError as Error};
|
use crate::errors::{TransferInvalid as Invalid, TransferValidationError as Error};
|
||||||
use ssz::TreeHash;
|
|
||||||
use types::beacon_state::helpers::verify_bitfield_length;
|
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Verify validity of ``slashable_attestation`` fields.
|
/// Indicates if a `Transfer` is valid to be included in a block in the current epoch of the given
|
||||||
|
/// state.
|
||||||
///
|
///
|
||||||
/// Returns `Ok(())` if all fields are valid.
|
/// Returns `Ok(())` if the `Transfer` is valid, otherwise indicates the reason for invalidity.
|
||||||
|
///
|
||||||
|
/// Note: this function is incomplete.
|
||||||
///
|
///
|
||||||
/// Spec v0.4.0
|
/// Spec v0.4.0
|
||||||
pub fn verify_transfer(
|
pub fn verify_transfer(
|
||||||
state: &BeaconState,
|
_state: &BeaconState,
|
||||||
transfer: &Transfer,
|
_transfer: &Transfer,
|
||||||
spec: &ChainSpec,
|
_spec: &ChainSpec,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// TODO: verify transfer.
|
// TODO: verify transfer.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user