Skip to content

Commit ee882b0

Browse files
committed
core,miner,params: implement EIP-7934 - RLP Execution Block Size Limit (#31990)
1 parent 1505a02 commit ee882b0

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

core/block_validator.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain) *Bloc
4949
// header's transaction and uncle roots. The headers are assumed to be already
5050
// validated at this point.
5151
func (v *BlockValidator) ValidateBody(block *types.Block) error {
52+
// check EIP 7934 RLP-encoded block size cap
53+
if v.config.IsOsaka(block.Number(), block.Time()) && block.Size() > params.BlockRLPSizeCap {
54+
return ErrBlockOversized
55+
}
5256
// Check whether the block is already imported.
5357
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
5458
return ErrKnownBlock

core/error.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ var (
2828

2929
// ErrNoGenesis is returned when there is no Genesis Block.
3030
ErrNoGenesis = errors.New("genesis not found in chain")
31+
32+
// ErrBlockOversized is returned if the size of the RLP-encoded block
33+
// exceeds the cap established by EIP 7934
34+
ErrBlockOversized = errors.New("block RLP-encoded size exceeds maximum")
3135
)
3236

3337
// List of evm-call-message pre-checking errors. All state transition messages will

miner/worker.go

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type environment struct {
5050
signer types.Signer
5151
state *state.StateDB // apply state changes here
5252
tcount int // tx count in cycle
53+
size uint64 // size of the block we are building
5354
gasPool *core.GasPool // available gas used to pack transactions
5455
coinbase common.Address
5556
evm *vm.EVM
@@ -69,6 +70,11 @@ const (
6970
commitInterruptNewHead
7071
commitInterruptResubmit
7172
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
7278
)
7379

7480
// newPayloadResult is the result of payload generation.
@@ -96,12 +102,37 @@ type generateParams struct {
96102
}
97103

98104
// 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)
101107
if err != nil {
102108
return &newPayloadResult{err: err}
103109
}
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 {
105136
interrupt := new(atomic.Int32)
106137
timer := time.AfterFunc(miner.config.Recommit, func() {
107138
interrupt.Store(commitInterruptTimeout)
@@ -113,8 +144,8 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo
113144
log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(miner.config.Recommit))
114145
}
115146
}
147+
body := types.Body{Transactions: work.txs, Withdrawals: includedWithdrawals}
116148

117-
body := types.Body{Transactions: work.txs, Withdrawals: params.withdrawals}
118149
allLogs := make([]*types.Log, 0)
119150
for _, r := range work.receipts {
120151
allLogs = append(allLogs, r.Logs...)
@@ -262,6 +293,7 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
262293
witness: state.Witness(),
263294
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, &coinbase), state, miner.chainConfig, vm.Config{}),
264295
chainConfig: miner.chainConfig,
296+
size: uint64(header.Size()),
265297
}, nil
266298
}
267299

@@ -275,6 +307,7 @@ func (miner *Miner) commitTransaction(env *environment, tx *types.Transaction) e
275307
}
276308
env.txs = append(env.txs, tx)
277309
env.receipts = append(env.receipts, receipt)
310+
env.size += tx.Size()
278311
env.tcount++
279312
return nil
280313
}
@@ -300,6 +333,7 @@ func (miner *Miner) commitBlobTransaction(env *environment, tx *types.Transactio
300333
env.receipts = append(env.receipts, receipt)
301334
env.sidecars = append(env.sidecars, sc)
302335
env.blobs += len(sc.Blobs)
336+
env.size += tx.WithoutBlobTxSidecar().Size()
303337
*env.header.BlobGasUsed += receipt.BlobGasUsed
304338
env.tcount++
305339
return nil
@@ -320,7 +354,11 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*
320354
}
321355

322356
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+
)
324362
if env.gasPool == nil {
325363
env.gasPool = new(core.GasPool).AddGas(gasLimit)
326364
}
@@ -376,7 +414,7 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
376414
// Most of the blob gas logic here is agnostic as to if the chain supports
377415
// blobs or not, however the max check panics when called on a chain without
378416
// 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 {
380418
left := eip4844.MaxBlobsPerBlock(miner.chainConfig, env.header.Time) - env.blobs
381419
if left < int(ltx.BlobGas/params.BlobTxBlobGasPerBlob) {
382420
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
393431
continue
394432
}
395433

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+
396440
// Make sure all transactions after osaka have cell proofs
397-
if miner.chainConfig.IsOsaka(env.header.Number, env.header.Time) {
441+
if isOsaka {
398442
if sidecar := tx.BlobTxSidecar(); sidecar != nil {
399443
if sidecar.Version == 0 {
400444
log.Info("Including blob tx with v0 sidecar, recomputing proofs", "hash", ltx.Hash)

params/protocol_params.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ const (
179179
BlobBaseCost = 1 << 14 // Base execution gas cost for a blob.
180180

181181
HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935.
182+
183+
WithdrawalSize = 23 // size of a withdrawal
184+
BlockRLPSizeCap = 9_961_472 // maximum size of an RLP-encoded block
182185
)
183186

184187
// Bls12381G1MultiExpDiscountTable is the gas discount table for BLS12-381 G1 multi exponentiation operation

0 commit comments

Comments
 (0)