diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 48bc5fb5c9..4de5a89885 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -606,7 +606,11 @@ func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*t } func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { - return core.GetBlockReceipts(fb.db, hash, core.GetBlockNumber(fb.db, hash)), nil + number := rawdb.ReadHeaderNumber(fb.db, hash) + if number == nil { + return nil, nil + } + return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil } func (fb *filterBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { diff --git a/core/blockchain.go b/core/blockchain.go index c96865d05a..845b939f65 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -68,6 +68,7 @@ var ( const ( bodyCacheLimit = 256 blockCacheLimit = 256 + receiptsCacheLimit = 32 maxFutureBlocks = 256 maxTimeFutureBlocks = 30 badBlockLimit = 10 @@ -141,6 +142,7 @@ type BlockChain struct { bodyCache *lru.Cache[common.Hash, *types.Body] // Cache for the most recent block bodies bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] // Cache for the most recent block bodies in RLP encoded format + receiptsCache *lru.Cache[common.Hash, types.Receipts] // Cache for the most recent block receipts blockCache *lru.Cache[common.Hash, *types.Block] // Cache for the most recent entire blocks resultProcess *lru.Cache[common.Hash, *ResultProcessBlock] // Cache for processed blocks calculatingBlock *lru.Cache[common.Hash, *CalculatedBlock] // Cache for processing blocks @@ -195,6 +197,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par quit: make(chan struct{}), bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit), bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit), + receiptsCache: lru.NewCache[common.Hash, types.Receipts](receiptsCacheLimit), blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit), futureBlocks: lru.NewCache[common.Hash, *types.Block](maxFutureBlocks), resultProcess: lru.NewCache[common.Hash, *ResultProcessBlock](blockCacheLimit), @@ -396,6 +399,7 @@ func (bc *BlockChain) SetHead(head uint64) error { // Clear out any stale content from the caches bc.bodyCache.Purge() bc.bodyRLPCache.Purge() + bc.receiptsCache.Purge() bc.blockCache.Purge() bc.futureBlocks.Purge() bc.blocksHashCache.Purge() @@ -808,7 +812,19 @@ func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block { // GetReceiptsByHash retrieves the receipts for all transactions in a given block. func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { - return GetBlockReceipts(bc.db, hash, GetBlockNumber(bc.db, hash)) + if receipts, ok := bc.receiptsCache.Get(hash); ok { + return receipts + } + number := rawdb.ReadHeaderNumber(bc.db, hash) + if number == nil { + return nil + } + receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig) + if receipts == nil { + return nil + } + bc.receiptsCache.Add(hash, receipts) + return receipts } // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors. diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index ebed7acffc..7073e8431a 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -214,6 +214,9 @@ func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Rec receipts := make(types.Receipts, len(storageReceipts)) for i, storageReceipt := range storageReceipts { receipts[i] = (*types.Receipt)(storageReceipt) + receipts[i].BlockHash = hash + receipts[i].BlockNumber = new(big.Int).SetUint64(number) + receipts[i].TransactionIndex = uint(i) } return receipts } diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index 0a08eeed69..26d098347e 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -25,7 +25,9 @@ import ( // The fields below define the low level database schema prefixing. var ( + // headBlockKey tracks the latest known full block's hash. headBlockKey = []byte("LastBlock") + // Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes). headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header headerHashSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + headerHashSuffix -> hash diff --git a/eth/api_backend.go b/eth/api_backend.go index ce8ddd05de..6d7f68fcd3 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -237,7 +237,7 @@ func (b *EthApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*t } func (b *EthApiBackend) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) { - return core.GetBlockReceipts(b.eth.chainDb, blockHash, core.GetBlockNumber(b.eth.chainDb, blockHash)), nil + return b.eth.blockchain.GetReceiptsByHash(blockHash), nil } func (b *EthApiBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { diff --git a/les/api_backend.go b/les/api_backend.go index 93c94b0b2b..e43d430735 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -24,18 +24,17 @@ import ( "os" "path/filepath" + "github.com/XinFinOrg/XDPoSChain/XDCx" "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" "github.com/XinFinOrg/XDPoSChain/XDCxlending" - "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind" - - "github.com/XinFinOrg/XDPoSChain/XDCx" - "github.com/XinFinOrg/XDPoSChain/accounts" + "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/math" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/core" "github.com/XinFinOrg/XDPoSChain/core/bloombits" + "github.com/XinFinOrg/XDPoSChain/core/rawdb" "github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/vm" @@ -171,7 +170,10 @@ func (b *LesApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*t } func (b *LesApiBackend) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) { - return light.GetBlockReceipts(ctx, b.eth.odr, blockHash, core.GetBlockNumber(b.eth.chainDb, blockHash)) + if number := rawdb.ReadHeaderNumber(b.eth.chainDb, blockHash); number != nil { + return light.GetBlockReceipts(ctx, b.eth.odr, blockHash, *number) + } + return nil, nil } func (b *LesApiBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {