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 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. // Create meta, in preparation of adding to the pool.
// Having the meta simplifies the check below for underpriced transactions. // 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) meta := newBlobTxMeta(tx)
// Calculate the eviction parameters for the transaction // Calculate the eviction parameters for the transaction
var ( var (
from, _ = types.Sender(p.signer, tx) // already validated above
next = p.state.GetNonce(from) next = p.state.GetNonce(from)
offset = int(meta.nonce - next) 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 // Check pool size limits before inserting the transaction. For this calculation
// If at limit, check whether it is underpriced. // 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 worse of the pool is still considered
// underpriced. This is to prevent constant replacement when the pool is full. // 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 { 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) log.Warn("Dropping blob transaction due to size", "tx", tx.Hash(), "size", meta.size, "err", err)
return 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, // Transaction permitted into the pool from a nonce and cost perspective,
// insert it into the database and update the indices // 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) id, err := p.store.Put(blob)
if err != nil { if err != nil {
return err return err