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.
This commit is contained in:
Csaba Kiraly 2026-03-06 10:31:56 +01:00
parent 61c8293a2d
commit 4daf354b2c
No known key found for this signature in database
GPG key ID: 0FE274EE8C95166E

View file

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