Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/state-transition/src/block/processDepositRequest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {FAR_FUTURE_EPOCH, ForkSeq, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
import {BLSPubkey, Bytes32, UintNum64, electra, ssz} from "@lodestar/types";
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
import {findBuilderIndexByPubkey, isBuilderWithdrawalCredential} from "../util/gloas.js";
import {findBuilderIndexByPubkey, isBuilderWithdrawalCredential, isPendingValidator} from "../util/gloas.js";
import {computeEpochAtSlot, isValidatorKnown} from "../util/index.js";
import {isValidDepositSignature} from "./processDeposit.js";

Expand Down Expand Up @@ -93,8 +93,9 @@ export function processDepositRequest(
const isValidator = isValidatorKnown(state, validatorIndex);
const isBuilderPrefix = isBuilderWithdrawalCredential(withdrawalCredentials);

// Route to builder if it's an existing builder OR has builder prefix and is not a validator
if (isBuilder || (isBuilderPrefix && !isValidator)) {
// Route to builder if it's an existing builder OR has builder prefix and is not a validator/pending validator
// Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/beacon-chain.md#modified-process_deposit_request
if (isBuilder || (isBuilderPrefix && !isValidator && !isPendingValidator(state.config, stateGloas, pubkey))) {
// Apply builder deposits immediately
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature, state.slot);
return;
Expand Down
33 changes: 32 additions & 1 deletion packages/state-transition/src/util/gloas.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {BeaconConfig} from "@lodestar/config";
import {
BUILDER_INDEX_FLAG,
BUILDER_PAYMENT_THRESHOLD_DENOMINATOR,
Expand All @@ -8,14 +9,44 @@ import {
MIN_DEPOSIT_AMOUNT,
SLOTS_PER_EPOCH,
} from "@lodestar/params";
import {BuilderIndex, Epoch, ValidatorIndex, gloas} from "@lodestar/types";
import {BLSPubkey, BuilderIndex, Epoch, ValidatorIndex, gloas} from "@lodestar/types";
import {AttestationData} from "@lodestar/types/phase0";
import {byteArrayEquals} from "@lodestar/utils";
import {isValidDepositSignature} from "../block/processDeposit.js";
import {CachedBeaconStateGloas} from "../types.js";
import {getBlockRootAtSlot} from "./blockRoot.js";
import {computeEpochAtSlot} from "./epoch.js";
import {RootCache} from "./rootCache.js";

/**
* Check if a pending deposit with a valid signature is in the queue for the given pubkey.
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/beacon-chain.md#new-is_pending_validator
*
* Note: This function naively revalidates deposit signatures on every call.
* Implementations SHOULD cache verification results to avoid repeated work.
* TODO GLOAS: Cache deposit signature validation results to avoid repeated BLS verification
*/
export function isPendingValidator(config: BeaconConfig, state: CachedBeaconStateGloas, pubkey: BLSPubkey): boolean {
for (let i = 0; i < state.pendingDeposits.length; i++) {
const pendingDeposit = state.pendingDeposits.getReadonly(i);
if (!byteArrayEquals(pendingDeposit.pubkey, pubkey)) {
continue;
}
if (
isValidDepositSignature(
config,
pendingDeposit.pubkey,
pendingDeposit.withdrawalCredentials,
pendingDeposit.amount,
pendingDeposit.signature
)
) {
return true;
}
}
return false;
}

export function isBuilderWithdrawalCredential(withdrawalCredentials: Uint8Array): boolean {
return withdrawalCredentials[0] === BUILDER_WITHDRAWAL_PREFIX;
}
Expand Down
Loading