use of tech.pegasys.teku.spec.datastructures.util.AttestationProcessingResult in project teku by ConsenSys.
the class ForkChoiceUtil method validateOnAttestation.
public AttestationProcessingResult validateOnAttestation(final ReadOnlyForkChoiceStrategy forkChoiceStrategy, final UInt64 currentEpoch, final AttestationData attestationData) {
final Checkpoint target = attestationData.getTarget();
// Use GENESIS_EPOCH for previous when genesis to avoid underflow
final UInt64 previousEpoch = currentEpoch.isGreaterThan(SpecConfig.GENESIS_EPOCH) ? currentEpoch.minus(UInt64.ONE) : SpecConfig.GENESIS_EPOCH;
if (!target.getEpoch().equals(previousEpoch) && !target.getEpoch().equals(currentEpoch)) {
return AttestationProcessingResult.invalid("Attestations must be from the current or previous epoch");
}
if (!target.getEpoch().equals(miscHelpers.computeEpochAtSlot(attestationData.getSlot()))) {
return AttestationProcessingResult.invalid("Attestation slot must be within specified epoch");
}
if (!forkChoiceStrategy.contains(target.getRoot())) {
// consideration until the block is found
return AttestationProcessingResult.UNKNOWN_BLOCK;
}
final Optional<UInt64> blockSlot = forkChoiceStrategy.blockSlot(attestationData.getBeacon_block_root());
if (blockSlot.isEmpty()) {
// block is found
return AttestationProcessingResult.UNKNOWN_BLOCK;
}
if (blockSlot.get().compareTo(attestationData.getSlot()) > 0) {
return AttestationProcessingResult.invalid("Attestations must not be for blocks in the future. If not, the attestation should not be considered");
}
// LMD vote must be consistent with FFG vote target
final UInt64 targetSlot = miscHelpers.computeStartSlotAtEpoch(target.getEpoch());
if (getAncestor(forkChoiceStrategy, attestationData.getBeacon_block_root(), targetSlot).map(ancestorRoot -> !ancestorRoot.equals(target.getRoot())).orElse(true)) {
return AttestationProcessingResult.invalid("LMD vote must be consistent with FFG vote target");
}
return AttestationProcessingResult.SUCCESSFUL;
}
use of tech.pegasys.teku.spec.datastructures.util.AttestationProcessingResult in project teku by ConsenSys.
the class AttestationUtil method isValidIndexedAttestationAsync.
public SafeFuture<AttestationProcessingResult> isValidIndexedAttestationAsync(Fork fork, BeaconState state, IndexedAttestation indexed_attestation, AsyncBLSSignatureVerifier signatureVerifier) {
SszUInt64List indices = indexed_attestation.getAttesting_indices();
if (indices.isEmpty() || !Comparators.isInStrictOrder(indices.asListUnboxed(), Comparator.naturalOrder())) {
return completedFuture(AttestationProcessingResult.invalid("Attesting indices are not sorted"));
}
List<BLSPublicKey> pubkeys = indices.streamUnboxed().flatMap(i -> beaconStateAccessors.getValidatorPubKey(state, i).stream()).collect(toList());
if (pubkeys.size() < indices.size()) {
return completedFuture(AttestationProcessingResult.invalid("Attesting indices include non-existent validator"));
}
BLSSignature signature = indexed_attestation.getSignature();
Bytes32 domain = beaconStateAccessors.getDomain(Domain.BEACON_ATTESTER, indexed_attestation.getData().getTarget().getEpoch(), fork, state.getGenesis_validators_root());
Bytes signing_root = miscHelpers.computeSigningRoot(indexed_attestation.getData(), domain);
return signatureVerifier.verify(pubkeys, signing_root, signature).thenApply(isValidSignature -> {
if (isValidSignature) {
return AttestationProcessingResult.SUCCESSFUL;
} else {
LOG.debug("AttestationUtil.is_valid_indexed_attestation: Verify aggregate signature");
return AttestationProcessingResult.invalid("Signature is invalid");
}
});
}
use of tech.pegasys.teku.spec.datastructures.util.AttestationProcessingResult in project teku by ConsenSys.
the class ForkChoice method onAttestation.
public SafeFuture<AttestationProcessingResult> onAttestation(final ValidateableAttestation attestation) {
return recentChainData.retrieveCheckpointState(attestation.getData().getTarget()).thenCompose(maybeTargetState -> {
final UpdatableStore store = recentChainData.getStore();
final AttestationProcessingResult validationResult = spec.validateAttestation(store, attestation, maybeTargetState);
if (!validationResult.isSuccessful()) {
return SafeFuture.completedFuture(validationResult);
}
return onForkChoiceThread(() -> {
final VoteUpdater transaction = recentChainData.startVoteUpdate();
getForkChoiceStrategy().onAttestation(transaction, getIndexedAttestation(attestation));
transaction.commit();
}).thenApply(__ -> validationResult);
}).exceptionallyCompose(error -> {
final Throwable rootCause = Throwables.getRootCause(error);
if (rootCause instanceof InvalidCheckpointException) {
return SafeFuture.completedFuture(AttestationProcessingResult.invalid(rootCause.getMessage()));
}
return SafeFuture.failedFuture(error);
});
}
use of tech.pegasys.teku.spec.datastructures.util.AttestationProcessingResult in project teku by ConsenSys.
the class ForkChoiceTest method onAttestation_shouldBeInvalidWhenInvalidCheckpointThrown.
@Test
void onAttestation_shouldBeInvalidWhenInvalidCheckpointThrown() {
final SignedBlockAndState targetBlock = chainBuilder.generateBlockAtSlot(5);
importBlock(targetBlock);
// Attestation where the target checkpoint has a slot prior to the block it references
final Checkpoint targetCheckpoint = new Checkpoint(ZERO, targetBlock.getRoot());
final Attestation attestation = attestationSchema.create(attestationSchema.getAggregationBitsSchema().ofBits(5), new AttestationData(targetBlock.getSlot(), spec.computeEpochAtSlot(targetBlock.getSlot()), targetBlock.getRoot(), targetBlock.getState().getCurrent_justified_checkpoint(), targetCheckpoint), BLSSignature.empty());
final SafeFuture<AttestationProcessingResult> result = forkChoice.onAttestation(ValidateableAttestation.from(spec, attestation));
assertThat(result).isCompletedWithValue(AttestationProcessingResult.invalid(String.format("Checkpoint state (%s) must be at or prior to checkpoint slot boundary (%s)", targetBlock.getSlot(), targetCheckpoint.getEpochStartSlot(spec))));
}
Aggregations