Fix failing attestation tests and misc electra attestation cleanup (#5810)

* - get attestation related beacon chain tests to pass
- observed attestations are now keyed off of data + committee index
- rename op pool attestationref to compactattestationref
- remove unwraps in agg pool and use options instead
- cherry pick some changes from ef-tests-electra

* cargo fmt

* fix failing test

* Revert dockerfile changes

* make committee_index return option

* function args shouldnt be a ref to attestation ref

* fmt

* fix dup imports

---------

Co-authored-by: realbigsean <seananderson33@GMAIL.com>
This commit is contained in:
Eitan Seri-Levi
2024-05-30 17:51:34 +02:00
committed by GitHub
parent 75432e1135
commit e340998241
28 changed files with 765 additions and 292 deletions

View File

@@ -21,6 +21,7 @@ pub enum Error {
SszTypesError(ssz_types::Error),
AlreadySigned(usize),
SubnetCountIsZero(ArithError),
IncorrectStateVariant,
}
#[superstruct(
@@ -42,7 +43,9 @@ pub enum Error {
serde(bound = "E: EthSpec", deny_unknown_fields),
arbitrary(bound = "E: EthSpec"),
),
ref_attributes(derive(TreeHash), tree_hash(enum_behaviour = "transparent"))
ref_attributes(derive(TreeHash), tree_hash(enum_behaviour = "transparent")),
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant")
)]
#[derive(
Debug,
@@ -74,14 +77,14 @@ pub struct Attestation<E: EthSpec> {
// TODO(electra): think about how to handle fork variants here
impl<E: EthSpec> TestRandom for Attestation<E> {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let aggregation_bits: BitList<E::MaxValidatorsPerCommittee> = BitList::random_for_test(rng);
// let committee_bits: BitList<E::MaxCommitteesPerSlot> = BitList::random_for_test(rng);
let aggregation_bits = BitList::random_for_test(rng);
let data = AttestationData::random_for_test(rng);
let signature = AggregateSignature::random_for_test(rng);
let committee_bits = BitVector::random_for_test(rng);
Self::Base(AttestationBase {
Self::Electra(AttestationElectra {
aggregation_bits,
// committee_bits,
committee_bits,
data,
signature,
})
@@ -166,9 +169,9 @@ impl<E: EthSpec> Attestation<E> {
}
}
pub fn committee_index(&self) -> u64 {
pub fn committee_index(&self) -> Option<u64> {
match self {
Attestation::Base(att) => att.data.index,
Attestation::Base(att) => Some(att.data.index),
Attestation::Electra(att) => att.committee_index(),
}
}
@@ -217,12 +220,31 @@ impl<'a, E: EthSpec> AttestationRef<'a, E> {
}
}
pub fn committee_index(&self) -> u64 {
pub fn committee_index(&self) -> Option<u64> {
match self {
AttestationRef::Base(att) => att.data.index,
AttestationRef::Base(att) => Some(att.data.index),
AttestationRef::Electra(att) => att.committee_index(),
}
}
pub fn set_aggregation_bits(&self) -> Vec<usize> {
match self {
Self::Base(att) => att
.aggregation_bits
.iter()
.enumerate()
.filter(|(_i, bit)| *bit)
.map(|(i, _bit)| i)
.collect::<Vec<_>>(),
Self::Electra(att) => att
.aggregation_bits
.iter()
.enumerate()
.filter(|(_i, bit)| *bit)
.map(|(i, _bit)| i)
.collect::<Vec<_>>(),
}
}
}
impl<E: EthSpec> AttestationElectra<E> {
@@ -236,8 +258,8 @@ impl<E: EthSpec> AttestationElectra<E> {
.is_zero()
}
pub fn committee_index(&self) -> u64 {
*self.get_committee_indices().first().unwrap_or(&0u64)
pub fn committee_index(&self) -> Option<u64> {
self.get_committee_indices().first().cloned()
}
pub fn get_committee_indices(&self) -> Vec<u64> {

View File

@@ -161,6 +161,12 @@ pub enum Error {
MerkleTreeError(merkle_proof::MerkleTreeError),
NoCommitteeFound(CommitteeIndex),
InvalidCommitteeIndex(CommitteeIndex),
InvalidSelectionProof {
aggregator_index: u64,
},
AggregatorNotInCommittee {
aggregator_index: u64,
},
}
/// Control whether an epoch-indexed field can be indexed at the next epoch or not.

View File

@@ -206,14 +206,17 @@ impl<E: EthSpec> Decode for IndexedAttestation<E> {
}
}
// TODO(electra): think about how to handle fork variants here
impl<E: EthSpec> TestRandom for IndexedAttestation<E> {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let attesting_indices = VariableList::random_for_test(rng);
// let committee_bits: BitList<E::MaxCommitteesPerSlot> = BitList::random_for_test(rng);
let data = AttestationData::random_for_test(rng);
let signature = AggregateSignature::random_for_test(rng);
Self::Base(IndexedAttestationBase {
attesting_indices,
// committee_bits,
data,
signature,
})

View File

@@ -74,7 +74,6 @@ impl<E: EthSpec> SignedAggregateAndProof<E> {
genesis_validators_root,
spec,
);
let target_epoch = message.aggregate().data().slot.epoch(E::slots_per_epoch());
let domain = spec.get_domain(
target_epoch,

View File

@@ -40,13 +40,15 @@ impl SubnetId {
/// Compute the subnet for an attestation where each slot in the
/// attestation epoch contains `committee_count_per_slot` committees.
pub fn compute_subnet_for_attestation<E: EthSpec>(
attestation: &AttestationRef<E>,
attestation: AttestationRef<E>,
committee_count_per_slot: u64,
spec: &ChainSpec,
) -> Result<SubnetId, ArithError> {
let committee_index = attestation.committee_index().ok_or(ArithError::Overflow)?;
Self::compute_subnet::<E>(
attestation.data().slot,
attestation.committee_index(),
committee_index,
committee_count_per_slot,
spec,
)