Merge branch 'v2.1-spec' into validate_block

This commit is contained in:
Paul Hauner 2018-09-22 11:25:56 +10:00
commit 5c0690d39c
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
10 changed files with 203 additions and 14 deletions

View File

@ -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;

View 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);
}
}

View File

@ -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;

View File

@ -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();

View File

@ -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),
}

View 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));
}
}

View 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;

View 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),
}

View File

@ -0,0 +1,10 @@
#[macro_export]
macro_rules! assert_error {
($exp: expr, $err: expr) => {
if ( !$exp ) {
return Err($err);
}
}
}

View File

@ -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;