From 6dc692e08ac30623e5a6d7898e659ed6d2604806 Mon Sep 17 00:00:00 2001 From: pk910 Date: Thu, 23 Jul 2026 13:26:46 +0200 Subject: [PATCH] Revert "adjust gaslimit if el ignores targetGasLimit" This reverts commit 79273c6699947cd3ed187945179cf052670d9a02. --- pkg/payload_builder/gaslimit.go | 21 -------- pkg/payload_builder/gaslimit_test.go | 71 ------------------------- pkg/payload_builder/payload_builder.go | 50 ++--------------- pkg/payload_builder/payload_modifier.go | 20 ++----- pkg/rpc/beacon/client.go | 32 ----------- 5 files changed, 8 insertions(+), 186 deletions(-) delete mode 100644 pkg/payload_builder/gaslimit.go delete mode 100644 pkg/payload_builder/gaslimit_test.go diff --git a/pkg/payload_builder/gaslimit.go b/pkg/payload_builder/gaslimit.go deleted file mode 100644 index 42535bfb..00000000 --- a/pkg/payload_builder/gaslimit.go +++ /dev/null @@ -1,21 +0,0 @@ -package payload_builder - -// expectedBidGasLimit returns the gas limit a Gloas execution payload bid -// must commit to for gossip validation to accept it: the parent block's -// committed gas limit moved toward the proposer's preferred target, clamped -// to the maximum per-block adjustment of parent/1024 - 1. Any other value is -// rejected with InvalidGasLimit, so an EL that builds toward a different -// target produces unbiddable payloads unless the gas limit is adjusted to -// this value. -func expectedBidGasLimit(parentGasLimit, targetGasLimit uint64) uint64 { - maxDiff := max(parentGasLimit/1024, 1) - 1 - - switch { - case targetGasLimit > parentGasLimit && targetGasLimit-parentGasLimit > maxDiff: - return parentGasLimit + maxDiff - case targetGasLimit < parentGasLimit && parentGasLimit-targetGasLimit > maxDiff: - return parentGasLimit - maxDiff - default: - return targetGasLimit - } -} diff --git a/pkg/payload_builder/gaslimit_test.go b/pkg/payload_builder/gaslimit_test.go deleted file mode 100644 index 2a990a97..00000000 --- a/pkg/payload_builder/gaslimit_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package payload_builder - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestExpectedBidGasLimit(t *testing.T) { - tests := []struct { - name string - parentGasLimit uint64 - targetGasLimit uint64 - expected uint64 - }{ - { - name: "target reachable within one step", - parentGasLimit: 300_000_000, - targetGasLimit: 300_000_000, - expected: 300_000_000, - }, - { - name: "target slightly above parent within bounds", - parentGasLimit: 299_903_641, - targetGasLimit: 300_000_000, - expected: 300_000_000, - }, - { - name: "target far above parent clamps to max step up", - parentGasLimit: 30_000_000, - targetGasLimit: 300_000_000, - expected: 30_000_000 + 30_000_000/1024 - 1, - }, - { - name: "target far below parent clamps to max step down", - parentGasLimit: 300_000_000, - targetGasLimit: 45_000_000, - expected: 300_000_000 - (300_000_000/1024 - 1), - }, - { - name: "target slightly below parent within bounds", - parentGasLimit: 300_000_000, - targetGasLimit: 299_900_000, - expected: 299_900_000, - }, - { - name: "boundary exactly at max diff up", - parentGasLimit: 1_024_000, - targetGasLimit: 1_024_000 + 999, - expected: 1_024_000 + 999, - }, - { - name: "boundary one above max diff up", - parentGasLimit: 1_024_000, - targetGasLimit: 1_024_000 + 1000, - expected: 1_024_000 + 999, - }, - { - name: "tiny parent has zero adjustment room", - parentGasLimit: 100, - targetGasLimit: 200, - expected: 100, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.expected, expectedBidGasLimit(tt.parentGasLimit, tt.targetGasLimit)) - }) - } -} diff --git a/pkg/payload_builder/payload_builder.go b/pkg/payload_builder/payload_builder.go index a48d03bf..e1452c3d 100644 --- a/pkg/payload_builder/payload_builder.go +++ b/pkg/payload_builder/payload_builder.go @@ -230,24 +230,6 @@ func (b *PayloadBuilder) BuildPayloadFromAttributes( "payload_id": fmt.Sprintf("%x", payloadID[:]), }).Debug("Payload build requested from attributes") - // Resolve the gas limit the slot's bid must commit to while the EL - // accumulates transactions. Bid gossip validation compares against the - // parent block's committed gas limit moved toward the proposer's target - // at the maximum per-block step; an EL that ignores the targetGasLimit - // payload attribute builds toward its own configured target instead, so - // the built payload's gas limit is corrected to the expected value below. - var expectedGasLimit uint64 - - if beaconFork >= version.DataVersionGloas && targetGasLimit > 0 { - parentInfo, err := b.clClient.GetBlockInfo(buildCtx, fmt.Sprintf("%#x", attrs.ParentBlockRoot[:])) - if err != nil { - b.log.WithError(err).WithField("slot", attrs.ProposalSlot). - Warn("Failed to fetch parent block gas limit, keeping EL gas limit") - } else { - expectedGasLimit = expectedBidGasLimit(parentInfo.GasLimit, targetGasLimit) - } - } - // Read the build time live from config so UI overrides take effect immediately. payloadBuildTime := b.cfg.PayloadBuildTime @@ -276,41 +258,15 @@ func (b *PayloadBuilder) BuildPayloadFromAttributes( return nil, fmt.Errorf("getPayload returned no execution payload") } - // Correct the payload gas limit when the EL built with a different one - // than the bid must commit to. Raising it is always safe; lowering it is - // impossible once the EL packed more gas than the expected limit allows. - var gasLimitOverride uint64 - - if expectedGasLimit > 0 && enginePayload.GasLimit != expectedGasLimit { - if enginePayload.GasUsed > expectedGasLimit { - b.log.WithFields(logrus.Fields{ - "slot": attrs.ProposalSlot, - "el_gas_limit": enginePayload.GasLimit, - "expected_gas_limit": expectedGasLimit, - "gas_used": enginePayload.GasUsed, - }).Warn("Cannot adjust payload gas limit below gas used, bid will fail gossip validation") - } else { - gasLimitOverride = expectedGasLimit - - b.log.WithFields(logrus.Fields{ - "slot": attrs.ProposalSlot, - "el_gas_limit": enginePayload.GasLimit, - "expected_gas_limit": expectedGasLimit, - }).Info("Adjusting payload gas limit to expected bid gas limit") - } - } - - // Inject our extra-data marker (and the gas limit correction) and - // recompute the block hash on the typed payload. - newHash, err := ModifyPayload( + // Inject our extra-data marker and recompute the block hash on the typed payload. + newHash, err := ModifyPayloadExtraData( enginePayload, resp.ExecutionRequests, []byte(b.cfg.ExtraData), - gasLimitOverride, common.Hash(attrs.ParentBeaconBlockRoot), ) if err != nil { - return nil, fmt.Errorf("failed to modify payload: %w", err) + return nil, fmt.Errorf("failed to modify payload extra data: %w", err) } // Single fork-independent conversions to the beacon types: the execution diff --git a/pkg/payload_builder/payload_modifier.go b/pkg/payload_builder/payload_modifier.go index 4b4f9c08..a1587353 100644 --- a/pkg/payload_builder/payload_modifier.go +++ b/pkg/payload_builder/payload_modifier.go @@ -17,14 +17,10 @@ import ( const maxExtraDataSize = 32 -// ModifyPayload rewrites header-only fields of a built execution payload in -// place and recomputes the block hash: the extraData field gets the given -// prefix prepended (truncating the original to stay within the 32-byte -// limit), and a non-zero gasLimitOverride replaces the gas limit the EL built -// with (used when the EL ignores the requested target gas limit; the caller -// must ensure the override stays >= gasUsed and within the EIP-1559 bounds of -// the parent). The payload's BlockHash field is updated and the new hash -// returned. +// ModifyPayloadExtraData rewrites the extraData field of a built execution +// payload in place, prepending the given prefix (truncating the original to +// stay within the 32-byte limit), recomputes the block hash, updates the +// payload's BlockHash field, and returns the new hash. // // The parentBeaconBlockRoot is required because it is part of the block header // (and therefore affects the block hash) but is not carried in the execution @@ -37,11 +33,10 @@ const maxExtraDataSize = 32 // The function first verifies it can reconstruct the original block hash from // the payload fields. If verification fails (e.g. an unhandled fork added new // header fields) it returns an error rather than producing an incorrect hash. -func ModifyPayload( +func ModifyPayloadExtraData( p *engineall.ExecutionPayload, executionRequests []prague.ExecutionRequest, extraDataPrefix []byte, - gasLimitOverride uint64, parentBeaconBlockRoot common.Hash, ) (common.Hash, error) { header, err := buildHeaderFromPayload(p, parentBeaconBlockRoot, executionRequests) @@ -75,11 +70,6 @@ func ModifyPayload( } } - if gasLimitOverride > 0 { - header.GasLimit = gasLimitOverride - p.GasLimit = gasLimitOverride - } - // Build new extra data: prefix + "/" separator + original (truncated to // fit). The separator keeps the prefix readable when concatenated with the // EL's original extra data (e.g. "buildoor-0/ethrex 17.0.0" rather than diff --git a/pkg/rpc/beacon/client.go b/pkg/rpc/beacon/client.go index 4240a089..0ee41bc6 100644 --- a/pkg/rpc/beacon/client.go +++ b/pkg/rpc/beacon/client.go @@ -275,10 +275,6 @@ type BlockInfo struct { FinalitySafeExecutionBlockHash phase0.Hash32 ParentRoot phase0.Root StateRoot phase0.Root - // Gas limit committed for the block's execution payload: the builder - // bid's gas_limit from Gloas on (present even when the payload was - // withheld), the embedded payload's gas_limit before. - GasLimit uint64 } // FinalityInfo contains finality checkpoint execution block hashes. @@ -328,11 +324,6 @@ func (c *Client) GetBlockInfo(ctx context.Context, blockID string) (*BlockInfo, return nil, fmt.Errorf("failed to get finality-safe execution block hash: %w", err) } - gasLimit, err := agnosticExecutionGasLimit(msg) - if err != nil { - return nil, fmt.Errorf("failed to get execution gas limit: %w", err) - } - return &BlockInfo{ Slot: msg.Slot, Root: root, @@ -340,7 +331,6 @@ func (c *Client) GetBlockInfo(ctx context.Context, blockID string) (*BlockInfo, FinalitySafeExecutionBlockHash: finalitySafeHash, ParentRoot: msg.ParentRoot, StateRoot: msg.StateRoot, - GasLimit: gasLimit, }, nil } @@ -390,28 +380,6 @@ func agnosticFinalitySafeExecutionBlockHash(msg *all.BeaconBlock) (phase0.Hash32 return body.ExecutionPayload.BlockHash, nil } -// agnosticExecutionGasLimit extracts the committed execution gas limit from a -// fork-agnostic beacon block. From Gloas on it is the builder bid's gas_limit -// (the value consensus gas-limit checks compare a child bid against, even when -// the payload was withheld); before Gloas it is the embedded payload's. -func agnosticExecutionGasLimit(msg *all.BeaconBlock) (uint64, error) { - body := msg.Body - - if msg.Version >= version.DataVersionGloas { - if body.SignedExecutionPayloadBid == nil || body.SignedExecutionPayloadBid.Message == nil { - return 0, fmt.Errorf("no execution payload bid in block") - } - - return body.SignedExecutionPayloadBid.Message.GasLimit, nil - } - - if body.ExecutionPayload == nil { - return 0, fmt.Errorf("no execution payload in block") - } - - return body.ExecutionPayload.GasLimit, nil -} - // GetFinalityInfo fetches finality checkpoints and returns execution block hashes. func (c *Client) GetFinalityInfo(ctx context.Context) (*FinalityInfo, error) { // Get finality checkpoints