diff --git a/lighthouse/state/mod.rs b/lighthouse/state/mod.rs index d10acf8fd..2c938cf29 100644 --- a/lighthouse/state/mod.rs +++ b/lighthouse/state/mod.rs @@ -15,3 +15,4 @@ pub mod crosslink_record; pub mod shard_and_committee; pub mod transition; pub mod validator_record; +pub mod validation; diff --git a/lighthouse/state/validation/attestation_validation.rs b/lighthouse/state/validation/attestation_validation.rs new file mode 100644 index 000000000..483fef55a --- /dev/null +++ b/lighthouse/state/validation/attestation_validation.rs @@ -0,0 +1,66 @@ +use super::super::crystallized_state::CrystallizedState; +use super::super::active_state::ActiveState; +use super::super::attestation_record::AttestationRecord; +use super::super::block::Block; +use super::super::chain_config::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 { + + 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))); + } + + return Ok(true); + } + + +#[cfg(test)] +mod tests { + + use super::*; + // test helper functions + + fn generate_standard_state() -> ( + CrystallizedState, + ActiveState, + AttestationRecord, + Block, + ChainConfig) { + + let mut crystallized_state = CrystallizedState::zero(); + let mut active_state = ActiveState::zero(); + let mut attestation_record = AttestationRecord::zero(); + let mut 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 (mut crystallized_state, mut active_state, mut attestation_record, mut block, mut 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)); + } +} diff --git a/lighthouse/state/validation/mod.rs b/lighthouse/state/validation/mod.rs new file mode 100644 index 000000000..98db2cb66 --- /dev/null +++ b/lighthouse/state/validation/mod.rs @@ -0,0 +1 @@ +mod attestation_validation; diff --git a/lighthouse/utils/errors.rs b/lighthouse/utils/errors.rs new file mode 100644 index 000000000..4f12cfbdd --- /dev/null +++ b/lighthouse/utils/errors.rs @@ -0,0 +1,12 @@ +// Collection of custom errors + +#[derive(Debug,PartialEq)] +pub enum AttestationValidationError { + SlotTooHigh, + SlotTooLow(String), + IncorrectBitField, + NonZeroTrailingBits, + AggregateSignatureFail +} + + diff --git a/lighthouse/utils/mod.rs b/lighthouse/utils/mod.rs index d116422be..4cb6ddf38 100644 --- a/lighthouse/utils/mod.rs +++ b/lighthouse/utils/mod.rs @@ -7,3 +7,4 @@ pub mod types; pub mod bls; pub mod test_helpers; pub mod logging; +pub mod errors;