use of tech.pegasys.teku.spec.datastructures.state.beaconstate.MutableBeaconState in project teku by ConsenSys.
the class BlockProcessorAltair method processSyncAggregate.
@Override
public void processSyncAggregate(final MutableBeaconState baseState, final SyncAggregate aggregate, final BLSSignatureVerifier signatureVerifier) throws BlockProcessingException {
final MutableBeaconStateAltair state = MutableBeaconStateAltair.required(baseState);
final List<BLSPublicKey> participantPubkeys = new ArrayList<>();
final List<BLSPublicKey> idlePubkeys = new ArrayList<>();
for (int i = 0; i < specConfigAltair.getSyncCommitteeSize(); i++) {
final BLSPublicKey publicKey = syncCommitteeUtil.getCurrentSyncCommitteeParticipantPubKey(state, i);
if (aggregate.getSyncCommitteeBits().getBit(i)) {
participantPubkeys.add(publicKey);
} else {
idlePubkeys.add(publicKey);
}
}
final UInt64 previousSlot = state.getSlot().minusMinZero(1);
final Bytes32 domain = beaconStateAccessors.getDomain(state.getForkInfo(), Domain.SYNC_COMMITTEE, miscHelpers.computeEpochAtSlot(previousSlot));
final Bytes32 signingRoot = miscHelpersAltair.computeSigningRoot(beaconStateAccessors.getBlockRootAtSlot(state, previousSlot), domain);
if (!eth2FastAggregateVerify(signatureVerifier, participantPubkeys, signingRoot, aggregate.getSyncCommitteeSignature().getSignature())) {
throw new BlockProcessingException("Invalid sync committee signature in " + aggregate);
}
// Compute participant and proposer rewards
final UInt64 totalActiveIncrements = beaconStateAccessors.getTotalActiveBalance(state).dividedBy(specConfig.getEffectiveBalanceIncrement());
final UInt64 totalBaseRewards = beaconStateAccessorsAltair.getBaseRewardPerIncrement(state).times(totalActiveIncrements);
final UInt64 maxParticipantRewards = totalBaseRewards.times(SYNC_REWARD_WEIGHT).dividedBy(WEIGHT_DENOMINATOR).dividedBy(specConfig.getSlotsPerEpoch());
final UInt64 participantReward = maxParticipantRewards.dividedBy(specConfigAltair.getSyncCommitteeSize());
final UInt64 proposerReward = participantReward.times(PROPOSER_WEIGHT).dividedBy(WEIGHT_DENOMINATOR.minus(PROPOSER_WEIGHT));
// Apply participant and proposer rewards
participantPubkeys.stream().map(pubkey -> validatorsUtil.getValidatorIndex(state, pubkey).orElseThrow()).forEach(participantIndex -> beaconStateMutators.increaseBalance(state, participantIndex, participantReward));
UInt64 totalProposerReward = proposerReward.times(participantPubkeys.size());
beaconStateMutators.increaseBalance(state, beaconStateAccessors.getBeaconProposerIndex(state), totalProposerReward);
// impose penalties for any idle validators
idlePubkeys.stream().map(pubkey -> validatorsUtil.getValidatorIndex(state, pubkey).orElseThrow()).forEach(participantIndex -> beaconStateMutators.decreaseBalance(state, participantIndex, participantReward));
}
use of tech.pegasys.teku.spec.datastructures.state.beaconstate.MutableBeaconState 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.beaconstate.MutableBeaconState in project teku by ConsenSys.
the class BeaconStateMutators method initiateValidatorExit.
public void initiateValidatorExit(MutableBeaconState state, int index) {
Validator validator = state.getValidators().get(index);
// Return if validator already initiated exit
if (!validator.getExit_epoch().equals(FAR_FUTURE_EPOCH)) {
return;
}
// Compute exit queue epoch
List<UInt64> exit_epochs = state.getValidators().stream().map(Validator::getExit_epoch).filter(exitEpoch -> !exitEpoch.equals(FAR_FUTURE_EPOCH)).collect(toList());
exit_epochs.add(miscHelpers.computeActivationExitEpoch(beaconStateAccessors.getCurrentEpoch(state)));
UInt64 exit_queue_epoch = Collections.max(exit_epochs);
final UInt64 final_exit_queue_epoch = exit_queue_epoch;
UInt64 exit_queue_churn = UInt64.valueOf(state.getValidators().stream().filter(v -> v.getExit_epoch().equals(final_exit_queue_epoch)).count());
if (exit_queue_churn.compareTo(beaconStateAccessors.getValidatorChurnLimit(state)) >= 0) {
exit_queue_epoch = exit_queue_epoch.plus(UInt64.ONE);
}
// Set validator exit epoch and withdrawable epoch
state.getValidators().set(index, validator.withExit_epoch(exit_queue_epoch).withWithdrawable_epoch(exit_queue_epoch.plus(specConfig.getMinValidatorWithdrawabilityDelay())));
}
use of tech.pegasys.teku.spec.datastructures.state.beaconstate.MutableBeaconState in project teku by ConsenSys.
the class AbstractBlockProcessor method processDepositWithoutCheckingMerkleProof.
@Override
public void processDepositWithoutCheckingMerkleProof(final MutableBeaconState state, final Deposit deposit, final Object2IntMap<BLSPublicKey> pubKeyToIndexMap) {
final BLSPublicKey pubkey = deposit.getData().getPubkey();
state.setEth1_deposit_index(state.getEth1_deposit_index().plus(UInt64.ONE));
// Find the validator index associated with this deposit, if it exists
OptionalInt existingIndex;
if (pubKeyToIndexMap != null) {
if (pubKeyToIndexMap.containsKey(pubkey)) {
existingIndex = OptionalInt.of(pubKeyToIndexMap.get(pubkey));
} else {
pubKeyToIndexMap.put(pubkey, state.getValidators().size());
existingIndex = OptionalInt.empty();
}
} else {
Function<Integer, BLSPublicKey> validatorPubkey = index -> beaconStateAccessors.getValidatorPubKey(state, UInt64.valueOf(index)).orElse(null);
existingIndex = IntStream.range(0, state.getValidators().size()).filter(index -> pubkey.equals(validatorPubkey.apply(index))).findFirst();
}
if (existingIndex.isEmpty()) {
// contract
if (depositSignatureIsValid(deposit, pubkey)) {
processNewValidator(state, deposit);
} else {
handleInvalidDeposit(deposit, pubkey, pubKeyToIndexMap);
}
} else {
// This validator already exists, increase their balance
beaconStateMutators.increaseBalance(state, existingIndex.getAsInt(), deposit.getData().getAmount());
}
}
use of tech.pegasys.teku.spec.datastructures.state.beaconstate.MutableBeaconState in project teku by ConsenSys.
the class AbstractEpochProcessor method processRegistryUpdates.
/**
* Processes validator registry updates
*/
@Override
public void processRegistryUpdates(MutableBeaconState state, List<ValidatorStatus> statuses) throws EpochProcessingException {
try {
// Process activation eligibility and ejections
SszMutableList<Validator> validators = state.getValidators();
final UInt64 currentEpoch = beaconStateAccessors.getCurrentEpoch(state);
for (int index = 0; index < validators.size(); index++) {
final ValidatorStatus status = statuses.get(index);
// confirm it isn't already in the queue.
if (!status.isActiveInCurrentEpoch() && status.getCurrentEpochEffectiveBalance().equals(specConfig.getMaxEffectiveBalance())) {
final Validator validator = validators.get(index);
if (validator.getActivation_eligibility_epoch().equals(SpecConfig.FAR_FUTURE_EPOCH)) {
validators.set(index, validator.withActivation_eligibility_epoch(currentEpoch.plus(UInt64.ONE)));
}
}
if (status.isActiveInCurrentEpoch() && status.getCurrentEpochEffectiveBalance().isLessThanOrEqualTo(specConfig.getEjectionBalance())) {
beaconStateMutators.initiateValidatorExit(state, index);
}
}
// Queue validators eligible for activation and not yet dequeued for activation
List<Integer> activationQueue = IntStream.range(0, state.getValidators().size()).filter(index -> !statuses.get(index).isActiveInCurrentEpoch()).filter(index -> {
Validator validator = state.getValidators().get(index);
return validatorsUtil.isEligibleForActivation(state, validator);
}).boxed().sorted((index1, index2) -> {
int comparisonResult = state.getValidators().get(index1).getActivation_eligibility_epoch().compareTo(state.getValidators().get(index2).getActivation_eligibility_epoch());
if (comparisonResult == 0) {
return index1.compareTo(index2);
} else {
return comparisonResult;
}
}).collect(Collectors.toList());
// Dequeued validators for activation up to churn limit (without resetting activation epoch)
int churnLimit = beaconStateAccessors.getValidatorChurnLimit(state).intValue();
int sublistSize = Math.min(churnLimit, activationQueue.size());
for (Integer index : activationQueue.subList(0, sublistSize)) {
state.getValidators().update(index, validator -> validator.withActivation_epoch(miscHelpers.computeActivationExitEpoch(currentEpoch)));
}
} catch (IllegalArgumentException e) {
throw new EpochProcessingException(e);
}
}
Aggregations