@@ -50,6 +50,7 @@ type environment struct {
50
50
signer types.Signer
51
51
state * state.StateDB // apply state changes here
52
52
tcount int // tx count in cycle
53
+ size uint64 // size of the block we are building
53
54
gasPool * core.GasPool // available gas used to pack transactions
54
55
coinbase common.Address
55
56
evm * vm.EVM
@@ -69,6 +70,11 @@ const (
69
70
commitInterruptNewHead
70
71
commitInterruptResubmit
71
72
commitInterruptTimeout
73
+
74
+ // cap the size of blocks we will produce below the max allowed by
75
+ // EIP-7934. This gives us buffer room if the estimated size of the
76
+ // block we are building is off from the actual encoded size.
77
+ blockRLPSizeCapBuffer = 1_000_000
72
78
)
73
79
74
80
// newPayloadResult is the result of payload generation.
@@ -96,12 +102,37 @@ type generateParams struct {
96
102
}
97
103
98
104
// generateWork generates a sealing block based on the given parameters.
99
- func (miner * Miner ) generateWork (params * generateParams , witness bool ) * newPayloadResult {
100
- work , err := miner .prepareWork (params , witness )
105
+ func (miner * Miner ) generateWork (genParam * generateParams , witness bool ) * newPayloadResult {
106
+ work , err := miner .prepareWork (genParam , witness )
101
107
if err != nil {
102
108
return & newPayloadResult {err : err }
103
109
}
104
- if ! params .noTxs {
110
+ var includedWithdrawals types.Withdrawals
111
+
112
+ // If we are post-osaka, incorporate the requested withdrawals into the
113
+ // block size calculation up-front to ensure that all requested withdrawals
114
+ // can be included even if we hit the size cap when filling the block with
115
+ // txs.
116
+ //
117
+ // Also, ensure that including all requested withdrawals wouldn't bring us
118
+ // over the block size cap limit. The withdrawal cap ensures that this can't
119
+ // actually happen right now, but it doesn't hurt to make this code
120
+ // future-proof for a situation where the withdrawal cap is lifted.
121
+ if miner .chainConfig .IsOsaka (work .header .Number , work .header .Time ) {
122
+ maxBlockSize := params .BlockRLPSizeCap - blockRLPSizeCapBuffer
123
+
124
+ for _ , withdrawal := range genParam .withdrawals {
125
+ if int (work .size )+ params .WithdrawalSize > maxBlockSize {
126
+ break
127
+ }
128
+ work .size += params .WithdrawalSize
129
+ includedWithdrawals = append (includedWithdrawals , withdrawal )
130
+ }
131
+ } else {
132
+ includedWithdrawals = genParam .withdrawals
133
+ }
134
+
135
+ if ! genParam .noTxs {
105
136
interrupt := new (atomic.Int32 )
106
137
timer := time .AfterFunc (miner .config .Recommit , func () {
107
138
interrupt .Store (commitInterruptTimeout )
@@ -113,8 +144,8 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo
113
144
log .Warn ("Block building is interrupted" , "allowance" , common .PrettyDuration (miner .config .Recommit ))
114
145
}
115
146
}
147
+ body := types.Body {Transactions : work .txs , Withdrawals : includedWithdrawals }
116
148
117
- body := types.Body {Transactions : work .txs , Withdrawals : params .withdrawals }
118
149
allLogs := make ([]* types.Log , 0 )
119
150
for _ , r := range work .receipts {
120
151
allLogs = append (allLogs , r .Logs ... )
@@ -262,6 +293,7 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
262
293
witness : state .Witness (),
263
294
evm : vm .NewEVM (core .NewEVMBlockContext (header , miner .chain , & coinbase ), state , miner .chainConfig , vm.Config {}),
264
295
chainConfig : miner .chainConfig ,
296
+ size : uint64 (header .Size ()),
265
297
}, nil
266
298
}
267
299
@@ -275,6 +307,7 @@ func (miner *Miner) commitTransaction(env *environment, tx *types.Transaction) e
275
307
}
276
308
env .txs = append (env .txs , tx )
277
309
env .receipts = append (env .receipts , receipt )
310
+ env .size += tx .Size ()
278
311
env .tcount ++
279
312
return nil
280
313
}
@@ -300,6 +333,7 @@ func (miner *Miner) commitBlobTransaction(env *environment, tx *types.Transactio
300
333
env .receipts = append (env .receipts , receipt )
301
334
env .sidecars = append (env .sidecars , sc )
302
335
env .blobs += len (sc .Blobs )
336
+ env .size += tx .WithoutBlobTxSidecar ().Size ()
303
337
* env .header .BlobGasUsed += receipt .BlobGasUsed
304
338
env .tcount ++
305
339
return nil
@@ -320,7 +354,11 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*
320
354
}
321
355
322
356
func (miner * Miner ) commitTransactions (env * environment , plainTxs , blobTxs * transactionsByPriceAndNonce , interrupt * atomic.Int32 ) error {
323
- gasLimit := env .header .GasLimit
357
+ var (
358
+ isOsaka = miner .chainConfig .IsOsaka (env .header .Number , env .header .Time )
359
+ isCancun = miner .chainConfig .IsCancun (env .header .Number , env .header .Time )
360
+ gasLimit = env .header .GasLimit
361
+ )
324
362
if env .gasPool == nil {
325
363
env .gasPool = new (core.GasPool ).AddGas (gasLimit )
326
364
}
@@ -376,7 +414,7 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
376
414
// Most of the blob gas logic here is agnostic as to if the chain supports
377
415
// blobs or not, however the max check panics when called on a chain without
378
416
// a defined schedule, so we need to verify it's safe to call.
379
- if miner . chainConfig . IsCancun ( env . header . Number , env . header . Time ) {
417
+ if isCancun {
380
418
left := eip4844 .MaxBlobsPerBlock (miner .chainConfig , env .header .Time ) - env .blobs
381
419
if left < int (ltx .BlobGas / params .BlobTxBlobGasPerBlob ) {
382
420
log .Trace ("Not enough blob space left for transaction" , "hash" , ltx .Hash , "left" , left , "needed" , ltx .BlobGas / params .BlobTxBlobGasPerBlob )
@@ -393,8 +431,14 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
393
431
continue
394
432
}
395
433
434
+ // if inclusion of the transaction would put the block size over the
435
+ // maximum we allow, don't add any more txs to the payload.
436
+ if isOsaka && env .size + tx .Size () > params .BlockRLPSizeCap - blockRLPSizeCapBuffer {
437
+ break
438
+ }
439
+
396
440
// Make sure all transactions after osaka have cell proofs
397
- if miner . chainConfig . IsOsaka ( env . header . Number , env . header . Time ) {
441
+ if isOsaka {
398
442
if sidecar := tx .BlobTxSidecar (); sidecar != nil {
399
443
if sidecar .Version == 0 {
400
444
log .Info ("Including blob tx with v0 sidecar, recomputing proofs" , "hash" , ltx .Hash )
0 commit comments