Skip to content
Merged
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
21 changes: 0 additions & 21 deletions pkg/payload_builder/gaslimit.go

This file was deleted.

71 changes: 0 additions & 71 deletions pkg/payload_builder/gaslimit_test.go

This file was deleted.

50 changes: 3 additions & 47 deletions pkg/payload_builder/payload_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
20 changes: 5 additions & 15 deletions pkg/payload_builder/payload_modifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
32 changes: 0 additions & 32 deletions pkg/rpc/beacon/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -328,19 +324,13 @@ 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,
ExecutionBlockHash: execBlockHash,
FinalitySafeExecutionBlockHash: finalitySafeHash,
ParentRoot: msg.ParentRoot,
StateRoot: msg.StateRoot,
GasLimit: gasLimit,
}, nil
}

Expand Down Expand Up @@ -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
Expand Down