Complete attestation_validation, bar tests
This commit is contained in:
parent
a8bfa4d733
commit
0f9482f9d1
@ -37,6 +37,7 @@ pub fn validate_attestation_for_block(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invalid::AttestationTooOld tests.
|
* Invalid::AttestationTooOld tests.
|
||||||
*/
|
*/
|
@ -1,42 +1,25 @@
|
|||||||
use super::db::stores::{BeaconBlockAtSlotError, BeaconBlockStore};
|
use super::db::stores::{BeaconBlockAtSlotError, BeaconBlockStore};
|
||||||
use super::db::ClientDB;
|
use super::db::ClientDB;
|
||||||
|
use super::types::AttestationData;
|
||||||
use super::types::Hash256;
|
use super::types::Hash256;
|
||||||
use super::types::{AttestationData, BeaconState};
|
|
||||||
use super::{Error, Invalid, Outcome};
|
use super::{Error, Invalid, Outcome};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Check that an attestation is valid with reference to some state.
|
/// Verify that a attestation's `data.justified_block_hash` matches the local hash of the block at the
|
||||||
pub fn validate_attestation_data_for_state<T>(
|
/// attestation's `data.justified_slot`.
|
||||||
|
///
|
||||||
|
/// `chain_tip_block_hash` is the tip of the chain in which the justified block hash should exist
|
||||||
|
/// locally. As Lightouse stores multiple chains locally, it is possible to have multiple blocks at
|
||||||
|
/// the same slot. `chain_tip_block_hash` serves to restrict the lookup to a single chain, where
|
||||||
|
/// each slot may have exactly zero or one blocks.
|
||||||
|
pub fn validate_attestation_justified_block_hash<T>(
|
||||||
data: &AttestationData,
|
data: &AttestationData,
|
||||||
chain_tip_block_hash: &Hash256,
|
chain_tip_block_hash: &Hash256,
|
||||||
state: &BeaconState,
|
|
||||||
block_store: &Arc<BeaconBlockStore<T>>,
|
block_store: &Arc<BeaconBlockStore<T>>,
|
||||||
) -> Result<Outcome, Error>
|
) -> Result<Outcome, Error>
|
||||||
where
|
where
|
||||||
T: ClientDB + Sized,
|
T: ClientDB + Sized,
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* The attestation's `justified_slot` must be the same as the last justified slot known to this
|
|
||||||
* client.
|
|
||||||
*
|
|
||||||
* In the case that an attestation references a slot _before_ the latest state transition, it
|
|
||||||
* is acceptable for the attestation to reference the previous known `justified_slot`. If this
|
|
||||||
* were not the case, all attestations created _prior_ to the last state recalculation would be
|
|
||||||
* rejected if a block was justified in that state recalculation. It is both ideal and likely
|
|
||||||
* that blocks will be justified during a state recalcuation.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
let permissable_justified_slot = if data.slot >= state.latest_state_recalculation_slot {
|
|
||||||
state.justified_slot
|
|
||||||
} else {
|
|
||||||
state.previous_justified_slot
|
|
||||||
};
|
|
||||||
verify_or!(
|
|
||||||
data.justified_slot == permissable_justified_slot,
|
|
||||||
reject!(Invalid::JustifiedSlotImpermissable)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The `justified_block_hash` in the attestation must match exactly the hash of the block at
|
* The `justified_block_hash` in the attestation must match exactly the hash of the block at
|
||||||
* that slot in the local chain.
|
* that slot in the local chain.
|
||||||
@ -53,28 +36,6 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* The `shard_block_hash` in the state's `latest_crosslinks` must match either the
|
|
||||||
* `latest_crosslink_hash` or the `shard_block_hash` on the attestation.
|
|
||||||
*
|
|
||||||
* TODO: figure out the reasoning behind this.
|
|
||||||
*/
|
|
||||||
match state.latest_crosslinks.get(data.shard as usize) {
|
|
||||||
None => reject!(Invalid::UnknownShard),
|
|
||||||
Some(crosslink) => {
|
|
||||||
let local_shard_block_hash = crosslink.shard_block_hash;
|
|
||||||
let shard_block_hash_is_permissable = {
|
|
||||||
(local_shard_block_hash == data.latest_crosslink_hash)
|
|
||||||
|| (local_shard_block_hash == data.shard_block_hash)
|
|
||||||
};
|
|
||||||
verify_or!(
|
|
||||||
shard_block_hash_is_permissable,
|
|
||||||
reject!(Invalid::ShardBlockHashMismatch)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
accept!()
|
accept!()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,3 +66,15 @@ impl From<BeaconBlockAtSlotError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
/*
|
||||||
|
* TODO: Implement tests.
|
||||||
|
*
|
||||||
|
* These tests will require the `BeaconBlock` and `BeaconBlockBody` updates, which are not
|
||||||
|
* yet included in the code base. Adding tests now will result in duplicated work.
|
||||||
|
*
|
||||||
|
* https://github.com/sigp/lighthouse/issues/97
|
||||||
|
*/
|
||||||
|
}
|
38
beacon_chain/attestation_validation/src/justified_slot.rs
Normal file
38
beacon_chain/attestation_validation/src/justified_slot.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use super::types::{AttestationData, BeaconState};
|
||||||
|
use super::{Error, Invalid, Outcome};
|
||||||
|
|
||||||
|
/// Verify that an attestation's `data.justified_slot` matches the justified slot known to the
|
||||||
|
/// `state`.
|
||||||
|
///
|
||||||
|
/// In the case that an attestation references a slot _before_ the latest state transition, is
|
||||||
|
/// acceptable for the attestation to reference the previous known `justified_slot`. If this were
|
||||||
|
/// not the case, all attestations created _prior_ to the last state recalculation would be rejected
|
||||||
|
/// if a block was justified in that state recalculation. It is both ideal and likely that blocks
|
||||||
|
/// will be justified during a state recalcuation.
|
||||||
|
pub fn validate_attestation_justified_slot(
|
||||||
|
data: &AttestationData,
|
||||||
|
state: &BeaconState,
|
||||||
|
) -> Result<Outcome, Error> {
|
||||||
|
let permissable_justified_slot = if data.slot >= state.latest_state_recalculation_slot {
|
||||||
|
state.justified_slot
|
||||||
|
} else {
|
||||||
|
state.previous_justified_slot
|
||||||
|
};
|
||||||
|
verify_or!(
|
||||||
|
data.justified_slot == permissable_justified_slot,
|
||||||
|
reject!(Invalid::JustifiedSlotImpermissable)
|
||||||
|
);
|
||||||
|
accept!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
/*
|
||||||
|
* TODO: Implement tests.
|
||||||
|
*
|
||||||
|
* These tests will require the `BeaconBlock` and `BeaconBlockBody` updates, which are not
|
||||||
|
* yet included in the code base. Adding tests now will result in duplicated work.
|
||||||
|
*
|
||||||
|
* https://github.com/sigp/lighthouse/issues/97
|
||||||
|
*/
|
||||||
|
}
|
@ -7,12 +7,17 @@ extern crate types;
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
|
mod block_inclusion;
|
||||||
mod enums;
|
mod enums;
|
||||||
mod validate_for_block;
|
mod justified_block;
|
||||||
mod validate_for_state;
|
mod justified_slot;
|
||||||
mod validate_signature;
|
mod shard_block;
|
||||||
|
mod signature;
|
||||||
|
|
||||||
pub use enums::{Invalid, Outcome, Error};
|
pub use enums::{Invalid, Outcome, Error};
|
||||||
pub use validate_for_block::validate_attestation_for_block;
|
pub use block_inclusion::validate_attestation_for_block;
|
||||||
pub use validate_for_state::validate_attestation_data_for_state;
|
pub use justified_slot::validate_attestation_justified_slot;
|
||||||
pub use validate_signature::validate_attestation_signature;
|
pub use justified_block::validate_attestation_justified_block_hash;
|
||||||
|
pub use signature::validate_attestation_signature;
|
||||||
|
pub use shard_block::validate_attestation_data_shard_block_hash;
|
||||||
|
46
beacon_chain/attestation_validation/src/shard_block.rs
Normal file
46
beacon_chain/attestation_validation/src/shard_block.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use super::db::ClientDB;
|
||||||
|
use super::types::{AttestationData, BeaconState};
|
||||||
|
use super::{Error, Invalid, Outcome};
|
||||||
|
|
||||||
|
/// Check that an attestation is valid with reference to some state.
|
||||||
|
pub fn validate_attestation_data_shard_block_hash<T>(
|
||||||
|
data: &AttestationData,
|
||||||
|
state: &BeaconState,
|
||||||
|
) -> Result<Outcome, Error>
|
||||||
|
where
|
||||||
|
T: ClientDB + Sized,
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The `shard_block_hash` in the state's `latest_crosslinks` must match either the
|
||||||
|
* `latest_crosslink_hash` or the `shard_block_hash` on the attestation.
|
||||||
|
*
|
||||||
|
* TODO: figure out the reasoning behind this.
|
||||||
|
*/
|
||||||
|
match state.latest_crosslinks.get(data.shard as usize) {
|
||||||
|
None => reject!(Invalid::UnknownShard),
|
||||||
|
Some(crosslink) => {
|
||||||
|
let local_shard_block_hash = crosslink.shard_block_hash;
|
||||||
|
let shard_block_hash_is_permissable = {
|
||||||
|
(local_shard_block_hash == data.latest_crosslink_hash)
|
||||||
|
|| (local_shard_block_hash == data.shard_block_hash)
|
||||||
|
};
|
||||||
|
verify_or!(
|
||||||
|
shard_block_hash_is_permissable,
|
||||||
|
reject!(Invalid::ShardBlockHashMismatch)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
accept!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
/*
|
||||||
|
* TODO: Implement tests.
|
||||||
|
*
|
||||||
|
* These tests will require the `BeaconBlock` and `BeaconBlockBody` updates, which are not
|
||||||
|
* yet included in the code base. Adding tests now will result in duplicated work.
|
||||||
|
*
|
||||||
|
* https://github.com/sigp/lighthouse/issues/97
|
||||||
|
*/
|
||||||
|
}
|
@ -12,7 +12,7 @@ pub const SSZ_ATTESTION_DATA_LENGTH: usize = {
|
|||||||
32 // justified_block_hash
|
32 // justified_block_hash
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
pub struct AttestationData {
|
pub struct AttestationData {
|
||||||
pub slot: u64,
|
pub slot: u64,
|
||||||
pub shard: u64,
|
pub shard: u64,
|
||||||
|
@ -15,7 +15,7 @@ pub const MIN_SSZ_BLOCK_LENGTH: usize = {
|
|||||||
};
|
};
|
||||||
pub const MAX_SSZ_BLOCK_LENGTH: usize = MIN_SSZ_BLOCK_LENGTH + (1 << 24);
|
pub const MAX_SSZ_BLOCK_LENGTH: usize = MIN_SSZ_BLOCK_LENGTH + (1 << 24);
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone, Default)]
|
||||||
pub struct BeaconBlock {
|
pub struct BeaconBlock {
|
||||||
pub slot: u64,
|
pub slot: u64,
|
||||||
pub randao_reveal: Hash256,
|
pub randao_reveal: Hash256,
|
||||||
|
0
beacon_chain/types/src/beacon_block_body.rs
Normal file
0
beacon_chain/types/src/beacon_block_body.rs
Normal file
Loading…
Reference in New Issue
Block a user