mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-09 11:25:55 +00:00
@@ -1,32 +1,16 @@
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use super::types::{
|
||||
AttestationRecord,
|
||||
AttesterMap,
|
||||
};
|
||||
use super::attestation_parent_hashes::{
|
||||
attestation_parent_hashes,
|
||||
ParentHashesError,
|
||||
};
|
||||
use super::db::{
|
||||
ClientDB,
|
||||
DBError
|
||||
};
|
||||
use super::db::stores::{
|
||||
BeaconBlockStore,
|
||||
BeaconBlockAtSlotError,
|
||||
ValidatorStore,
|
||||
};
|
||||
use super::types::{
|
||||
Hash256,
|
||||
};
|
||||
use super::attestation_parent_hashes::{attestation_parent_hashes, ParentHashesError};
|
||||
use super::db::stores::{BeaconBlockAtSlotError, BeaconBlockStore, ValidatorStore};
|
||||
use super::db::{ClientDB, DBError};
|
||||
use super::message_generation::generate_signed_message;
|
||||
use super::signature_verification::{
|
||||
verify_aggregate_signature_for_indices,
|
||||
SignatureVerificationError,
|
||||
verify_aggregate_signature_for_indices, SignatureVerificationError,
|
||||
};
|
||||
use super::types::Hash256;
|
||||
use super::types::{AttestationRecord, AttesterMap};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug,PartialEq)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum AttestationValidationError {
|
||||
ParentSlotTooHigh,
|
||||
ParentSlotTooLow,
|
||||
@@ -52,7 +36,8 @@ pub enum AttestationValidationError {
|
||||
|
||||
/// The context against which some attestation should be validated.
|
||||
pub struct AttestationValidationContext<T>
|
||||
where T: ClientDB + Sized
|
||||
where
|
||||
T: ClientDB + Sized,
|
||||
{
|
||||
/// The slot as determined by the system time.
|
||||
pub block_slot: u64,
|
||||
@@ -73,7 +58,8 @@ pub struct AttestationValidationContext<T>
|
||||
}
|
||||
|
||||
impl<T> AttestationValidationContext<T>
|
||||
where T: ClientDB
|
||||
where
|
||||
T: ClientDB,
|
||||
{
|
||||
/// Validate a (fully deserialized) AttestationRecord against this context.
|
||||
///
|
||||
@@ -82,9 +68,10 @@ impl<T> AttestationValidationContext<T>
|
||||
///
|
||||
/// The attestation's aggregate signature will be verified, therefore the function must able to
|
||||
/// access all required validation public keys via the `validator_store`.
|
||||
pub fn validate_attestation(&self, a: &AttestationRecord)
|
||||
-> Result<HashSet<usize>, AttestationValidationError>
|
||||
{
|
||||
pub fn validate_attestation(
|
||||
&self,
|
||||
a: &AttestationRecord,
|
||||
) -> Result<HashSet<usize>, AttestationValidationError> {
|
||||
/*
|
||||
* The attesation slot must be less than or equal to the parent of the slot of the block
|
||||
* that contained the attestation.
|
||||
@@ -97,8 +84,10 @@ impl<T> AttestationValidationContext<T>
|
||||
* The slot of this attestation must not be more than cycle_length + 1 distance
|
||||
* from the parent_slot of block that contained it.
|
||||
*/
|
||||
if a.slot < self.parent_block_slot
|
||||
.saturating_sub(u64::from(self.cycle_length).saturating_add(1)) {
|
||||
if a.slot < self
|
||||
.parent_block_slot
|
||||
.saturating_sub(u64::from(self.cycle_length).saturating_add(1))
|
||||
{
|
||||
return Err(AttestationValidationError::ParentSlotTooLow);
|
||||
}
|
||||
|
||||
@@ -124,18 +113,18 @@ impl<T> AttestationValidationContext<T>
|
||||
* This is an array mapping the order that validators will appear in the bitfield to the
|
||||
* canonincal index of a validator.
|
||||
*/
|
||||
let attestation_indices = self.attester_map.get(&(a.slot, a.shard_id))
|
||||
let attestation_indices = self
|
||||
.attester_map
|
||||
.get(&(a.slot, a.shard_id))
|
||||
.ok_or(AttestationValidationError::BadAttesterMap)?;
|
||||
|
||||
/*
|
||||
* The bitfield must be no longer than the minimum required to represent each validator in the
|
||||
* attestation indices for this slot and shard id.
|
||||
*/
|
||||
if a.attester_bitfield.num_bytes() !=
|
||||
bytes_for_bits(attestation_indices.len())
|
||||
{
|
||||
if a.attester_bitfield.num_bytes() != bytes_for_bits(attestation_indices.len()) {
|
||||
return Err(AttestationValidationError::BadBitfieldLength);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are excess bits in the bitfield because the number of a validators in not a
|
||||
@@ -145,7 +134,7 @@ impl<T> AttestationValidationContext<T>
|
||||
* refer to the same AttesationRecord.
|
||||
*/
|
||||
if a.attester_bitfield.len() > attestation_indices.len() {
|
||||
return Err(AttestationValidationError::InvalidBitfieldEndBits)
|
||||
return Err(AttestationValidationError::InvalidBitfieldEndBits);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -156,7 +145,8 @@ impl<T> AttestationValidationContext<T>
|
||||
self.block_slot,
|
||||
a.slot,
|
||||
&self.recent_block_hashes,
|
||||
&a.oblique_parent_hashes)?;
|
||||
&a.oblique_parent_hashes,
|
||||
)?;
|
||||
|
||||
/*
|
||||
* The specified justified block hash supplied in the attestation must be in the chain at
|
||||
@@ -166,11 +156,15 @@ impl<T> AttestationValidationContext<T>
|
||||
* block store (database) we iterate back through the blocks until we find (or fail to
|
||||
* find) the justified block hash referenced in the attestation record.
|
||||
*/
|
||||
let latest_parent_hash = parent_hashes.last()
|
||||
let latest_parent_hash = parent_hashes
|
||||
.last()
|
||||
.ok_or(AttestationValidationError::BadCurrentHashes)?;
|
||||
match self.block_store.block_at_slot(&latest_parent_hash, a.justified_slot)? {
|
||||
match self
|
||||
.block_store
|
||||
.block_at_slot(&latest_parent_hash, a.justified_slot)?
|
||||
{
|
||||
Some((ref hash, _)) if *hash == a.justified_block_hash.to_vec() => (),
|
||||
_ => return Err(AttestationValidationError::InvalidJustifiedBlockHash)
|
||||
_ => return Err(AttestationValidationError::InvalidJustifiedBlockHash),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -182,16 +176,17 @@ impl<T> AttestationValidationContext<T>
|
||||
&parent_hashes,
|
||||
a.shard_id,
|
||||
&a.shard_block_hash,
|
||||
a.justified_slot)
|
||||
a.justified_slot,
|
||||
)
|
||||
};
|
||||
|
||||
let voted_hashset =
|
||||
verify_aggregate_signature_for_indices(
|
||||
&signed_message,
|
||||
&a.aggregate_sig,
|
||||
&attestation_indices,
|
||||
&a.attester_bitfield,
|
||||
&self.validator_store)?;
|
||||
let voted_hashset = verify_aggregate_signature_for_indices(
|
||||
&signed_message,
|
||||
&a.aggregate_sig,
|
||||
&attestation_indices,
|
||||
&a.attester_bitfield,
|
||||
&self.validator_store,
|
||||
)?;
|
||||
|
||||
/*
|
||||
* If the hashset of voters is None, the signature verification failed.
|
||||
@@ -210,16 +205,11 @@ fn bytes_for_bits(bits: usize) -> usize {
|
||||
impl From<ParentHashesError> for AttestationValidationError {
|
||||
fn from(e: ParentHashesError) -> Self {
|
||||
match e {
|
||||
ParentHashesError::BadCurrentHashes
|
||||
=> AttestationValidationError::BadCurrentHashes,
|
||||
ParentHashesError::BadObliqueHashes
|
||||
=> AttestationValidationError::BadObliqueHashes,
|
||||
ParentHashesError::SlotTooLow
|
||||
=> AttestationValidationError::BlockSlotTooLow,
|
||||
ParentHashesError::SlotTooHigh
|
||||
=> AttestationValidationError::BlockSlotTooHigh,
|
||||
ParentHashesError::IntWrapping
|
||||
=> AttestationValidationError::IntWrapping
|
||||
ParentHashesError::BadCurrentHashes => AttestationValidationError::BadCurrentHashes,
|
||||
ParentHashesError::BadObliqueHashes => AttestationValidationError::BadObliqueHashes,
|
||||
ParentHashesError::SlotTooLow => AttestationValidationError::BlockSlotTooLow,
|
||||
ParentHashesError::SlotTooHigh => AttestationValidationError::BlockSlotTooHigh,
|
||||
ParentHashesError::IntWrapping => AttestationValidationError::IntWrapping,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,8 +218,7 @@ impl From<BeaconBlockAtSlotError> for AttestationValidationError {
|
||||
fn from(e: BeaconBlockAtSlotError) -> Self {
|
||||
match e {
|
||||
BeaconBlockAtSlotError::DBError(s) => AttestationValidationError::DBError(s),
|
||||
_ => AttestationValidationError::InvalidJustifiedBlockHash
|
||||
|
||||
_ => AttestationValidationError::InvalidJustifiedBlockHash,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,14 +232,16 @@ impl From<DBError> for AttestationValidationError {
|
||||
impl From<SignatureVerificationError> for AttestationValidationError {
|
||||
fn from(e: SignatureVerificationError) -> Self {
|
||||
match e {
|
||||
SignatureVerificationError::BadValidatorIndex
|
||||
=> AttestationValidationError::BadAttesterMap,
|
||||
SignatureVerificationError::PublicKeyCorrupt
|
||||
=> AttestationValidationError::PublicKeyCorrupt,
|
||||
SignatureVerificationError::NoPublicKeyForValidator
|
||||
=> AttestationValidationError::NoPublicKeyForValidator,
|
||||
SignatureVerificationError::DBError(s)
|
||||
=> AttestationValidationError::DBError(s),
|
||||
SignatureVerificationError::BadValidatorIndex => {
|
||||
AttestationValidationError::BadAttesterMap
|
||||
}
|
||||
SignatureVerificationError::PublicKeyCorrupt => {
|
||||
AttestationValidationError::PublicKeyCorrupt
|
||||
}
|
||||
SignatureVerificationError::NoPublicKeyForValidator => {
|
||||
AttestationValidationError::NoPublicKeyForValidator
|
||||
}
|
||||
SignatureVerificationError::DBError(s) => AttestationValidationError::DBError(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user