From a37f85f9fc67590374577fd6b3c57652f1ab11b1 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:57:09 -0700 Subject: [PATCH 1/3] chore: clean up single-used function --- .../epoch/processEffectiveBalanceUpdates.ts | 10 +-- .../src/epoch/processPendingConsolidations.ts | 13 ++-- .../src/slot/upgradeStateToElectra.ts | 69 ++++++------------- packages/state-transition/src/util/electra.ts | 21 +----- .../state-transition/src/util/validator.ts | 8 --- 5 files changed, 30 insertions(+), 91 deletions(-) diff --git a/packages/state-transition/src/epoch/processEffectiveBalanceUpdates.ts b/packages/state-transition/src/epoch/processEffectiveBalanceUpdates.ts index 26180d0d9f34..1fe5c92eea1a 100644 --- a/packages/state-transition/src/epoch/processEffectiveBalanceUpdates.ts +++ b/packages/state-transition/src/epoch/processEffectiveBalanceUpdates.ts @@ -5,12 +5,10 @@ import { HYSTERESIS_QUOTIENT, HYSTERESIS_UPWARD_MULTIPLIER, MAX_EFFECTIVE_BALANCE, - MAX_EFFECTIVE_BALANCE_ELECTRA, - MIN_ACTIVATION_BALANCE, TIMELY_TARGET_FLAG_INDEX, } from "@lodestar/params"; import {EpochTransitionCache, CachedBeaconStateAllForks, BeaconStateAltair} from "../types.js"; -import {hasCompoundingWithdrawalCredential} from "../util/electra.js"; +import {getMaxEffectiveBalance} from "../util/validator.js"; /** Same to https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.5/specs/altair/beacon-chain.md#has_flag */ const TIMELY_TARGET = 1 << TIMELY_TARGET_FLAG_INDEX; @@ -46,7 +44,6 @@ export function processEffectiveBalanceUpdates( // so it's recycled here for performance. const balances = cache.balances ?? state.balances.getAll(); const currentEpochValidators = cache.validators; - const newCompoundingValidators = cache.newCompoundingValidators ?? new Set(); let numUpdate = 0; for (let i = 0, len = balances.length; i < len; i++) { @@ -61,10 +58,7 @@ export function processEffectiveBalanceUpdates( effectiveBalanceLimit = MAX_EFFECTIVE_BALANCE; } else { // from electra, effectiveBalanceLimit is per validator - const isCompoundingValidator = - hasCompoundingWithdrawalCredential(currentEpochValidators[i].withdrawalCredentials) || - newCompoundingValidators.has(i); - effectiveBalanceLimit = isCompoundingValidator ? MAX_EFFECTIVE_BALANCE_ELECTRA : MIN_ACTIVATION_BALANCE; + effectiveBalanceLimit = getMaxEffectiveBalance(currentEpochValidators[i].withdrawalCredentials); } if ( diff --git a/packages/state-transition/src/epoch/processPendingConsolidations.ts b/packages/state-transition/src/epoch/processPendingConsolidations.ts index 28178a509bba..e0058ca67890 100644 --- a/packages/state-transition/src/epoch/processPendingConsolidations.ts +++ b/packages/state-transition/src/epoch/processPendingConsolidations.ts @@ -1,7 +1,7 @@ import {ValidatorIndex} from "@lodestar/types"; import {CachedBeaconStateElectra, EpochTransitionCache} from "../types.js"; import {decreaseBalance, increaseBalance} from "../util/balance.js"; -import {getActiveBalance} from "../util/validator.js"; +import {getMaxEffectiveBalance} from "../util/validator.js"; import {switchToCompoundingValidator} from "../util/electra.js"; /** @@ -40,12 +40,13 @@ export function processPendingConsolidations(state: CachedBeaconStateElectra, ca switchToCompoundingValidator(state, targetIndex); newCompoundingValidators.add(targetIndex); // Move active balance to target. Excess balance is withdrawable. - const activeBalance = getActiveBalance(state, sourceIndex); - decreaseBalance(state, sourceIndex, activeBalance); - increaseBalance(state, targetIndex, activeBalance); + const maxEffectiveBalance = getMaxEffectiveBalance(state.validators.getReadonly(sourceIndex).withdrawalCredentials); + const sourceEffectiveBalance = Math.min(state.balances.get(sourceIndex), maxEffectiveBalance); + decreaseBalance(state, sourceIndex, sourceEffectiveBalance); + increaseBalance(state, targetIndex, sourceEffectiveBalance); if (cachedBalances) { - cachedBalances[sourceIndex] -= activeBalance; - cachedBalances[targetIndex] += activeBalance; + cachedBalances[sourceIndex] -= sourceEffectiveBalance; + cachedBalances[targetIndex] += sourceEffectiveBalance; } nextPendingConsolidation++; diff --git a/packages/state-transition/src/slot/upgradeStateToElectra.ts b/packages/state-transition/src/slot/upgradeStateToElectra.ts index b64ac242f83c..98e9fbd52ce7 100644 --- a/packages/state-transition/src/slot/upgradeStateToElectra.ts +++ b/packages/state-transition/src/slot/upgradeStateToElectra.ts @@ -1,14 +1,11 @@ import {Epoch, ValidatorIndex, ssz} from "@lodestar/types"; -import {FAR_FUTURE_EPOCH, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params"; +import {FAR_FUTURE_EPOCH, GENESIS_SLOT, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params"; import {CachedBeaconStateDeneb} from "../types.js"; import {CachedBeaconStateElectra, getCachedBeaconState} from "../cache/stateCache.js"; -import { - hasCompoundingWithdrawalCredential, - queueEntireBalanceAndResetValidator, - queueExcessActiveBalance, -} from "../util/electra.js"; +import {hasCompoundingWithdrawalCredential, queueExcessActiveBalance} from "../util/electra.js"; import {computeActivationExitEpoch} from "../util/epoch.js"; import {getActivationExitChurnLimit, getConsolidationChurnLimit} from "../util/validator.js"; +import {G2_POINT_AT_INFINITY} from "../constants/constants.js"; /** * Upgrade a state from Deneb to Electra. @@ -93,7 +90,23 @@ export function upgradeStateToElectra(stateDeneb: CachedBeaconStateDeneb): Cache }); for (const validatorIndex of preActivation) { - queueEntireBalanceAndResetValidator(stateElectraView as CachedBeaconStateElectra, validatorIndex); + const stateElectra = stateElectraView as CachedBeaconStateElectra; + const balance = stateElectra.balances.get(validatorIndex); + stateElectra.balances.set(validatorIndex, 0); + + const validator = stateElectra.validators.get(validatorIndex); + validator.effectiveBalance = 0; + stateElectra.epochCtx.effectiveBalanceIncrementsSet(validatorIndex, 0); + validator.activationEligibilityEpoch = FAR_FUTURE_EPOCH; + + const pendingDeposit = ssz.electra.PendingDeposit.toViewDU({ + pubkey: validator.pubkey, + withdrawalCredentials: validator.withdrawalCredentials, + amount: balance, + signature: new Uint8Array(G2_POINT_AT_INFINITY), + slot: GENESIS_SLOT, + }); + stateElectra.pendingDeposits.push(pendingDeposit); } for (let i = 0; i < validatorsArr.length; i++) { @@ -114,45 +127,3 @@ export function upgradeStateToElectra(stateDeneb: CachedBeaconStateDeneb): Cache return stateElectra; } - -export function upgradeStateToElectraOriginal(stateDeneb: CachedBeaconStateDeneb): CachedBeaconStateElectra { - const {config} = stateDeneb; - - const stateElectraNode = ssz.deneb.BeaconState.commitViewDU(stateDeneb); - const stateElectraView = ssz.electra.BeaconState.getViewDU(stateElectraNode); - - const stateElectra = getCachedBeaconState(stateElectraView, stateDeneb); - - stateElectra.fork = ssz.phase0.Fork.toViewDU({ - previousVersion: stateDeneb.fork.currentVersion, - currentVersion: config.ELECTRA_FORK_VERSION, - epoch: stateDeneb.epochCtx.epoch, - }); - - // default value of depositRequestsStartIndex is UNSET_DEPOSIT_REQUESTS_START_INDEX - stateElectra.depositRequestsStartIndex = UNSET_DEPOSIT_REQUESTS_START_INDEX; - - const validatorsArr = stateElectra.validators.getAllReadonly(); - - for (let i = 0; i < validatorsArr.length; i++) { - const validator = validatorsArr[i]; - - // [EIP-7251]: add validators that are not yet active to pending balance deposits - if (validator.activationEligibilityEpoch === FAR_FUTURE_EPOCH) { - queueEntireBalanceAndResetValidator(stateElectra, i); - } - - // [EIP-7251]: Ensure early adopters of compounding credentials go through the activation churn - const withdrawalCredential = validator.withdrawalCredentials; - if (hasCompoundingWithdrawalCredential(withdrawalCredential)) { - queueExcessActiveBalance(stateElectra, i); - } - } - - // Commit new added fields ViewDU to the root node - stateElectra.commit(); - // Clear cache to ensure the cache of deneb fields is not used by new ELECTRA fields - stateElectra["clearCache"](); - - return stateElectra; -} diff --git a/packages/state-transition/src/util/electra.ts b/packages/state-transition/src/util/electra.ts index 90dd9a3881df..cd5f47e2c78d 100644 --- a/packages/state-transition/src/util/electra.ts +++ b/packages/state-transition/src/util/electra.ts @@ -1,4 +1,4 @@ -import {COMPOUNDING_WITHDRAWAL_PREFIX, FAR_FUTURE_EPOCH, GENESIS_SLOT, MIN_ACTIVATION_BALANCE} from "@lodestar/params"; +import {COMPOUNDING_WITHDRAWAL_PREFIX, GENESIS_SLOT, MIN_ACTIVATION_BALANCE} from "@lodestar/params"; import {ValidatorIndex, ssz} from "@lodestar/types"; import {CachedBeaconStateElectra} from "../types.js"; import {G2_POINT_AT_INFINITY} from "../constants/constants.js"; @@ -47,22 +47,3 @@ export function queueExcessActiveBalance(state: CachedBeaconStateElectra, index: state.pendingDeposits.push(pendingDeposit); } } - -export function queueEntireBalanceAndResetValidator(state: CachedBeaconStateElectra, index: ValidatorIndex): void { - const balance = state.balances.get(index); - state.balances.set(index, 0); - - const validator = state.validators.get(index); - validator.effectiveBalance = 0; - state.epochCtx.effectiveBalanceIncrementsSet(index, 0); - validator.activationEligibilityEpoch = FAR_FUTURE_EPOCH; - - const pendingDeposit = ssz.electra.PendingDeposit.toViewDU({ - pubkey: validator.pubkey, - withdrawalCredentials: validator.withdrawalCredentials, - amount: balance, - signature: G2_POINT_AT_INFINITY, - slot: GENESIS_SLOT, - }); - state.pendingDeposits.push(pendingDeposit); -} diff --git a/packages/state-transition/src/util/validator.ts b/packages/state-transition/src/util/validator.ts index ebad21d9d25c..083b1ce1a572 100644 --- a/packages/state-transition/src/util/validator.ts +++ b/packages/state-transition/src/util/validator.ts @@ -84,14 +84,6 @@ export function getMaxEffectiveBalance(withdrawalCredentials: Uint8Array): numbe } } -export function getActiveBalance(state: CachedBeaconStateElectra, validatorIndex: ValidatorIndex): number { - const validatorMaxEffectiveBalance = getMaxEffectiveBalance( - state.validators.getReadonly(validatorIndex).withdrawalCredentials - ); - - return Math.min(state.balances.get(validatorIndex), validatorMaxEffectiveBalance); -} - export function getPendingBalanceToWithdraw(state: CachedBeaconStateElectra, validatorIndex: ValidatorIndex): number { return state.pendingPartialWithdrawals .getAllReadonly() From 133031dedf790a43b7a996382d7a6bc070e11382 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:46:04 -0700 Subject: [PATCH 2/3] Remove Uint8Array --- packages/state-transition/src/slot/upgradeStateToElectra.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/state-transition/src/slot/upgradeStateToElectra.ts b/packages/state-transition/src/slot/upgradeStateToElectra.ts index 98e9fbd52ce7..3c29436c2e5d 100644 --- a/packages/state-transition/src/slot/upgradeStateToElectra.ts +++ b/packages/state-transition/src/slot/upgradeStateToElectra.ts @@ -103,7 +103,7 @@ export function upgradeStateToElectra(stateDeneb: CachedBeaconStateDeneb): Cache pubkey: validator.pubkey, withdrawalCredentials: validator.withdrawalCredentials, amount: balance, - signature: new Uint8Array(G2_POINT_AT_INFINITY), + signature: G2_POINT_AT_INFINITY, slot: GENESIS_SLOT, }); stateElectra.pendingDeposits.push(pendingDeposit); From 4fc7ee02feb25da5b1a55b676bf0c9717194511a Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:57:07 -0700 Subject: [PATCH 3/3] Present state-transition constants in Uint8Array --- .../state-transition/src/constants/constants.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/state-transition/src/constants/constants.ts b/packages/state-transition/src/constants/constants.ts index c3ff3f9ac79e..3afb4e687508 100644 --- a/packages/state-transition/src/constants/constants.ts +++ b/packages/state-transition/src/constants/constants.ts @@ -1,10 +1,12 @@ -export const ZERO_HASH = Buffer.alloc(32, 0); -export const EMPTY_SIGNATURE = Buffer.alloc(96, 0); +export const ZERO_HASH = new Uint8Array(32).fill(0); +export const EMPTY_SIGNATURE = new Uint8Array(96).fill(0); export const SECONDS_PER_DAY = 86400; export const BASE_REWARDS_PER_EPOCH = 4; -export const G2_POINT_AT_INFINITY = Buffer.from( - "c000000000000000000000000000000000000000000000000000000000000000" + - "0000000000000000000000000000000000000000000000000000000000000000" + - "0000000000000000000000000000000000000000000000000000000000000000", - "hex" +export const G2_POINT_AT_INFINITY = new Uint8Array( + Buffer.from( + "c000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000", + "hex" + ) );