core/blockchain: add txhash cache for on-chain txs

Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
This commit is contained in:
Csaba Kiraly 2025-12-18 09:25:32 +01:00
parent 90344dc27b
commit b8f264aad6
No known key found for this signature in database
GPG key ID: 0FE274EE8C95166E
2 changed files with 22 additions and 7 deletions

View file

@ -122,6 +122,7 @@ const (
blockCacheLimit = 256 blockCacheLimit = 256
receiptsCacheLimit = 32 receiptsCacheLimit = 32
txLookupCacheLimit = 1024 txLookupCacheLimit = 1024
txOnChainCacheLimit = txLookupCacheLimit * 16
// BlockChainVersion ensures that an incompatible database forces a resync from scratch. // BlockChainVersion ensures that an incompatible database forces a resync from scratch.
// //
@ -330,6 +331,7 @@ type BlockChain struct {
txLookupLock sync.RWMutex txLookupLock sync.RWMutex
txLookupCache *lru.Cache[common.Hash, txLookup] txLookupCache *lru.Cache[common.Hash, txLookup]
txOnChainCache *lru.Cache[common.Hash, struct{}] // For filtering incoming tx announcements
stopping atomic.Bool // false if chain is running, true when stopped stopping atomic.Bool // false if chain is running, true when stopped
procInterrupt atomic.Bool // interrupt signaler for block processing procInterrupt atomic.Bool // interrupt signaler for block processing
@ -388,6 +390,7 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine,
receiptsCache: lru.NewCache[common.Hash, []*types.Receipt](receiptsCacheLimit), receiptsCache: lru.NewCache[common.Hash, []*types.Receipt](receiptsCacheLimit),
blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit), blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit),
txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit), txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit),
txOnChainCache: lru.NewCache[common.Hash, struct{}](txOnChainCacheLimit),
engine: engine, engine: engine,
logger: cfg.VmConfig.Tracer, logger: cfg.VmConfig.Tracer,
slowBlockThreshold: cfg.SlowBlockThreshold, slowBlockThreshold: cfg.SlowBlockThreshold,
@ -1100,6 +1103,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
bc.receiptsCache.Purge() bc.receiptsCache.Purge()
bc.blockCache.Purge() bc.blockCache.Purge()
bc.txLookupCache.Purge() bc.txLookupCache.Purge()
bc.txOnChainCache.Purge()
// Clear safe block, finalized block if needed // Clear safe block, finalized block if needed
if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.Number.Uint64() { if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.Number.Uint64() {
@ -1230,6 +1234,11 @@ func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
// //
// Note, this function assumes that the `mu` mutex is held! // Note, this function assumes that the `mu` mutex is held!
func (bc *BlockChain) writeHeadBlock(block *types.Block) { func (bc *BlockChain) writeHeadBlock(block *types.Block) {
// Add transaction hashes to the in-memory cache
for _, tx := range block.Transactions() {
bc.txOnChainCache.Add(tx.Hash(), struct{}{})
}
// Add the block to the canonical chain number scheme and mark as the head // Add the block to the canonical chain number scheme and mark as the head
batch := bc.db.NewBatch() batch := bc.db.NewBatch()
rawdb.WriteHeadHeaderHash(batch, block.Hash()) rawdb.WriteHeadHeaderHash(batch, block.Hash())
@ -2584,6 +2593,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
} }
// Reset the tx lookup cache to clear stale txlookup cache. // Reset the tx lookup cache to clear stale txlookup cache.
bc.txLookupCache.Purge() bc.txLookupCache.Purge()
bc.txOnChainCache.Purge()
// Release the tx-lookup lock after mutation. // Release the tx-lookup lock after mutation.
bc.txLookupLock.Unlock() bc.txLookupLock.Unlock()

View file

@ -329,7 +329,12 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max
// access altogether. // access altogether.
func (bc *BlockChain) HasCanonicalTransaction(hash common.Hash, cacheOnly bool) bool { func (bc *BlockChain) HasCanonicalTransaction(hash common.Hash, cacheOnly bool) bool {
// Check in memory cache first // Check in memory cache first
if _, exist := bc.txLookupCache.Get(hash); exist { if _, exist := bc.txOnChainCache.Get(hash); exist {
return true
}
// Check in memory tx cache next, without bumping the LRU
if bc.txLookupCache.Contains(hash) {
return true return true
} }