From 4daf354b2c977d93867c279a483c481b117dcae3 Mon Sep 17 00:00:00 2001 From: Csaba Kiraly Date: Fri, 6 Mar 2026 10:31:56 +0100 Subject: [PATCH] core/txpool/blobpool: fix uint32 underflow in storage size diff storageSizeDiff was a uint32. When replacing a transaction with a smaller one, the subtraction (new - old) would underflow, and the subsequent cast to uint64 would produce a huge value, making the datacap check always trigger incorrectly. Use int64 for the diff instead. When negative (pool shrinking), skip the capacity check entirely. When positive, the cast to uint64 is safe since we've confirmed it's positive. --- core/txpool/blobpool/blobpool.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 0dd341939c..7efb6e9c01 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -1619,7 +1619,7 @@ func (p *BlobPool) addLocked(tx *types.Transaction, checkGapped bool) (err error // Check pool size limits before inserting the transaction. For this calculation // we have to RLP encode the transaction to get the size. - // Note: equal priority as the current worse of the pool is still considered + // Note: equal priority as the current worst of the pool is still considered // underpriced. This is to prevent constant replacement when the pool is full. blob, err := rlp.EncodeToBytes(tx) if err != nil { @@ -1627,18 +1627,19 @@ func (p *BlobPool) addLocked(tx *types.Transaction, checkGapped bool) (err error log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err) return err } - storageSizeDiff, err := getSlotSize(p.newSlotter(), uint32(len(blob))) + newStorageSize, err := getSlotSize(p.newSlotter(), uint32(len(blob))) if err != nil { // This should also not happen at this stage log.Warn("Dropping blob transaction due to size", "tx", tx.Hash(), "size", meta.size, "err", err) return err } - // is this a possible replacent? If so, we need to consider the storage size difference - // instead of the full size of the new transaction. + // Is this a possible replacement? If so, we need to consider the storage size + // difference instead of the full size of the new transaction. + storageSizeDiff := int64(newStorageSize) if offset < len(p.index[from]) { - storageSizeDiff -= p.index[from][offset].storageSize + storageSizeDiff -= int64(p.index[from][offset].storageSize) } - if p.stored+uint64(storageSizeDiff) > p.config.Datacap { + if storageSizeDiff > 0 && p.stored+uint64(storageSizeDiff) > p.config.Datacap { if p.evict.Underpriced(meta) { log.Trace("Dropping underpriced blob transaction", "tx", tx.Hash(), "feecap", tx.GasFeeCap(), "tipcap", tx.GasTipCap(), "blobfeecap", tx.BlobGasFeeCap()) return txpool.ErrUnderpriced