Skip to content

Commit

Permalink
7549 fix attestation validation (#8315)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbenr committed May 17, 2024
1 parent 212b33f commit 9339c41
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ private SignedAggregateAndProof generateWithAnyValidAggregatorIndex(
final Attestation aggregate) {
final List<Integer> beaconCommittee =
spec.getBeaconCommittee(
stateAtSlot, aggregate.getData().getSlot(), aggregate.getData().getIndex());
stateAtSlot, aggregate.getData().getSlot(), aggregate.getFirstCommitteeIndex());
for (int validatorIndex : beaconCommittee) {
final Optional<BLSSignature> maybeSelectionProof =
createValidSelectionProof(validatorIndex, stateAtSlot, aggregate);
Expand Down Expand Up @@ -164,15 +164,15 @@ private Attestation createAttestationForCommittee(
final UInt64 slot, final UInt64 committeeIndex) {
return attestationGenerator
.streamAttestations(blockAndState, slot)
.filter(attestation -> attestation.getData().getIndex().equals(committeeIndex))
.filter(attestation -> attestation.getFirstCommitteeIndex().equals(committeeIndex))
.findFirst()
.orElseThrow();
}

private Optional<BLSSignature> createValidSelectionProof(
final int validatorIndex, final BeaconState state, final Attestation attestation) {
final UInt64 slot = attestation.getData().getSlot();
final UInt64 committeeIndex = attestation.getData().getIndex();
final UInt64 committeeIndex = attestation.getFirstCommitteeIndex();
final SpecVersion specVersion = spec.atSlot(slot);
final List<Integer> beaconCommittee = spec.getBeaconCommittee(state, slot, committeeIndex);
final int aggregatorModulo =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
Expand All @@ -32,6 +33,7 @@
import tech.pegasys.teku.bls.BLSTestUtil;
import tech.pegasys.teku.infrastructure.async.SyncAsyncRunner;
import tech.pegasys.teku.infrastructure.ssz.collections.SszBitlist;
import tech.pegasys.teku.infrastructure.ssz.collections.SszBitvector;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockSummary;
Expand Down Expand Up @@ -85,23 +87,29 @@ public static List<Attestation> groupAndAggregateAttestations(List<Attestation>

private static Attestation aggregateAttestations(List<Attestation> srcAttestations) {
Preconditions.checkArgument(!srcAttestations.isEmpty(), "Expected at least one attestation");
AttestationSchema<? extends Attestation> attestationSchema = srcAttestations.get(0).getSchema();
int targetBitlistSize =

final AttestationSchema<? extends Attestation> attestationSchema =
srcAttestations.get(0).getSchema();
final int targetBitlistSize =
srcAttestations.stream().mapToInt(a -> a.getAggregationBits().size()).max().getAsInt();
SszBitlist targetBitlist =
final SszBitlist targetBitlist =
srcAttestations.stream()
.map(Attestation::getAggregationBits)
.reduce(
attestationSchema.getAggregationBitsSchema().ofBits(targetBitlistSize),
SszBitlist::or,
SszBitlist::or);
BLSSignature targetSig =
final BLSSignature targetSig =
BLS.aggregate(
srcAttestations.stream()
.map(attestation -> attestation.getAggregateSignature())
.collect(Collectors.toList()));

return attestationSchema.create(targetBitlist, srcAttestations.get(0).getData(), targetSig);
return attestationSchema.create(
targetBitlist,
srcAttestations.get(0).getData(),
() -> srcAttestations.get(0).getCommitteeBitsRequired(),
targetSig);
}

public Attestation validAttestation(final StateAndBlockSummary blockAndState) {
Expand Down Expand Up @@ -351,7 +359,8 @@ private void generateNextAttestation() {
validatorKeyPair,
indexIntoCommittee,
committee,
genericAttestationData));
genericAttestationData,
committeeIndex));
break;
}

Expand All @@ -363,45 +372,65 @@ private void generateNextAttestationFromSchedule() {
if (schedule.isDone()) {
nextAttestation = Optional.empty();
} else {
final UInt64 currentCommittee = schedule.getCurrentCommittee();
final IntList indices = schedule.getCommittee(currentCommittee);
final UInt64 currentCommitteeIndex = schedule.getCurrentCommittee();
final IntList indices = schedule.getCommittee(currentCommitteeIndex);
final Integer indexIntoCommittee = schedule.getIndexIntoCommittee();
final Integer validatorIndex = indices.getInt(indexIntoCommittee);
final Committee cc = new Committee(currentCommittee, indices);
final Committee currentCommittee = new Committee(currentCommitteeIndex, indices);
final BLSKeyPair validatorKeyPair = validatorKeySupplier.apply(validatorIndex);
final AttestationData genericAttestationData =
spec.getGenericAttestationData(assignedSlot, headState, headBlock, currentCommittee);
spec.getGenericAttestationData(
assignedSlot, headState, headBlock, currentCommitteeIndex);
nextAttestation =
Optional.of(
createAttestation(
headState, validatorKeyPair, indexIntoCommittee, cc, genericAttestationData));
headState,
validatorKeyPair,
indexIntoCommittee,
currentCommittee,
genericAttestationData,
currentCommittee.getIndex()));
schedule.next();
}
}

