From 215f402231b78f3d1edc430a171802ae0a33df86 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Sun, 20 Jul 2025 15:18:51 +0200 Subject: [PATCH] core, params: add limit for max blobs in blob transaction --- core/block_validator.go | 5 +++++ core/error.go | 3 +++ core/state_transition.go | 6 +++++- params/protocol_params.go | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/core/block_validator.go b/core/block_validator.go index 008444fbbc..3a0635b517 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -86,8 +86,13 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { } // Blob transactions may be present after the Cancun fork. + isOsaka := v.config.IsOsaka(block.Number(), block.Time()) var blobs int for i, tx := range block.Transactions() { + if isOsaka && len(tx.BlobHashes()) > params.BlobTxMaxBlobs { + return ErrTooManyBlobs + } + // Count the number of blobs to validate against the header's blobGasUsed blobs += len(tx.BlobHashes()) diff --git a/core/error.go b/core/error.go index b9e894bd9b..635d802863 100644 --- a/core/error.go +++ b/core/error.go @@ -118,6 +118,9 @@ var ( // ErrMissingBlobHashes is returned if a blob transaction has no blob hashes. ErrMissingBlobHashes = errors.New("blob transaction missing blob hashes") + // ErrTooManyBlobs is returned if a blob transaction exceeds the maximum number of blobs. + ErrTooManyBlobs = errors.New("blob transaction has too many blobs") + // ErrBlobTxCreate is returned if a blob transaction has no explicit to field. ErrBlobTxCreate = errors.New("blob transaction of type create") diff --git a/core/state_transition.go b/core/state_transition.go index de4558253b..681c300696 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -354,6 +354,7 @@ func (st *stateTransition) preCheck() error { } } // Check the blob version validity + isOsaka := st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber, st.evm.Context.Time) if msg.BlobHashes != nil { // The to field of a blob tx type is mandatory, and a `BlobTx` transaction internally // has it as a non-nillable value, so any msg derived from blob transaction has it non-nil. @@ -364,6 +365,9 @@ func (st *stateTransition) preCheck() error { if len(msg.BlobHashes) == 0 { return ErrMissingBlobHashes } + if isOsaka && len(msg.BlobHashes) > params.BlobTxMaxBlobs { + return ErrTooManyBlobs + } for i, hash := range msg.BlobHashes { if !kzg4844.IsValidVersionedHash(hash[:]) { return fmt.Errorf("blob %d has invalid hash version", i) @@ -395,7 +399,7 @@ func (st *stateTransition) preCheck() error { } } // Verify tx gas limit does not exceed EIP-7825 cap. - if st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber, st.evm.Context.Time) && msg.GasLimit > params.MaxTxGas { + if isOsaka && msg.GasLimit > params.MaxTxGas { return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, msg.GasLimit) } return st.buyGas() diff --git a/params/protocol_params.go b/params/protocol_params.go index 3b48709a88..2ec3a5c249 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -177,6 +177,7 @@ const ( BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size) BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs BlobTxPointEvaluationPrecompileGas = 50000 // Gas price for the point evaluation precompile. + BlobTxMaxBlobs = 6 BlobBaseCost = 1 << 13 // Base execution gas cost for a blob. HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935.