Skip to content

Commit 19a9479

Browse files
authored
Superstruct AggregateAndProof (#5715)
* Upgrade `superstruct` to `0.8.0` * superstruct `AggregateAndProof`
1 parent 7c6526d commit 19a9479

File tree

28 files changed

+408
-223
lines changed

28 files changed

+408
-223
lines changed

Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ smallvec = "1.11.2"
162162
snap = "1"
163163
ssz_types = "0.6"
164164
strum = { version = "0.24", features = ["derive"] }
165-
superstruct = "0.7"
165+
superstruct = { git = "https://github.com/sigp/superstruct", rev = "45eecbfb9708c9fe11dbb6a6a5bd8d618f02269e" }
166166
syn = "1"
167167
sysinfo = "0.26"
168168
tempfile = "3"

beacon_node/beacon_chain/src/attestation_verification.rs

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ use std::borrow::Cow;
5555
use strum::AsRefStr;
5656
use tree_hash::TreeHash;
5757
use types::{
58-
Attestation, BeaconCommittee, ChainSpec, CommitteeIndex, Epoch, EthSpec, ForkName, Hash256,
59-
IndexedAttestation, SelectionProof, SignedAggregateAndProof, Slot, SubnetId,
58+
Attestation, AttestationRef, BeaconCommittee, ChainSpec, CommitteeIndex, Epoch, EthSpec,
59+
ForkName, Hash256, IndexedAttestation, SelectionProof, SignedAggregateAndProof, Slot, SubnetId,
6060
};
6161

6262
pub use batch::{batch_verify_aggregated_attestations, batch_verify_unaggregated_attestations};
@@ -274,7 +274,7 @@ struct IndexedAggregatedAttestation<'a, T: BeaconChainTypes> {
274274
///
275275
/// These attestations have *not* undergone signature verification.
276276
struct IndexedUnaggregatedAttestation<'a, T: BeaconChainTypes> {
277-
attestation: &'a Attestation<T::EthSpec>,
277+
attestation: AttestationRef<'a, T::EthSpec>,
278278
indexed_attestation: IndexedAttestation<T::EthSpec>,
279279
subnet_id: SubnetId,
280280
validator_index: u64,
@@ -295,7 +295,7 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
295295

296296
/// Wraps an `Attestation` that has been fully verified for propagation on the gossip network.
297297
pub struct VerifiedUnaggregatedAttestation<'a, T: BeaconChainTypes> {
298-
attestation: &'a Attestation<T::EthSpec>,
298+
attestation: AttestationRef<'a, T::EthSpec>,
299299
indexed_attestation: IndexedAttestation<T::EthSpec>,
300300
subnet_id: SubnetId,
301301
}
@@ -322,20 +322,20 @@ impl<'a, T: BeaconChainTypes> Clone for IndexedUnaggregatedAttestation<'a, T> {
322322
/// A helper trait implemented on wrapper types that can be progressed to a state where they can be
323323
/// verified for application to fork choice.
324324
pub trait VerifiedAttestation<T: BeaconChainTypes>: Sized {
325-
fn attestation(&self) -> &Attestation<T::EthSpec>;
325+
fn attestation(&self) -> AttestationRef<T::EthSpec>;
326326

327327
fn indexed_attestation(&self) -> &IndexedAttestation<T::EthSpec>;
328328

329329
// Inefficient default implementation. This is overridden for gossip verified attestations.
330330
fn into_attestation_and_indices(self) -> (Attestation<T::EthSpec>, Vec<u64>) {
331-
let attestation = self.attestation().clone();
331+
let attestation = self.attestation().clone_as_attestation();
332332
let attesting_indices = self.indexed_attestation().attesting_indices_to_vec();
333333
(attestation, attesting_indices)
334334
}
335335
}
336336

337337
impl<'a, T: BeaconChainTypes> VerifiedAttestation<T> for VerifiedAggregatedAttestation<'a, T> {
338-
fn attestation(&self) -> &Attestation<T::EthSpec> {
338+
fn attestation(&self) -> AttestationRef<T::EthSpec> {
339339
self.attestation()
340340
}
341341

@@ -345,7 +345,7 @@ impl<'a, T: BeaconChainTypes> VerifiedAttestation<T> for VerifiedAggregatedAttes
345345
}
346346

347347
impl<'a, T: BeaconChainTypes> VerifiedAttestation<T> for VerifiedUnaggregatedAttestation<'a, T> {
348-
fn attestation(&self) -> &Attestation<T::EthSpec> {
348+
fn attestation(&self) -> AttestationRef<T::EthSpec> {
349349
self.attestation
350350
}
351351

@@ -357,7 +357,7 @@ impl<'a, T: BeaconChainTypes> VerifiedAttestation<T> for VerifiedUnaggregatedAtt
357357
/// Information about invalid attestations which might still be slashable despite being invalid.
358358
pub enum AttestationSlashInfo<'a, T: BeaconChainTypes, TErr> {
359359
/// The attestation is invalid, but its signature wasn't checked.
360-
SignatureNotChecked(&'a Attestation<T::EthSpec>, TErr),
360+
SignatureNotChecked(AttestationRef<'a, T::EthSpec>, TErr),
361361
/// As for `SignatureNotChecked`, but we know the `IndexedAttestation`.
362362
SignatureNotCheckedIndexed(IndexedAttestation<T::EthSpec>, TErr),
363363
/// The attestation's signature is invalid, so it will never be slashable.
@@ -446,7 +446,7 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
446446
signed_aggregate: &SignedAggregateAndProof<T::EthSpec>,
447447
chain: &BeaconChain<T>,
448448
) -> Result<Hash256, Error> {
449-
let attestation = &signed_aggregate.message.aggregate;
449+
let attestation = signed_aggregate.message().aggregate();
450450

451451
// Ensure attestation is within the last ATTESTATION_PROPAGATION_SLOT_RANGE slots (within a
452452
// MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance).
@@ -471,14 +471,14 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
471471
if chain
472472
.observed_attestations
473473
.write()
474-
.is_known_subset(attestation.to_ref(), attestation_data_root)
474+
.is_known_subset(attestation, attestation_data_root)
475475
.map_err(|e| Error::BeaconChainError(e.into()))?
476476
{
477477
metrics::inc_counter(&metrics::AGGREGATED_ATTESTATION_SUBSETS);
478478
return Err(Error::AttestationSupersetKnown(attestation_data_root));
479479
}
480480

481-
let aggregator_index = signed_aggregate.message.aggregator_index;
481+
let aggregator_index = signed_aggregate.message().aggregator_index();
482482

483483
// Ensure there has been no other observed aggregate for the given `aggregator_index`.
484484
//
@@ -532,11 +532,16 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
532532
) -> Result<Self, AttestationSlashInfo<'a, T, Error>> {
533533
use AttestationSlashInfo::*;
534534

535-
let attestation = &signed_aggregate.message.aggregate;
536-
let aggregator_index = signed_aggregate.message.aggregator_index;
535+
let attestation = signed_aggregate.message().aggregate();
536+
let aggregator_index = signed_aggregate.message().aggregator_index();
537537
let attestation_data_root = match Self::verify_early_checks(signed_aggregate, chain) {
538538
Ok(root) => root,
539-
Err(e) => return Err(SignatureNotChecked(&signed_aggregate.message.aggregate, e)),
539+
Err(e) => {
540+
return Err(SignatureNotChecked(
541+
signed_aggregate.message().aggregate(),
542+
e,
543+
))
544+
}
540545
};
541546

542547
let get_indexed_attestation_with_committee =
@@ -545,7 +550,7 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
545550
//
546551
// Future optimizations should remove this clone.
547552
let selection_proof =
548-
SelectionProof::from(signed_aggregate.message.selection_proof.clone());
553+
SelectionProof::from(signed_aggregate.message().selection_proof().clone());
549554

550555
if !selection_proof
551556
.is_aggregator(committee.committee.len(), &chain.spec)
@@ -559,7 +564,7 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
559564
return Err(Error::AggregatorNotInCommittee { aggregator_index });
560565
}
561566

562-
get_indexed_attestation(committee.committee, attestation.to_ref())
567+
get_indexed_attestation(committee.committee, attestation)
563568
.map_err(|e| BeaconChainError::from(e).into())
564569
};
565570

@@ -569,7 +574,12 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
569574
get_indexed_attestation_with_committee,
570575
) {
571576
Ok(indexed_attestation) => indexed_attestation,
572-
Err(e) => return Err(SignatureNotChecked(&signed_aggregate.message.aggregate, e)),
577+
Err(e) => {
578+
return Err(SignatureNotChecked(
579+
signed_aggregate.message().aggregate(),
580+
e,
581+
))
582+
}
573583
};
574584

575585
Ok(IndexedAggregatedAttestation {
@@ -587,8 +597,8 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
587597
attestation_data_root: Hash256,
588598
chain: &BeaconChain<T>,
589599
) -> Result<(), Error> {
590-
let attestation = &signed_aggregate.message.aggregate;
591-
let aggregator_index = signed_aggregate.message.aggregator_index;
600+
let attestation = signed_aggregate.message().aggregate();
601+
let aggregator_index = signed_aggregate.message().aggregator_index();
592602

593603
// Observe the valid attestation so we do not re-process it.
594604
//
@@ -597,7 +607,7 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
597607
if let ObserveOutcome::Subset = chain
598608
.observed_attestations
599609
.write()
600-
.observe_item(attestation.to_ref(), Some(attestation_data_root))
610+
.observe_item(attestation, Some(attestation_data_root))
601611
.map_err(|e| Error::BeaconChainError(e.into()))?
602612
{
603613
metrics::inc_counter(&metrics::AGGREGATED_ATTESTATION_SUBSETS);
@@ -696,8 +706,8 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
696706
}
697707

698708
/// Returns the underlying `attestation` for the `signed_aggregate`.
699-
pub fn attestation(&self) -> &Attestation<T::EthSpec> {
700-
&self.signed_aggregate.message.aggregate
709+
pub fn attestation(&self) -> AttestationRef<'a, T::EthSpec> {
710+
self.signed_aggregate.message().aggregate()
701711
}
702712

703713
/// Returns the underlying `signed_aggregate`.
@@ -709,7 +719,7 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
709719
impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
710720
/// Run the checks that happen before an indexed attestation is constructed.
711721
pub fn verify_early_checks(
712-
attestation: &Attestation<T::EthSpec>,
722+
attestation: AttestationRef<T::EthSpec>,
713723
chain: &BeaconChain<T>,
714724
) -> Result<(), Error> {
715725
let attestation_epoch = attestation.data().slot.epoch(T::EthSpec::slots_per_epoch());
@@ -750,7 +760,7 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
750760

751761
/// Run the checks that apply to the indexed attestation before the signature is checked.
752762
pub fn verify_middle_checks(
753-
attestation: &Attestation<T::EthSpec>,
763+
attestation: AttestationRef<T::EthSpec>,
754764
indexed_attestation: &IndexedAttestation<T::EthSpec>,
755765
committees_per_slot: u64,
756766
subnet_id: Option<SubnetId>,
@@ -806,7 +816,7 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
806816
subnet_id: Option<SubnetId>,
807817
chain: &BeaconChain<T>,
808818
) -> Result<Self, Error> {
809-
Self::verify_slashable(attestation, subnet_id, chain)
819+
Self::verify_slashable(attestation.to_ref(), subnet_id, chain)
810820
.map(|verified_unaggregated| {
811821
if let Some(slasher) = chain.slasher.as_ref() {
812822
slasher.accept_attestation(verified_unaggregated.indexed_attestation.clone());
@@ -818,7 +828,7 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
818828

819829
/// Verify the attestation, producing extra information about whether it might be slashable.
820830
pub fn verify_slashable(
821-
attestation: &'a Attestation<T::EthSpec>,
831+
attestation: AttestationRef<'a, T::EthSpec>,
822832
subnet_id: Option<SubnetId>,
823833
chain: &BeaconChain<T>,
824834
) -> Result<Self, AttestationSlashInfo<'a, T, Error>> {
@@ -867,7 +877,7 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
867877
impl<'a, T: BeaconChainTypes> VerifiedUnaggregatedAttestation<'a, T> {
868878
/// Run the checks that apply after the signature has been checked.
869879
fn verify_late_checks(
870-
attestation: &Attestation<T::EthSpec>,
880+
attestation: AttestationRef<T::EthSpec>,
871881
validator_index: u64,
872882
chain: &BeaconChain<T>,
873883
) -> Result<(), Error> {
@@ -961,7 +971,7 @@ impl<'a, T: BeaconChainTypes> VerifiedUnaggregatedAttestation<'a, T> {
961971
}
962972

963973
/// Returns the wrapped `attestation`.
964-
pub fn attestation(&self) -> &Attestation<T::EthSpec> {
974+
pub fn attestation(&self) -> AttestationRef<T::EthSpec> {
965975
self.attestation
966976
}
967977

@@ -991,7 +1001,7 @@ impl<'a, T: BeaconChainTypes> VerifiedUnaggregatedAttestation<'a, T> {
9911001
/// already finalized.
9921002
fn verify_head_block_is_known<T: BeaconChainTypes>(
9931003
chain: &BeaconChain<T>,
994-
attestation: &Attestation<T::EthSpec>,
1004+
attestation: AttestationRef<T::EthSpec>,
9951005
max_skip_slots: Option<u64>,
9961006
) -> Result<ProtoBlock, Error> {
9971007
let block_opt = chain
@@ -1039,7 +1049,7 @@ fn verify_head_block_is_known<T: BeaconChainTypes>(
10391049
/// Accounts for `MAXIMUM_GOSSIP_CLOCK_DISPARITY`.
10401050
pub fn verify_propagation_slot_range<S: SlotClock, E: EthSpec>(
10411051
slot_clock: &S,
1042-
attestation: &Attestation<E>,
1052+
attestation: AttestationRef<E>,
10431053
spec: &ChainSpec,
10441054
) -> Result<(), Error> {
10451055
let attestation_slot = attestation.data().slot;
@@ -1124,7 +1134,7 @@ pub fn verify_attestation_signature<T: BeaconChainTypes>(
11241134
/// `attestation.data.beacon_block_root`.
11251135
pub fn verify_attestation_target_root<E: EthSpec>(
11261136
head_block: &ProtoBlock,
1127-
attestation: &Attestation<E>,
1137+
attestation: AttestationRef<E>,
11281138
) -> Result<(), Error> {
11291139
// Check the attestation target root.
11301140
let head_block_epoch = head_block.slot.epoch(E::slots_per_epoch());
@@ -1193,7 +1203,7 @@ pub fn verify_signed_aggregate_signatures<T: BeaconChainTypes>(
11931203
.try_read_for(VALIDATOR_PUBKEY_CACHE_LOCK_TIMEOUT)
11941204
.ok_or(BeaconChainError::ValidatorPubkeyCacheLockTimeout)?;
11951205

1196-
let aggregator_index = signed_aggregate.message.aggregator_index;
1206+
let aggregator_index = signed_aggregate.message().aggregator_index();
11971207
if aggregator_index >= pubkey_cache.len() as u64 {
11981208
return Err(Error::AggregatorPubkeyUnknown(aggregator_index));
11991209
}
@@ -1240,10 +1250,10 @@ type CommitteesPerSlot = u64;
12401250
/// public keys cached in the `chain`.
12411251
pub fn obtain_indexed_attestation_and_committees_per_slot<T: BeaconChainTypes>(
12421252
chain: &BeaconChain<T>,
1243-
attestation: &Attestation<T::EthSpec>,
1253+
attestation: AttestationRef<T::EthSpec>,
12441254
) -> Result<(IndexedAttestation<T::EthSpec>, CommitteesPerSlot), Error> {
12451255
map_attestation_committee(chain, attestation, |(committee, committees_per_slot)| {
1246-
get_indexed_attestation(committee.committee, attestation.to_ref())
1256+
get_indexed_attestation(committee.committee, attestation)
12471257
.map(|attestation| (attestation, committees_per_slot))
12481258
.map_err(Error::Invalid)
12491259
})
@@ -1260,7 +1270,7 @@ pub fn obtain_indexed_attestation_and_committees_per_slot<T: BeaconChainTypes>(
12601270
/// from disk and then update the `shuffling_cache`.
12611271
fn map_attestation_committee<T, F, R>(
12621272
chain: &BeaconChain<T>,
1263-
attestation: &Attestation<T::EthSpec>,
1273+
attestation: AttestationRef<T::EthSpec>,
12641274
map_fn: F,
12651275
) -> Result<R, Error>
12661276
where

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,8 +1966,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
19661966
// This method is called for API and gossip attestations, so this covers all unaggregated attestation events
19671967
if let Some(event_handler) = self.event_handler.as_ref() {
19681968
if event_handler.has_attestation_subscribers() {
1969-
event_handler
1970-
.register(EventKind::Attestation(Box::new(v.attestation().clone())));
1969+
event_handler.register(EventKind::Attestation(Box::new(
1970+
v.attestation().clone_as_attestation(),
1971+
)));
19711972
}
19721973
}
19731974
metrics::inc_counter(&metrics::UNAGGREGATED_ATTESTATION_PROCESSING_SUCCESSES);
@@ -2003,8 +2004,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
20032004
// This method is called for API and gossip attestations, so this covers all aggregated attestation events
20042005
if let Some(event_handler) = self.event_handler.as_ref() {
20052006
if event_handler.has_attestation_subscribers() {
2006-
event_handler
2007-
.register(EventKind::Attestation(Box::new(v.attestation().clone())));
2007+
event_handler.register(EventKind::Attestation(Box::new(
2008+
v.attestation().clone_as_attestation(),
2009+
)));
20082010
}
20092011
}
20102012
metrics::inc_counter(&metrics::AGGREGATED_ATTESTATION_PROCESSING_SUCCESSES);

beacon_node/beacon_chain/src/bellatrix_readiness.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
244244
});
245245
}
246246

247-
if let Some(&expected) = expected_withdrawals_root {
248-
if let Some(&got) = got_withdrawals_root {
247+
if let Some(expected) = expected_withdrawals_root {
248+
if let Some(got) = got_withdrawals_root {
249249
if got != expected {
250250
return Ok(GenesisExecutionPayloadStatus::WithdrawalsRootMismatch {
251251
got,

0 commit comments

Comments
 (0)