Skip to content

Commit c47819c

Browse files
committed
core, cmd: add generic LRU implementation (ethereum#26162)
1 parent 96e2743 commit c47819c

File tree

5 files changed

+66
-87
lines changed

5 files changed

+66
-87
lines changed

cmd/gc/main.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
"github.com/XinFinOrg/XDPoSChain/ethdb/leveldb"
2121
"github.com/XinFinOrg/XDPoSChain/rlp"
2222
"github.com/XinFinOrg/XDPoSChain/trie"
23-
lru "github.com/hashicorp/golang-lru"
23+
"github.com/XinFinOrg/XDPoSChain/common/lru"
2424
)
2525

2626
var (
@@ -29,7 +29,7 @@ var (
2929
sercureKey = []byte("secure-key-")
3030
nWorker = runtime.NumCPU() / 2
3131
cleanAddress = []common.Address{common.BlockSignersBinary}
32-
cache *lru.Cache
32+
cache *lru.Cache[common.Hash, struct{}]
3333
finish = int32(0)
3434
running = true
3535
stateRoots = make(chan TrieRoot)
@@ -58,7 +58,7 @@ func main() {
5858
currentHeader := core.GetHeader(lddb, head, core.GetBlockNumber(lddb, head))
5959
tridb := trie.NewDatabase(lddb)
6060
catchEventInterupt(db)
61-
cache, _ = lru.New(*cacheSize)
61+
cache = lru.NewCache[common.Hash, struct{}](*cacheSize)
6262
go func() {
6363
for i := uint64(1); i <= currentHeader.Number.Uint64(); i++ {
6464
hash := core.GetCanonicalHash(lddb, i)
@@ -222,7 +222,7 @@ func processNodes(node StateNode, db *leveldb.Database) ([17]*StateNode, [17]*[]
222222
}
223223
}
224224
}
225-
cache.Add(commonHash, true)
225+
cache.Add(commonHash, struct{}{})
226226
}
227227
return newNodes, keys, number
228228
}

core/blockchain.go

Lines changed: 47 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
3333
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
3434
"github.com/XinFinOrg/XDPoSChain/common"
35+
"github.com/XinFinOrg/XDPoSChain/common/lru"
3536
"github.com/XinFinOrg/XDPoSChain/common/mclock"
3637
"github.com/XinFinOrg/XDPoSChain/common/prque"
3738
"github.com/XinFinOrg/XDPoSChain/common/sort"
@@ -52,7 +53,6 @@ import (
5253
"github.com/XinFinOrg/XDPoSChain/params"
5354
"github.com/XinFinOrg/XDPoSChain/rlp"
5455
"github.com/XinFinOrg/XDPoSChain/trie"
55-
lru "github.com/hashicorp/golang-lru"
5656
)
5757

5858
var (
@@ -140,37 +140,40 @@ type BlockChain struct {
140140

141141
stateCache state.Database // State database to reuse between imports (contains state cache)
142142

143-
bodyCache *lru.Cache // Cache for the most recent block bodies
144-
bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format
145-
blockCache *lru.Cache // Cache for the most recent entire blocks
146-
futureBlocks *lru.Cache // future blocks are blocks added for later processing
147-
resultProcess *lru.Cache // Cache for processed blocks
148-
calculatingBlock *lru.Cache // Cache for processing blocks
149-
downloadingBlock *lru.Cache // Cache for downloading blocks (avoid duplication from fetcher)
150-
quit chan struct{} // blockchain quit channel
151-
running int32 // running must be called atomically
152-
// procInterrupt must be atomically called
153-
procInterrupt int32 // interrupt signaler for block processing
143+
bodyCache *lru.Cache[common.Hash, *types.Body] // Cache for the most recent block bodies
144+
bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] // Cache for the most recent block bodies in RLP encoded format
145+
blockCache *lru.Cache[common.Hash, *types.Block] // Cache for the most recent entire blocks
146+
resultProcess *lru.Cache[common.Hash, *ResultProcessBlock] // Cache for processed blocks
147+
calculatingBlock *lru.Cache[common.Hash, *CalculatedBlock] // Cache for processing blocks
148+
downloadingBlock *lru.Cache[common.Hash, struct{}] // Cache for downloading blocks (avoid duplication from fetcher)
149+
badBlocks *lru.Cache[common.Hash, *types.Header] // Bad block cache
150+
151+
// future blocks are blocks added for later processing
152+
futureBlocks *lru.Cache[common.Hash, *types.Block]
153+
154154
wg sync.WaitGroup // chain processing wait group for shutting down
155+
quit chan struct{} // shutdown signal, closed in Stop.
156+
running int32 // 0 if chain is running, 1 when stopped
157+
procInterrupt int32 // interrupt signaler for block processing
155158

156159
engine consensus.Engine
157160
processor Processor // block processor interface
158161
validator Validator // block and state validator interface
159162
vmConfig vm.Config
160163

161-
badBlocks *lru.Cache // Bad block cache
162164
shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block.
163165
IPCEndpoint string
164166
Client bind.ContractBackend // Global ipc client instance.
167+
165168
// Blocks hash array by block number
166169
// cache field for tracking finality purpose, can't use for tracking block vs block relationship
167-
blocksHashCache *lru.Cache
170+
blocksHashCache *lru.Cache[uint64, []common.Hash]
168171

169-
resultTrade *lru.Cache // trades result: key - takerOrderHash, value: trades corresponding to takerOrder
170-
rejectedOrders *lru.Cache // rejected orders: key - takerOrderHash, value: rejected orders corresponding to takerOrder
171-
resultLendingTrade *lru.Cache
172-
rejectedLendingItem *lru.Cache
173-
finalizedTrade *lru.Cache // include both trades which force update to closed/liquidated by the protocol
172+
resultTrade *lru.Cache[common.Hash, interface{}] // trades result: key - takerOrderHash, value: trades corresponding to takerOrder
173+
rejectedOrders *lru.Cache[common.Hash, interface{}] // rejected orders: key - takerOrderHash, value: rejected orders corresponding to takerOrder
174+
resultLendingTrade *lru.Cache[common.Hash, interface{}]
175+
rejectedLendingItem *lru.Cache[common.Hash, interface{}]
176+
finalizedTrade *lru.Cache[common.Hash, interface{}] // include both trades which force update to closed/liquidated by the protocol
174177
}
175178

176179
// NewBlockChain returns a fully initialised block chain using information
@@ -183,47 +186,30 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
183186
TrieTimeLimit: 5 * time.Minute,
184187
}
185188
}
186-
bodyCache, _ := lru.New(bodyCacheLimit)
187-
bodyRLPCache, _ := lru.New(bodyCacheLimit)
188-
blockCache, _ := lru.New(blockCacheLimit)
189-
blocksHashCache, _ := lru.New(blocksHashCacheLimit)
190-
futureBlocks, _ := lru.New(maxFutureBlocks)
191-
badBlocks, _ := lru.New(badBlockLimit)
192-
resultProcess, _ := lru.New(blockCacheLimit)
193-
preparingBlock, _ := lru.New(blockCacheLimit)
194-
downloadingBlock, _ := lru.New(blockCacheLimit)
195-
196-
// for XDCx
197-
resultTrade, _ := lru.New(tradingstate.OrderCacheLimit)
198-
rejectedOrders, _ := lru.New(tradingstate.OrderCacheLimit)
199-
200-
// XDCxlending
201-
resultLendingTrade, _ := lru.New(tradingstate.OrderCacheLimit)
202-
rejectedLendingItem, _ := lru.New(tradingstate.OrderCacheLimit)
203-
finalizedTrade, _ := lru.New(tradingstate.OrderCacheLimit)
189+
204190
bc := &BlockChain{
205191
chainConfig: chainConfig,
206192
cacheConfig: cacheConfig,
207193
db: db,
208194
triegc: prque.New(nil),
209195
stateCache: state.NewDatabase(db),
210196
quit: make(chan struct{}),
211-
bodyCache: bodyCache,
212-
bodyRLPCache: bodyRLPCache,
213-
blockCache: blockCache,
214-
futureBlocks: futureBlocks,
215-
resultProcess: resultProcess,
216-
calculatingBlock: preparingBlock,
217-
downloadingBlock: downloadingBlock,
197+
bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit),
198+
bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit),
199+
blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit),
200+
futureBlocks: lru.NewCache[common.Hash, *types.Block](maxFutureBlocks),
201+
resultProcess: lru.NewCache[common.Hash, *ResultProcessBlock](blockCacheLimit),
202+
calculatingBlock: lru.NewCache[common.Hash, *CalculatedBlock](blockCacheLimit),
203+
downloadingBlock: lru.NewCache[common.Hash, struct{}](blockCacheLimit),
218204
engine: engine,
219205
vmConfig: vmConfig,
220-
badBlocks: badBlocks,
221-
blocksHashCache: blocksHashCache,
222-
resultTrade: resultTrade,
223-
rejectedOrders: rejectedOrders,
224-
resultLendingTrade: resultLendingTrade,
225-
rejectedLendingItem: rejectedLendingItem,
226-
finalizedTrade: finalizedTrade,
206+
badBlocks: lru.NewCache[common.Hash, *types.Header](badBlockLimit),
207+
blocksHashCache: lru.NewCache[uint64, []common.Hash](blocksHashCacheLimit),
208+
resultTrade: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit),
209+
rejectedOrders: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit),
210+
resultLendingTrade: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit),
211+
rejectedLendingItem: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit),
212+
finalizedTrade: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit),
227213
}
228214
bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
229215
bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
@@ -720,8 +706,7 @@ func (bc *BlockChain) Genesis() *types.Block {
720706
func (bc *BlockChain) GetBody(hash common.Hash) *types.Body {
721707
// Short circuit if the body's already in the cache, retrieve otherwise
722708
if cached, ok := bc.bodyCache.Get(hash); ok {
723-
body := cached.(*types.Body)
724-
return body
709+
return cached
725710
}
726711
body := GetBody(bc.db, hash, bc.hc.GetBlockNumber(hash))
727712
if body == nil {
@@ -737,7 +722,7 @@ func (bc *BlockChain) GetBody(hash common.Hash) *types.Body {
737722
func (bc *BlockChain) GetBodyRLP(hash common.Hash) rlp.RawValue {
738723
// Short circuit if the body's already in the cache, retrieve otherwise
739724
if cached, ok := bc.bodyRLPCache.Get(hash); ok {
740-
return cached.(rlp.RawValue)
725+
return cached
741726
}
742727
body := GetBodyRLP(bc.db, hash, bc.hc.GetBlockNumber(hash))
743728
if len(body) == 0 {
@@ -794,7 +779,7 @@ func (bc *BlockChain) HasBlockAndFullState(hash common.Hash, number uint64) bool
794779
func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
795780
// Short circuit if the block's already in the cache, retrieve otherwise
796781
if block, ok := bc.blockCache.Get(hash); ok {
797-
return block.(*types.Block)
782+
return block
798783
}
799784
block := GetBlock(bc.db, hash, number)
800785
if block == nil {
@@ -847,7 +832,7 @@ func (bc *BlockChain) GetBlocksHashCache(number uint64) []common.Hash {
847832
cached, ok := bc.blocksHashCache.Get(number)
848833

849834
if ok {
850-
return cached.([]common.Hash)
835+
return cached
851836
}
852837
return nil
853838
}
@@ -980,7 +965,7 @@ func (bc *BlockChain) procFutureBlocks() {
980965
blocks := make([]*types.Block, 0, bc.futureBlocks.Len())
981966
for _, hash := range bc.futureBlocks.Keys() {
982967
if block, exist := bc.futureBlocks.Peek(hash); exist {
983-
blocks = append(blocks, block.(*types.Block))
968+
blocks = append(blocks, block)
984969
}
985970
}
986971
if len(blocks) > 0 {
@@ -1491,7 +1476,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
14911476
for i, block := range chain {
14921477
headers[i] = block.Header()
14931478
seals[i] = verifySeals
1494-
bc.downloadingBlock.Add(block.Hash(), true)
1479+
bc.downloadingBlock.Add(block.Hash(), struct{}{})
14951480
}
14961481
abort, results := bc.engine.VerifyHeaders(bc, headers, seals)
14971482
defer close(abort)
@@ -1805,11 +1790,11 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu
18051790
if verifiedM2 {
18061791
if result, check := bc.resultProcess.Get(block.HashNoValidator()); check {
18071792
log.Debug("Get result block from cache ", "number", block.NumberU64(), "hash", block.Hash(), "hash no validator", block.HashNoValidator())
1808-
return result.(*ResultProcessBlock), nil
1793+
return result, nil
18091794
}
18101795
log.Debug("Not found cache prepare block ", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.HashNoValidator())
18111796
if calculatedBlock, _ := bc.calculatingBlock.Get(block.HashNoValidator()); calculatedBlock != nil {
1812-
calculatedBlock.(*CalculatedBlock).stop = true
1797+
calculatedBlock.stop = true
18131798
}
18141799
}
18151800
calculatedBlock = &CalculatedBlock{block, false}
@@ -2007,7 +1992,7 @@ func (bc *BlockChain) UpdateBlocksHashCache(block *types.Block) []common.Hash {
20071992
cached, ok := bc.blocksHashCache.Get(blockNumber)
20081993

20091994
if ok {
2010-
hashArr := cached.([]common.Hash)
1995+
hashArr := cached
20111996
hashArr = append(hashArr, block.Hash())
20121997
bc.blocksHashCache.Remove(blockNumber)
20131998
bc.blocksHashCache.Add(blockNumber, hashArr)
@@ -2340,8 +2325,7 @@ type BadBlockArgs struct {
23402325
func (bc *BlockChain) BadBlocks() ([]BadBlockArgs, error) {
23412326
headers := make([]BadBlockArgs, 0, bc.badBlocks.Len())
23422327
for _, hash := range bc.badBlocks.Keys() {
2343-
if hdr, exist := bc.badBlocks.Peek(hash); exist {
2344-
header := hdr.(*types.Header)
2328+
if header, exist := bc.badBlocks.Peek(hash); exist {
23452329
headers = append(headers, BadBlockArgs{header.Hash(), header})
23462330
}
23472331
}

core/blockchain_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1367,7 +1367,7 @@ func TestBlocksHashCacheUpdate(t *testing.T) {
13671367
}
13681368
cachedAt, _ := chain.blocksHashCache.Get(uint64(3))
13691369

1370-
if len(cachedAt.([]common.Hash)) != 2 {
1370+
if len(cachedAt) != 2 {
13711371
t.Error("BlocksHashCache doesn't add new cache after concating new fork ")
13721372
}
13731373
})

core/headerchain.go

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ import (
2727
"time"
2828

2929
"github.com/XinFinOrg/XDPoSChain/common"
30+
"github.com/XinFinOrg/XDPoSChain/common/lru"
3031
"github.com/XinFinOrg/XDPoSChain/consensus"
3132
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
3233
"github.com/XinFinOrg/XDPoSChain/core/types"
3334
"github.com/XinFinOrg/XDPoSChain/ethdb"
3435
"github.com/XinFinOrg/XDPoSChain/log"
3536
"github.com/XinFinOrg/XDPoSChain/params"
36-
lru "github.com/hashicorp/golang-lru"
3737
)
3838

3939
const (
@@ -56,9 +56,9 @@ type HeaderChain struct {
5656
currentHeader atomic.Value // Current head of the header chain (may be above the block chain!)
5757
currentHeaderHash common.Hash // Hash of the current head of the header chain (prevent recomputing all the time)
5858

59-
headerCache *lru.Cache // Cache for the most recent block headers
60-
tdCache *lru.Cache // Cache for the most recent block total difficulties
61-
numberCache *lru.Cache // Cache for the most recent block numbers
59+
headerCache *lru.Cache[common.Hash, *types.Header]
60+
tdCache *lru.Cache[common.Hash, *big.Int] // most recent total difficulties
61+
numberCache *lru.Cache[common.Hash, uint64] // most recent block numbers
6262

6363
procInterrupt func() bool
6464

@@ -72,10 +72,6 @@ type HeaderChain struct {
7272
// procInterrupt points to the parent's interrupt semaphore
7373
// wg points to the parent's shutdown wait group
7474
func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine consensus.Engine, procInterrupt func() bool) (*HeaderChain, error) {
75-
headerCache, _ := lru.New(headerCacheLimit)
76-
tdCache, _ := lru.New(tdCacheLimit)
77-
numberCache, _ := lru.New(numberCacheLimit)
78-
7975
// Seed a fast but crypto originating random generator
8076
seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
8177
if err != nil {
@@ -85,9 +81,9 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
8581
hc := &HeaderChain{
8682
config: config,
8783
chainDb: chainDb,
88-
headerCache: headerCache,
89-
tdCache: tdCache,
90-
numberCache: numberCache,
84+
headerCache: lru.NewCache[common.Hash, *types.Header](headerCacheLimit),
85+
tdCache: lru.NewCache[common.Hash, *big.Int](tdCacheLimit),
86+
numberCache: lru.NewCache[common.Hash, uint64](numberCacheLimit),
9187
procInterrupt: procInterrupt,
9288
rand: mrand.New(mrand.NewSource(seed.Int64())),
9389
engine: engine,
@@ -113,7 +109,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
113109
// from the cache or database
114110
func (hc *HeaderChain) GetBlockNumber(hash common.Hash) uint64 {
115111
if cached, ok := hc.numberCache.Get(hash); ok {
116-
return cached.(uint64)
112+
return cached
117113
}
118114
number := GetBlockNumber(hc.chainDb, hash)
119115
if number != missingNumber {
@@ -312,7 +308,7 @@ func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []co
312308
func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int {
313309
// Short circuit if the td's already in the cache, retrieve otherwise
314310
if cached, ok := hc.tdCache.Get(hash); ok {
315-
return cached.(*big.Int)
311+
return cached
316312
}
317313
td := GetTd(hc.chainDb, hash, number)
318314
if td == nil {
@@ -344,7 +340,7 @@ func (hc *HeaderChain) WriteTd(hash common.Hash, number uint64, td *big.Int) err
344340
func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header {
345341
// Short circuit if the header's already in the cache, retrieve otherwise
346342
if header, ok := hc.headerCache.Get(hash); ok {
347-
return header.(*types.Header)
343+
return header
348344
}
349345
header := GetHeader(hc.chainDb, hash, number)
350346
if header == nil {

core/state/database.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import (
2020
"fmt"
2121

2222
"github.com/XinFinOrg/XDPoSChain/common"
23+
"github.com/XinFinOrg/XDPoSChain/common/lru"
2324
"github.com/XinFinOrg/XDPoSChain/ethdb"
2425
"github.com/XinFinOrg/XDPoSChain/trie"
25-
lru "github.com/hashicorp/golang-lru"
2626
)
2727

2828
const (
@@ -107,16 +107,15 @@ func NewDatabase(db ethdb.Database) Database {
107107
// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a
108108
// large memory cache.
109109
func NewDatabaseWithCache(db ethdb.Database, cache int) Database {
110-
csc, _ := lru.New(codeSizeCacheSize)
111110
return &cachingDB{
112111
db: trie.NewDatabaseWithCache(db, cache),
113-
codeSizeCache: csc,
112+
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
114113
}
115114
}
116115

117116
type cachingDB struct {
118117
db *trie.Database
119-
codeSizeCache *lru.Cache
118+
codeSizeCache *lru.Cache[common.Hash, int]
120119
}
121120

122121
// OpenTrie opens the main account trie at a specific root hash.
@@ -151,7 +150,7 @@ func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error
151150
// ContractCodeSize retrieves a particular contracts code's size.
152151
func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) {
153152
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
154-
return cached.(int), nil
153+
return cached, nil
155154
}
156155
code, err := db.ContractCode(addrHash, codeHash)
157156
return len(code), err

0 commit comments

Comments
 (0)