mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 21:34:46 +00:00
Verify attestation justified_block_hash.
Previously there was not a check that the hash was in the chain, just that it was known (in the database in any chain)
This commit is contained in:
@@ -12,7 +12,11 @@ use super::db::{
|
||||
ClientDB,
|
||||
DBError
|
||||
};
|
||||
use super::db::stores::ValidatorStore;
|
||||
use super::db::stores::{
|
||||
BlockStore,
|
||||
BlockAtSlotError,
|
||||
ValidatorStore,
|
||||
};
|
||||
use super::types::{
|
||||
Hash256,
|
||||
};
|
||||
@@ -27,7 +31,7 @@ pub enum AttestationValidationError {
|
||||
SlotTooHigh,
|
||||
SlotTooLow,
|
||||
JustifiedSlotIncorrect,
|
||||
UnknownJustifiedBlock,
|
||||
InvalidJustifiedBlockHash,
|
||||
TooManyObliqueHashes,
|
||||
BadCurrentHashes,
|
||||
BadObliqueHashes,
|
||||
@@ -54,10 +58,10 @@ pub struct AttestationValidationContext<T>
|
||||
pub cycle_length: u8,
|
||||
/// The last justified slot as per the client's view of the canonical chain.
|
||||
pub last_justified_slot: u64,
|
||||
/// The last justified block hash as per the client's view of the canonical chain.
|
||||
pub last_justified_block_hash: Hash256,
|
||||
/// A vec of the hashes of the blocks preceeding the present slot.
|
||||
pub parent_hashes: Arc<Vec<Hash256>>,
|
||||
/// The store containing block information.
|
||||
pub block_store: Arc<BlockStore<T>>,
|
||||
/// The store containing validator information.
|
||||
pub validator_store: Arc<ValidatorStore<T>>,
|
||||
/// A map of (slot, shard_id) to the attestation set of validation indices.
|
||||
@@ -97,18 +101,10 @@ impl<T> AttestationValidationContext<T>
|
||||
* The attestation must indicate that its last justified slot is the same as the last justified
|
||||
* slot known to us.
|
||||
*/
|
||||
if a.justified_slot != self.last_justified_slot {
|
||||
if a.justified_slot > self.last_justified_slot {
|
||||
return Err(AttestationValidationError::JustifiedSlotIncorrect);
|
||||
}
|
||||
|
||||
/*
|
||||
* The specified justified block hash supplied in the attestation must match our knowledge
|
||||
* of the last justified block this chain.
|
||||
*/
|
||||
if a.justified_block_hash != self.last_justified_block_hash {
|
||||
return Err(AttestationValidationError::UnknownJustifiedBlock)
|
||||
}
|
||||
|
||||
/*
|
||||
* There is no need to include more oblique parents hashes than there are blocks
|
||||
* in a cycle.
|
||||
@@ -147,13 +143,35 @@ impl<T> AttestationValidationContext<T>
|
||||
return Err(AttestationValidationError::InvalidBitfieldEndBits)
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the parent hashes for this attestation
|
||||
*/
|
||||
let parent_hashes = attestation_parent_hashes(
|
||||
self.cycle_length,
|
||||
self.block_slot,
|
||||
a.slot,
|
||||
&self.parent_hashes,
|
||||
&a.oblique_parent_hashes)?;
|
||||
|
||||
/*
|
||||
* The specified justified block hash supplied in the attestation must be in the chain at
|
||||
* the given slot number.
|
||||
*
|
||||
* First, we find the latest parent hash from the parent_hashes array. Then, using the
|
||||
* 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()
|
||||
.ok_or(AttestationValidationError::BadCurrentHashes)?;
|
||||
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)
|
||||
};
|
||||
|
||||
/*
|
||||
* Generate the message that this attestation aggregate signature must sign across.
|
||||
*/
|
||||
let signed_message = {
|
||||
let parent_hashes = attestation_parent_hashes(
|
||||
self.cycle_length,
|
||||
self.block_slot,
|
||||
a.slot,
|
||||
&self.parent_hashes,
|
||||
&a.oblique_parent_hashes)?;
|
||||
generate_signed_message(
|
||||
a.slot,
|
||||
&parent_hashes,
|
||||
@@ -201,6 +219,16 @@ impl From<ParentHashesError> for AttestationValidationError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BlockAtSlotError> for AttestationValidationError {
|
||||
fn from(e: BlockAtSlotError) -> Self {
|
||||
match e {
|
||||
BlockAtSlotError::DBError(s) => AttestationValidationError::DBError(s),
|
||||
_ => AttestationValidationError::InvalidJustifiedBlockHash
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DBError> for AttestationValidationError {
|
||||
fn from(e: DBError) -> Self {
|
||||
AttestationValidationError::DBError(e.message)
|
||||
|
||||
@@ -207,8 +207,8 @@ impl<T> BlockValidationContext<T>
|
||||
block_slot,
|
||||
cycle_length: self.cycle_length,
|
||||
last_justified_slot: self.last_justified_slot,
|
||||
last_justified_block_hash: self.last_justified_block_hash,
|
||||
parent_hashes: self.parent_hashes.clone(),
|
||||
block_store: self.block_store.clone(),
|
||||
validator_store: self.validator_store.clone(),
|
||||
attester_map: self.attester_map.clone(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user