From 9674c3764a8d27607e8b4b8c45929e0357fa314f Mon Sep 17 00:00:00 2001 From: meta-duck <96756526+meta-duck@users.noreply.github.com> Date: Wed, 13 Aug 2025 02:36:17 +0000 Subject: [PATCH 1/6] feat: Make BUILDER_PROPOSAL_DELAY_TOLERANCE Configurable --- beacon_chain/conf.nim | 5 +++++ beacon_chain/spec/mev/electra_mev.nim | 3 ++- docs/builder-proposal-delay-tolerance.md | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 docs/builder-proposal-delay-tolerance.md diff --git a/beacon_chain/conf.nim b/beacon_chain/conf.nim index e6810357b5..8dd1b0d626 100644 --- a/beacon_chain/conf.nim +++ b/beacon_chain/conf.nim @@ -683,6 +683,11 @@ type defaultValue: 10 name: "local-block-value-boost" .}: uint8 + builderProposalDelayTolerance* {. + desc: "Timeout for builder proposal delay tolerance in milliseconds" + defaultValue: 1500 + name: "builder-proposal-delay-tolerance" .}: int + historyMode* {. desc: "Retention strategy for historical data (archive/prune)" defaultValue: HistoryMode.Prune diff --git a/beacon_chain/spec/mev/electra_mev.nim b/beacon_chain/spec/mev/electra_mev.nim index 49f7a0f2fe..8a8ad55824 100644 --- a/beacon_chain/spec/mev/electra_mev.nim +++ b/beacon_chain/spec/mev/electra_mev.nim @@ -99,7 +99,8 @@ const # Spec is 1 second, but mev-boost indirection can induce delay when the relay # itself has already consumed the entire second. - BUILDER_PROPOSAL_DELAY_TOLERANCE* = 1500.milliseconds + import ../conf + BUILDER_PROPOSAL_DELAY_TOLERANCE* = builderProposalDelayTolerance.milliseconds func shortLog*(v: BlindedBeaconBlock): auto = ( diff --git a/docs/builder-proposal-delay-tolerance.md b/docs/builder-proposal-delay-tolerance.md new file mode 100644 index 0000000000..51f7da2c33 --- /dev/null +++ b/docs/builder-proposal-delay-tolerance.md @@ -0,0 +1,18 @@ +## Builder Proposal Delay Tolerance + +You can now configure the builder proposal delay tolerance (MEV block builder timeout) via the following flag: + +``` +--builder-proposal-delay-tolerance= +``` + +- **Default value:** 1500 (milliseconds) +- **Description:** Timeout for builder proposal delay tolerance. Increasing this value may allow the builder extra time to gather more transactions or MEV value, potentially improving block value and network efficiency. Lower values may reduce block proposal latency. + +**Example usage:** + +``` +./nimbus_beacon_node --builder-proposal-delay-tolerance=2000 +``` + +This option is useful for node operators who wish to tune performance for different environments or experiment with MEV builder timing. From 407a1af2825e8ac4c71e719586fbef01d8683b87 Mon Sep 17 00:00:00 2001 From: meta-duck <96756526+meta-duck@users.noreply.github.com> Date: Wed, 13 Aug 2025 06:57:02 +0000 Subject: [PATCH 2/6] feat: make BUILDER_PROPOSAL_DELAY_TOLERANCE configurable via flag --- beacon_chain/spec/mev/electra_mev.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_chain/spec/mev/electra_mev.nim b/beacon_chain/spec/mev/electra_mev.nim index 8a8ad55824..561c2109fa 100644 --- a/beacon_chain/spec/mev/electra_mev.nim +++ b/beacon_chain/spec/mev/electra_mev.nim @@ -8,6 +8,7 @@ {.push raises: [].} import ".."/datatypes/[altair, bellatrix, electra] +import ../conf from stew/byteutils import to0xHex from ".."/datatypes/phase0 import AttesterSlashing @@ -99,7 +100,6 @@ const # Spec is 1 second, but mev-boost indirection can induce delay when the relay # itself has already consumed the entire second. - import ../conf BUILDER_PROPOSAL_DELAY_TOLERANCE* = builderProposalDelayTolerance.milliseconds func shortLog*(v: BlindedBeaconBlock): auto = From 4207f3e96d1be7ef7833c12f3c4087367d768777 Mon Sep 17 00:00:00 2001 From: meta-duck <96756526+meta-duck@users.noreply.github.com> Date: Wed, 13 Aug 2025 08:25:07 +0000 Subject: [PATCH 3/6] fix wrong config path --- beacon_chain/spec/mev/electra_mev.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_chain/spec/mev/electra_mev.nim b/beacon_chain/spec/mev/electra_mev.nim index 561c2109fa..ea45f86f11 100644 --- a/beacon_chain/spec/mev/electra_mev.nim +++ b/beacon_chain/spec/mev/electra_mev.nim @@ -8,7 +8,7 @@ {.push raises: [].} import ".."/datatypes/[altair, bellatrix, electra] -import ../conf +import ../../conf from stew/byteutils import to0xHex from ".."/datatypes/phase0 import AttesterSlashing From b6672a988f8735fe5a47ef47ece67977a578031b Mon Sep 17 00:00:00 2001 From: meta-duck <96756526+meta-duck@users.noreply.github.com> Date: Wed, 13 Aug 2025 10:23:44 +0000 Subject: [PATCH 4/6] feat: pass builder proposal delay tolerance as config parameter, remove global const --- beacon_chain/spec/mev/electra_mev.nim | 4 +-- beacon_chain/validators/beacon_validators.nim | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/beacon_chain/spec/mev/electra_mev.nim b/beacon_chain/spec/mev/electra_mev.nim index ea45f86f11..af180c8caf 100644 --- a/beacon_chain/spec/mev/electra_mev.nim +++ b/beacon_chain/spec/mev/electra_mev.nim @@ -8,7 +8,7 @@ {.push raises: [].} import ".."/datatypes/[altair, bellatrix, electra] -import ../../conf +# import ../../conf from stew/byteutils import to0xHex from ".."/datatypes/phase0 import AttesterSlashing @@ -100,7 +100,7 @@ const # Spec is 1 second, but mev-boost indirection can induce delay when the relay # itself has already consumed the entire second. - BUILDER_PROPOSAL_DELAY_TOLERANCE* = builderProposalDelayTolerance.milliseconds + # BUILDER_PROPOSAL_DELAY_TOLERANCE* = builderProposalDelayTolerance.milliseconds func shortLog*(v: BlindedBeaconBlock): auto = ( diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index d8025ec5ae..910f81e854 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -618,9 +618,9 @@ proc makeBeaconBlockForHeadAndSlot*( proc getBlindedExecutionPayload[ EPH: electra_mev.BlindedExecutionPayloadAndBlobsBundle | fulu_mev.BlindedExecutionPayloadAndBlobsBundle]( - node: BeaconNode, payloadBuilderClient: RestClientRef, slot: Slot, - executionBlockHash: Eth2Digest, pubkey: ValidatorPubKey): - Future[BlindedBlockResult[EPH]] {.async: (raises: [CancelledError, RestError]).} = + node: BeaconNode, payloadBuilderClient: RestClientRef, slot: Slot, + executionBlockHash: Eth2Digest, pubkey: ValidatorPubKey, builderTimeout: Duration): + Future[BlindedBlockResult[EPH]] {.async: (raises: [CancelledError, RestError]).} = # Not ideal to use `when` where instead of splitting into separate functions, # but Nim doesn't overload on generic EPH type parameter. when EPH is electra_mev.BlindedExecutionPayloadAndBlobsBundle: @@ -628,7 +628,7 @@ proc getBlindedExecutionPayload[ response = awaitWithTimeout( payloadBuilderClient.getHeader( slot, executionBlockHash, pubkey), - BUILDER_PROPOSAL_DELAY_TOLERANCE): + builderTimeout): return err "Timeout obtaining Electra blinded header from builder" res = decodeBytesJsonOrSsz( @@ -646,7 +646,7 @@ proc getBlindedExecutionPayload[ response = awaitWithTimeout( payloadBuilderClient.getHeader( slot, executionBlockHash, pubkey), - BUILDER_PROPOSAL_DELAY_TOLERANCE): + builderTimeout): return err "Timeout obtaining Fulu blinded header from builder" res = decodeBytesJsonOrSsz( @@ -772,11 +772,11 @@ func getUnsignedBlindedBeaconBlock[ proc getBlindedBlockParts[ EPH: electra_mev.BlindedExecutionPayloadAndBlobsBundle | fulu_mev.BlindedExecutionPayloadAndBlobsBundle]( - node: BeaconNode, payloadBuilderClient: RestClientRef, head: BlockRef, - pubkey: ValidatorPubKey, slot: Slot, randao: ValidatorSig, - validator_index: ValidatorIndex, graffiti: GraffitiBytes): - Future[Result[(EPH, UInt256, UInt256, ForkedBeaconBlock, ExecutionRequests), string]] - {.async: (raises: [CancelledError]).} = + node: BeaconNode, payloadBuilderClient: RestClientRef, head: BlockRef, + pubkey: ValidatorPubKey, slot: Slot, randao: ValidatorSig, + validator_index: ValidatorIndex, graffiti: GraffitiBytes, builderTimeout: Duration): + Future[Result[(EPH, UInt256, UInt256, ForkedBeaconBlock, ExecutionRequests), string]] + {.async: (raises: [CancelledError]).} = let executionBlockHash = node.dag.loadExecutionBlockHash(head).valueOr: # With checkpoint sync, the checkpoint block may be unavailable, @@ -790,8 +790,8 @@ proc getBlindedBlockParts[ try: awaitWithTimeout( getBlindedExecutionPayload[EPH]( - node, payloadBuilderClient, slot, executionBlockHash, pubkey), - BUILDER_PROPOSAL_DELAY_TOLERANCE): + node, payloadBuilderClient, slot, executionBlockHash, pubkey, builderTimeout), + builderTimeout): BlindedBlockResult[EPH].err("getBlindedExecutionPayload timed out") except RestDecodingError as exc: BlindedBlockResult[EPH].err( @@ -886,9 +886,10 @@ proc getBuilderBid[ else: static: doAssert false + let builderTimeout = node.config.builderProposalDelayTolerance.milliseconds let blindedBlockParts = await getBlindedBlockParts[EPH]( node, payloadBuilderClient, head, validator_pubkey, slot, randao, - validator_index, graffitiBytes) + validator_index, graffitiBytes, builderTimeout) if blindedBlockParts.isErr: # Not signed yet, fine to try to fall back on EL beacon_block_builder_missed_with_fallback.inc() From e34f69ac4d889e98e40becd0d9d93acdbee3ce1c Mon Sep 17 00:00:00 2001 From: meta-duck <96756526+meta-duck@users.noreply.github.com> Date: Wed, 13 Aug 2025 16:01:16 +0000 Subject: [PATCH 5/6] refactor(conf): remove unused code, change builderProposalDelayTolerance type from int to uint16 --- beacon_chain/conf.nim | 2 +- beacon_chain/spec/mev/electra_mev.nim | 2 -- beacon_chain/validators/beacon_validators.nim | 4 +--- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/beacon_chain/conf.nim b/beacon_chain/conf.nim index 8dd1b0d626..fd4ce37116 100644 --- a/beacon_chain/conf.nim +++ b/beacon_chain/conf.nim @@ -686,7 +686,7 @@ type builderProposalDelayTolerance* {. desc: "Timeout for builder proposal delay tolerance in milliseconds" defaultValue: 1500 - name: "builder-proposal-delay-tolerance" .}: int + name: "builder-proposal-delay-tolerance" .}: uint16 historyMode* {. desc: "Retention strategy for historical data (archive/prune)" diff --git a/beacon_chain/spec/mev/electra_mev.nim b/beacon_chain/spec/mev/electra_mev.nim index af180c8caf..4587ede414 100644 --- a/beacon_chain/spec/mev/electra_mev.nim +++ b/beacon_chain/spec/mev/electra_mev.nim @@ -8,7 +8,6 @@ {.push raises: [].} import ".."/datatypes/[altair, bellatrix, electra] -# import ../../conf from stew/byteutils import to0xHex from ".."/datatypes/phase0 import AttesterSlashing @@ -100,7 +99,6 @@ const # Spec is 1 second, but mev-boost indirection can induce delay when the relay # itself has already consumed the entire second. - # BUILDER_PROPOSAL_DELAY_TOLERANCE* = builderProposalDelayTolerance.milliseconds func shortLog*(v: BlindedBeaconBlock): auto = ( diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index 910f81e854..cd5c8ad117 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -996,9 +996,7 @@ proc collectBids( engineBlockFut = makeBeaconBlockForHeadAndSlot( EPS, node, randao, validator_index, graffitiBytes, head, slot) - # getBuilderBid times out after BUILDER_PROPOSAL_DELAY_TOLERANCE, with 1 more - # second for remote validators. makeBeaconBlockForHeadAndSlot times out after - # 1 second. + await allFutures(payloadBuilderBidFut, engineBlockFut) doAssert payloadBuilderBidFut.finished and engineBlockFut.finished From 819dd8171c6242a6db569c1bd61b98f76121a201 Mon Sep 17 00:00:00 2001 From: meta-duck <96756526+meta-duck@users.noreply.github.com> Date: Thu, 14 Aug 2025 06:29:05 +0000 Subject: [PATCH 6/6] remove extra blank lines, edit doc --- beacon_chain/validators/beacon_validators.nim | 1 - docs/builder-proposal-delay-tolerance.md | 18 ------------------ .../src/external-block-builder.md | 11 +++++++++++ 3 files changed, 11 insertions(+), 19 deletions(-) delete mode 100644 docs/builder-proposal-delay-tolerance.md diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index cd5c8ad117..8be989ba14 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -996,7 +996,6 @@ proc collectBids( engineBlockFut = makeBeaconBlockForHeadAndSlot( EPS, node, randao, validator_index, graffitiBytes, head, slot) - await allFutures(payloadBuilderBidFut, engineBlockFut) doAssert payloadBuilderBidFut.finished and engineBlockFut.finished diff --git a/docs/builder-proposal-delay-tolerance.md b/docs/builder-proposal-delay-tolerance.md deleted file mode 100644 index 51f7da2c33..0000000000 --- a/docs/builder-proposal-delay-tolerance.md +++ /dev/null @@ -1,18 +0,0 @@ -## Builder Proposal Delay Tolerance - -You can now configure the builder proposal delay tolerance (MEV block builder timeout) via the following flag: - -``` ---builder-proposal-delay-tolerance= -``` - -- **Default value:** 1500 (milliseconds) -- **Description:** Timeout for builder proposal delay tolerance. Increasing this value may allow the builder extra time to gather more transactions or MEV value, potentially improving block value and network efficiency. Lower values may reduce block proposal latency. - -**Example usage:** - -``` -./nimbus_beacon_node --builder-proposal-delay-tolerance=2000 -``` - -This option is useful for node operators who wish to tune performance for different environments or experiment with MEV builder timing. diff --git a/docs/the_nimbus_book/src/external-block-builder.md b/docs/the_nimbus_book/src/external-block-builder.md index a48ef4695f..80b794d591 100644 --- a/docs/the_nimbus_book/src/external-block-builder.md +++ b/docs/the_nimbus_book/src/external-block-builder.md @@ -49,6 +49,17 @@ Additionally, the URL of the service exposing the [builder API](https://ethereum build/nimbus_validator_client \ --payload-builder=true ``` +### Builder Proposal Delay Tolerance + +You can configure the builder proposal delay tolerance (MEV block builder timeout) via the following flag: + +``` +--builder-proposal-delay-tolerance= +``` + +- **Default value:** 1500 (milliseconds) +- **Description:** Timeout for builder proposal delay tolerance. Increasing this value may allow the builder extra time to gather more transactions or MEV value, potentially improving block value and network efficiency. Lower values may reduce block proposal latency. + ## Useful resources