mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-23 23:04:53 +00:00
Aggregate subsets (#3493)
## Issue Addressed Resolves #3238 ## Proposed Changes Please list or describe the changes introduced by this PR. ## Additional Info Please provide any additional information. For example, future considerations or information useful for reviewers.
This commit is contained in:
@@ -117,14 +117,14 @@ pub enum Error {
|
||||
///
|
||||
/// The peer has sent an invalid message.
|
||||
AggregatorPubkeyUnknown(u64),
|
||||
/// The attestation has been seen before; either in a block, on the gossip network or from a
|
||||
/// local validator.
|
||||
/// The attestation or a superset of this attestation's aggregations bits for the same data
|
||||
/// has been seen before; either in a block, on the gossip network or from a local validator.
|
||||
///
|
||||
/// ## Peer scoring
|
||||
///
|
||||
/// It's unclear if this attestation is valid, however we have already observed it and do not
|
||||
/// need to observe it again.
|
||||
AttestationAlreadyKnown(Hash256),
|
||||
AttestationSupersetKnown(Hash256),
|
||||
/// There has already been an aggregation observed for this validator, we refuse to process a
|
||||
/// second.
|
||||
///
|
||||
@@ -268,7 +268,7 @@ enum CheckAttestationSignature {
|
||||
struct IndexedAggregatedAttestation<'a, T: BeaconChainTypes> {
|
||||
signed_aggregate: &'a SignedAggregateAndProof<T::EthSpec>,
|
||||
indexed_attestation: IndexedAttestation<T::EthSpec>,
|
||||
attestation_root: Hash256,
|
||||
attestation_data_root: Hash256,
|
||||
}
|
||||
|
||||
/// Wraps a `Attestation` that has been verified up until the point that an `IndexedAttestation` can
|
||||
@@ -467,14 +467,17 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
|
||||
}
|
||||
|
||||
// Ensure the valid aggregated attestation has not already been seen locally.
|
||||
let attestation_root = attestation.tree_hash_root();
|
||||
let attestation_data = &attestation.data;
|
||||
let attestation_data_root = attestation_data.tree_hash_root();
|
||||
|
||||
if chain
|
||||
.observed_attestations
|
||||
.write()
|
||||
.is_known(attestation, attestation_root)
|
||||
.is_known_subset(attestation, attestation_data_root)
|
||||
.map_err(|e| Error::BeaconChainError(e.into()))?
|
||||
{
|
||||
return Err(Error::AttestationAlreadyKnown(attestation_root));
|
||||
metrics::inc_counter(&metrics::AGGREGATED_ATTESTATION_SUBSETS);
|
||||
return Err(Error::AttestationSupersetKnown(attestation_data_root));
|
||||
}
|
||||
|
||||
let aggregator_index = signed_aggregate.message.aggregator_index;
|
||||
@@ -520,7 +523,7 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
|
||||
if attestation.aggregation_bits.is_zero() {
|
||||
Err(Error::EmptyAggregationBitfield)
|
||||
} else {
|
||||
Ok(attestation_root)
|
||||
Ok(attestation_data_root)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,7 +536,7 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
|
||||
|
||||
let attestation = &signed_aggregate.message.aggregate;
|
||||
let aggregator_index = signed_aggregate.message.aggregator_index;
|
||||
let attestation_root = match Self::verify_early_checks(signed_aggregate, chain) {
|
||||
let attestation_data_root = match Self::verify_early_checks(signed_aggregate, chain) {
|
||||
Ok(root) => root,
|
||||
Err(e) => return Err(SignatureNotChecked(&signed_aggregate.message.aggregate, e)),
|
||||
};
|
||||
@@ -568,7 +571,7 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
|
||||
Ok(IndexedAggregatedAttestation {
|
||||
signed_aggregate,
|
||||
indexed_attestation,
|
||||
attestation_root,
|
||||
attestation_data_root,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -577,7 +580,7 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
|
||||
/// Run the checks that happen after the indexed attestation and signature have been checked.
|
||||
fn verify_late_checks(
|
||||
signed_aggregate: &SignedAggregateAndProof<T::EthSpec>,
|
||||
attestation_root: Hash256,
|
||||
attestation_data_root: Hash256,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(), Error> {
|
||||
let attestation = &signed_aggregate.message.aggregate;
|
||||
@@ -587,13 +590,14 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
|
||||
//
|
||||
// It's important to double check that the attestation is not already known, otherwise two
|
||||
// attestations processed at the same time could be published.
|
||||
if let ObserveOutcome::AlreadyKnown = chain
|
||||
if let ObserveOutcome::Subset = chain
|
||||
.observed_attestations
|
||||
.write()
|
||||
.observe_item(attestation, Some(attestation_root))
|
||||
.observe_item(attestation, Some(attestation_data_root))
|
||||
.map_err(|e| Error::BeaconChainError(e.into()))?
|
||||
{
|
||||
return Err(Error::AttestationAlreadyKnown(attestation_root));
|
||||
metrics::inc_counter(&metrics::AGGREGATED_ATTESTATION_SUBSETS);
|
||||
return Err(Error::AttestationSupersetKnown(attestation_data_root));
|
||||
}
|
||||
|
||||
// Observe the aggregator so we don't process another aggregate from them.
|
||||
@@ -653,7 +657,7 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
|
||||
let IndexedAggregatedAttestation {
|
||||
signed_aggregate,
|
||||
indexed_attestation,
|
||||
attestation_root,
|
||||
attestation_data_root,
|
||||
} = signed_aggregate;
|
||||
|
||||
match check_signature {
|
||||
@@ -677,7 +681,7 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
|
||||
CheckAttestationSignature::No => (),
|
||||
};
|
||||
|
||||
if let Err(e) = Self::verify_late_checks(signed_aggregate, attestation_root, chain) {
|
||||
if let Err(e) = Self::verify_late_checks(signed_aggregate, attestation_data_root, chain) {
|
||||
return Err(SignatureValid(indexed_attestation, e));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user