private Attestation createAttestation(
BeaconState state,
BLSKeyPair attesterKeyPair,
int indexIntoCommittee,
Committee committee,
AttestationData attestationData) {
int committeeSize = committee.getCommitteeSize();
final BeaconState state,
final BLSKeyPair attesterKeyPair,
final int indexIntoCommittee,
final Committee committee,
final AttestationData attestationData,
final UInt64 committeeIndex) {
final int committeeSize = committee.getCommitteeSize();
final AttestationSchema<?> attestationSchema =
spec.atSlot(attestationData.getSlot()).getSchemaDefinitions().getAttestationSchema();
SszBitlist aggregationBitfield =
final SszBitlist aggregationBitfield =
getAggregationBits(attestationSchema, committeeSize, indexIntoCommittee);

BLSSignature signature =
final BLSSignature signature =
new LocalSigner(spec, attesterKeyPair, SyncAsyncRunner.SYNC_RUNNER)
.signAttestationData(attestationData, state.getForkInfo())
.join();
return attestationSchema.create(aggregationBitfield, attestationData, signature);
return attestationSchema.create(
aggregationBitfield,
attestationData,
getCommitteeBitsSupplier(attestationSchema, committeeIndex),
signature);
}

private SszBitlist getAggregationBits(
final AttestationSchema<?> attestationSchema, int committeeSize, int indexIntoCommittee) {
// Create aggregation bitfield
return attestationSchema.getAggregationBitsSchema().ofBits(committeeSize, indexIntoCommittee);
}

private Supplier<SszBitvector> getCommitteeBitsSupplier(
final AttestationSchema<?> attestationSchema, final UInt64 committeeIndex) {
return () ->
attestationSchema
.getCommitteeBitsSchema()
.orElseThrow()
.ofBits(committeeIndex.intValue());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,23 @@ SafeFuture<InternalValidationResultWithState> singleOrAggregateAttestationChecks
return completedFuture(InternalValidationResultWithState.saveForFuture());
}

if (attestation.requiresCommitteeBits()) {
// [REJECT] len(committee_indices) == 1, where committee_indices =
// get_committee_indices(attestation)
if (attestation.getCommitteeBitsRequired().getBitCount() != 1) {
return SafeFuture.completedFuture(
InternalValidationResultWithState.reject(
"Rejecting attestation because committee bits count is not 1"));
}

// [REJECT] attestation.data.index == 0
if (!attestation.getData().getIndex().isZero()) {
return SafeFuture.completedFuture(
InternalValidationResultWithState.reject(
"Rejecting attestation because attestation data index must be 0"));
}
}

return stateSelector
.getStateToValidate(attestation.getData())
.thenCompose(
Expand Down

0 comments on commit 9339c41

Please sign in to comment.