Merge branch 'v2.1-spec' into validate_block
This commit is contained in:
commit
5c0690d39c
@ -6,11 +6,12 @@ extern crate clap;
|
|||||||
extern crate network_libp2p;
|
extern crate network_libp2p;
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
pub mod utils;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod utils;
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
71
lighthouse/state/helpers.rs
Normal file
71
lighthouse/state/helpers.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Collection of helper functions used in the state transition modules
|
||||||
|
*/
|
||||||
|
use super::active_state::ActiveState;
|
||||||
|
use super::block::Block;
|
||||||
|
use super::chain_config::ChainConfig;
|
||||||
|
use super::utils::errors::ParameterError;
|
||||||
|
use super::utils::types::Hash256;
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub fn get_signed_parent_hashes(
|
||||||
|
active_state: &ActiveState,
|
||||||
|
block: &Block,
|
||||||
|
attestation: &AttestationRecord,
|
||||||
|
chain_config: &ChainConfig)
|
||||||
|
-> Vec<Hash256> {
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub fn get_block_hash(
|
||||||
|
active_state_recent_block_hashes: &Vec<Hash256>,
|
||||||
|
current_block_slot: &u64,
|
||||||
|
slot: &u64,
|
||||||
|
cycle_length: &u64, // convert from standard u8
|
||||||
|
) -> Result<Hash256, ParameterError> {
|
||||||
|
// active_state must have at 2*cycle_length hashes
|
||||||
|
assert_error!(
|
||||||
|
active_state_recent_block_hashes.len() as u64 == cycle_length * 2,
|
||||||
|
ParameterError::InvalidInput(String::from(
|
||||||
|
"active state has incorrect number of block hashes"
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
let state_start_slot = (*current_block_slot)
|
||||||
|
.checked_sub(cycle_length * 2)
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
assert_error!(
|
||||||
|
(state_start_slot <= *slot) && (*slot < *current_block_slot),
|
||||||
|
ParameterError::InvalidInput(String::from("incorrect slot number"))
|
||||||
|
);
|
||||||
|
|
||||||
|
let index = 2 * cycle_length + (*slot) - *current_block_slot; // should always be positive
|
||||||
|
Ok(active_state_recent_block_hashes[index as usize])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_block_hash() {
|
||||||
|
let block_slot: u64 = 10;
|
||||||
|
let slot: u64 = 3;
|
||||||
|
let cycle_length: u64 = 8;
|
||||||
|
|
||||||
|
let mut block_hashes: Vec<Hash256> = Vec::new();
|
||||||
|
for _i in 0..2 * cycle_length {
|
||||||
|
block_hashes.push(Hash256::random());
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = get_block_hash(&block_hashes, &block_slot, &slot, &cycle_length).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
block_hashes[(2 * cycle_length + slot - block_slot) as usize]
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("{:?}", result);
|
||||||
|
}
|
||||||
|
}
|
@ -17,3 +17,5 @@ pub mod crosslink_record;
|
|||||||
pub mod shard_and_committee;
|
pub mod shard_and_committee;
|
||||||
pub mod transition;
|
pub mod transition;
|
||||||
pub mod validator_record;
|
pub mod validator_record;
|
||||||
|
pub mod validation;
|
||||||
|
pub mod helpers;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use super::Hash256;
|
use super::Hash256;
|
||||||
use super::TransitionError;
|
use super::ParameterError;
|
||||||
|
|
||||||
/// This function is used to select the hashes used in
|
/// This function is used to select the hashes used in
|
||||||
/// the signing of an AttestationRecord.
|
/// the signing of an AttestationRecord.
|
||||||
@ -18,22 +18,22 @@ pub fn attestation_parent_hashes(
|
|||||||
attestation_slot: u64,
|
attestation_slot: u64,
|
||||||
current_hashes: &[Hash256],
|
current_hashes: &[Hash256],
|
||||||
oblique_hashes: &[Hash256])
|
oblique_hashes: &[Hash256])
|
||||||
-> Result<Vec<Hash256>, TransitionError>
|
-> Result<Vec<Hash256>, ParameterError>
|
||||||
{
|
{
|
||||||
// This cast places a limit on cycle_length. If you change it, check math
|
// This cast places a limit on cycle_length. If you change it, check math
|
||||||
// for overflow.
|
// for overflow.
|
||||||
let cycle_length: u64 = u64::from(cycle_length);
|
let cycle_length: u64 = u64::from(cycle_length);
|
||||||
|
|
||||||
if current_hashes.len() as u64 != (cycle_length * 2) {
|
if current_hashes.len() as u64 != (cycle_length * 2) {
|
||||||
return Err(TransitionError::InvalidInput(String::from(
|
return Err(ParameterError::InvalidInput(String::from(
|
||||||
"current_hashes.len() must equal cycle_length * 2")));
|
"current_hashes.len() must equal cycle_length * 2")));
|
||||||
}
|
}
|
||||||
if attestation_slot >= block_slot {
|
if attestation_slot >= block_slot {
|
||||||
return Err(TransitionError::InvalidInput(String::from(
|
return Err(ParameterError::InvalidInput(String::from(
|
||||||
"attestation_slot must be less than block_slot")));
|
"attestation_slot must be less than block_slot")));
|
||||||
}
|
}
|
||||||
if oblique_hashes.len() as u64 > cycle_length {
|
if oblique_hashes.len() as u64 > cycle_length {
|
||||||
return Err(TransitionError::InvalidInput(String::from(
|
return Err(ParameterError::InvalidInput(String::from(
|
||||||
"oblique_hashes.len() must be <= cycle_length * 2")));
|
"oblique_hashes.len() must be <= cycle_length * 2")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ pub fn attestation_parent_hashes(
|
|||||||
let attestation_distance = block_slot - attestation_slot;
|
let attestation_distance = block_slot - attestation_slot;
|
||||||
|
|
||||||
if attestation_distance > cycle_length {
|
if attestation_distance > cycle_length {
|
||||||
return Err(TransitionError::InvalidInput(String::from(
|
return Err(ParameterError::InvalidInput(String::from(
|
||||||
"attestation_slot must be withing one cycle of block_slot")));
|
"attestation_slot must be withing one cycle of block_slot")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ pub fn attestation_parent_hashes(
|
|||||||
*/
|
*/
|
||||||
let end = start.checked_add(cycle_length)
|
let end = start.checked_add(cycle_length)
|
||||||
.and_then(|x| x.checked_sub(oblique_hashes.len() as u64))
|
.and_then(|x| x.checked_sub(oblique_hashes.len() as u64))
|
||||||
.ok_or(TransitionError::IntWrapping)?;
|
.ok_or(ParameterError::IntWrapping)?;
|
||||||
|
|
||||||
|
|
||||||
let mut hashes = Vec::new();
|
let mut hashes = Vec::new();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::block;
|
use super::block;
|
||||||
use super::Logger;
|
use super::Logger;
|
||||||
use super::utils::types::Hash256;
|
use super::utils::types::Hash256;
|
||||||
|
use super::utils::errors::ParameterError;
|
||||||
use super::db;
|
use super::db;
|
||||||
|
|
||||||
mod attestation_parent_hashes;
|
mod attestation_parent_hashes;
|
||||||
@ -10,12 +11,6 @@ mod validate_block;
|
|||||||
pub use self::attestation_parent_hashes::attestation_parent_hashes;
|
pub use self::attestation_parent_hashes::attestation_parent_hashes;
|
||||||
pub use self::shuffling::shuffle;
|
pub use self::shuffling::shuffle;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum TransitionError {
|
|
||||||
IntWrapping,
|
|
||||||
OutOfBounds,
|
|
||||||
InvalidInput(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
81
lighthouse/state/validation/attestation_validation.rs
Normal file
81
lighthouse/state/validation/attestation_validation.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use super::CrystallizedState;
|
||||||
|
use super::ActiveState;
|
||||||
|
use super::AttestationRecord;
|
||||||
|
use super::Block;
|
||||||
|
use super::ChainConfig;
|
||||||
|
|
||||||
|
use ::utils::errors::AttestationValidationError;
|
||||||
|
|
||||||
|
// implementation of validate_attestation in the v2.1 python reference implementation
|
||||||
|
// see: https://github.com/ethereum/beacon_chain/blob/a79ab2c6f03cbdabf2b6d9d435c26e2b216e09a5/beacon_chain/state/state_transition.py#L61
|
||||||
|
pub fn validate_attestation(
|
||||||
|
crystallized_state: &CrystallizedState,
|
||||||
|
active_state: &ActiveState,
|
||||||
|
attestation: &AttestationRecord,
|
||||||
|
block: &Block,
|
||||||
|
chain_config: &ChainConfig)
|
||||||
|
-> Result<bool, AttestationValidationError> {
|
||||||
|
|
||||||
|
if !(attestation.slot < block.slot_number) {
|
||||||
|
return Err(AttestationValidationError::SlotTooHigh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(attestation.slot > (block.slot_number - chain_config.cycle_length as u64)) {
|
||||||
|
return Err(AttestationValidationError::SlotTooLow(format!("Attestation slot number too low\n\tFound: {:?}, Needed greater than: {:?}", attestation.slot, block.slot_number - chain_config.cycle_length as u64)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
// test helper functions
|
||||||
|
|
||||||
|
fn generate_standard_state() -> (
|
||||||
|
CrystallizedState,
|
||||||
|
ActiveState,
|
||||||
|
AttestationRecord,
|
||||||
|
Block,
|
||||||
|
ChainConfig) {
|
||||||
|
|
||||||
|
let crystallized_state = CrystallizedState::zero();
|
||||||
|
let active_state = ActiveState::zero();
|
||||||
|
let attestation_record = AttestationRecord::zero();
|
||||||
|
let block = Block::zero();
|
||||||
|
let chain_config = ChainConfig::standard();
|
||||||
|
|
||||||
|
return (crystallized_state, active_state, attestation_record, block, chain_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_attestation_validation_slot_high() {
|
||||||
|
// generate standard state
|
||||||
|
let (crystallized_state, active_state, mut attestation_record, mut block, chain_config) = generate_standard_state();
|
||||||
|
// set slot too high
|
||||||
|
attestation_record.slot = 30;
|
||||||
|
block.slot_number = 10;
|
||||||
|
|
||||||
|
let result = validate_attestation(&crystallized_state, &active_state, &attestation_record, &block, &chain_config);
|
||||||
|
assert_eq!(result, Err(AttestationValidationError::SlotTooHigh));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_attestation_validation_slot_low() {
|
||||||
|
// generate standard state
|
||||||
|
let (crystallized_state, active_state, mut attestation_record, mut block, chain_config) = generate_standard_state();
|
||||||
|
// set slot too high
|
||||||
|
attestation_record.slot = 2;
|
||||||
|
block.slot_number = 10;
|
||||||
|
|
||||||
|
let result = validate_attestation(
|
||||||
|
&crystallized_state,
|
||||||
|
&active_state,
|
||||||
|
&attestation_record,
|
||||||
|
&block,
|
||||||
|
&chain_config);
|
||||||
|
//assert_eq!(result, Err(AttestationValidationError::SlotTooLow));
|
||||||
|
}
|
||||||
|
}
|
7
lighthouse/state/validation/mod.rs
Normal file
7
lighthouse/state/validation/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use super::crystallized_state::CrystallizedState;
|
||||||
|
use super::active_state::ActiveState;
|
||||||
|
use super::attestation_record::AttestationRecord;
|
||||||
|
use super::block::Block;
|
||||||
|
use super::chain_config::ChainConfig;
|
||||||
|
|
||||||
|
mod attestation_validation;
|
17
lighthouse/utils/errors.rs
Normal file
17
lighthouse/utils/errors.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Collection of custom errors
|
||||||
|
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub enum AttestationValidationError {
|
||||||
|
SlotTooHigh,
|
||||||
|
SlotTooLow(String),
|
||||||
|
IncorrectBitField,
|
||||||
|
NonZeroTrailingBits,
|
||||||
|
AggregateSignatureFail
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub enum ParameterError {
|
||||||
|
IntWrapping,
|
||||||
|
OutOfBounds,
|
||||||
|
InvalidInput(String),
|
||||||
|
}
|
10
lighthouse/utils/macros.rs
Normal file
10
lighthouse/utils/macros.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#[macro_export]
|
||||||
|
macro_rules! assert_error {
|
||||||
|
($exp: expr, $err: expr) => {
|
||||||
|
if ( !$exp ) {
|
||||||
|
return Err($err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -3,8 +3,13 @@ extern crate blake2_rfc as blake2;
|
|||||||
extern crate crypto_mac;
|
extern crate crypto_mac;
|
||||||
extern crate boolean_bitfield;
|
extern crate boolean_bitfield;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
pub mod macros;
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod bls;
|
pub mod bls;
|
||||||
pub mod test_helpers;
|
pub mod test_helpers;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
|
pub mod errors;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user