github.com/klaytn/klaytn@v1.12.1/storage/database/cache_manager.go (about)

     1  // Copyright 2019 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package database
    18  
    19  import (
    20  	"math/big"
    21  	"reflect"
    22  
    23  	"github.com/klaytn/klaytn/blockchain/types"
    24  	"github.com/klaytn/klaytn/common"
    25  	"github.com/klaytn/klaytn/rlp"
    26  )
    27  
    28  // NOTE-Klaytn-Cache BlockChain Caches
    29  // Below is the list of the constants for cache size.
    30  // TODO-Klaytn: Below should be handled by ini or other configurations.
    31  const (
    32  	maxHeaderCache        = 512
    33  	maxTdCache            = 1024
    34  	maxBlockNumberCache   = 2048
    35  	maxCanonicalHashCache = 2048
    36  
    37  	maxBodyCache            = 256
    38  	maxBlockCache           = 256
    39  	maxRecentTransactions   = 30000
    40  	maxRecentBlockReceipts  = 30
    41  	maxRecentTxReceipt      = 30000
    42  	maxSenderTxHashToTxHash = 30000
    43  )
    44  
    45  const (
    46  	numShardsHeaderCache        = 4096
    47  	numShardsTdCache            = 4096
    48  	numShardsBlockNumberCache   = 4096
    49  	numShardsCanonicalHashCache = 4096
    50  
    51  	numShardsBodyCache            = 4096
    52  	numShardsBlockCache           = 4096
    53  	numShardsRecentTransactions   = 4096
    54  	numShardsRecentBlockReceipts  = 4096
    55  	numShardsRecentTxReceipt      = 4096
    56  	numShardsSenderTxHashToTxHash = 4096
    57  )
    58  
    59  type cacheKey int
    60  
    61  const (
    62  	headerCacheIndex cacheKey = iota
    63  	tdCacheIndex
    64  	blockNumberCacheIndex
    65  	canonicalCacheIndex
    66  
    67  	bodyCacheIndex
    68  	bodyRLPCacheIndex
    69  	blockCacheIndex
    70  	recentTxAndLookupInfoIndex
    71  	recentBlockReceiptsIndex
    72  	recentTxReceiptIndex
    73  	senderTxHashToTxHashIndex
    74  
    75  	cacheKeySize
    76  )
    77  
    78  var lruCacheConfig = [cacheKeySize]common.CacheConfiger{
    79  	headerCacheIndex:      common.LRUConfig{CacheSize: maxHeaderCache, IsScaled: true},
    80  	tdCacheIndex:          common.LRUConfig{CacheSize: maxTdCache, IsScaled: true},
    81  	blockNumberCacheIndex: common.LRUConfig{CacheSize: maxBlockNumberCache, IsScaled: true},
    82  	canonicalCacheIndex:   common.LRUConfig{CacheSize: maxCanonicalHashCache, IsScaled: true},
    83  
    84  	bodyCacheIndex:             common.LRUConfig{CacheSize: maxBodyCache, IsScaled: true},
    85  	bodyRLPCacheIndex:          common.LRUConfig{CacheSize: maxBodyCache, IsScaled: true},
    86  	blockCacheIndex:            common.LRUConfig{CacheSize: maxBlockCache, IsScaled: true},
    87  	recentTxAndLookupInfoIndex: common.LRUConfig{CacheSize: maxRecentTransactions, IsScaled: true},
    88  	recentBlockReceiptsIndex:   common.LRUConfig{CacheSize: maxRecentBlockReceipts, IsScaled: true},
    89  	recentTxReceiptIndex:       common.LRUConfig{CacheSize: maxRecentTxReceipt, IsScaled: true},
    90  	senderTxHashToTxHashIndex:  common.LRUConfig{CacheSize: maxSenderTxHashToTxHash, IsScaled: true},
    91  }
    92  
    93  var lruShardCacheConfig = [cacheKeySize]common.CacheConfiger{
    94  	headerCacheIndex:      common.LRUShardConfig{CacheSize: maxHeaderCache, NumShards: numShardsHeaderCache, IsScaled: true},
    95  	tdCacheIndex:          common.LRUShardConfig{CacheSize: maxTdCache, NumShards: numShardsTdCache, IsScaled: true},
    96  	blockNumberCacheIndex: common.LRUShardConfig{CacheSize: maxBlockNumberCache, NumShards: numShardsBlockNumberCache, IsScaled: true},
    97  	canonicalCacheIndex:   common.LRUShardConfig{CacheSize: maxCanonicalHashCache, NumShards: numShardsCanonicalHashCache, IsScaled: true},
    98  
    99  	bodyCacheIndex:             common.LRUShardConfig{CacheSize: maxBodyCache, NumShards: numShardsBodyCache, IsScaled: true},
   100  	bodyRLPCacheIndex:          common.LRUShardConfig{CacheSize: maxBodyCache, NumShards: numShardsBodyCache, IsScaled: true},
   101  	blockCacheIndex:            common.LRUShardConfig{CacheSize: maxBlockCache, NumShards: numShardsBlockCache, IsScaled: true},
   102  	recentTxAndLookupInfoIndex: common.LRUShardConfig{CacheSize: maxRecentTransactions, NumShards: numShardsRecentTransactions, IsScaled: true},
   103  	recentBlockReceiptsIndex:   common.LRUShardConfig{CacheSize: maxRecentBlockReceipts, NumShards: numShardsRecentBlockReceipts, IsScaled: true},
   104  	recentTxReceiptIndex:       common.LRUShardConfig{CacheSize: maxRecentTxReceipt, NumShards: numShardsRecentTxReceipt, IsScaled: true},
   105  	senderTxHashToTxHashIndex:  common.LRUShardConfig{CacheSize: maxSenderTxHashToTxHash, NumShards: numShardsSenderTxHashToTxHash, IsScaled: true},
   106  }
   107  
   108  var fifoCacheConfig = [cacheKeySize]common.CacheConfiger{
   109  	headerCacheIndex:      common.FIFOCacheConfig{CacheSize: maxHeaderCache, IsScaled: true},
   110  	tdCacheIndex:          common.FIFOCacheConfig{CacheSize: maxTdCache, IsScaled: true},
   111  	blockNumberCacheIndex: common.FIFOCacheConfig{CacheSize: maxBlockNumberCache, IsScaled: true},
   112  	canonicalCacheIndex:   common.FIFOCacheConfig{CacheSize: maxCanonicalHashCache, IsScaled: true},
   113  
   114  	bodyCacheIndex:             common.FIFOCacheConfig{CacheSize: maxBodyCache, IsScaled: true},
   115  	bodyRLPCacheIndex:          common.FIFOCacheConfig{CacheSize: maxBodyCache, IsScaled: true},
   116  	blockCacheIndex:            common.FIFOCacheConfig{CacheSize: maxBlockCache, IsScaled: true},
   117  	recentTxAndLookupInfoIndex: common.FIFOCacheConfig{CacheSize: maxRecentTransactions, IsScaled: true},
   118  	recentBlockReceiptsIndex:   common.FIFOCacheConfig{CacheSize: maxRecentBlockReceipts, IsScaled: true},
   119  	recentTxReceiptIndex:       common.FIFOCacheConfig{CacheSize: maxRecentTxReceipt, IsScaled: true},
   120  	senderTxHashToTxHashIndex:  common.FIFOCacheConfig{CacheSize: maxSenderTxHashToTxHash, IsScaled: true},
   121  }
   122  
   123  func newCache(cacheNameKey cacheKey, cacheType common.CacheType) common.Cache {
   124  	var cache common.Cache
   125  
   126  	switch cacheType {
   127  	case common.FIFOCacheType:
   128  		cache = common.NewCache(fifoCacheConfig[cacheNameKey])
   129  	case common.LRUCacheType:
   130  		cache = common.NewCache(lruCacheConfig[cacheNameKey])
   131  	case common.LRUShardCacheType:
   132  		cache = common.NewCache(lruShardCacheConfig[cacheNameKey])
   133  	default:
   134  		cache = common.NewCache(fifoCacheConfig[cacheNameKey])
   135  	}
   136  	return cache
   137  }
   138  
   139  type TransactionLookup struct {
   140  	Tx *types.Transaction
   141  	*TxLookupEntry
   142  }
   143  
   144  // cacheManager handles caches of data structures stored in Database.
   145  // Previously, most of them were handled by blockchain.HeaderChain or
   146  // blockchain.BlockChain.
   147  type cacheManager struct {
   148  	// caches from blockchain.HeaderChain
   149  	headerCache        common.Cache
   150  	tdCache            common.Cache
   151  	blockNumberCache   common.Cache
   152  	canonicalHashCache common.Cache
   153  
   154  	// caches from blockchain.BlockChain
   155  	bodyCache             common.Cache // Cache for the most recent block bodies
   156  	bodyRLPCache          common.Cache // Cache for the most recent block bodies in RLP encoded format
   157  	blockCache            common.Cache // Cache for the most recent entire blocks
   158  	recentTxAndLookupInfo common.Cache // recent TX and LookupInfo cache
   159  	recentBlockReceipts   common.Cache // recent block receipts cache
   160  	recentTxReceipt       common.Cache // recent TX receipt cache
   161  
   162  	senderTxHashToTxHashCache common.Cache
   163  }
   164  
   165  // newCacheManager returns a pointer of cacheManager with predefined configurations.
   166  func newCacheManager() *cacheManager {
   167  	cm := &cacheManager{
   168  		headerCache:        newCache(headerCacheIndex, common.DefaultCacheType),
   169  		tdCache:            newCache(tdCacheIndex, common.DefaultCacheType),
   170  		blockNumberCache:   newCache(blockNumberCacheIndex, common.DefaultCacheType),
   171  		canonicalHashCache: newCache(canonicalCacheIndex, common.DefaultCacheType),
   172  
   173  		bodyCache:    newCache(bodyCacheIndex, common.DefaultCacheType),
   174  		bodyRLPCache: newCache(bodyRLPCacheIndex, common.DefaultCacheType),
   175  		blockCache:   newCache(blockCacheIndex, common.DefaultCacheType),
   176  
   177  		recentTxAndLookupInfo: newCache(recentTxAndLookupInfoIndex, common.DefaultCacheType),
   178  		recentBlockReceipts:   newCache(recentBlockReceiptsIndex, common.DefaultCacheType),
   179  		recentTxReceipt:       newCache(recentTxReceiptIndex, common.DefaultCacheType),
   180  
   181  		senderTxHashToTxHashCache: newCache(recentTxReceiptIndex, common.DefaultCacheType),
   182  	}
   183  	return cm
   184  }
   185  
   186  // clearHeaderChainCache flushes out 1) headerCache, 2) tdCache and 3) blockNumberCache.
   187  func (cm *cacheManager) clearHeaderChainCache() {
   188  	cm.headerCache.Purge()
   189  	cm.tdCache.Purge()
   190  	cm.blockNumberCache.Purge()
   191  	cm.canonicalHashCache.Purge()
   192  }
   193  
   194  // clearBlockChainCache flushes out 1) bodyCache, 2) bodyRLPCache, 3) blockCache,
   195  // 4) recentTxAndLookupInfo, 5) recentBlockReceipts and 6) recentTxReceipt.
   196  func (cm *cacheManager) clearBlockChainCache() {
   197  	cm.bodyCache.Purge()
   198  	cm.bodyRLPCache.Purge()
   199  	cm.blockCache.Purge()
   200  	cm.recentTxAndLookupInfo.Purge()
   201  	cm.recentBlockReceipts.Purge()
   202  	cm.recentTxReceipt.Purge()
   203  	cm.senderTxHashToTxHashCache.Purge()
   204  }
   205  
   206  // readHeaderCache looks for cached header in headerCache.
   207  // It returns nil if not found.
   208  func (cm *cacheManager) readHeaderCache(hash common.Hash) *types.Header {
   209  	if header, ok := cm.headerCache.Get(hash); ok && header != nil {
   210  		cacheGetHeaderHitMeter.Mark(1)
   211  		return header.(*types.Header)
   212  	}
   213  	cacheGetHeaderMissMeter.Mark(1)
   214  	return nil
   215  }
   216  
   217  // writeHeaderCache writes header as a value, headerHash as a key.
   218  func (cm *cacheManager) writeHeaderCache(hash common.Hash, header *types.Header) {
   219  	if header == nil {
   220  		return
   221  	}
   222  	cm.headerCache.Add(hash, header)
   223  }
   224  
   225  // deleteHeaderCache writes nil as a value, headerHash as a key, to indicate given
   226  // headerHash is deleted in headerCache.
   227  func (cm *cacheManager) deleteHeaderCache(hash common.Hash) {
   228  	cm.headerCache.Add(hash, nil)
   229  }
   230  
   231  // hasHeaderInCache returns if a cachedHeader exists with given headerHash.
   232  func (cm *cacheManager) hasHeaderInCache(hash common.Hash) bool {
   233  	if cached, ok := cm.headerCache.Get(hash); ok && cached != nil {
   234  		return true
   235  	}
   236  	return false
   237  }
   238  
   239  // readTdCache looks for cached total blockScore in tdCache.
   240  // It returns nil if not found.
   241  func (cm *cacheManager) readTdCache(hash common.Hash) *big.Int {
   242  	if cached, ok := cm.tdCache.Get(hash); ok && cached != nil {
   243  		cacheGetTDHitMeter.Mark(1)
   244  		return cached.(*big.Int)
   245  	}
   246  	cacheGetTDMissMeter.Mark(1)
   247  	return nil
   248  }
   249  
   250  // writeHeaderCache writes total blockScore as a value, headerHash as a key.
   251  func (cm *cacheManager) writeTdCache(hash common.Hash, td *big.Int) {
   252  	if td == nil {
   253  		return
   254  	}
   255  	cm.tdCache.Add(hash, td)
   256  }
   257  
   258  // deleteTdCache writes nil as a value, headerHash as a key, to indicate given
   259  // headerHash is deleted in TdCache.
   260  func (cm *cacheManager) deleteTdCache(hash common.Hash) {
   261  	cm.tdCache.Add(hash, nil)
   262  }
   263  
   264  // readBlockNumberCache looks for cached headerNumber in blockNumberCache.
   265  // It returns nil if not found.
   266  func (cm *cacheManager) readBlockNumberCache(hash common.Hash) *uint64 {
   267  	if cached, ok := cm.blockNumberCache.Get(hash); ok && cached != nil {
   268  		cacheGetBlockNumberHitMeter.Mark(1)
   269  		blockNumber := cached.(uint64)
   270  		return &blockNumber
   271  	}
   272  	cacheGetBlockNumberMissMeter.Mark(1)
   273  	return nil
   274  }
   275  
   276  // writeHeaderCache writes headerNumber as a value, headerHash as a key.
   277  func (cm *cacheManager) writeBlockNumberCache(hash common.Hash, number uint64) {
   278  	cm.blockNumberCache.Add(hash, number)
   279  }
   280  
   281  // deleteBlockNumberCache deletes headerNumber with a headerHash as a key.
   282  func (cm *cacheManager) deleteBlockNumberCache(hash common.Hash) {
   283  	cm.blockNumberCache.Add(hash, nil)
   284  }
   285  
   286  // readCanonicalHashCache looks for cached canonical hash in canonicalHashCache.
   287  // It returns empty hash if not found.
   288  func (cm *cacheManager) readCanonicalHashCache(number uint64) common.Hash {
   289  	if cached, ok := cm.canonicalHashCache.Get(common.CacheKeyUint64(number)); ok {
   290  		cacheGetCanonicalHashHitMeter.Mark(1)
   291  		canonicalHash := cached.(common.Hash)
   292  		return canonicalHash
   293  	}
   294  	cacheGetCanonicalHashMissMeter.Mark(1)
   295  	return common.Hash{}
   296  }
   297  
   298  // writeCanonicalHashCache writes canonical hash as a value, headerNumber as a key.
   299  func (cm *cacheManager) writeCanonicalHashCache(number uint64, hash common.Hash) {
   300  	cm.canonicalHashCache.Add(common.CacheKeyUint64(number), hash)
   301  }
   302  
   303  // readBodyCache looks for cached blockBody in bodyCache.
   304  // It returns nil if not found.
   305  func (cm *cacheManager) readBodyCache(hash common.Hash) *types.Body {
   306  	if cachedBody, ok := cm.bodyCache.Get(hash); ok && cachedBody != nil {
   307  		cacheGetBlockBodyHitMeter.Mark(1)
   308  		return cachedBody.(*types.Body)
   309  	}
   310  	cacheGetBlockBodyMissMeter.Mark(1)
   311  	return nil
   312  }
   313  
   314  // writeBodyCache writes blockBody as a value, blockHash as a key.
   315  func (cm *cacheManager) writeBodyCache(hash common.Hash, body *types.Body) {
   316  	if body == nil {
   317  		return
   318  	}
   319  	cm.bodyCache.Add(hash, body)
   320  }
   321  
   322  // deleteBodyCache writes nil as a value, blockHash as a key, to indicate given
   323  // txHash is deleted in bodyCache and bodyRLPCache.
   324  func (cm *cacheManager) deleteBodyCache(hash common.Hash) {
   325  	cm.bodyCache.Add(hash, nil)
   326  	cm.bodyRLPCache.Add(hash, nil)
   327  }
   328  
   329  // readBodyRLPCache looks for cached RLP-encoded blockBody in bodyRLPCache.
   330  // It returns nil if not found.
   331  func (cm *cacheManager) readBodyRLPCache(hash common.Hash) rlp.RawValue {
   332  	if cachedBodyRLP, ok := cm.bodyRLPCache.Get(hash); ok && cachedBodyRLP != nil {
   333  		cacheGetBlockBodyRLPHitMeter.Mark(1)
   334  		return cachedBodyRLP.(rlp.RawValue)
   335  	}
   336  	cacheGetBlockBodyRLPMissMeter.Mark(1)
   337  	return nil
   338  }
   339  
   340  // writeBodyRLPCache writes RLP-encoded blockBody as a value, blockHash as a key.
   341  func (cm *cacheManager) writeBodyRLPCache(hash common.Hash, bodyRLP rlp.RawValue) {
   342  	if bodyRLP == nil {
   343  		return
   344  	}
   345  	cm.bodyRLPCache.Add(hash, bodyRLP)
   346  }
   347  
   348  // readBlockCache looks for cached block in blockCache.
   349  // It returns nil if not found.
   350  func (cm *cacheManager) readBlockCache(hash common.Hash) *types.Block {
   351  	if cachedBlock, ok := cm.blockCache.Get(hash); ok && cachedBlock != nil {
   352  		cacheGetBlockHitMeter.Mark(1)
   353  		return cachedBlock.(*types.Block)
   354  	}
   355  	cacheGetBlockMissMeter.Mark(1)
   356  	return nil
   357  }
   358  
   359  // hasBlockInCache returns if given hash exists in blockCache.
   360  func (cm *cacheManager) hasBlockInCache(hash common.Hash) bool {
   361  	if cachedBlock, ok := cm.blockCache.Get(hash); ok && cachedBlock != nil {
   362  		return true
   363  	}
   364  	return false
   365  }
   366  
   367  // writeBlockCache writes block as a value, blockHash as a key.
   368  func (cm *cacheManager) writeBlockCache(hash common.Hash, block *types.Block) {
   369  	if block == nil {
   370  		return
   371  	}
   372  	cm.blockCache.Add(hash, block)
   373  }
   374  
   375  // deleteBlockCache writes nil as a value, blockHash as a key,
   376  // to indicate given blockHash is deleted in recentBlockReceipts.
   377  func (cm *cacheManager) deleteBlockCache(hash common.Hash) {
   378  	cm.blockCache.Add(hash, nil)
   379  }
   380  
   381  // readTxAndLookupInfoInCache looks for cached tx and its look up information in recentTxAndLookupInfo.
   382  // It returns nil and empty values if not found.
   383  func (cm *cacheManager) readTxAndLookupInfoInCache(txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
   384  	if value, ok := cm.recentTxAndLookupInfo.Get(txHash); ok && value != nil {
   385  		cacheGetRecentTransactionsHitMeter.Mark(1)
   386  		txLookup, ok := value.(*TransactionLookup)
   387  		if !ok {
   388  			logger.Error("invalid type in recentTxAndLookupInfo. expected=*TransactionLookup", "actual=", reflect.TypeOf(value))
   389  			return nil, common.Hash{}, 0, 0
   390  		}
   391  		return txLookup.Tx, txLookup.BlockHash, txLookup.BlockIndex, txLookup.Index
   392  	}
   393  	cacheGetRecentTransactionsMissMeter.Mark(1)
   394  	return nil, common.Hash{}, 0, 0
   395  }
   396  
   397  // writeTxAndLookupInfoCache writes a tx and its lookup information as a value, txHash as a key.
   398  func (cm *cacheManager) writeTxAndLookupInfoCache(txHash common.Hash, txLookup *TransactionLookup) {
   399  	if txLookup == nil {
   400  		return
   401  	}
   402  	cm.recentTxAndLookupInfo.Add(txHash, txLookup)
   403  }
   404  
   405  // readBlockReceiptsInCache looks for cached blockReceipts in recentBlockReceipts.
   406  // It returns nil if not found.
   407  func (cm *cacheManager) readBlockReceiptsInCache(blockHash common.Hash) types.Receipts {
   408  	if cachedBlockReceipts, ok := cm.recentBlockReceipts.Get(blockHash); ok && cachedBlockReceipts != nil {
   409  		cacheGetRecentBlockReceiptsHitMeter.Mark(1)
   410  		return cachedBlockReceipts.(types.Receipts)
   411  	}
   412  	cacheGetRecentBlockReceiptsMissMeter.Mark(1)
   413  	return nil
   414  }
   415  
   416  // writeBlockReceiptsCache writes blockReceipts as a value, blockHash as a key.
   417  func (cm *cacheManager) writeBlockReceiptsCache(blockHash common.Hash, receipts types.Receipts) {
   418  	if receipts == nil {
   419  		return
   420  	}
   421  	cm.recentBlockReceipts.Add(blockHash, receipts)
   422  }
   423  
   424  // deleteBlockReceiptsCache writes nil as a value, blockHash as a key, to indicate given
   425  // blockHash is deleted in recentBlockReceipts.
   426  func (cm *cacheManager) deleteBlockReceiptsCache(blockHash common.Hash) {
   427  	cm.recentBlockReceipts.Add(blockHash, nil)
   428  }
   429  
   430  // readTxReceiptInCache looks for cached txReceipt in recentTxReceipt.
   431  // It returns nil if not found.
   432  func (cm *cacheManager) readTxReceiptInCache(txHash common.Hash) *types.Receipt {
   433  	if cachedReceipt, ok := cm.recentTxReceipt.Get(txHash); ok && cachedReceipt != nil {
   434  		cacheGetRecentTxReceiptHitMeter.Mark(1)
   435  		return cachedReceipt.(*types.Receipt)
   436  	}
   437  	cacheGetRecentTxReceiptMissMeter.Mark(1)
   438  	return nil
   439  }
   440  
   441  // writeTxReceiptCache writes txReceipt as a value, txHash as a key.
   442  func (cm *cacheManager) writeTxReceiptCache(txHash common.Hash, receipt *types.Receipt) {
   443  	if receipt == nil {
   444  		return
   445  	}
   446  	cm.recentTxReceipt.Add(txHash, receipt)
   447  }
   448  
   449  // deleteTxReceiptCache writes nil as a value, blockHash as a key, to indicate given
   450  // txHash is deleted in recentTxReceipt.
   451  func (cm *cacheManager) deleteTxReceiptCache(txHash common.Hash) {
   452  	cm.recentTxReceipt.Add(txHash, nil)
   453  }
   454  
   455  // writeSenderTxHashToTxHashCache writes senderTxHash to txHash mapping information to cache.
   456  func (cm *cacheManager) writeSenderTxHashToTxHashCache(senderTxHash, txHash common.Hash) {
   457  	cm.senderTxHashToTxHashCache.Add(senderTxHash, txHash)
   458  }
   459  
   460  // readSenderTxHashToTxHashCache looks for matching txHash from senderTxHash.
   461  // If txHash does not exist in the cache, it returns an empty hash.
   462  func (cm *cacheManager) readSenderTxHashToTxHashCache(senderTxHash common.Hash) common.Hash {
   463  	if matchedTxHash, ok := cm.senderTxHashToTxHashCache.Get(senderTxHash); ok && matchedTxHash != nil {
   464  		return matchedTxHash.(common.Hash)
   465  	}
   466  	return common.Hash{}
   467  }