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

@@ -1169,7 +1169,7 @@ where
};
let subnet_id = SubnetId::compute_subnet_for_attestation::<E>(
&attestation.to_ref(),
attestation.to_ref(),
committee_count,
&self.chain.spec,
)
@@ -1343,7 +1343,10 @@ where
// If there are any attestations in this committee, create an aggregate.
if let Some((attestation, _)) = committee_attestations.first() {
let bc = state
.get_beacon_committee(attestation.data().slot, attestation.data().index)
.get_beacon_committee(
attestation.data().slot,
attestation.committee_index().unwrap(),
)
.unwrap();
// Find an aggregator if one exists. Return `None` if there are no
@@ -1370,21 +1373,42 @@ where
})
.copied()?;
let fork_name = self.spec.fork_name_at_slot::<E>(slot);
let aggregate = if fork_name >= ForkName::Electra {
self.chain
.get_aggregated_attestation_electra(
slot,
&attestation.data().tree_hash_root(),
bc.index,
)
.unwrap()
.unwrap_or_else(|| {
committee_attestations.iter().skip(1).fold(
attestation.clone(),
|mut agg, (att, _)| {
agg.aggregate(att.to_ref());
agg
},
)
})
} else {
self.chain
.get_aggregated_attestation_base(attestation.data())
.unwrap()
.unwrap_or_else(|| {
committee_attestations.iter().skip(1).fold(
attestation.clone(),
|mut agg, (att, _)| {
agg.aggregate(att.to_ref());
agg
},
)
})
};
// If the chain is able to produce an aggregate, use that. Otherwise, build an
// aggregate locally.
let aggregate = self
.chain
.get_aggregated_attestation_base(attestation.data())
.unwrap()
.unwrap_or_else(|| {
committee_attestations.iter().skip(1).fold(
attestation.clone(),
|mut agg, (att, _)| {
agg.aggregate(att.to_ref());
agg
},
)
});
let signed_aggregate = SignedAggregateAndProof::from_aggregate(
aggregator_index as u64,
@@ -1514,54 +1538,101 @@ where
) -> AttesterSlashing<E> {
let fork = self.chain.canonical_head.cached_head().head_fork();
// TODO(electra): consider making this test fork-agnostic
let mut attestation_1 = IndexedAttestationBase {
attesting_indices: VariableList::new(validator_indices).unwrap(),
data: AttestationData {
slot: Slot::new(0),
index: 0,
beacon_block_root: Hash256::zero(),
target: Checkpoint {
root: Hash256::zero(),
epoch: target1.unwrap_or(fork.epoch),
let fork_name = self.spec.fork_name_at_slot::<E>(Slot::new(0));
let mut attestation_1 = if fork_name >= ForkName::Electra {
IndexedAttestation::Electra(IndexedAttestationElectra {
attesting_indices: VariableList::new(validator_indices).unwrap(),
data: AttestationData {
slot: Slot::new(0),
index: 0,
beacon_block_root: Hash256::zero(),
target: Checkpoint {
root: Hash256::zero(),
epoch: target1.unwrap_or(fork.epoch),
},
source: Checkpoint {
root: Hash256::zero(),
epoch: source1.unwrap_or(Epoch::new(0)),
},
},
source: Checkpoint {
root: Hash256::zero(),
epoch: source1.unwrap_or(Epoch::new(0)),
signature: AggregateSignature::infinity(),
})
} else {
IndexedAttestation::Base(IndexedAttestationBase {
attesting_indices: VariableList::new(validator_indices).unwrap(),
data: AttestationData {
slot: Slot::new(0),
index: 0,
beacon_block_root: Hash256::zero(),
target: Checkpoint {
root: Hash256::zero(),
epoch: target1.unwrap_or(fork.epoch),
},
source: Checkpoint {
root: Hash256::zero(),
epoch: source1.unwrap_or(Epoch::new(0)),
},
},
},
signature: AggregateSignature::infinity(),
signature: AggregateSignature::infinity(),
})
};
let mut attestation_2 = attestation_1.clone();
attestation_2.data.index += 1;
attestation_2.data.source.epoch = source2.unwrap_or(Epoch::new(0));
attestation_2.data.target.epoch = target2.unwrap_or(fork.epoch);
attestation_2.data_mut().index += 1;
attestation_2.data_mut().source.epoch = source2.unwrap_or(Epoch::new(0));
attestation_2.data_mut().target.epoch = target2.unwrap_or(fork.epoch);
for attestation in &mut [&mut attestation_1, &mut attestation_2] {
// TODO(electra) we could explore iter mut here
for i in attestation.attesting_indices.iter() {
let sk = &self.validator_keypairs[*i as usize].sk;
match attestation {
IndexedAttestation::Base(attestation) => {
for i in attestation.attesting_indices.iter() {
let sk = &self.validator_keypairs[*i as usize].sk;
let genesis_validators_root = self.chain.genesis_validators_root;
let genesis_validators_root = self.chain.genesis_validators_root;
let domain = self.chain.spec.get_domain(
attestation.data.target.epoch,
Domain::BeaconAttester,
&fork,
genesis_validators_root,
);
let message = attestation.data.signing_root(domain);
let domain = self.chain.spec.get_domain(
attestation.data.target.epoch,
Domain::BeaconAttester,
&fork,
genesis_validators_root,
);
let message = attestation.data.signing_root(domain);
attestation.signature.add_assign(&sk.sign(message));
attestation.signature.add_assign(&sk.sign(message));
}
}
IndexedAttestation::Electra(attestation) => {
for i in attestation.attesting_indices.iter() {
let sk = &self.validator_keypairs[*i as usize].sk;
let genesis_validators_root = self.chain.genesis_validators_root;
let domain = self.chain.spec.get_domain(
attestation.data.target.epoch,
Domain::BeaconAttester,
&fork,
genesis_validators_root,
);
let message = attestation.data.signing_root(domain);
attestation.signature.add_assign(&sk.sign(message));
}
}
}
}
// TODO(electra): fix this test
AttesterSlashing::Base(AttesterSlashingBase {
attestation_1,
attestation_2,
})
if fork_name >= ForkName::Electra {
AttesterSlashing::Electra(AttesterSlashingElectra {
attestation_1: attestation_1.as_electra().unwrap().clone(),
attestation_2: attestation_2.as_electra().unwrap().clone(),
})
} else {
AttesterSlashing::Base(AttesterSlashingBase {
attestation_1: attestation_1.as_base().unwrap().clone(),
attestation_2: attestation_2.as_base().unwrap().clone(),
})
}
}
pub fn make_attester_slashing_different_indices(
@@ -1569,6 +1640,8 @@ where
validator_indices_1: Vec<u64>,
validator_indices_2: Vec<u64>,
) -> AttesterSlashing<E> {
let fork_name = self.spec.fork_name_at_slot::<E>(Slot::new(0));
let data = AttestationData {
slot: Slot::new(0),
index: 0,
@@ -1583,45 +1656,95 @@ where
},
};
// TODO(electra): make this test fork-agnostic
let mut attestation_1 = IndexedAttestationBase {
attesting_indices: VariableList::new(validator_indices_1).unwrap(),
data: data.clone(),
signature: AggregateSignature::infinity(),
let (mut attestation_1, mut attestation_2) = if fork_name >= ForkName::Electra {
let attestation_1 = IndexedAttestationElectra {
attesting_indices: VariableList::new(validator_indices_1).unwrap(),
data: data.clone(),
signature: AggregateSignature::infinity(),
};
let attestation_2 = IndexedAttestationElectra {
attesting_indices: VariableList::new(validator_indices_2).unwrap(),
data,
signature: AggregateSignature::infinity(),
};
(
IndexedAttestation::Electra(attestation_1),
IndexedAttestation::Electra(attestation_2),
)
} else {
let attestation_1 = IndexedAttestationBase {
attesting_indices: VariableList::new(validator_indices_1).unwrap(),
data: data.clone(),
signature: AggregateSignature::infinity(),
};
let attestation_2 = IndexedAttestationBase {
attesting_indices: VariableList::new(validator_indices_2).unwrap(),
data,
signature: AggregateSignature::infinity(),
};
(
IndexedAttestation::Base(attestation_1),
IndexedAttestation::Base(attestation_2),
)
};
let mut attestation_2 = IndexedAttestationBase {
attesting_indices: VariableList::new(validator_indices_2).unwrap(),
data,
signature: AggregateSignature::infinity(),
};
attestation_2.data.index += 1;
attestation_2.data_mut().index += 1;
let fork = self.chain.canonical_head.cached_head().head_fork();
for attestation in &mut [&mut attestation_1, &mut attestation_2] {
for i in attestation.attesting_indices.iter() {
let sk = &self.validator_keypairs[*i as usize].sk;
match attestation {
IndexedAttestation::Base(attestation) => {
for i in attestation.attesting_indices.iter() {
let sk = &self.validator_keypairs[*i as usize].sk;
let genesis_validators_root = self.chain.genesis_validators_root;
let genesis_validators_root = self.chain.genesis_validators_root;
let domain = self.chain.spec.get_domain(
attestation.data.target.epoch,
Domain::BeaconAttester,
&fork,
genesis_validators_root,
);
let message = attestation.data.signing_root(domain);
let domain = self.chain.spec.get_domain(
attestation.data.target.epoch,
Domain::BeaconAttester,
&fork,
genesis_validators_root,
);
let message = attestation.data.signing_root(domain);
attestation.signature.add_assign(&sk.sign(message));
attestation.signature.add_assign(&sk.sign(message));
}
}
IndexedAttestation::Electra(attestation) => {
for i in attestation.attesting_indices.iter() {
let sk = &self.validator_keypairs[*i as usize].sk;
let genesis_validators_root = self.chain.genesis_validators_root;
let domain = self.chain.spec.get_domain(
attestation.data.target.epoch,
Domain::BeaconAttester,
&fork,
genesis_validators_root,
);
let message = attestation.data.signing_root(domain);
attestation.signature.add_assign(&sk.sign(message));
}
}
}
}
// TODO(electra): fix this test
AttesterSlashing::Base(AttesterSlashingBase {
attestation_1,
attestation_2,
})
if fork_name >= ForkName::Electra {
AttesterSlashing::Electra(AttesterSlashingElectra {
attestation_1: attestation_1.as_electra().unwrap().clone(),
attestation_2: attestation_2.as_electra().unwrap().clone(),
})
} else {
AttesterSlashing::Base(AttesterSlashingBase {
attestation_1: attestation_1.as_base().unwrap().clone(),
attestation_2: attestation_2.as_base().unwrap().clone(),
})
}
}
pub fn make_proposer_slashing(&self, validator_index: u64) -> ProposerSlashing {
@@ -2413,6 +2536,7 @@ where
AttestationStrategy::AllValidators => self.get_all_validators(),
AttestationStrategy::SomeValidators(vals) => vals,
};
let state_root = state.update_tree_hash_cache().unwrap();
let (_, _, last_produced_block_hash, _) = self
.add_attested_blocks_at_slots_with_sync(
@@ -2539,6 +2663,7 @@ pub fn generate_rand_block_and_blobs<E: EthSpec>(
rng: &mut impl Rng,
) -> (SignedBeaconBlock<E, FullPayload<E>>, Vec<BlobSidecar<E>>) {
let inner = map_fork_name!(fork_name, BeaconBlock, <_>::random_for_test(rng));
let mut block = SignedBeaconBlock::from_block(inner, types::Signature::random_for_test(rng));
let mut blob_sidecars = vec![];
@@ -2575,7 +2700,6 @@ pub fn generate_rand_block_and_blobs<E: EthSpec>(
};
let (bundle, transactions) =
execution_layer::test_utils::generate_blobs::<E>(num_blobs).unwrap();
payload.execution_payload.transactions = <_>::default();
for tx in Vec::from(transactions) {
payload.execution_payload.transactions.push(tx).unwrap();