use of tech.pegasys.teku.spec.config.Constants.ATTESTATION_PROPAGATION_SLOT_RANGE in project teku by ConsenSys.
the class AttestationValidator method singleOrAggregateAttestationChecks.
SafeFuture<InternalValidationResult> singleOrAggregateAttestationChecks(final AsyncBLSSignatureVerifier signatureVerifier, final ValidateableAttestation validateableAttestation, final OptionalInt receivedOnSubnetId) {
Attestation attestation = validateableAttestation.getAttestation();
final AttestationData data = attestation.getData();
// The attestation's epoch matches its target
if (!data.getTarget().getEpoch().equals(spec.computeEpochAtSlot(data.getSlot()))) {
return completedFuture(InternalValidationResult.reject("Attestation slot %s is not from target epoch %s", data.getSlot(), data.getTarget().getEpoch()));
}
// attestation.data.slot is within the last ATTESTATION_PROPAGATION_SLOT_RANGE slots (within a
// MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance) -- i.e. attestation.data.slot +
// ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot (a client MAY
// queue
// future attestations for processing at the appropriate slot).
final UInt64 currentTimeMillis = secondsToMillis(recentChainData.getStore().getTime());
if (isCurrentTimeAfterAttestationPropagationSlotRange(currentTimeMillis, attestation) || isFromFarFuture(attestation, currentTimeMillis)) {
return completedFuture(InternalValidationResult.IGNORE);
}
if (isCurrentTimeBeforeMinimumAttestationBroadcastTime(attestation, currentTimeMillis)) {
return completedFuture(InternalValidationResult.SAVE_FOR_FUTURE);
}
// If it's not in the store, it may not have been processed yet so save for future.
return recentChainData.retrieveBlockState(data.getBeacon_block_root()).thenCompose(maybeState -> maybeState.isEmpty() ? completedFuture(Optional.empty()) : resolveStateForAttestation(attestation, maybeState.get())).thenCompose(maybeState -> {
if (maybeState.isEmpty()) {
return completedFuture(InternalValidationResult.SAVE_FOR_FUTURE);
}
final BeaconState state = maybeState.get();
// The committee index is within the expected range
if (data.getIndex().isGreaterThanOrEqualTo(spec.getCommitteeCountPerSlot(state, data.getTarget().getEpoch()))) {
return completedFuture(InternalValidationResult.reject("Committee index %s is out of range", data.getIndex()));
}
// subnet.
if (receivedOnSubnetId.isPresent() && spec.computeSubnetForAttestation(state, attestation) != receivedOnSubnetId.getAsInt()) {
return completedFuture(InternalValidationResult.reject("Attestation received on incorrect subnet (%s) for specified committee index (%s)", attestation.getData().getIndex(), receivedOnSubnetId.getAsInt()));
}
// The check below is not specified in the Eth2 networking spec, yet an attestation
// with aggregation bits size greater/less than the committee size is invalid. So we
// reject those attestations at the networking layer.
final IntList committee = spec.getBeaconCommittee(state, data.getSlot(), data.getIndex());
if (committee.size() != attestation.getAggregationBits().size()) {
return completedFuture(InternalValidationResult.reject("Aggregation bit size %s is greater than committee size %s", attestation.getAggregationBits().size(), committee.size()));
}
return spec.isValidIndexedAttestation(state, validateableAttestation, signatureVerifier).thenApply(signatureResult -> {
if (!signatureResult.isSuccessful()) {
return InternalValidationResult.reject("Attestation is not a valid indexed attestation: %s", signatureResult.getInvalidReason());
}
// LMD vote
if (!spec.getAncestor(recentChainData.getForkChoiceStrategy().orElseThrow(), data.getBeacon_block_root(), spec.computeStartSlotAtEpoch(data.getTarget().getEpoch())).map(ancestorOfLMDVote -> ancestorOfLMDVote.equals(data.getTarget().getRoot())).orElse(false)) {
return InternalValidationResult.reject("Attestation LMD vote block does not descend from target block");
}
// The current finalized_checkpoint is an ancestor of the block defined by
// aggregate.data.beacon_block_root
// Because all nodes in the proto-array descend from the finalized block,
// no further validation is needed to satisfy this rule.
// Save committee shuffling seed since the state is available and
// attestation is valid
validateableAttestation.saveCommitteeShufflingSeed(state);
return InternalValidationResult.ACCEPT;
});
});
}
Aggregations