Skip to content

Commit b755cec

Browse files
fjlholiman
authored andcommitted
beacon/engine: strip type byte in requests (#30576)
This change brings geth into compliance with the current engine API specification for the Prague fork. I have moved the assignment of ExecutionPayloadEnvelope.Requests into BlockToExecutableData to ensure there is a single place where the type is removed. While doing so, I noticed that handling of requests in the miner was not quite correct for the empty payload. It would return `nil` requests for the empty payload even for blocks after the Prague fork. To fix this, I have added the emptyRequests field in miner.Payload.
1 parent 7a625d3 commit b755cec

File tree

4 files changed

+54
-30
lines changed

4 files changed

+54
-30
lines changed

beacon/blsync/engineclient.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func (ec *engineClient) updateLoop(headCh <-chan types.ChainHeadEvent) {
9292
}
9393

9494
func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent) (string, error) {
95-
execData := engine.BlockToExecutableData(event.Block, nil, nil).ExecutionPayload
95+
execData := engine.BlockToExecutableData(event.Block, nil, nil, nil).ExecutionPayload
9696

9797
var (
9898
method string

beacon/engine/types.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,15 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
260260

261261
var requestsHash *common.Hash
262262
if requests != nil {
263-
h := types.CalcRequestsHash(requests)
263+
// Put back request type byte.
264+
typedRequests := make([][]byte, len(requests))
265+
for i, reqdata := range requests {
266+
typedReqdata := make([]byte, len(reqdata)+1)
267+
typedReqdata[0] = byte(i)
268+
copy(typedReqdata[1:], reqdata)
269+
typedRequests[i] = typedReqdata
270+
}
271+
h := types.CalcRequestsHash(typedRequests)
264272
requestsHash = &h
265273
}
266274

@@ -294,7 +302,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
294302

295303
// BlockToExecutableData constructs the ExecutableData structure by filling the
296304
// fields from the given block. It assumes the given block is post-merge block.
297-
func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope {
305+
func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar, requests [][]byte) *ExecutionPayloadEnvelope {
298306
data := &ExecutableData{
299307
BlockHash: block.Hash(),
300308
ParentHash: block.ParentHash(),
@@ -315,6 +323,8 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
315323
ExcessBlobGas: block.ExcessBlobGas(),
316324
ExecutionWitness: block.ExecutionWitness(),
317325
}
326+
327+
// Add blobs.
318328
bundle := BlobsBundleV1{
319329
Commitments: make([]hexutil.Bytes, 0),
320330
Blobs: make([]hexutil.Bytes, 0),
@@ -327,7 +337,23 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
327337
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
328338
}
329339
}
330-
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
340+
341+
// Remove type byte in requests.
342+
var plainRequests [][]byte
343+
if requests != nil {
344+
plainRequests = make([][]byte, len(requests))
345+
for i, reqdata := range requests {
346+
plainRequests[i] = reqdata[1:]
347+
}
348+
}
349+
350+
return &ExecutionPayloadEnvelope{
351+
ExecutionPayload: data,
352+
BlockValue: fees,
353+
BlobsBundle: &bundle,
354+
Requests: plainRequests,
355+
Override: false,
356+
}
331357
}
332358

333359
// ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange

eth/catalyst/api_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1600,7 +1600,7 @@ func TestBlockToPayloadWithBlobs(t *testing.T) {
16001600
}
16011601

16021602
block := types.NewBlock(&header, &types.Body{Transactions: txs}, nil, trie.NewStackTrie(nil))
1603-
envelope := engine.BlockToExecutableData(block, nil, sidecars)
1603+
envelope := engine.BlockToExecutableData(block, nil, sidecars, nil)
16041604
var want int
16051605
for _, tx := range txs {
16061606
want += len(tx.BlobHashes())

miner/payload_building.go

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -69,26 +69,28 @@ func (args *BuildPayloadArgs) Id() engine.PayloadID {
6969
// the revenue. Therefore, the empty-block here is always available and full-block
7070
// will be set/updated afterwards.
7171
type Payload struct {
72-
id engine.PayloadID
73-
empty *types.Block
74-
emptyWitness *stateless.Witness
75-
full *types.Block
76-
fullWitness *stateless.Witness
77-
sidecars []*types.BlobTxSidecar
78-
requests [][]byte
79-
fullFees *big.Int
80-
stop chan struct{}
81-
lock sync.Mutex
82-
cond *sync.Cond
72+
id engine.PayloadID
73+
empty *types.Block
74+
emptyWitness *stateless.Witness
75+
full *types.Block
76+
fullWitness *stateless.Witness
77+
sidecars []*types.BlobTxSidecar
78+
emptyRequests [][]byte
79+
requests [][]byte
80+
fullFees *big.Int
81+
stop chan struct{}
82+
lock sync.Mutex
83+
cond *sync.Cond
8384
}
8485

8586
// newPayload initializes the payload object.
86-
func newPayload(empty *types.Block, witness *stateless.Witness, id engine.PayloadID) *Payload {
87+
func newPayload(empty *types.Block, emptyRequests [][]byte, witness *stateless.Witness, id engine.PayloadID) *Payload {
8788
payload := &Payload{
88-
id: id,
89-
empty: empty,
90-
emptyWitness: witness,
91-
stop: make(chan struct{}),
89+
id: id,
90+
empty: empty,
91+
emptyRequests: emptyRequests,
92+
emptyWitness: witness,
93+
stop: make(chan struct{}),
9294
}
9395
log.Info("Starting work on payload", "id", payload.id)
9496
payload.cond = sync.NewCond(&payload.lock)
@@ -143,16 +145,14 @@ func (payload *Payload) Resolve() *engine.ExecutionPayloadEnvelope {
143145
close(payload.stop)
144146
}
145147
if payload.full != nil {
146-
envelope := engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars)
147-
envelope.Requests = payload.requests
148+
envelope := engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars, payload.emptyRequests)
148149
if payload.fullWitness != nil {
149150
envelope.Witness = new(hexutil.Bytes)
150151
*envelope.Witness, _ = rlp.EncodeToBytes(payload.fullWitness) // cannot fail
151152
}
152153
return envelope
153154
}
154-
envelope := engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil)
155-
envelope.Requests = payload.requests
155+
envelope := engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil, payload.emptyRequests)
156156
if payload.emptyWitness != nil {
157157
envelope.Witness = new(hexutil.Bytes)
158158
*envelope.Witness, _ = rlp.EncodeToBytes(payload.emptyWitness) // cannot fail
@@ -166,8 +166,7 @@ func (payload *Payload) ResolveEmpty() *engine.ExecutionPayloadEnvelope {
166166
payload.lock.Lock()
167167
defer payload.lock.Unlock()
168168

169-
envelope := engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil)
170-
envelope.Requests = payload.requests
169+
envelope := engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil, payload.emptyRequests)
171170
if payload.emptyWitness != nil {
172171
envelope.Witness = new(hexutil.Bytes)
173172
*envelope.Witness, _ = rlp.EncodeToBytes(payload.emptyWitness) // cannot fail
@@ -198,8 +197,7 @@ func (payload *Payload) ResolveFull() *engine.ExecutionPayloadEnvelope {
198197
default:
199198
close(payload.stop)
200199
}
201-
envelope := engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars)
202-
envelope.Requests = payload.requests
200+
envelope := engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars, payload.requests)
203201
if payload.fullWitness != nil {
204202
envelope.Witness = new(hexutil.Bytes)
205203
*envelope.Witness, _ = rlp.EncodeToBytes(payload.fullWitness) // cannot fail
@@ -227,7 +225,7 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs, witness bool) (*Payload
227225
return nil, empty.err
228226
}
229227
// Construct a payload object for return.
230-
payload := newPayload(empty.block, empty.witness, args.Id())
228+
payload := newPayload(empty.block, empty.requests, empty.witness, args.Id())
231229

232230
// Spin up a routine for updating the payload in background. This strategy
233231
// can maximum the revenue for including transactions with highest fee.

0 commit comments

Comments
 (0)