use of tech.pegasys.teku.spec.datastructures.state.SyncCommittee in project teku by ConsenSys.
the class ChainDataProvider method getSyncCommitteesFromState.
private StateSyncCommittees getSyncCommitteesFromState(final tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState state, final Optional<UInt64> epochQueryParam) {
final UInt64 epoch = epochQueryParam.orElse(spec.computeEpochAtSlot(state.getSlot()));
final UInt64 slot = spec.computeStartSlotAtEpoch(epoch);
final Optional<SyncCommittee> maybeCommittee = spec.getSyncCommitteeUtil(slot).map(util -> util.getSyncCommittee(state, epoch));
// returned
if (maybeCommittee.isEmpty()) {
return new StateSyncCommittees(List.of(), List.of());
}
final SyncCommittee committee = maybeCommittee.get();
final List<UInt64> committeeIndices = committee.getPubkeys().stream().flatMap(pubkey -> spec.getValidatorIndex(state, pubkey.getBLSPublicKey()).stream()).map(UInt64::valueOf).collect(toList());
return new StateSyncCommittees(committeeIndices, Lists.partition(committeeIndices, spec.atEpoch(epoch).getConfig().getTargetCommitteeSize()));
}
use of tech.pegasys.teku.spec.datastructures.state.SyncCommittee in project teku by ConsenSys.
the class SyncCommitteeUtil method getSyncSubcommittees.
public Map<UInt64, SyncSubcommitteeAssignments> getSyncSubcommittees(final BeaconState state, final UInt64 epoch) {
final UInt64 syncCommitteePeriod = computeSyncCommitteePeriod(epoch);
final UInt64 currentEpoch = beaconStateAccessors.getCurrentEpoch(state);
final UInt64 currentSyncCommitteePeriod = computeSyncCommitteePeriod(currentEpoch);
checkArgument(isStateUsableForCommitteeCalculationAtEpoch(state, epoch), "State must be in the same or previous sync committee period. Cannot calculate epoch %s from state at slot %s", epoch, state.getSlot());
final BeaconStateAltair altairState = BeaconStateAltair.required(state);
return BeaconStateCache.getTransitionCaches(altairState).getSyncCommitteeCache().get(syncCommitteePeriod, period -> {
final SyncCommittee syncCommittee;
if (syncCommitteePeriod.equals(currentSyncCommitteePeriod)) {
syncCommittee = altairState.getCurrentSyncCommittee();
} else {
syncCommittee = altairState.getNextSyncCommittee();
}
final int subcommitteeSize = getSubcommitteeSize();
final SszVector<SszPublicKey> pubkeys = syncCommittee.getPubkeys();
final Map<UInt64, SyncSubcommitteeAssignments.Builder> subcommitteeAssignments = new HashMap<>();
for (int index = 0; index < pubkeys.size(); index++) {
final BLSPublicKey pubkey = pubkeys.get(index).getBLSPublicKey();
final UInt64 validatorIndex = UInt64.valueOf(validatorsUtil.getValidatorIndex(altairState, pubkey).orElseThrow(() -> new IllegalStateException("Unknown validator assigned to sync committee: " + pubkey)));
final int subcommitteeIndex = index / subcommitteeSize;
final int subcommitteeParticipationIndex = index - (subcommitteeIndex * subcommitteeSize);
// Note we're using plain HashMap here instead of a concurrent alternative as they
// are created once here and then never modified so safe to access from multiple
// threads.
subcommitteeAssignments.computeIfAbsent(validatorIndex, __ -> SyncSubcommitteeAssignments.builder()).addAssignment(subcommitteeIndex, subcommitteeParticipationIndex).addCommitteeIndex(index);
}
return subcommitteeAssignments.entrySet().stream().collect(toUnmodifiableMap(Map.Entry::getKey, entry -> entry.getValue().build()));
});
}
use of tech.pegasys.teku.spec.datastructures.state.SyncCommittee in project teku by ConsenSys.
the class BeaconStateAccessorsAltair method getNextSyncCommittee.
/**
* Return the *next* sync committee for a given state.
*
* <p>SyncCommittee contains an aggregate pubkey that enables resource-constrained clients to save
* some computation when verifying the sync committee's signature.
*
* <p>SyncCommittee can also contain duplicate pubkeys, when {@link
* #getNextSyncCommitteeIndices(BeaconState)} returns duplicate indices. Implementations must take
* care when handling optimizations relating to aggregation and verification in the presence of
* duplicates.
*
* <p>Note: This function should only be called at sync committee period boundaries by {@link
* tech.pegasys.teku.spec.logic.common.statetransition.epoch.EpochProcessor#processSyncCommitteeUpdates(MutableBeaconState)}
* as {@link #getNextSyncCommitteeIndices(BeaconState)} is not stable within a given period.
*
* @param state the state to get the sync committee for
* @return the SyncCommittee
*/
public SyncCommittee getNextSyncCommittee(final BeaconState state) {
final IntList indices = getNextSyncCommitteeIndices(state);
final List<BLSPublicKey> pubkeys = indices.intStream().mapToObj(index -> getValidatorPubKey(state, UInt64.valueOf(index)).orElseThrow()).collect(toList());
final BLSPublicKey aggregatePubkey = BLSPublicKey.aggregate(pubkeys);
return state.getBeaconStateSchema().getNextSyncCommitteeSchemaOrThrow().create(pubkeys.stream().map(SszPublicKey::new).collect(toList()), new SszPublicKey(aggregatePubkey));
}
use of tech.pegasys.teku.spec.datastructures.state.SyncCommittee in project teku by ConsenSys.
the class ChainDataProviderTest method setupAltairState.
private ChainDataProvider setupAltairState() {
final Spec altair = TestSpecFactory.createMinimalAltair();
final DataStructureUtil dataStructureUtil = new DataStructureUtil(altair);
final ChainDataProvider provider = new ChainDataProvider(altair, recentChainData, mockCombinedChainDataClient);
final SszList<tech.pegasys.teku.spec.datastructures.state.Validator> validators = dataStructureUtil.randomSszList(dataStructureUtil.getBeaconStateSchema().getValidatorsSchema(), 16, dataStructureUtil::randomValidator);
final SyncCommittee currentSyncCommittee = dataStructureUtil.randomSyncCommittee(validators);
final tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState internalState = dataStructureUtil.stateBuilderAltair().validators(validators).currentSyncCommittee(currentSyncCommittee).build();
final tech.pegasys.teku.storage.client.ChainHead chainHead = tech.pegasys.teku.storage.client.ChainHead.create(StateAndBlockSummary.create(internalState));
when(mockCombinedChainDataClient.getChainHead()).thenReturn(Optional.of(chainHead));
return provider;
}
use of tech.pegasys.teku.spec.datastructures.state.SyncCommittee in project teku by ConsenSys.
the class SignedContributionAndProofValidator method validateWithState.
private SafeFuture<InternalValidationResult> validateWithState(final SignedContributionAndProof proof, final ContributionAndProof contributionAndProof, final SyncCommitteeContribution contribution, final SyncCommitteeUtil syncCommitteeUtil, final UniquenessKey uniquenessKey, final BeaconStateAltair state) {
final BeaconStateAccessors beaconStateAccessors = spec.atSlot(contribution.getSlot()).beaconStateAccessors();
final Optional<BLSPublicKey> aggregatorPublicKey = beaconStateAccessors.getValidatorPubKey(state, contributionAndProof.getAggregatorIndex());
if (aggregatorPublicKey.isEmpty()) {
return futureFailureResult("Rejecting proof because aggregator index %s is an unknown validator", contributionAndProof.getAggregatorIndex());
}
final UInt64 contributionEpoch = syncCommitteeUtil.getEpochForDutiesAtSlot(contribution.getSlot());
// state.current_sync_committee.pubkeys.
if (!isInSyncSubcommittee(syncCommitteeUtil, contribution, state, contributionEpoch, contributionAndProof.getAggregatorIndex())) {
return futureFailureResult("Rejecting proof because aggregator index %s is not in the current sync subcommittee", contributionAndProof.getAggregatorIndex());
}
// contribution.slot, contribution_and_proof.selection_proof) returns True.
if (!syncCommitteeUtil.isSyncCommitteeAggregator(contributionAndProof.getSelectionProof())) {
return futureFailureResult("Rejecting proof because selection proof %s is not an aggregator", contributionAndProof.getSelectionProof());
}
final AsyncBatchBLSSignatureVerifier signatureVerifier = new AsyncBatchBLSSignatureVerifier(this.signatureVerifier);
// [REJECT] The contribution_and_proof.selection_proof is a valid signature of the
// contribution.slot by the validator with index
// contribution_and_proof.aggregator_index.
final Bytes signingRoot = syncCommitteeUtil.getSyncAggregatorSelectionDataSigningRoot(syncCommitteeUtil.createSyncAggregatorSelectionData(contribution.getSlot(), contribution.getSubcommitteeIndex()), state.getForkInfo());
if (!signatureVerifier.verify(aggregatorPublicKey.get(), signingRoot, contributionAndProof.getSelectionProof())) {
return futureFailureResult("Rejecting proof at slot %s for subcommittee index %s because selection proof is invalid", contribution.getSlot(), contribution.getSubcommitteeIndex());
}
// valid.
if (!signatureVerifier.verify(aggregatorPublicKey.get(), syncCommitteeUtil.getContributionAndProofSigningRoot(state, contributionAndProof), proof.getSignature())) {
return futureFailureResult("Rejecting proof %s because aggregator signature is invalid", proof.getSignature());
}
final SpecConfigAltair config = SpecConfigAltair.required(spec.getSpecConfig(contributionEpoch));
final SyncCommittee syncCommittee = syncCommitteeUtil.getSyncCommittee(state, contributionEpoch);
final int subcommitteeSize = config.getSyncCommitteeSize() / SYNC_COMMITTEE_SUBNET_COUNT;
// [REJECT] The aggregate signature is valid for the message beacon_block_root and
// aggregate pubkey derived from the participation info in aggregation_bits for the
// subcommittee specified by the subcommittee_index.
final List<BLSPublicKey> contributorPublicKeys = contribution.getAggregationBits().streamAllSetBits().mapToObj(participantIndex -> getParticipantPublicKey(state, syncCommittee, contribution, subcommitteeSize, participantIndex)).collect(Collectors.toList());
if (!signatureVerifier.verify(contributorPublicKeys, syncCommitteeUtil.getSyncCommitteeMessageSigningRoot(contribution.getBeaconBlockRoot(), contributionEpoch, state.getForkInfo()), contribution.getSignature())) {
return futureFailureResult("Rejecting proof because aggregate signature %s is invalid", contribution.getSignature());
}
return signatureVerifier.batchVerify().thenApply(signatureValid -> {
if (!signatureValid) {
return failureResult("Rejecting proof with signature %s because batch signature check failed", contribution.getSignature());
}
if (!seenIndices.add(uniquenessKey)) {
// Got added by another thread while we were validating it
return IGNORE;
}
return ACCEPT;
});
}
Aggregations