Skip to content

Commit

Permalink
superstruct Attester Fork Variants
Browse files Browse the repository at this point in the history
  • Loading branch information
ethDreamer committed Apr 24, 2024
1 parent 4a48d7b commit 10a5472
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 60 deletions.
4 changes: 2 additions & 2 deletions consensus/fork_choice/src/fork_choice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,8 +1093,8 @@ where
.copied()
.collect::<BTreeSet<_>>()
};
let att1_indices = attesting_indices_set(&slashing.attestation_1);
let att2_indices = attesting_indices_set(&slashing.attestation_2);
let att1_indices = attesting_indices_set(slashing.attestation_1());
let att2_indices = attesting_indices_set(slashing.attestation_2());
self.fc_store
.extend_equivocating_indices(att1_indices.intersection(&att2_indices).copied());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,12 @@ where
) -> Result<()> {
self.sets
.sets
.reserve(block.message().body().attester_slashings().len() * 2);
.reserve(block.message().body().attester_slashings_len() * 2);

block
.message()
.body()
.attester_slashings()
.iter()
.try_for_each(|attester_slashing| {
let (set_1, set_2) = attester_slashing_signature_sets(
self.state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,16 +231,19 @@ pub fn process_proposer_slashings<E: EthSpec>(
///
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
/// an `Err` describing the invalid object or cause of failure.
pub fn process_attester_slashings<E: EthSpec>(
pub fn process_attester_slashings<'a, E: EthSpec, I>(
state: &mut BeaconState<E>,
attester_slashings: &[AttesterSlashing<E>],
attester_slashings: I,
verify_signatures: VerifySignatures,
ctxt: &mut ConsensusContext<E>,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
) -> Result<(), BlockProcessingError>
where
I: Iterator<Item = AttesterSlashingRef<'a, E>>,
{
state.build_slashings_cache()?;

for (i, attester_slashing) in attester_slashings.iter().enumerate() {
for (i, attester_slashing) in attester_slashings.enumerate() {
let slashable_indices =
verify_attester_slashing(state, attester_slashing, verify_signatures, spec)
.map_err(|e| e.into_with_index(i))?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use ssz::DecodeError;
use std::borrow::Cow;
use tree_hash::TreeHash;
use types::{
AbstractExecPayload, AggregateSignature, AttesterSlashing, BeaconBlockRef, BeaconState,
AbstractExecPayload, AggregateSignature, AttesterSlashingRef, BeaconBlockRef, BeaconState,
BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256,
InconsistentFork, IndexedAttestation, ProposerSlashing, PublicKey, PublicKeyBytes, Signature,
SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader,
Expand Down Expand Up @@ -335,7 +335,7 @@ where
pub fn attester_slashing_signature_sets<'a, E, F>(
state: &'a BeaconState<E>,
get_pubkey: F,
attester_slashing: &'a AttesterSlashing<E>,
attester_slashing: AttesterSlashingRef<'a, E>,
spec: &'a ChainSpec,
) -> Result<(SignatureSet<'a>, SignatureSet<'a>)>
where
Expand All @@ -346,15 +346,15 @@ where
indexed_attestation_signature_set(
state,
get_pubkey.clone(),
&attester_slashing.attestation_1.signature,
&attester_slashing.attestation_1,
&attester_slashing.attestation_1().signature,
&attester_slashing.attestation_1(),
spec,
)?,
indexed_attestation_signature_set(
state,
get_pubkey,
&attester_slashing.attestation_2.signature,
&attester_slashing.attestation_2,
&attester_slashing.attestation_2().signature,
&attester_slashing.attestation_2(),
spec,
)?,
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
/// Returns `Ok(indices)` with `indices` being a non-empty vec of validator indices in ascending
/// order if the `AttesterSlashing` is valid. Otherwise returns `Err(e)` with the reason for
/// invalidity.
pub fn verify_attester_slashing<E: EthSpec>(
pub fn verify_attester_slashing<'a, E: EthSpec>(
state: &BeaconState<E>,
attester_slashing: &AttesterSlashing<E>,
attester_slashing: AttesterSlashingRef<'a, E>,
verify_signatures: VerifySignatures,
spec: &ChainSpec,
) -> Result<Vec<u64>> {
let attestation_1 = &attester_slashing.attestation_1;
let attestation_2 = &attester_slashing.attestation_2;
let attestation_1 = attester_slashing.attestation_1();
let attestation_2 = attester_slashing.attestation_2();

// Spec: is_slashable_attestation_data
verify!(
Expand All @@ -43,9 +43,9 @@ pub fn verify_attester_slashing<E: EthSpec>(
/// For a given attester slashing, return the indices able to be slashed in ascending order.
///
/// Returns Ok(indices) if `indices.len() > 0`
pub fn get_slashable_indices<E: EthSpec>(
pub fn get_slashable_indices<'a, E: EthSpec>(
state: &BeaconState<E>,
attester_slashing: &AttesterSlashing<E>,
attester_slashing: AttesterSlashingRef<'a, E>,
) -> Result<Vec<u64>> {
get_slashable_indices_modular(state, attester_slashing, |_, validator| {
validator.is_slashable_at(state.current_epoch())
Expand All @@ -54,16 +54,16 @@ pub fn get_slashable_indices<E: EthSpec>(

/// Same as `gather_attester_slashing_indices` but allows the caller to specify the criteria
/// for determining whether a given validator should be considered slashable.
pub fn get_slashable_indices_modular<F, E: EthSpec>(
pub fn get_slashable_indices_modular<'a, F, E: EthSpec>(
state: &BeaconState<E>,
attester_slashing: &AttesterSlashing<E>,
attester_slashing: AttesterSlashingRef<'a, E>,
is_slashable: F,
) -> Result<Vec<u64>>
where
F: Fn(u64, &Validator) -> bool,
{
let attestation_1 = &attester_slashing.attestation_1;
let attestation_2 = &attester_slashing.attestation_2;
let attestation_1 = attester_slashing.attestation_1();
let attestation_2 = attester_slashing.attestation_2();

let attesting_indices_1 = attestation_1
.attesting_indices
Expand Down
38 changes: 35 additions & 3 deletions consensus/state_processing/src/verify_operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ use smallvec::{smallvec, SmallVec};
use ssz::{Decode, Encode};
use ssz_derive::{Decode, Encode};
use std::marker::PhantomData;
use types::{AttesterSlashingBase, AttesterSlashingElectra, AttesterSlashingRef};
use types::{
AttesterSlashing, BeaconState, ChainSpec, Epoch, EthSpec, Fork, ForkVersion, ProposerSlashing,
BeaconState, ChainSpec, Epoch, EthSpec, Fork, ForkVersion, ProposerSlashing,
SignedBlsToExecutionChange, SignedVoluntaryExit,
};

Expand Down Expand Up @@ -144,15 +145,46 @@ impl<E: EthSpec> VerifyOperation<E> for SignedVoluntaryExit {
}
}

impl<E: EthSpec> VerifyOperation<E> for AttesterSlashing<E> {
impl<E: EthSpec> VerifyOperation<E> for AttesterSlashingBase<E> {
type Error = AttesterSlashingValidationError;

fn validate(
self,
state: &BeaconState<E>,
spec: &ChainSpec,
) -> Result<SigVerifiedOp<Self, E>, Self::Error> {
verify_attester_slashing(state, &self, VerifySignatures::True, spec)?;
verify_attester_slashing(
state,
AttesterSlashingRef::Base(&self),
VerifySignatures::True,
spec,
)?;
Ok(SigVerifiedOp::new(self, state))
}

#[allow(clippy::arithmetic_side_effects)]
fn verification_epochs(&self) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]> {
smallvec![
self.attestation_1.data.target.epoch,
self.attestation_2.data.target.epoch
]
}
}

impl<E: EthSpec> VerifyOperation<E> for AttesterSlashingElectra<E> {
type Error = AttesterSlashingValidationError;

fn validate(
self,
state: &BeaconState<E>,
spec: &ChainSpec,
) -> Result<SigVerifiedOp<Self, E>, Self::Error> {
verify_attester_slashing(
state,
AttesterSlashingRef::Electra(&self),
VerifySignatures::True,
spec,
)?;
Ok(SigVerifiedOp::new(self, state))
}

Expand Down
40 changes: 25 additions & 15 deletions consensus/types/src/attester_slashing.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
use crate::{test_utils::TestRandom, EthSpec, IndexedAttestation};

use derivative::Derivative;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use superstruct::superstruct;
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;

/// Two conflicting attestations.
///
/// Spec v0.12.1
#[superstruct(
variants(Base, Electra),
variant_attributes(
derive(
Derivative,
Debug,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
arbitrary::Arbitrary
),
derivative(PartialEq, Eq, Hash(bound = "E: EthSpec")),
serde(bound = "E: EthSpec"),
arbitrary(bound = "E: EthSpec")
)
)]
#[derive(
Derivative,
Debug,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
arbitrary::Arbitrary,
Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Derivative, arbitrary::Arbitrary,
)]
#[derivative(PartialEq, Eq, Hash(bound = "E: EthSpec"))]
#[serde(bound = "E: EthSpec")]
#[serde(bound = "E: EthSpec", untagged)]
#[arbitrary(bound = "E: EthSpec")]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
pub struct AttesterSlashing<E: EthSpec> {
pub attestation_1: IndexedAttestation<E>,
pub attestation_2: IndexedAttestation<E>,
Expand Down
25 changes: 23 additions & 2 deletions consensus/types/src/beacon_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBase<E, Payload> {
signed_header_2: signed_header,
};

let attester_slashing = AttesterSlashing {
let attester_slashing = AttesterSlashingBase {
attestation_1: indexed_attestation.clone(),
attestation_2: indexed_attestation,
};
Expand Down Expand Up @@ -603,6 +603,25 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockElectra<E, Payload>
/// Return a Electra block where the block has maximum size.
pub fn full(spec: &ChainSpec) -> Self {
let base_block: BeaconBlockBase<_, Payload> = BeaconBlockBase::full(spec);
let indexed_attestation: IndexedAttestation<E> = IndexedAttestation {
attesting_indices: VariableList::new(vec![
0_u64;
E::MaxValidatorsPerCommittee::to_usize()
])
.unwrap(),
data: AttestationData::default(),
signature: AggregateSignature::empty(),
};
// TODO(electra): fix this so we calculate this size correctly
let attester_slashings = vec![
AttesterSlashingElectra {
attestation_1: indexed_attestation.clone(),
attestation_2: indexed_attestation,
};
E::max_attester_slashings_electra()
]
.into();

let bls_to_execution_changes = vec![
SignedBlsToExecutionChange {
message: BlsToExecutionChange {
Expand All @@ -626,7 +645,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockElectra<E, Payload>
state_root: Hash256::zero(),
body: BeaconBlockBodyElectra {
proposer_slashings: base_block.body.proposer_slashings,
attester_slashings: base_block.body.attester_slashings,
attester_slashings,
attestations: base_block.body.attestations,
deposits: base_block.body.deposits,
voluntary_exits: base_block.body.voluntary_exits,
Expand All @@ -641,6 +660,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockElectra<E, Payload>
graffiti: Graffiti::default(),
execution_payload: Payload::Electra::default(),
blob_kzg_commitments: VariableList::empty(),
consolidations: VariableList::empty(),
},
}
}
Expand Down Expand Up @@ -671,6 +691,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> EmptyBlock for BeaconBlockElec
execution_payload: Payload::Electra::default(),
bls_to_execution_changes: VariableList::empty(),
blob_kzg_commitments: VariableList::empty(),
consolidations: VariableList::empty(),
},
}
}
Expand Down
Loading

0 comments on commit 10a5472

Please sign in to comment.