mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-22 06:14:38 +00:00
Attestation superstruct changes for EIP 7549 (#5644)
* update * experiment * superstruct changes * revert * superstruct changes * fix tests * indexed attestation * indexed attestation superstruct * updated TODOs
This commit is contained in:
@@ -329,7 +329,7 @@ pub trait VerifiedAttestation<T: BeaconChainTypes>: Sized {
|
||||
// Inefficient default implementation. This is overridden for gossip verified attestations.
|
||||
fn into_attestation_and_indices(self) -> (Attestation<T::EthSpec>, Vec<u64>) {
|
||||
let attestation = self.attestation().clone();
|
||||
let attesting_indices = self.indexed_attestation().attesting_indices.clone().into();
|
||||
let attesting_indices = self.indexed_attestation().attesting_indices_to_vec();
|
||||
(attestation, attesting_indices)
|
||||
}
|
||||
}
|
||||
@@ -455,17 +455,17 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
|
||||
verify_propagation_slot_range(&chain.slot_clock, attestation, &chain.spec)?;
|
||||
|
||||
// Check the attestation's epoch matches its target.
|
||||
if attestation.data.slot.epoch(T::EthSpec::slots_per_epoch())
|
||||
!= attestation.data.target.epoch
|
||||
if attestation.data().slot.epoch(T::EthSpec::slots_per_epoch())
|
||||
!= attestation.data().target.epoch
|
||||
{
|
||||
return Err(Error::InvalidTargetEpoch {
|
||||
slot: attestation.data.slot,
|
||||
epoch: attestation.data.target.epoch,
|
||||
slot: attestation.data().slot,
|
||||
epoch: attestation.data().target.epoch,
|
||||
});
|
||||
}
|
||||
|
||||
// Ensure the valid aggregated attestation has not already been seen locally.
|
||||
let attestation_data = &attestation.data;
|
||||
let attestation_data = attestation.data();
|
||||
let attestation_data_root = attestation_data.tree_hash_root();
|
||||
|
||||
if chain
|
||||
@@ -486,7 +486,7 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
|
||||
match chain
|
||||
.observed_aggregators
|
||||
.read()
|
||||
.validator_has_been_observed(attestation.data.target.epoch, aggregator_index as usize)
|
||||
.validator_has_been_observed(attestation.data().target.epoch, aggregator_index as usize)
|
||||
{
|
||||
Ok(true) => Err(Error::AggregatorAlreadyKnown(aggregator_index)),
|
||||
Ok(false) => Ok(()),
|
||||
@@ -518,7 +518,7 @@ impl<'a, T: BeaconChainTypes> IndexedAggregatedAttestation<'a, T> {
|
||||
verify_attestation_target_root::<T::EthSpec>(&head_block, attestation)?;
|
||||
|
||||
// Ensure that the attestation has participants.
|
||||
if attestation.aggregation_bits.is_zero() {
|
||||
if attestation.is_aggregation_bits_zero() {
|
||||
Err(Error::EmptyAggregationBitfield)
|
||||
} else {
|
||||
Ok(attestation_data_root)
|
||||
@@ -611,12 +611,12 @@ impl<'a, T: BeaconChainTypes> VerifiedAggregatedAttestation<'a, T> {
|
||||
if chain
|
||||
.observed_aggregators
|
||||
.write()
|
||||
.observe_validator(attestation.data.target.epoch, aggregator_index as usize)
|
||||
.observe_validator(attestation.data().target.epoch, aggregator_index as usize)
|
||||
.map_err(BeaconChainError::from)?
|
||||
{
|
||||
return Err(Error::PriorAttestationKnown {
|
||||
validator_index: aggregator_index,
|
||||
epoch: attestation.data.target.epoch,
|
||||
epoch: attestation.data().target.epoch,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -712,13 +712,13 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
|
||||
attestation: &Attestation<T::EthSpec>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(), Error> {
|
||||
let attestation_epoch = attestation.data.slot.epoch(T::EthSpec::slots_per_epoch());
|
||||
let attestation_epoch = attestation.data().slot.epoch(T::EthSpec::slots_per_epoch());
|
||||
|
||||
// Check the attestation's epoch matches its target.
|
||||
if attestation_epoch != attestation.data.target.epoch {
|
||||
if attestation_epoch != attestation.data().target.epoch {
|
||||
return Err(Error::InvalidTargetEpoch {
|
||||
slot: attestation.data.slot,
|
||||
epoch: attestation.data.target.epoch,
|
||||
slot: attestation.data().slot,
|
||||
epoch: attestation.data().target.epoch,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -730,7 +730,7 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
|
||||
|
||||
// Check to ensure that the attestation is "unaggregated". I.e., it has exactly one
|
||||
// aggregation bit set.
|
||||
let num_aggregation_bits = attestation.aggregation_bits.num_set_bits();
|
||||
let num_aggregation_bits = attestation.num_set_aggregation_bits();
|
||||
if num_aggregation_bits != 1 {
|
||||
return Err(Error::NotExactlyOneAggregationBitSet(num_aggregation_bits));
|
||||
}
|
||||
@@ -757,7 +757,7 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(u64, SubnetId), Error> {
|
||||
let expected_subnet_id = SubnetId::compute_subnet_for_attestation_data::<T::EthSpec>(
|
||||
&indexed_attestation.data,
|
||||
indexed_attestation.data(),
|
||||
committees_per_slot,
|
||||
&chain.spec,
|
||||
)
|
||||
@@ -774,8 +774,7 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
|
||||
};
|
||||
|
||||
let validator_index = *indexed_attestation
|
||||
.attesting_indices
|
||||
.first()
|
||||
.attesting_indices_first()
|
||||
.ok_or(Error::NotExactlyOneAggregationBitSet(0))?;
|
||||
|
||||
/*
|
||||
@@ -785,12 +784,12 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
|
||||
if chain
|
||||
.observed_gossip_attesters
|
||||
.read()
|
||||
.validator_has_been_observed(attestation.data.target.epoch, validator_index as usize)
|
||||
.validator_has_been_observed(attestation.data().target.epoch, validator_index as usize)
|
||||
.map_err(BeaconChainError::from)?
|
||||
{
|
||||
return Err(Error::PriorAttestationKnown {
|
||||
validator_index,
|
||||
epoch: attestation.data.target.epoch,
|
||||
epoch: attestation.data().target.epoch,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -881,12 +880,12 @@ impl<'a, T: BeaconChainTypes> VerifiedUnaggregatedAttestation<'a, T> {
|
||||
if chain
|
||||
.observed_gossip_attesters
|
||||
.write()
|
||||
.observe_validator(attestation.data.target.epoch, validator_index as usize)
|
||||
.observe_validator(attestation.data().target.epoch, validator_index as usize)
|
||||
.map_err(BeaconChainError::from)?
|
||||
{
|
||||
return Err(Error::PriorAttestationKnown {
|
||||
validator_index,
|
||||
epoch: attestation.data.target.epoch,
|
||||
epoch: attestation.data().target.epoch,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
@@ -998,28 +997,28 @@ fn verify_head_block_is_known<T: BeaconChainTypes>(
|
||||
let block_opt = chain
|
||||
.canonical_head
|
||||
.fork_choice_read_lock()
|
||||
.get_block(&attestation.data.beacon_block_root)
|
||||
.get_block(&attestation.data().beacon_block_root)
|
||||
.or_else(|| {
|
||||
chain
|
||||
.early_attester_cache
|
||||
.get_proto_block(attestation.data.beacon_block_root)
|
||||
.get_proto_block(attestation.data().beacon_block_root)
|
||||
});
|
||||
|
||||
if let Some(block) = block_opt {
|
||||
// Reject any block that exceeds our limit on skipped slots.
|
||||
if let Some(max_skip_slots) = max_skip_slots {
|
||||
if attestation.data.slot > block.slot + max_skip_slots {
|
||||
if attestation.data().slot > block.slot + max_skip_slots {
|
||||
return Err(Error::TooManySkippedSlots {
|
||||
head_block_slot: block.slot,
|
||||
attestation_slot: attestation.data.slot,
|
||||
attestation_slot: attestation.data().slot,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(block)
|
||||
} else if chain.is_pre_finalization_block(attestation.data.beacon_block_root)? {
|
||||
} else if chain.is_pre_finalization_block(attestation.data().beacon_block_root)? {
|
||||
Err(Error::HeadBlockFinalized {
|
||||
beacon_block_root: attestation.data.beacon_block_root,
|
||||
beacon_block_root: attestation.data().beacon_block_root,
|
||||
})
|
||||
} else {
|
||||
// The block is either:
|
||||
@@ -1029,7 +1028,7 @@ fn verify_head_block_is_known<T: BeaconChainTypes>(
|
||||
// 2) A post-finalization block that we don't know about yet. We'll queue
|
||||
// the attestation until the block becomes available (or we time out).
|
||||
Err(Error::UnknownHeadBlock {
|
||||
beacon_block_root: attestation.data.beacon_block_root,
|
||||
beacon_block_root: attestation.data().beacon_block_root,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1043,7 +1042,7 @@ pub fn verify_propagation_slot_range<S: SlotClock, E: EthSpec>(
|
||||
attestation: &Attestation<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let attestation_slot = attestation.data.slot;
|
||||
let attestation_slot = attestation.data().slot;
|
||||
let latest_permissible_slot = slot_clock
|
||||
.now_with_future_tolerance(spec.maximum_gossip_clock_disparity())
|
||||
.ok_or(BeaconChainError::UnableToReadSlot)?;
|
||||
@@ -1095,11 +1094,11 @@ pub fn verify_attestation_signature<T: BeaconChainTypes>(
|
||||
|
||||
let fork = chain
|
||||
.spec
|
||||
.fork_at_epoch(indexed_attestation.data.target.epoch);
|
||||
.fork_at_epoch(indexed_attestation.data().target.epoch);
|
||||
|
||||
let signature_set = indexed_attestation_signature_set_from_pubkeys(
|
||||
|validator_index| pubkey_cache.get(validator_index).map(Cow::Borrowed),
|
||||
&indexed_attestation.signature,
|
||||
indexed_attestation.signature(),
|
||||
indexed_attestation,
|
||||
&fork,
|
||||
chain.genesis_validators_root,
|
||||
@@ -1127,7 +1126,7 @@ pub fn verify_attestation_target_root<E: EthSpec>(
|
||||
) -> Result<(), Error> {
|
||||
// Check the attestation target root.
|
||||
let head_block_epoch = head_block.slot.epoch(E::slots_per_epoch());
|
||||
let attestation_epoch = attestation.data.slot.epoch(E::slots_per_epoch());
|
||||
let attestation_epoch = attestation.data().slot.epoch(E::slots_per_epoch());
|
||||
if head_block_epoch > attestation_epoch {
|
||||
// The epoch references an invalid head block from a future epoch.
|
||||
//
|
||||
@@ -1140,7 +1139,7 @@ pub fn verify_attestation_target_root<E: EthSpec>(
|
||||
// Reference:
|
||||
// https://github.com/ethereum/eth2.0-specs/pull/2001#issuecomment-699246659
|
||||
return Err(Error::InvalidTargetRoot {
|
||||
attestation: attestation.data.target.root,
|
||||
attestation: attestation.data().target.root,
|
||||
// It is not clear what root we should expect in this case, since the attestation is
|
||||
// fundamentally invalid.
|
||||
expected: None,
|
||||
@@ -1159,9 +1158,9 @@ pub fn verify_attestation_target_root<E: EthSpec>(
|
||||
};
|
||||
|
||||
// Reject any attestation with an invalid target root.
|
||||
if target_root != attestation.data.target.root {
|
||||
if target_root != attestation.data().target.root {
|
||||
return Err(Error::InvalidTargetRoot {
|
||||
attestation: attestation.data.target.root,
|
||||
attestation: attestation.data().target.root,
|
||||
expected: Some(target_root),
|
||||
});
|
||||
}
|
||||
@@ -1199,7 +1198,7 @@ pub fn verify_signed_aggregate_signatures<T: BeaconChainTypes>(
|
||||
|
||||
let fork = chain
|
||||
.spec
|
||||
.fork_at_epoch(indexed_attestation.data.target.epoch);
|
||||
.fork_at_epoch(indexed_attestation.data().target.epoch);
|
||||
|
||||
let signature_sets = vec![
|
||||
signed_aggregate_selection_proof_signature_set(
|
||||
@@ -1220,7 +1219,7 @@ pub fn verify_signed_aggregate_signatures<T: BeaconChainTypes>(
|
||||
.map_err(BeaconChainError::SignatureSetError)?,
|
||||
indexed_attestation_signature_set_from_pubkeys(
|
||||
|validator_index| pubkey_cache.get(validator_index).map(Cow::Borrowed),
|
||||
&indexed_attestation.signature,
|
||||
indexed_attestation.signature(),
|
||||
indexed_attestation,
|
||||
&fork,
|
||||
chain.genesis_validators_root,
|
||||
@@ -1266,8 +1265,8 @@ where
|
||||
T: BeaconChainTypes,
|
||||
F: Fn((BeaconCommittee, CommitteesPerSlot)) -> Result<R, Error>,
|
||||
{
|
||||
let attestation_epoch = attestation.data.slot.epoch(T::EthSpec::slots_per_epoch());
|
||||
let target = &attestation.data.target;
|
||||
let attestation_epoch = attestation.data().slot.epoch(T::EthSpec::slots_per_epoch());
|
||||
let target = &attestation.data().target;
|
||||
|
||||
// Attestation target must be for a known block.
|
||||
//
|
||||
@@ -1290,12 +1289,12 @@ where
|
||||
let committees_per_slot = committee_cache.committees_per_slot();
|
||||
|
||||
Ok(committee_cache
|
||||
.get_beacon_committee(attestation.data.slot, attestation.data.index)
|
||||
.get_beacon_committee(attestation.data().slot, attestation.data().index)
|
||||
.map(|committee| map_fn((committee, committees_per_slot)))
|
||||
.unwrap_or_else(|| {
|
||||
Err(Error::NoCommitteeForSlotAndIndex {
|
||||
slot: attestation.data.slot,
|
||||
index: attestation.data.index,
|
||||
slot: attestation.data().slot,
|
||||
index: attestation.data().index,
|
||||
})
|
||||
}))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user