diff --git a/beacon_chain/attestation_validation/src/enums.rs b/beacon_chain/attestation_validation/src/enums.rs index 3174d1154..6c94c628c 100644 --- a/beacon_chain/attestation_validation/src/enums.rs +++ b/beacon_chain/attestation_validation/src/enums.rs @@ -1,4 +1,5 @@ /// Reasons why an `AttestationRecord` can be invalid. +#[derive(PartialEq, Debug)] pub enum Invalid { AttestationTooRecent, AttestationTooOld, @@ -14,6 +15,7 @@ pub enum Invalid { /// /// Distinct from the `Error` enum as an `Outcome` indicates that validation executed sucessfully /// and determined the validity `AttestationRecord`. +#[derive(PartialEq, Debug)] pub enum Outcome { Valid, Invalid(Invalid), @@ -23,6 +25,7 @@ pub enum Outcome { /// /// Distinct from the `Outcome` enum as `Errors` indicate that validation encountered an unexpected /// condition and was unable to perform its duty. +#[derive(PartialEq, Debug)] pub enum Error { BlockHasNoParent, BadValidatorIndex, diff --git a/beacon_chain/attestation_validation/src/validate_signature.rs b/beacon_chain/attestation_validation/src/validate_signature.rs index 67ba7d2ec..050f9cdf9 100644 --- a/beacon_chain/attestation_validation/src/validate_signature.rs +++ b/beacon_chain/attestation_validation/src/validate_signature.rs @@ -62,3 +62,88 @@ impl From for Error { Error::OutOfBoundsBitfieldIndex } } + +#[cfg(test)] +mod tests { + use super::super::bls::{Keypair, Signature}; + use super::super::db::MemoryDB; + use super::*; + use std::sync::Arc; + + /* + * TODO: Test cases are not comprehensive. + * https://github.com/sigp/lighthouse/issues/94 + */ + + #[test] + fn test_signature_verification() { + let attestation_data = AttestationData::zero(); + let message = attestation_data_signing_message(&attestation_data); + let signing_keypairs = vec![ + Keypair::random(), + Keypair::random(), + Keypair::random(), + Keypair::random(), + Keypair::random(), + Keypair::random(), + ]; + let non_signing_keypairs = vec![ + Keypair::random(), + Keypair::random(), + Keypair::random(), + Keypair::random(), + Keypair::random(), + Keypair::random(), + ]; + /* + * Signing keypairs first, then non-signing + */ + let mut all_keypairs = signing_keypairs.clone(); + all_keypairs.append(&mut non_signing_keypairs.clone()); + + let attestation_indices: Vec = (0..all_keypairs.len()).collect(); + let mut bitfield = Bitfield::from_elem(all_keypairs.len(), false); + for i in 0..signing_keypairs.len() { + bitfield.set(i, true).unwrap(); + } + + let db = Arc::new(MemoryDB::open()); + let store = ValidatorStore::new(db); + + for (i, keypair) in all_keypairs.iter().enumerate() { + store.put_public_key_by_index(i, &keypair.pk).unwrap(); + } + + let mut agg_sig = AggregateSignature::new(); + for keypair in &signing_keypairs { + let sig = Signature::new(&message, &keypair.sk); + agg_sig.add(&sig); + } + + /* + * Test using all valid parameters. + */ + let outcome = validate_attestation_signature( + &attestation_data, + &bitfield, + &agg_sig, + &attestation_indices, + &store, + ).unwrap(); + assert_eq!(outcome, Outcome::Valid); + + /* + * Add another validator to the bitfield, run validation will all other + * parameters the same and assert that it fails. + */ + bitfield.set(signing_keypairs.len() + 1, true).unwrap(); + let outcome = validate_attestation_signature( + &attestation_data, + &bitfield, + &agg_sig, + &attestation_indices, + &store, + ).unwrap(); + assert_eq!(outcome, Outcome::Invalid(Invalid::SignatureInvalid)); + } +}