Skip to content

Commit

Permalink
update voluntary exit
Browse files Browse the repository at this point in the history
  • Loading branch information
ensi321 committed Apr 12, 2024
1 parent a457953 commit 026fca6
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {FAR_FUTURE_EPOCH, MIN_ACTIVATION_BALANCE, PENDING_CONSOLIDATIONS_LIMIT}
import {verifyConsolidationSignature} from "../signatureSets/index.js";

import {CachedBeaconStateElectra} from "../types.js";
import {getActiveBalance, getConsolidationChurnLimit, isActiveValidator} from "../util/validator.js";
import {getConsolidationChurnLimit, isActiveValidator} from "../util/validator.js";
import {hasExecutionWithdrawalCredential} from "../util/electra.js";
import {computeConsolidationEpochAndUpdateChurn} from "../util/epoch.js";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import {toHexString} from "@chainsafe/ssz";
import {electra, phase0, ssz} from "@lodestar/types";
import {FAR_FUTURE_EPOCH, MIN_ACTIVATION_BALANCE, PENDING_PARTIAL_WITHDRAWALS_LIMIT, FULL_EXIT_REQUEST_AMOUNT} from "@lodestar/params";
import {
FAR_FUTURE_EPOCH,
MIN_ACTIVATION_BALANCE,
PENDING_PARTIAL_WITHDRAWALS_LIMIT,
FULL_EXIT_REQUEST_AMOUNT,
} from "@lodestar/params";

import {CachedBeaconStateElectra} from "../types.js";
import {hasCompoundingWithdrawalCredential, hasExecutionWithdrawalCredential} from "../util/electra.js";
Expand Down Expand Up @@ -51,14 +56,20 @@ export function processExecutionLayerWithdrawRequest(
// TODO Electra: add log here
}
return;
}
}

const hasSufficientEffectiveBalance = validator.effectiveBalance >= MIN_ACTIVATION_BALANCE;
const hasExcessBalance = validatorBalance > MIN_ACTIVATION_BALANCE + pendingBalanceToWithdraw;

// Only allow partial withdrawals with compounding withdrawal credentials
if (hasCompoundingWithdrawalCredential(validator.withdrawalCredentials) && hasSufficientEffectiveBalance && hasExcessBalance) {
const amountToWithdraw = BigInt(Math.min(validatorBalance - MIN_ACTIVATION_BALANCE - pendingBalanceToWithdraw, amount));
if (
hasCompoundingWithdrawalCredential(validator.withdrawalCredentials) &&
hasSufficientEffectiveBalance &&
hasExcessBalance
) {
const amountToWithdraw = BigInt(
Math.min(validatorBalance - MIN_ACTIVATION_BALANCE - pendingBalanceToWithdraw, amount)
);
const exitQueueEpoch = computeExitEpochAndUpdateChurn(state, amountToWithdraw);
const withdrawableEpoch = exitQueueEpoch + config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY;

Expand All @@ -68,7 +79,7 @@ export function processExecutionLayerWithdrawRequest(
withdrawableEpoch,
});
state.pendingPartialWithdrawals.push(pendingPartialWithdrawal);
}
}
}

function isValidValidator(
Expand Down
22 changes: 17 additions & 5 deletions packages/state-transition/src/block/processVoluntaryExit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ export function processVoluntaryExit(
signedVoluntaryExit: phase0.SignedVoluntaryExit,
verifySignature = true
): void {
if (!isValidVoluntaryExit(fork, state, signedVoluntaryExit, verifySignature)) {
const isAfterElectra = fork >= ForkSeq.electra;
if (
(!isAfterElectra && !isValidVoluntaryExit(state, signedVoluntaryExit, verifySignature)) ||
(isAfterElectra &&
!isValidVoluntaryExitElectra(state as CachedBeaconStateElectra, signedVoluntaryExit, verifySignature))
) {
throw Error("Invalid voluntary exit");
}

Expand All @@ -25,7 +30,6 @@ export function processVoluntaryExit(
}

export function isValidVoluntaryExit(
fork: ForkSeq,
state: CachedBeaconStateAllForks,
signedVoluntaryExit: phase0.SignedVoluntaryExit,
verifySignature = true
Expand All @@ -34,7 +38,6 @@ export function isValidVoluntaryExit(
const voluntaryExit = signedVoluntaryExit.message;
const validator = state.validators.get(voluntaryExit.validatorIndex);
const currentEpoch = epochCtx.epoch;
const isAfterElectra = fork >= ForkSeq.electra;

return (
// verify the validator is active
Expand All @@ -45,9 +48,18 @@ export function isValidVoluntaryExit(
currentEpoch >= voluntaryExit.epoch &&
// verify the validator had been active long enough
currentEpoch >= validator.activationEpoch + config.SHARD_COMMITTEE_PERIOD &&
// only exit validator if it has no pending withdrawals in the queue (post-Electra only)
isAfterElectra ? getPendingBalanceToWithdraw(state as CachedBeaconStateElectra, voluntaryExit.validatorIndex) === 0 : true &&
// verify signature
(!verifySignature || verifyVoluntaryExitSignature(state, signedVoluntaryExit))
);
}

function isValidVoluntaryExitElectra(
state: CachedBeaconStateElectra,
signedVoluntaryExit: phase0.SignedVoluntaryExit,
verifySignature = true
): boolean {
const isValidPreElectra = isValidVoluntaryExit(state, signedVoluntaryExit, verifySignature);

// only exit validator if it has no pending withdrawals in the queue (post-Electra only)
return isValidPreElectra && getPendingBalanceToWithdraw(state, signedVoluntaryExit.message.validatorIndex) === 0;
}
6 changes: 5 additions & 1 deletion packages/state-transition/src/block/processWithdrawals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ export function getExpectedWithdrawals(

const validator = validators.getReadonly(withdrawal.index);

if (validator.exitEpoch === FAR_FUTURE_EPOCH && validator.effectiveBalance >= MIN_ACTIVATION_BALANCE && balances.get(withdrawalIndex) > MIN_ACTIVATION_BALANCE) {
if (
validator.exitEpoch === FAR_FUTURE_EPOCH &&
validator.effectiveBalance >= MIN_ACTIVATION_BALANCE &&
balances.get(withdrawalIndex) > MIN_ACTIVATION_BALANCE
) {
const balanceOverMinActivationBalance = BigInt(balances.get(withdrawalIndex) - MIN_ACTIVATION_BALANCE);
const withdrawableBalance =
balanceOverMinActivationBalance < withdrawal.amount ? balanceOverMinActivationBalance : withdrawal.amount;
Expand Down
2 changes: 1 addition & 1 deletion packages/state-transition/src/util/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ export function getPendingBalanceToWithdraw(state: CachedBeaconStateElectra, val
.getAllReadonly()
.filter((item) => item.index === validatorIndex)
.reduce((total, item) => total + Number(item.amount), 0);
}
}

0 comments on commit 026fca6

Please sign in to comment.