From dab11c1eed548e1b607d39e200d9e9ed7c721b25 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Mon, 20 May 2019 15:06:36 +1000 Subject: [PATCH] spec v0.6.1: verify attester slashing --- .../verify_attester_slashing.rs | 69 +++++++++---------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/eth2/state_processing/src/per_block_processing/verify_attester_slashing.rs b/eth2/state_processing/src/per_block_processing/verify_attester_slashing.rs index 6e6a5a521..0fdf92be7 100644 --- a/eth2/state_processing/src/per_block_processing/verify_attester_slashing.rs +++ b/eth2/state_processing/src/per_block_processing/verify_attester_slashing.rs @@ -7,30 +7,27 @@ use types::*; /// /// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity. /// -/// Spec v0.5.1 +/// Spec v0.6.1 pub fn verify_attester_slashing( state: &BeaconState, attester_slashing: &AttesterSlashing, should_verify_indexed_attestations: bool, spec: &ChainSpec, ) -> Result<(), Error> { - let indexed_attestation_1 = &attester_slashing.indexed_attestation_1; - let indexed_attestation_2 = &attester_slashing.indexed_attestation_2; + let attestation_1 = &attester_slashing.attestation_1; + let attestation_2 = &attester_slashing.attestation_2; + // Spec: is_slashable_attestation_data verify!( - indexed_attestation_1.data != indexed_attestation_2.data, - Invalid::AttestationDataIdentical - ); - verify!( - indexed_attestation_1.is_double_vote(indexed_attestation_2, spec) - | indexed_attestation_1.is_surround_vote(indexed_attestation_2, spec), + attestation_1.is_double_vote(attestation_2, spec) + || attestation_1.is_surround_vote(attestation_2, spec), Invalid::NotSlashable ); if should_verify_indexed_attestations { - verify_indexed_attestation(state, &indexed_attestation_1, spec) + verify_indexed_attestation(state, &attestation_1, spec) .map_err(|e| Error::Invalid(Invalid::IndexedAttestation1Invalid(e.into())))?; - verify_indexed_attestation(state, &indexed_attestation_2, spec) + verify_indexed_attestation(state, &attestation_2, spec) .map_err(|e| Error::Invalid(Invalid::IndexedAttestation2Invalid(e.into())))?; } @@ -41,8 +38,8 @@ pub fn verify_attester_slashing( /// /// Returns Ok(indices) if `indices.len() > 0`. /// -/// Spec v0.5.1 -pub fn gather_attester_slashing_indices( +/// Spec v0.6.1 +pub fn get_slashable_indices( state: &BeaconState, attester_slashing: &AttesterSlashing, spec: &ChainSpec, @@ -50,47 +47,47 @@ pub fn gather_attester_slashing_indices( gather_attester_slashing_indices_modular( state, attester_slashing, - |_, validator| validator.slashed, + |_, validator| validator.is_slashable_at(state.current_epoch()), spec, ) } /// Same as `gather_attester_slashing_indices` but allows the caller to specify the criteria -/// for determining whether a given validator should be considered slashed. -pub fn gather_attester_slashing_indices_modular( +/// for determining whether a given validator should be considered slashable. +pub fn get_slashable_indices_modular( state: &BeaconState, attester_slashing: &AttesterSlashing, - is_slashed: F, + is_slashable: F, spec: &ChainSpec, ) -> Result, Error> where F: Fn(u64, &Validator) -> bool, { - let indexed_attestation_1 = &attester_slashing.indexed_attestation_1; - let indexed_attestation_2 = &attester_slashing.indexed_attestation_2; + let attestation_1 = &attester_slashing.attestation_1; + let attestation_2 = &attester_slashing.attestation_2; - let mut indexed_indices = Vec::with_capacity(spec.max_indices_per_indexed_vote); - for i in &indexed_attestation_1.validator_indices { + let mut attesting_indices_1 = HashSet::new(); + attesting_indices_1.extend(attestation_1.custody_bit_0_indices.clone()); + attesting_indices_1.extend(attestation_1.custody_bit_1_indices.clone()); + + let mut attesting_indices_2 = HashSet::new(); + attesting_indices_2.extend(attestation_2.custody_bit_0_indices.clone()); + attesting_indices_2.extend(attestation_2.custody_bit_1_indices.clone()); + + let mut slashable_indices = vec![]; + + for index in &attesting_indices_1 & &attesting_indices_2 { let validator = state .validator_registry - .get(*i as usize) - .ok_or_else(|| Error::Invalid(Invalid::UnknownValidator(*i)))?; + .get(index as usize) + .ok_or_else(|| Error::Invalid(Invalid::UnknownValidator(index)))?; - if indexed_attestation_2.validator_indices.contains(&i) & !is_slashed(*i, validator) { - // TODO: verify that we should reject any indexed attestation which includes a - // withdrawn validator. PH has asked the question on gitter, awaiting response. - verify!( - validator.withdrawable_epoch > state.slot.epoch(spec.slots_per_epoch), - Invalid::ValidatorAlreadyWithdrawn(*i) - ); - - indexed_indices.push(*i); + if is_slashable(index, validator) { + slashable_indices.push(index); } } - verify!(!indexed_indices.is_empty(), Invalid::NoSlashableIndices); + verify!(!slashable_indices.is_empty(), Invalid::NoSlashableIndices); - indexed_indices.shrink_to_fit(); - - Ok(indexed_indices) + Ok(slashable_indices) }