From 5adb4ef364e321e5ad0a29b9dd4f504a0a4f8a3b Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 15 Oct 2024 04:50:22 +0100 Subject: [PATCH] fix: enforce strict timeout for builder to provide bid (#7151) * fix: enforce strict timeout for builder to provide bid * Use math.round --- packages/beacon-node/src/api/impl/validator/index.ts | 4 ++-- packages/beacon-node/src/execution/builder/http.ts | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index 6be825b5eb07..17d327c61034 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -89,7 +89,7 @@ import {computeSubnetForCommitteesAtSlot, getPubkeysForIndices, selectBlockProdu export const SYNC_TOLERANCE_EPOCHS = 1; /** - * Cutoff time to wait for execution and builder block production apis to resolve + * Cutoff time to wait from start of the slot for execution and builder block production apis to resolve * Post this time, race execution and builder to pick whatever resolves first * * Empirically the builder block resolves in ~1.5+ seconds, and execution should resolve <1 sec. @@ -637,7 +637,7 @@ export function getValidatorApi( : Promise.reject(new Error("Engine disabled")); const [builder, engine] = await resolveOrRacePromises([builderPromise, enginePromise], { - resolveTimeoutMs: BLOCK_PRODUCTION_RACE_CUTOFF_MS, + resolveTimeoutMs: Math.max(0, BLOCK_PRODUCTION_RACE_CUTOFF_MS - Math.round(chain.clock.secFromSlot(slot) * 1000)), raceTimeoutMs: BLOCK_PRODUCTION_RACE_TIMEOUT_MS, signal: controller.signal, }); diff --git a/packages/beacon-node/src/execution/builder/http.ts b/packages/beacon-node/src/execution/builder/http.ts index 934b874f5ae3..7872c5c17410 100644 --- a/packages/beacon-node/src/execution/builder/http.ts +++ b/packages/beacon-node/src/execution/builder/http.ts @@ -37,6 +37,12 @@ export const defaultExecutionBuilderHttpOpts: ExecutionBuilderHttpOpts = { timeout: 12000, }; +/** + * Duration given to the builder to provide a `SignedBuilderBid` before the deadline + * is reached, aborting the external builder flow in favor of the local build process. + */ +const BUILDER_PROPOSAL_DELAY_TOLERANCE = 1000; + export class ExecutionBuilderHttp implements IExecutionBuilder { readonly api: BuilderApi; readonly config: ChainForkConfig; @@ -115,7 +121,9 @@ export class ExecutionBuilderHttp implements IExecutionBuilder { executionPayloadValue: Wei; blobKzgCommitments?: deneb.BlobKzgCommitments; }> { - const signedBuilderBid = (await this.api.getHeader({slot, parentHash, proposerPubkey})).value(); + const signedBuilderBid = ( + await this.api.getHeader({slot, parentHash, proposerPubkey}, {timeoutMs: BUILDER_PROPOSAL_DELAY_TOLERANCE}) + ).value(); if (!signedBuilderBid) { throw Error("No bid received");