From 76a0ba2d6c452bc9472f5eb3cbb0063bf9e2f7cf Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Sun, 3 Mar 2019 11:18:12 +1100 Subject: [PATCH] Add attester slashing support to block processing At spec v0.2.0 --- .../state_processing/src/block_processable.rs | 18 +++++- .../verify_slashable_attestation.rs | 63 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 eth2/state_processing/src/block_processable/verify_slashable_attestation.rs diff --git a/eth2/state_processing/src/block_processable.rs b/eth2/state_processing/src/block_processable.rs index e434b0c83..32327aad3 100644 --- a/eth2/state_processing/src/block_processable.rs +++ b/eth2/state_processing/src/block_processable.rs @@ -1,3 +1,4 @@ +use self::verify_slashable_attestation::verify_slashable_attestation; use crate::SlotProcessingError; use hashing::hash; use int_to_bytes::int_to_bytes32; @@ -5,6 +6,8 @@ use log::{debug, trace}; use ssz::{ssz_encode, TreeHash}; use types::*; +mod verify_slashable_attestation; + const PHASE_0_CUSTODY_BIT: bool = false; #[derive(Debug, PartialEq)] @@ -23,7 +26,9 @@ pub enum Error { BadRandaoSignature, MaxProposerSlashingsExceeded, BadProposerSlashing, + MaxAttesterSlashingsExceed, MaxAttestationsExceeded, + BadAttesterSlashing, InvalidAttestation(AttestationValidationError), NoBlockRoot, MaxDepositsExceeded, @@ -82,7 +87,7 @@ impl BlockProcessable for BeaconState { } fn per_block_processing_signature_optional( - state: &mut BeaconState, + mut state: &mut BeaconState, block: &BeaconBlock, verify_block_signature: bool, spec: &ChainSpec, @@ -205,6 +210,17 @@ fn per_block_processing_signature_optional( state.penalize_validator(proposer_slashing.proposer_index as usize, spec)?; } + /* + * Attester slashings + */ + ensure!( + block.body.attester_slashings.len() as u64 <= spec.max_attester_slashings, + Error::MaxAttesterSlashingsExceed + ); + for attester_slashing in &block.body.attester_slashings { + verify_slashable_attestation(&mut state, &attester_slashing, spec)?; + } + /* * Attestations */ diff --git a/eth2/state_processing/src/block_processable/verify_slashable_attestation.rs b/eth2/state_processing/src/block_processable/verify_slashable_attestation.rs new file mode 100644 index 000000000..dddc2eb1f --- /dev/null +++ b/eth2/state_processing/src/block_processable/verify_slashable_attestation.rs @@ -0,0 +1,63 @@ +use super::Error; +use log::error; +use types::*; + +macro_rules! ensure { + ($condition: expr, $result: expr) => { + if !$condition { + return Err($result); + } + }; +} + +pub fn verify_slashable_attestation( + state: &mut BeaconState, + attester_slashing: &AttesterSlashing, + spec: &ChainSpec, +) -> Result<(), Error> { + let slashable_attestation_1 = &attester_slashing.slashable_attestation_1; + let slashable_attestation_2 = &attester_slashing.slashable_attestation_2; + + ensure!( + slashable_attestation_1.data != slashable_attestation_2.data, + Error::BadAttesterSlashing + ); + ensure!( + slashable_attestation_1.is_double_vote(slashable_attestation_2, spec) + | slashable_attestation_1.is_surround_vote(slashable_attestation_2, spec), + Error::BadAttesterSlashing + ); + error!("this a"); + ensure!( + state.verify_slashable_attestation(&slashable_attestation_1, spec), + Error::BadAttesterSlashing + ); + error!("this b"); + ensure!( + state.verify_slashable_attestation(&slashable_attestation_2, spec), + Error::BadAttesterSlashing + ); + error!("this c"); + + let mut slashable_indices = vec![]; + for i in &slashable_attestation_1.validator_indices { + let validator = state + .validator_registry + .get(*i as usize) + .ok_or_else(|| Error::BadAttesterSlashing)?; + + if slashable_attestation_1.validator_indices.contains(&i) + & !validator.is_penalized_at(state.current_epoch(spec)) + { + slashable_indices.push(i); + } + } + + ensure!(slashable_indices.len() >= 1, Error::BadAttesterSlashing); + + for i in slashable_indices { + state.penalize_validator(*i as usize, spec)?; + } + + Ok(()) +}