Progress further on attestation validation
This commit is contained in:
parent
f9f5a9e49c
commit
26537c1184
@ -1,3 +1,4 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
use super::AttestationRecord;
|
use super::AttestationRecord;
|
||||||
use super::attestation_parent_hashes::{
|
use super::attestation_parent_hashes::{
|
||||||
attestation_parent_hashes,
|
attestation_parent_hashes,
|
||||||
@ -12,33 +13,35 @@ use super::db::stores::{
|
|||||||
ValidatorStore,
|
ValidatorStore,
|
||||||
};
|
};
|
||||||
use super::ssz::SszStream;
|
use super::ssz::SszStream;
|
||||||
use super::bls::{
|
|
||||||
AggregateSignature,
|
|
||||||
AggregatePublicKey,
|
|
||||||
PublicKey,
|
|
||||||
};
|
|
||||||
use super::utils::hash::canonical_hash;
|
use super::utils::hash::canonical_hash;
|
||||||
use super::utils::types::{
|
use super::utils::types::{
|
||||||
Hash256,
|
Hash256,
|
||||||
Bitfield,
|
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use super::signatures::{
|
||||||
|
verify_aggregate_signature_for_indices,
|
||||||
|
SignatureVerificationError,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug,PartialEq)]
|
#[derive(Debug,PartialEq)]
|
||||||
pub enum AttestationValidationError {
|
pub enum AttestationValidationError {
|
||||||
SlotTooHigh,
|
SlotTooHigh,
|
||||||
SlotTooLow,
|
SlotTooLow,
|
||||||
JustifiedSlotTooHigh,
|
JustifiedSlotTooHigh,
|
||||||
|
UnknownJustifiedBlock,
|
||||||
TooManyObliqueHashes,
|
TooManyObliqueHashes,
|
||||||
BadCurrentHashes,
|
BadCurrentHashes,
|
||||||
BadObliqueHashes,
|
BadObliqueHashes,
|
||||||
BadAttesterMap,
|
BadAttesterMap,
|
||||||
IntWrapping,
|
IntWrapping,
|
||||||
|
PublicKeyCorrupt,
|
||||||
|
NoPublicKeyForValidator,
|
||||||
IncorrectBitField,
|
IncorrectBitField,
|
||||||
NoSignatures,
|
NoSignatures,
|
||||||
NonZeroTrailingBits,
|
NonZeroTrailingBits,
|
||||||
AggregateSignatureFail
|
AggregateSignatureFail,
|
||||||
|
DBError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
type Slot = u64;
|
type Slot = u64;
|
||||||
@ -55,8 +58,9 @@ pub fn validate_attestation<T>(a: &AttestationRecord,
|
|||||||
known_last_justified_slot: u64,
|
known_last_justified_slot: u64,
|
||||||
known_parent_hashes: Arc<Vec<Hash256>>,
|
known_parent_hashes: Arc<Vec<Hash256>>,
|
||||||
block_store: BlockStore<T>,
|
block_store: BlockStore<T>,
|
||||||
|
validator_store: ValidatorStore<T>,
|
||||||
attester_map: Arc<AttesterMap>)
|
attester_map: Arc<AttesterMap>)
|
||||||
-> Result<bool, AttestationValidationError>
|
-> Result<(bool, Option<HashSet<usize>>), AttestationValidationError>
|
||||||
where T: ClientDB + Sized
|
where T: ClientDB + Sized
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -92,15 +96,46 @@ pub fn validate_attestation<T>(a: &AttestationRecord,
|
|||||||
return Err(AttestationValidationError::TooManyObliqueHashes);
|
return Err(AttestationValidationError::TooManyObliqueHashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve the set of attestation indices for this slot and shard id.
|
||||||
|
*
|
||||||
|
* This is an array mapping the order that validators will appear in the bitfield to the
|
||||||
|
* canonincal index of a validator.
|
||||||
|
*/
|
||||||
let attestation_indices = attester_map.get(&(a.slot, a.shard_id.into()))
|
let attestation_indices = attester_map.get(&(a.slot, a.shard_id.into()))
|
||||||
.ok_or(AttestationValidationError::BadAttesterMap)?;
|
.ok_or(AttestationValidationError::BadAttesterMap)?;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The bitfield must be no longer than the minimum required to represent each validator in the
|
||||||
|
* attestation indicies for this slot and shard id.
|
||||||
|
*/
|
||||||
if a.attester_bitfield.num_bytes() !=
|
if a.attester_bitfield.num_bytes() !=
|
||||||
bytes_for_bits(attestation_indices.len())
|
bytes_for_bits(attestation_indices.len())
|
||||||
{
|
{
|
||||||
return Err(AttestationValidationError::IncorrectBitField);
|
return Err(AttestationValidationError::IncorrectBitField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there are excess bits in the bitfield because the number of a validators in not a
|
||||||
|
* multiple of 8, reject this attestation record.
|
||||||
|
*
|
||||||
|
* Allow extra set bits would permit mutliple different byte layouts (and therefore hashes) to
|
||||||
|
* refer to the same AttesationRecord.
|
||||||
|
*/
|
||||||
|
let last_byte =
|
||||||
|
a.attester_bitfield.get_byte(a.attester_bitfield.num_bytes())
|
||||||
|
.ok_or(AttestationValidationError::IncorrectBitField)?;
|
||||||
|
if any_of_last_n_bits_are_set(last_byte, a.attester_bitfield.len() % 8) {
|
||||||
|
return Err(AttestationValidationError::IncorrectBitField)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The specified justified block hash must be known to us
|
||||||
|
*/
|
||||||
|
if !block_store.block_exists(&a.justified_block_hash)? {
|
||||||
|
return Err(AttestationValidationError::UnknownJustifiedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
let signed_message = {
|
let signed_message = {
|
||||||
let parent_hashes = attestation_parent_hashes(
|
let parent_hashes = attestation_parent_hashes(
|
||||||
cycle_length,
|
cycle_length,
|
||||||
@ -116,15 +151,20 @@ pub fn validate_attestation<T>(a: &AttestationRecord,
|
|||||||
a.justified_slot)
|
a.justified_slot)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(false)
|
let (signature_valid, voted_hashmap) =
|
||||||
|
verify_aggregate_signature_for_indices(
|
||||||
|
&signed_message,
|
||||||
|
&a.aggregate_sig,
|
||||||
|
&attestation_indices,
|
||||||
|
&a.attester_bitfield,
|
||||||
|
&validator_store)?;
|
||||||
|
|
||||||
|
Ok((signature_valid, voted_hashmap))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_pub_keys(attestation_indices: &Vec<usize>,
|
fn any_of_last_n_bits_are_set(byte: &u8, n: usize) -> bool {
|
||||||
bitfield: &Bitfield)
|
let shift = 8_u8.saturating_sub(n as u8);
|
||||||
-> Option<Vec<PublicKey>>
|
((!0 >> shift) & byte) > 0
|
||||||
{
|
|
||||||
// cats
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates the message used to validate the signature provided with an AttestationRecord.
|
/// Generates the message used to validate the signature provided with an AttestationRecord.
|
||||||
@ -161,16 +201,37 @@ fn generate_signed_message(slot: u64,
|
|||||||
impl From<ParentHashesError> for AttestationValidationError {
|
impl From<ParentHashesError> for AttestationValidationError {
|
||||||
fn from(e: ParentHashesError) -> Self {
|
fn from(e: ParentHashesError) -> Self {
|
||||||
match e {
|
match e {
|
||||||
ParentHashesError::BadCurrentHashes =>
|
ParentHashesError::BadCurrentHashes
|
||||||
AttestationValidationError::BadCurrentHashes,
|
=> AttestationValidationError::BadCurrentHashes,
|
||||||
ParentHashesError::BadObliqueHashes =>
|
ParentHashesError::BadObliqueHashes
|
||||||
AttestationValidationError::BadObliqueHashes,
|
=> AttestationValidationError::BadObliqueHashes,
|
||||||
ParentHashesError::SlotTooLow =>
|
ParentHashesError::SlotTooLow
|
||||||
AttestationValidationError::SlotTooLow,
|
=> AttestationValidationError::SlotTooLow,
|
||||||
ParentHashesError::SlotTooHigh =>
|
ParentHashesError::SlotTooHigh
|
||||||
AttestationValidationError::SlotTooHigh,
|
=> AttestationValidationError::SlotTooHigh,
|
||||||
ParentHashesError::IntWrapping =>
|
ParentHashesError::IntWrapping
|
||||||
AttestationValidationError::IntWrapping
|
=> AttestationValidationError::IntWrapping
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DBError> for AttestationValidationError {
|
||||||
|
fn from(e: DBError) -> Self {
|
||||||
|
AttestationValidationError::DBError(e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user