Move attestation validator to BeaconState
fn
This commit is contained in:
parent
b487db68a1
commit
fd47f6c433
@ -1,17 +1,16 @@
|
|||||||
use super::{BeaconChain, ClientDB, DBError, SlotClock};
|
use super::{BeaconChain, ClientDB, DBError, SlotClock};
|
||||||
use bls::{AggregatePublicKey, AggregateSignature, PublicKey, Signature};
|
use bls::{PublicKey, Signature};
|
||||||
use boolean_bitfield::BooleanBitfield;
|
use boolean_bitfield::BooleanBitfield;
|
||||||
use hashing::hash;
|
use hashing::hash;
|
||||||
use slot_clock::{SystemTimeSlotClockError, TestingSlotClockError};
|
use slot_clock::{SystemTimeSlotClockError, TestingSlotClockError};
|
||||||
use ssz::{ssz_encode, TreeHash};
|
use ssz::{ssz_encode, TreeHash};
|
||||||
use types::{
|
use types::{
|
||||||
beacon_state::SlotProcessingError, readers::BeaconBlockReader, AttestationData,
|
beacon_state::{AttestationValidationError, SlotProcessingError},
|
||||||
AttestationDataAndCustodyBit, BeaconBlock, BeaconState, Exit, Fork, Hash256,
|
readers::BeaconBlockReader,
|
||||||
PendingAttestation,
|
AttestationData, BeaconBlock, BeaconState, Exit, Fork, Hash256, PendingAttestation,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: define elsehwere.
|
// TODO: define elsehwere.
|
||||||
const DOMAIN_ATTESTATION: u64 = 1;
|
|
||||||
const DOMAIN_PROPOSAL: u64 = 2;
|
const DOMAIN_PROPOSAL: u64 = 2;
|
||||||
const DOMAIN_EXIT: u64 = 3;
|
const DOMAIN_EXIT: u64 = 3;
|
||||||
const DOMAIN_RANDAO: u64 = 4;
|
const DOMAIN_RANDAO: u64 = 4;
|
||||||
@ -43,7 +42,7 @@ pub enum Error {
|
|||||||
MaxProposerSlashingsExceeded,
|
MaxProposerSlashingsExceeded,
|
||||||
BadProposerSlashing,
|
BadProposerSlashing,
|
||||||
MaxAttestationsExceeded,
|
MaxAttestationsExceeded,
|
||||||
BadAttestation,
|
InvalidAttestation(AttestationValidationError),
|
||||||
NoBlockRoot,
|
NoBlockRoot,
|
||||||
MaxDepositsExceeded,
|
MaxDepositsExceeded,
|
||||||
MaxExitsExceeded,
|
MaxExitsExceeded,
|
||||||
@ -218,67 +217,8 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
for attestation in &block.body.attestations {
|
for attestation in &block.body.attestations {
|
||||||
ensure!(
|
state.validate_attestation(attestation, &self.spec)?;
|
||||||
attestation.data.slot + self.spec.min_attestation_inclusion_delay <= state.slot,
|
|
||||||
Error::BadAttestation
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
attestation.data.slot + self.spec.epoch_length >= state.slot,
|
|
||||||
Error::BadAttestation
|
|
||||||
);
|
|
||||||
if state.justified_slot >= state.slot - (state.slot % self.spec.epoch_length) {
|
|
||||||
ensure!(
|
|
||||||
attestation.data.justified_slot == state.justified_slot,
|
|
||||||
Error::BadAttestation
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ensure!(
|
|
||||||
attestation.data.justified_slot == state.previous_justified_slot,
|
|
||||||
Error::BadAttestation
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ensure!(
|
|
||||||
attestation.data.justified_block_root
|
|
||||||
== *state
|
|
||||||
.get_block_root(attestation.data.justified_slot, &self.spec)
|
|
||||||
.ok_or(Error::NoBlockRoot)?,
|
|
||||||
Error::BadAttestation
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
(attestation.data.latest_crosslink_root
|
|
||||||
== state.latest_crosslinks[attestation.data.shard as usize].shard_block_root)
|
|
||||||
|| (attestation.data.shard_block_root
|
|
||||||
== state.latest_crosslinks[attestation.data.shard as usize]
|
|
||||||
.shard_block_root),
|
|
||||||
Error::BadAttestation
|
|
||||||
);
|
|
||||||
let participants = get_attestation_participants(
|
|
||||||
&state,
|
|
||||||
&attestation.data,
|
|
||||||
&attestation.aggregation_bitfield,
|
|
||||||
);
|
|
||||||
let mut group_public_key = AggregatePublicKey::new();
|
|
||||||
for participant in participants {
|
|
||||||
group_public_key.add(
|
|
||||||
state.validator_registry[participant as usize]
|
|
||||||
.pubkey
|
|
||||||
.as_raw(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// Signature verification.
|
|
||||||
ensure!(
|
|
||||||
bls_verify_aggregate(
|
|
||||||
&group_public_key,
|
|
||||||
&attestation.signable_message(),
|
|
||||||
&attestation.aggregate_signature,
|
|
||||||
get_domain(&state.fork_data, attestation.data.slot, DOMAIN_ATTESTATION)
|
|
||||||
),
|
|
||||||
Error::BadProposerSlashing
|
|
||||||
);
|
|
||||||
ensure!(
|
|
||||||
attestation.data.shard_block_root == self.spec.zero_hash,
|
|
||||||
Error::BadAttestation
|
|
||||||
);
|
|
||||||
let pending_attestation = PendingAttestation {
|
let pending_attestation = PendingAttestation {
|
||||||
data: attestation.data.clone(),
|
data: attestation.data.clone(),
|
||||||
aggregation_bitfield: attestation.aggregation_bitfield.clone(),
|
aggregation_bitfield: attestation.aggregation_bitfield.clone(),
|
||||||
@ -365,15 +305,6 @@ fn initiate_validator_exit(_state: &BeaconState, _index: u32) {
|
|||||||
// TODO: stubbed out.
|
// TODO: stubbed out.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_attestation_participants(
|
|
||||||
_state: &BeaconState,
|
|
||||||
_attestation_data: &AttestationData,
|
|
||||||
_aggregation_bitfield: &BooleanBitfield,
|
|
||||||
) -> Vec<usize> {
|
|
||||||
// TODO: stubbed out.
|
|
||||||
vec![0, 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn penalize_validator(_state: &BeaconState, _proposer_index: usize) {
|
fn penalize_validator(_state: &BeaconState, _proposer_index: usize) {
|
||||||
// TODO: stubbed out.
|
// TODO: stubbed out.
|
||||||
}
|
}
|
||||||
@ -388,16 +319,6 @@ fn bls_verify(pubkey: &PublicKey, message: &[u8], signature: &Signature, _domain
|
|||||||
signature.verify(message, pubkey)
|
signature.verify(message, pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bls_verify_aggregate(
|
|
||||||
pubkey: &AggregatePublicKey,
|
|
||||||
message: &[u8],
|
|
||||||
signature: &AggregateSignature,
|
|
||||||
_domain: u64,
|
|
||||||
) -> bool {
|
|
||||||
// TODO: add domain
|
|
||||||
signature.verify(message, pubkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DBError> for Error {
|
impl From<DBError> for Error {
|
||||||
fn from(e: DBError) -> Error {
|
fn from(e: DBError) -> Error {
|
||||||
Error::DBError(e.message)
|
Error::DBError(e.message)
|
||||||
@ -423,3 +344,9 @@ impl From<SlotProcessingError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<AttestationValidationError> for Error {
|
||||||
|
fn from(e: AttestationValidationError) -> Error {
|
||||||
|
Error::InvalidAttestation(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
96
eth2/types/src/beacon_state/attestation_validation.rs
Normal file
96
eth2/types/src/beacon_state/attestation_validation.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
use crate::{AggregatePublicKey, Attestation, BeaconState, ChainSpec, Fork};
|
||||||
|
use bls::bls_verify_aggregate;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Error {
|
||||||
|
IncludedTooEarly,
|
||||||
|
IncludedTooLate,
|
||||||
|
WrongJustifiedSlot,
|
||||||
|
WrongJustifiedRoot,
|
||||||
|
BadLatestCrosslinkRoot,
|
||||||
|
BadSignature,
|
||||||
|
ShardBlockRootNotZero,
|
||||||
|
NoBlockRoot,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ensure {
|
||||||
|
($condition: expr, $result: expr) => {
|
||||||
|
if !$condition {
|
||||||
|
return Err($result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: define elsehwere.
|
||||||
|
const DOMAIN_ATTESTATION: u64 = 1;
|
||||||
|
|
||||||
|
impl BeaconState {
|
||||||
|
pub fn validate_attestation(
|
||||||
|
&self,
|
||||||
|
attestation: &Attestation,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
ensure!(
|
||||||
|
attestation.data.slot + spec.min_attestation_inclusion_delay <= self.slot,
|
||||||
|
Error::IncludedTooEarly
|
||||||
|
);
|
||||||
|
ensure!(
|
||||||
|
attestation.data.slot + spec.epoch_length >= self.slot,
|
||||||
|
Error::IncludedTooLate
|
||||||
|
);
|
||||||
|
if self.justified_slot >= self.slot - (self.slot % spec.epoch_length) {
|
||||||
|
ensure!(
|
||||||
|
attestation.data.justified_slot == self.justified_slot,
|
||||||
|
Error::WrongJustifiedSlot
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ensure!(
|
||||||
|
attestation.data.justified_slot == self.previous_justified_slot,
|
||||||
|
Error::WrongJustifiedSlot
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ensure!(
|
||||||
|
attestation.data.justified_block_root
|
||||||
|
== *self
|
||||||
|
.get_block_root(attestation.data.justified_slot, &spec)
|
||||||
|
.ok_or(Error::NoBlockRoot)?,
|
||||||
|
Error::WrongJustifiedRoot
|
||||||
|
);
|
||||||
|
ensure!(
|
||||||
|
(attestation.data.latest_crosslink_root
|
||||||
|
== self.latest_crosslinks[attestation.data.shard as usize].shard_block_root)
|
||||||
|
|| (attestation.data.shard_block_root
|
||||||
|
== self.latest_crosslinks[attestation.data.shard as usize].shard_block_root),
|
||||||
|
Error::BadLatestCrosslinkRoot
|
||||||
|
);
|
||||||
|
let participants =
|
||||||
|
self.get_attestation_participants(&attestation.data, &attestation.aggregation_bitfield);
|
||||||
|
let mut group_public_key = AggregatePublicKey::new();
|
||||||
|
for participant in participants {
|
||||||
|
group_public_key.add(
|
||||||
|
self.validator_registry[participant as usize]
|
||||||
|
.pubkey
|
||||||
|
.as_raw(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ensure!(
|
||||||
|
bls_verify_aggregate(
|
||||||
|
&group_public_key,
|
||||||
|
&attestation.signable_message(),
|
||||||
|
&attestation.aggregate_signature,
|
||||||
|
get_domain(&self.fork_data, attestation.data.slot, DOMAIN_ATTESTATION)
|
||||||
|
),
|
||||||
|
Error::BadSignature
|
||||||
|
);
|
||||||
|
ensure!(
|
||||||
|
attestation.data.shard_block_root == spec.zero_hash,
|
||||||
|
Error::ShardBlockRootNotZero
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_domain(_fork: &Fork, _slot: u64, _domain_type: u64) -> u64 {
|
||||||
|
// TODO: stubbed out.
|
||||||
|
0
|
||||||
|
}
|
@ -10,10 +10,12 @@ use rand::RngCore;
|
|||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
||||||
|
|
||||||
|
mod attestation_validation;
|
||||||
mod epoch_processing;
|
mod epoch_processing;
|
||||||
mod slot_processing;
|
mod slot_processing;
|
||||||
mod winning_root;
|
mod winning_root;
|
||||||
|
|
||||||
|
pub use self::attestation_validation::Error as AttestationValidationError;
|
||||||
pub use self::epoch_processing::Error as EpochProcessingError;
|
pub use self::epoch_processing::Error as EpochProcessingError;
|
||||||
pub use self::slot_processing::Error as SlotProcessingError;
|
pub use self::slot_processing::Error as SlotProcessingError;
|
||||||
|
|
||||||
|
@ -40,3 +40,13 @@ pub fn create_proof_of_possession(keypair: &Keypair) -> Signature {
|
|||||||
extend_if_needed(&mut hash);
|
extend_if_needed(&mut hash);
|
||||||
Signature::new_hashed(&hash, &keypair.sk)
|
Signature::new_hashed(&hash, &keypair.sk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bls_verify_aggregate(
|
||||||
|
pubkey: &AggregatePublicKey,
|
||||||
|
message: &[u8],
|
||||||
|
signature: &AggregateSignature,
|
||||||
|
_domain: u64,
|
||||||
|
) -> bool {
|
||||||
|
// TODO: add domain
|
||||||
|
signature.verify(message, pubkey)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user