fix storage size calculation

Exact storage size calculation needs RLP encoding. Since this is
not cheap, we also move the Reserver check before this.

Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
This commit is contained in:
Csaba Kiraly 2026-03-05 10:50:49 +01:00
parent 102a272f00
commit b04fb3e688
No known key found for this signature in database
GPG key ID: 0FE274EE8C95166E

View file

@ -1564,13 +1564,35 @@ func (p *BlobPool) addLocked(tx *types.Transaction, checkGapped bool) (err error
return err
}
// If the address is not yet known, request exclusivity to track the account
// This is a cheap check, so we do it before all the other checks.
// only by this subpool until all transactions are evicted
from, _ := types.Sender(p.signer, tx) // already validated above
if _, ok := p.index[from]; !ok {
if err := p.reserver.Hold(from); err != nil {
addNonExclusiveMeter.Mark(1)
return err
}
defer func() {
// If the transaction is rejected by some post-validation check, remove
// the lock on the reservation set.
//
// Note, `err` here is the named error return, which will be initialized
// by a return statement before running deferred methods. Take care with
// removing or subscoping err as it will break this clause.
if err != nil {
p.reserver.Release(from)
}
}()
}
// Create meta, in preparation of adding to the pool.
// Having the meta simplifies the check below for underpriced transactions.
// Note: the meta will be finalized with storage information after the transaction is stored
meta := newBlobTxMeta(tx)
// Calculate the eviction parameters for the transaction
var (
from, _ = types.Sender(p.signer, tx) // already validated above
next = p.state.GetNonce(from)
offset = int(meta.nonce - next)
)
@ -1590,13 +1612,19 @@ func (p *BlobPool) addLocked(tx *types.Transaction, checkGapped bool) (err error
}
}
// Check pool size limits before inserting the transaction
// If at limit, check whether it is underpriced.
// 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
// underpriced. This is to prevent constant replacement when the pool is full.
storageSizeDiff, err := getSlotSize(p.slotter, uint32(meta.size))
blob, err := rlp.EncodeToBytes(tx)
if err != nil {
// This should nver happen, but better safe than sorry.
// This should never happen, but better safe than sorry.
log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err)
return err
}
storageSizeDiff, err := getSlotSize(p.slotter, 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
}
@ -1612,32 +1640,8 @@ func (p *BlobPool) addLocked(tx *types.Transaction, checkGapped bool) (err error
}
}
// If the address is not yet known, request exclusivity to track the account
// only by this subpool until all transactions are evicted
if _, ok := p.index[from]; !ok {
if err := p.reserver.Hold(from); err != nil {
addNonExclusiveMeter.Mark(1)
return err
}
defer func() {
// If the transaction is rejected by some post-validation check, remove
// the lock on the reservation set.
//
// Note, `err` here is the named error return, which will be initialized
// by a return statement before running deferred methods. Take care with
// removing or subscoping err as it will break this clause.
if err != nil {
p.reserver.Release(from)
}
}()
}
// Transaction permitted into the pool from a nonce and cost perspective,
// insert it into the database and update the indices
blob, err := rlp.EncodeToBytes(tx)
if err != nil {
log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err)
return err
}
id, err := p.store.Put(blob)
if err != nil {
return err