use of tech.pegasys.teku.spec.logic.common.util.AsyncBLSSignatureVerifier 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;
});
});
}
use of tech.pegasys.teku.spec.logic.common.util.AsyncBLSSignatureVerifier in project teku by ConsenSys.
the class AttestationValidatorTest method shouldRejectAttestationsThatHaveLMDVotesInconsistentWithTargetRoot.
@Test
public void shouldRejectAttestationsThatHaveLMDVotesInconsistentWithTargetRoot() {
final StateAndBlockSummary blockAndState = storageSystem.getChainHead();
final Attestation attestation = attestationGenerator.validAttestation(blockAndState);
final AsyncBLSSignatureVerifier signatureVerifier = mock(AsyncBLSSignatureVerifier.class);
final AttestationValidator validator = new AttestationValidator(spec, recentChainData, signatureVerifier);
final AttestationData data = attestation.getData();
final Checkpoint checkpoint = new Checkpoint(data.getTarget().getEpoch().minusMinZero(1), blockAndState.getBeaconBlock().orElseThrow().getParentRoot());
final int expectedSubnetId = spec.computeSubnetForAttestation(blockAndState.getState(), attestation);
// the signature would be invalid, but it's actually not the point of the test case.
when(signatureVerifier.verify(anyList(), any(Bytes.class), any())).thenReturn(SafeFuture.completedFuture(true));
assertThat(validator.validate(ValidateableAttestation.fromNetwork(spec, attestationSchema.create(attestation.getAggregationBits(), new AttestationData(data.getSlot(), data.getIndex(), data.getBeacon_block_root(), data.getSource(), checkpoint), attestation.getAggregateSignature()), expectedSubnetId))).matches(rejected("descend from target block"), "Rejected does not descend from target block");
}
Aggregations