core, params: add limit for max blobs in blob transaction (#32246)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run

[EIP-7594](https://eips.ethereum.org/EIPS/eip-7594) defines a limit of
max 6 blobs per transaction. We need to enforce this limit during block
processing.

> Additionally, a limit of 6 blobs per transaction is introduced.
Clients MUST enforce this limit when validating blob transactions at
submission time, when received from the network, and during block
production and processing.
This commit is contained in:
Felix Lange 2025-07-21 16:26:24 +02:00 committed by GitHub
parent d80094f788
commit f96f82bd6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 12 additions and 4 deletions

View file

@ -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")

View file

@ -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()

View file

@ -65,7 +65,7 @@ const (
// carry. We choose a smaller limit than the protocol-permitted MaxBlobsPerBlock
// in order to ensure network and txpool stability.
// Note: if you increase this, validation will fail on txMaxSize.
maxBlobsPerTx = 7
maxBlobsPerTx = params.BlobTxMaxBlobs
// maxTxsPerAccount is the maximum number of blob transactions admitted from
// a single account. The limit is enforced to minimize the DoS potential of

View file

@ -1191,8 +1191,8 @@ func TestBlobCountLimit(t *testing.T) {
// Attempt to add transactions.
var (
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 7, key1)
tx2 = makeMultiBlobTx(0, 1, 800, 70, 8, key2)
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, key1)
tx2 = makeMultiBlobTx(0, 1, 800, 70, 7, key2)
)
errs := pool.Add([]*types.Transaction{tx1, tx2}, true)

View file

@ -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.