From 82ff8c19a05d71d22b7db46259dba4843c9d730f Mon Sep 17 00:00:00 2001 From: Daniel Liu Date: Tue, 17 Dec 2024 17:35:07 +0800 Subject: [PATCH] all: remove uses of untyped golang-lru --- XDCx/XDCx.go | 32 +++----- XDCx/token.go | 11 ++- XDCx/tradingstate/database.go | 15 +--- XDCxDAO/leveldb.go | 6 -- XDCxDAO/mongodb.go | 7 +- XDCxlending/XDCxlending.go | 39 ++++------ XDCxlending/lendingstate/database.go | 16 ++-- consensus/XDPoS/XDPoS.go | 44 ++++------- consensus/XDPoS/engines/engine_v1/engine.go | 44 ++++------- consensus/XDPoS/engines/engine_v1/snapshot.go | 7 +- consensus/XDPoS/engines/engine_v1/utils.go | 5 +- consensus/XDPoS/engines/engine_v2/engine.go | 28 +++---- .../XDPoS/engines/engine_v2/epochSwitch.go | 7 +- consensus/XDPoS/engines/engine_v2/snapshot.go | 3 +- consensus/XDPoS/engines/engine_v2/utils.go | 10 +-- .../XDPoS/engines/engine_v2/verifyHeader.go | 2 +- consensus/XDPoS/utils/types.go | 3 + consensus/clique/clique.go | 21 +++-- consensus/clique/snapshot.go | 10 ++- consensus/ethash/ethash.go | 72 +++++++++-------- contracts/utils.go | 9 +-- core/state/trc21_reader.go | 14 ++-- eth/fetcher/fetcher.go | 11 ++- eth/handler.go | 77 ++++++++----------- eth/hooks/engine_v1_hooks.go | 7 +- eth/hooks/engine_v2_hooks.go | 14 ++-- go.mod | 1 - go.sum | 2 - light/lightchain.go | 29 +++---- 29 files changed, 226 insertions(+), 320 deletions(-) diff --git a/XDCx/XDCx.go b/XDCx/XDCx.go index ac3f83d582f4..3fbaf0c783e2 100644 --- a/XDCx/XDCx.go +++ b/XDCx/XDCx.go @@ -10,6 +10,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" "github.com/XinFinOrg/XDPoSChain/XDCxDAO" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/common/prque" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/core/state" @@ -17,7 +18,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/p2p" "github.com/XinFinOrg/XDPoSChain/rpc" - lru "github.com/hashicorp/golang-lru" "golang.org/x/sync/syncmap" ) @@ -59,8 +59,8 @@ type XDCX struct { sdkNode bool settings syncmap.Map // holds configuration settings that can be dynamically changed - tokenDecimalCache *lru.Cache - orderCache *lru.Cache + tokenDecimalCache *lru.Cache[common.Address, *big.Int] + orderCache *lru.Cache[common.Hash, map[common.Hash]tradingstate.OrderHistoryItem] } func (XDCx *XDCX) Protocols() []p2p.Protocol { @@ -94,19 +94,11 @@ func NewMongoDBEngine(cfg *Config) *XDCxDAO.MongoDatabase { } func New(cfg *Config) *XDCX { - tokenDecimalCache, err := lru.New(defaultCacheLimit) - if err != nil { - log.Warn("[XDCx-New] fail to create new lru for token decimal", "error", err) - } - orderCache, err := lru.New(tradingstate.OrderCacheLimit) - if err != nil { - log.Warn("[XDCx-New] fail to create new lru for order", "error", err) - } XDCX := &XDCX{ orderNonce: make(map[common.Address]*big.Int), Triegc: prque.New(nil), - tokenDecimalCache: tokenDecimalCache, - orderCache: orderCache, + tokenDecimalCache: lru.NewCache[common.Address, *big.Int](defaultCacheLimit), + orderCache: lru.NewCache[common.Hash, map[common.Hash]tradingstate.OrderHistoryItem](tradingstate.OrderCacheLimit), } // default DBEngine: levelDB @@ -607,12 +599,9 @@ func (XDCx *XDCX) GetTradingStateRoot(block *types.Block, author common.Address) } func (XDCx *XDCX) UpdateOrderCache(baseToken, quoteToken common.Address, orderHash common.Hash, txhash common.Hash, lastState tradingstate.OrderHistoryItem) { - var orderCacheAtTxHash map[common.Hash]tradingstate.OrderHistoryItem - c, ok := XDCx.orderCache.Get(txhash) - if !ok || c == nil { + orderCacheAtTxHash, ok := XDCx.orderCache.Get(txhash) + if !ok || orderCacheAtTxHash == nil { orderCacheAtTxHash = make(map[common.Hash]tradingstate.OrderHistoryItem) - } else { - orderCacheAtTxHash = c.(map[common.Hash]tradingstate.OrderHistoryItem) } orderKey := tradingstate.GetOrderHistoryKey(baseToken, quoteToken, orderHash) _, ok = orderCacheAtTxHash[orderKey] @@ -629,16 +618,15 @@ func (XDCx *XDCX) RollbackReorgTxMatch(txhash common.Hash) error { items := db.GetListItemByTxHash(txhash, &tradingstate.OrderItem{}) if items != nil { for _, order := range items.([]*tradingstate.OrderItem) { - c, ok := XDCx.orderCache.Get(txhash) - log.Debug("XDCx reorg: rollback order", "txhash", txhash.Hex(), "order", tradingstate.ToJSON(order), "orderHistoryItem", c) - if !ok { + orderCacheAtTxHash, ok := XDCx.orderCache.Get(txhash) + log.Debug("XDCx reorg: rollback order", "txhash", txhash.Hex(), "order", tradingstate.ToJSON(order), "orderHistoryItem", orderCacheAtTxHash) + if !ok || orderCacheAtTxHash == nil { log.Debug("XDCx reorg: remove order due to no orderCache", "order", tradingstate.ToJSON(order)) if err := db.DeleteObject(order.Hash, &tradingstate.OrderItem{}); err != nil { log.Crit("SDKNode: failed to remove reorg order", "err", err.Error(), "order", tradingstate.ToJSON(order)) } continue } - orderCacheAtTxHash := c.(map[common.Hash]tradingstate.OrderHistoryItem) orderHistoryItem := orderCacheAtTxHash[tradingstate.GetOrderHistoryKey(order.BaseToken, order.QuoteToken, order.Hash)] if (orderHistoryItem == tradingstate.OrderHistoryItem{}) { log.Debug("XDCx reorg: remove order due to empty orderHistory", "order", tradingstate.ToJSON(order)) diff --git a/XDCx/token.go b/XDCx/token.go index 5aa8554cf9f5..c44dbe7e297f 100644 --- a/XDCx/token.go +++ b/XDCx/token.go @@ -4,15 +4,14 @@ import ( "math/big" "strings" - "github.com/XinFinOrg/XDPoSChain/contracts/XDCx/contract" - "github.com/XinFinOrg/XDPoSChain/core" - "github.com/XinFinOrg/XDPoSChain/log" - "github.com/XinFinOrg/XDPoSChain" "github.com/XinFinOrg/XDPoSChain/accounts/abi" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/consensus" + "github.com/XinFinOrg/XDPoSChain/contracts/XDCx/contract" + "github.com/XinFinOrg/XDPoSChain/core" "github.com/XinFinOrg/XDPoSChain/core/state" + "github.com/XinFinOrg/XDPoSChain/log" ) // GetTokenAbi return token abi @@ -45,8 +44,8 @@ func RunContract(chain consensus.ChainContext, statedb *state.StateDB, contractA } func (XDCx *XDCX) GetTokenDecimal(chain consensus.ChainContext, statedb *state.StateDB, tokenAddr common.Address) (*big.Int, error) { - if tokenDecimal, ok := XDCx.tokenDecimalCache.Get(tokenAddr); ok { - return tokenDecimal.(*big.Int), nil + if tokenDecimal, ok := XDCx.tokenDecimalCache.Get(tokenAddr); ok && tokenDecimal != nil { + return tokenDecimal, nil } if tokenAddr == common.XDCNativeAddressBinary { XDCx.tokenDecimalCache.Add(tokenAddr, common.BasePrice) diff --git a/XDCx/tradingstate/database.go b/XDCx/tradingstate/database.go index b40f916a0f7f..2fe21932438e 100644 --- a/XDCx/tradingstate/database.go +++ b/XDCx/tradingstate/database.go @@ -23,7 +23,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/trie" - lru "github.com/hashicorp/golang-lru" ) // Trie cache generation limit after which to evic trie nodes from memory. @@ -33,9 +32,6 @@ const ( // Number of past tries to keep. This value is chosen such that // reasonable chain reorg depths will hit an existing trie. maxPastTries = 12 - - // Number of codehash->size associations to keep. - codeSizeCacheSize = 100000 ) // Database wraps access to tries and contract code. @@ -79,18 +75,15 @@ type Trie interface { // intermediate trie-node memory pool between the low level storage layer and the // high level trie abstraction. func NewDatabase(db ethdb.Database) Database { - csc, _ := lru.New(codeSizeCacheSize) return &cachingDB{ - db: trie.NewDatabase(db), - codeSizeCache: csc, + db: trie.NewDatabase(db), } } type cachingDB struct { - db *trie.Database - mu sync.Mutex - pastTries []*XDCXTrie - codeSizeCache *lru.Cache + db *trie.Database + mu sync.Mutex + pastTries []*XDCXTrie } // OpenTrie opens the main account trie. diff --git a/XDCxDAO/leveldb.go b/XDCxDAO/leveldb.go index 2a76162d4ca4..a6d90dd57a9f 100644 --- a/XDCxDAO/leveldb.go +++ b/XDCxDAO/leveldb.go @@ -8,10 +8,8 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/core/rawdb" - "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/log" - lru "github.com/hashicorp/golang-lru" ) type BatchItem struct { @@ -21,7 +19,6 @@ type BatchItem struct { type BatchDatabase struct { db ethdb.Database emptyKey []byte - cacheItems *lru.Cache // Cache for reading lock sync.RWMutex cacheLimit int Debug bool @@ -44,11 +41,8 @@ func NewBatchDatabaseWithEncode(datadir string, cacheLimit int) *BatchDatabase { itemCacheLimit = cacheLimit } - cacheItems, _ := lru.New(itemCacheLimit) - batchDB := &BatchDatabase{ db: db, - cacheItems: cacheItems, emptyKey: EmptyKey(), // pre alloc for comparison cacheLimit: itemCacheLimit, } diff --git a/XDCxDAO/mongodb.go b/XDCxDAO/mongodb.go index 5c0352db7a59..8c8e45052ca7 100644 --- a/XDCxDAO/mongodb.go +++ b/XDCxDAO/mongodb.go @@ -10,11 +10,11 @@ import ( "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" "github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/log" "github.com/globalsign/mgo" "github.com/globalsign/mgo/bson" - lru "github.com/hashicorp/golang-lru" ) const ( @@ -32,7 +32,7 @@ type MongoDatabase struct { Session *mgo.Session dbName string emptyKey []byte - cacheItems *lru.Cache // Cache for reading + cacheItems *lru.Cache[string, interface{}] // Cache for reading orderBulk *mgo.Bulk tradeBulk *mgo.Bulk epochPriceBulk *mgo.Bulk @@ -64,12 +64,11 @@ func NewMongoDatabase(session *mgo.Session, dbName string, mongoURL string, repl if cacheLimit > 0 { itemCacheLimit = cacheLimit } - cacheItems, _ := lru.New(itemCacheLimit) db := &MongoDatabase{ Session: session, dbName: dbName, - cacheItems: cacheItems, + cacheItems: lru.NewCache[string, interface{}](itemCacheLimit), } if err := db.EnsureIndexes(); err != nil { return nil, err diff --git a/XDCxlending/XDCxlending.go b/XDCxlending/XDCxlending.go index 28e9321aff24..1bf2496ff237 100644 --- a/XDCxlending/XDCxlending.go +++ b/XDCxlending/XDCxlending.go @@ -13,6 +13,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/XDCxDAO" "github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/common/prque" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/core/state" @@ -20,7 +21,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/p2p" "github.com/XinFinOrg/XDPoSChain/rpc" - lru "github.com/hashicorp/golang-lru" ) const ( @@ -42,8 +42,8 @@ type Lending struct { orderNonce map[common.Address]*big.Int XDCx *XDCx.XDCX - lendingItemHistory *lru.Cache - lendingTradeHistory *lru.Cache + lendingItemHistory *lru.Cache[common.Hash, map[common.Hash]lendingstate.LendingItemHistoryItem] + lendingTradeHistory *lru.Cache[common.Hash, map[common.Hash]lendingstate.LendingTradeHistoryItem] } func (l *Lending) Protocols() []p2p.Protocol { @@ -62,13 +62,11 @@ func (l *Lending) Stop() error { } func New(XDCx *XDCx.XDCX) *Lending { - itemCache, _ := lru.New(defaultCacheLimit) - lendingTradeCache, _ := lru.New(defaultCacheLimit) lending := &Lending{ orderNonce: make(map[common.Address]*big.Int), Triegc: prque.New(nil), - lendingItemHistory: itemCache, - lendingTradeHistory: lendingTradeCache, + lendingItemHistory: lru.NewCache[common.Hash, map[common.Hash]lendingstate.LendingItemHistoryItem](defaultCacheLimit), + lendingTradeHistory: lru.NewCache[common.Hash, map[common.Hash]lendingstate.LendingTradeHistoryItem](defaultCacheLimit), } lending.StateCache = lendingstate.NewDatabase(XDCx.GetLevelDB()) lending.XDCx = XDCx @@ -705,12 +703,9 @@ func (l *Lending) GetLendingStateRoot(block *types.Block, author common.Address) } func (l *Lending) UpdateLendingItemCache(LendingToken, CollateralToken common.Address, hash common.Hash, txhash common.Hash, lastState lendingstate.LendingItemHistoryItem) { - var lendingCacheAtTxHash map[common.Hash]lendingstate.LendingItemHistoryItem - c, ok := l.lendingItemHistory.Get(txhash) - if !ok || c == nil { + lendingCacheAtTxHash, ok := l.lendingItemHistory.Get(txhash) + if !ok || lendingCacheAtTxHash == nil { lendingCacheAtTxHash = make(map[common.Hash]lendingstate.LendingItemHistoryItem) - } else { - lendingCacheAtTxHash = c.(map[common.Hash]lendingstate.LendingItemHistoryItem) } orderKey := lendingstate.GetLendingItemHistoryKey(LendingToken, CollateralToken, hash) _, ok = lendingCacheAtTxHash[orderKey] @@ -722,11 +717,9 @@ func (l *Lending) UpdateLendingItemCache(LendingToken, CollateralToken common.Ad func (l *Lending) UpdateLendingTradeCache(hash common.Hash, txhash common.Hash, lastState lendingstate.LendingTradeHistoryItem) { var lendingCacheAtTxHash map[common.Hash]lendingstate.LendingTradeHistoryItem - c, ok := l.lendingTradeHistory.Get(txhash) - if !ok || c == nil { + lendingCacheAtTxHash, ok := l.lendingTradeHistory.Get(txhash) + if !ok || lendingCacheAtTxHash == nil { lendingCacheAtTxHash = make(map[common.Hash]lendingstate.LendingTradeHistoryItem) - } else { - lendingCacheAtTxHash = c.(map[common.Hash]lendingstate.LendingTradeHistoryItem) } _, ok = lendingCacheAtTxHash[hash] if !ok { @@ -743,16 +736,15 @@ func (l *Lending) RollbackLendingData(txhash common.Hash) error { items := db.GetListItemByTxHash(txhash, &lendingstate.LendingItem{}) if items != nil { for _, item := range items.([]*lendingstate.LendingItem) { - c, ok := l.lendingItemHistory.Get(txhash) - log.Debug("XDCxlending reorg: rollback lendingItem", "txhash", txhash.Hex(), "item", lendingstate.ToJSON(item), "lendingItemHistory", c) - if !ok { + cacheAtTxHash, ok := l.lendingItemHistory.Get(txhash) + log.Debug("XDCxlending reorg: rollback lendingItem", "txhash", txhash.Hex(), "item", lendingstate.ToJSON(item), "lendingItemHistory", cacheAtTxHash) + if !ok || cacheAtTxHash == nil { log.Debug("XDCxlending reorg: remove item due to no lendingItemHistory", "item", lendingstate.ToJSON(item)) if err := db.DeleteObject(item.Hash, &lendingstate.LendingItem{}); err != nil { return fmt.Errorf("failed to remove reorg LendingItem. Err: %v . Item: %s", err.Error(), lendingstate.ToJSON(item)) } continue } - cacheAtTxHash := c.(map[common.Hash]lendingstate.LendingItemHistoryItem) lendingItemHistory := cacheAtTxHash[lendingstate.GetLendingItemHistoryKey(item.LendingToken, item.CollateralToken, item.Hash)] if (lendingItemHistory == lendingstate.LendingItemHistoryItem{}) { log.Debug("XDCxlending reorg: remove item due to empty lendingItemHistory", "item", lendingstate.ToJSON(item)) @@ -776,16 +768,15 @@ func (l *Lending) RollbackLendingData(txhash common.Hash) error { items = db.GetListItemByTxHash(txhash, &lendingstate.LendingTrade{}) if items != nil { for _, trade := range items.([]*lendingstate.LendingTrade) { - c, ok := l.lendingTradeHistory.Get(txhash) - log.Debug("XDCxlending reorg: rollback LendingTrade", "txhash", txhash.Hex(), "trade", lendingstate.ToJSON(trade), "LendingTradeHistory", c) - if !ok { + cacheAtTxHash, ok := l.lendingTradeHistory.Get(txhash) + log.Debug("XDCxlending reorg: rollback LendingTrade", "txhash", txhash.Hex(), "trade", lendingstate.ToJSON(trade), "LendingTradeHistory", cacheAtTxHash) + if !ok || cacheAtTxHash == nil { log.Debug("XDCxlending reorg: remove trade due to no LendingTradeHistory", "trade", lendingstate.ToJSON(trade)) if err := db.DeleteObject(trade.Hash, &lendingstate.LendingTrade{}); err != nil { return fmt.Errorf("failed to remove reorg LendingTrade. Err: %v . Trade: %s", err.Error(), lendingstate.ToJSON(trade)) } continue } - cacheAtTxHash := c.(map[common.Hash]lendingstate.LendingTradeHistoryItem) lendingTradeHistoryItem := cacheAtTxHash[trade.Hash] if (lendingTradeHistoryItem == lendingstate.LendingTradeHistoryItem{}) { log.Debug("XDCxlending reorg: remove trade due to empty LendingTradeHistory", "trade", lendingstate.ToJSON(trade)) diff --git a/XDCxlending/lendingstate/database.go b/XDCxlending/lendingstate/database.go index d765a1eade76..7c4934bc7fec 100644 --- a/XDCxlending/lendingstate/database.go +++ b/XDCxlending/lendingstate/database.go @@ -23,7 +23,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/trie" - lru "github.com/hashicorp/golang-lru" ) // Trie cache generation limit after which to evic trie nodes from memory. @@ -33,9 +32,6 @@ const ( // Number of past tries to keep. This value is chosen such that // reasonable chain reorg depths will hit an existing trie. maxPastTries = 12 - - // Number of codehash->size associations to keep. - codeSizeCacheSize = 100000 ) // Database wraps access to tries and contract code. @@ -78,18 +74,16 @@ type Trie interface { // intermediate trie-node memory pool between the low level storage layer and the // high level trie abstraction. func NewDatabase(db ethdb.Database) Database { - csc, _ := lru.New(codeSizeCacheSize) return &cachingDB{ - db: trie.NewDatabase(db), - codeSizeCache: csc, + db: trie.NewDatabase(db), + // codeSizeCache: csc, } } type cachingDB struct { - db *trie.Database - mu sync.Mutex - pastTries []*XDCXTrie - codeSizeCache *lru.Cache + db *trie.Database + mu sync.Mutex + pastTries []*XDCXTrie } // OpenTrie opens the main account trie. diff --git a/consensus/XDPoS/XDPoS.go b/consensus/XDPoS/XDPoS.go index 5001abe4e8f1..411411d51857 100644 --- a/consensus/XDPoS/XDPoS.go +++ b/consensus/XDPoS/XDPoS.go @@ -22,20 +22,19 @@ import ( "math/big" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/engines/engine_v1" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/engines/engine_v2" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils" - "github.com/XinFinOrg/XDPoSChain/event" - "github.com/XinFinOrg/XDPoSChain/consensus/clique" "github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/ethdb" + "github.com/XinFinOrg/XDPoSChain/event" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/params" "github.com/XinFinOrg/XDPoSChain/rpc" - lru "github.com/hashicorp/golang-lru" ) const ( @@ -60,7 +59,7 @@ type XDPoS struct { db ethdb.Database // Database to store and retrieve snapshot checkpoints // Transaction cache, only make sense for adaptor level - signingTxsCache *lru.Cache + signingTxsCache *lru.Cache[common.Hash, []*types.Transaction] // Share Channel MinePeriodCh chan int // Miner wait Period Channel @@ -109,17 +108,12 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database) *XDPoS { minePeriodCh := make(chan int) newRoundCh := make(chan types.Round, newRoundChanSize) - // Allocate the snapshot caches and create the engine - signingTxsCache, _ := lru.New(utils.BlockSignersCacheLimit) - return &XDPoS{ - config: config, - db: db, - - MinePeriodCh: minePeriodCh, - NewRoundCh: newRoundCh, - - signingTxsCache: signingTxsCache, + config: config, + db: db, + MinePeriodCh: minePeriodCh, + NewRoundCh: newRoundCh, + signingTxsCache: lru.NewCache[common.Hash, []*types.Transaction](utils.BlockSignersCacheLimit), EngineV1: engine_v1.New(chainConfig, db), EngineV2: engine_v2.New(chainConfig, db, minePeriodCh, newRoundCh), } @@ -138,22 +132,16 @@ func NewFaker(db ethdb.Database, chainConfig *params.ChainConfig) *XDPoS { minePeriodCh := make(chan int) newRoundCh := make(chan types.Round, newRoundChanSize) - // Allocate the snapshot caches and create the engine - signingTxsCache, _ := lru.New(utils.BlockSignersCacheLimit) - fakeEngine = &XDPoS{ - config: conf, - db: db, - - MinePeriodCh: minePeriodCh, - NewRoundCh: newRoundCh, - + config: conf, + db: db, + MinePeriodCh: minePeriodCh, + NewRoundCh: newRoundCh, GetXDCXService: func() utils.TradingService { return nil }, GetLendingService: func() utils.LendingService { return nil }, - - signingTxsCache: signingTxsCache, - EngineV1: engine_v1.NewFaker(db, chainConfig), - EngineV2: engine_v2.New(chainConfig, db, minePeriodCh, newRoundCh), + signingTxsCache: lru.NewCache[common.Hash, []*types.Transaction](utils.BlockSignersCacheLimit), + EngineV1: engine_v1.NewFaker(db, chainConfig), + EngineV2: engine_v2.New(chainConfig, db, minePeriodCh, newRoundCh), } return fakeEngine } @@ -554,7 +542,7 @@ func (x *XDPoS) CacheSigningTxs(hash common.Hash, txs []*types.Transaction) []*t return signTxs } -func (x *XDPoS) GetCachedSigningTxs(hash common.Hash) (interface{}, bool) { +func (x *XDPoS) GetCachedSigningTxs(hash common.Hash) ([]*types.Transaction, bool) { return x.signingTxsCache.Get(hash) } diff --git a/consensus/XDPoS/engines/engine_v1/engine.go b/consensus/XDPoS/engines/engine_v1/engine.go index b93a8729d6ef..54d4d48b876e 100644 --- a/consensus/XDPoS/engines/engine_v1/engine.go +++ b/consensus/XDPoS/engines/engine_v1/engine.go @@ -14,8 +14,8 @@ import ( "github.com/XinFinOrg/XDPoSChain/accounts" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/consensus" - "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils" "github.com/XinFinOrg/XDPoSChain/consensus/clique" "github.com/XinFinOrg/XDPoSChain/consensus/misc" @@ -26,7 +26,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/params" - lru "github.com/hashicorp/golang-lru" ) const ( @@ -44,10 +43,10 @@ type XDPoS_v1 struct { config *params.XDPoSConfig // Consensus engine configuration parameters db ethdb.Database // Database to store and retrieve snapshot checkpoints - recents *lru.ARCCache // Snapshots for recent block to speed up reorgs - signatures *lru.ARCCache // Signatures of recent blocks to speed up mining - validatorSignatures *lru.ARCCache // Signatures of recent blocks to speed up mining - verifiedHeaders *lru.ARCCache + recents *lru.Cache[common.Hash, *SnapshotV1] // Snapshots for recent block to speed up reorgs + signatures *utils.SigLRU // Signatures of recent blocks to speed up mining + validatorSignatures *utils.SigLRU // Signatures of recent blocks to speed up mining + verifiedHeaders *lru.Cache[common.Hash, struct{}] proposals map[common.Address]bool // Current list of proposals we are pushing signer common.Address // Ethereum address of the signing key @@ -92,20 +91,16 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database) *XDPoS_v1 { conf.Epoch = utils.EpochLength } - recents, _ := lru.NewARC(utils.InmemorySnapshots) - signatures, _ := lru.NewARC(utils.InmemorySnapshots) - validatorSignatures, _ := lru.NewARC(utils.InmemorySnapshots) - verifiedHeaders, _ := lru.NewARC(utils.InmemorySnapshots) return &XDPoS_v1{ chainConfig: chainConfig, config: &conf, db: db, - recents: recents, - signatures: signatures, - verifiedHeaders: verifiedHeaders, - validatorSignatures: validatorSignatures, + recents: lru.NewCache[common.Hash, *SnapshotV1](utils.InmemorySnapshots), + signatures: lru.NewCache[common.Hash, common.Address](utils.InmemorySnapshots), + verifiedHeaders: lru.NewCache[common.Hash, struct{}](utils.InmemorySnapshots), + validatorSignatures: lru.NewCache[common.Hash, common.Address](utils.InmemorySnapshots), proposals: make(map[common.Address]bool), } } @@ -145,7 +140,7 @@ func (x *XDPoS_v1) verifyHeaderWithCache(chain consensus.ChainReader, header *ty } err := x.verifyHeader(chain, header, parents, fullVerify) if err == nil { - x.verifiedHeaders.Add(header.Hash(), true) + x.verifiedHeaders.Add(header.Hash(), struct{}{}) } return err } @@ -483,8 +478,8 @@ func (x *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash com ) for { // If an in-memory SnapshotV1 was found, use that - if s, ok := x.recents.Get(hash); ok { - snap = s.(*SnapshotV1) + if s, ok := x.recents.Get(hash); ok && s != nil { + snap = s break } // If an on-disk checkpoint snapshot can be found, use that @@ -979,7 +974,7 @@ func (x *XDPoS_v1) RecoverValidator(header *types.Header) (common.Address, error // If the signature's already cached, return that hash := header.Hash() if address, known := x.validatorSignatures.Get(hash); known { - return address.(common.Address), nil + return address, nil } // Retrieve the signature from the header.Validator // len equals 65 bytes @@ -1044,20 +1039,15 @@ func NewFaker(db ethdb.Database, chainConfig *params.ChainConfig) *XDPoS_v1 { // Set any missing consensus parameters to their defaults conf := chainConfig.XDPoS - // Allocate the snapshot caches and create the engine - recents, _ := lru.NewARC(utils.InmemorySnapshots) - signatures, _ := lru.NewARC(utils.InmemorySnapshots) - validatorSignatures, _ := lru.NewARC(utils.InmemorySnapshots) - verifiedHeaders, _ := lru.NewARC(utils.InmemorySnapshots) fakeEngine = &XDPoS_v1{ chainConfig: chainConfig, config: conf, db: db, - recents: recents, - signatures: signatures, - verifiedHeaders: verifiedHeaders, - validatorSignatures: validatorSignatures, + recents: lru.NewCache[common.Hash, *SnapshotV1](utils.InmemorySnapshots), + signatures: lru.NewCache[common.Hash, common.Address](utils.InmemorySnapshots), + verifiedHeaders: lru.NewCache[common.Hash, struct{}](utils.InmemorySnapshots), + validatorSignatures: lru.NewCache[common.Hash, common.Address](utils.InmemorySnapshots), proposals: make(map[common.Address]bool), } return fakeEngine diff --git a/consensus/XDPoS/engines/engine_v1/snapshot.go b/consensus/XDPoS/engines/engine_v1/snapshot.go index 3ad8b221894a..012b29aabea0 100644 --- a/consensus/XDPoS/engines/engine_v1/snapshot.go +++ b/consensus/XDPoS/engines/engine_v1/snapshot.go @@ -10,7 +10,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/params" - lru "github.com/hashicorp/golang-lru" ) // Vote represents a single vote that an authorized signer made to modify the @@ -32,7 +31,7 @@ import ( // Snapshot is the state of the authorization voting at a given point in time. type SnapshotV1 struct { config *params.XDPoSConfig // Consensus engine parameters to fine tune behavior - sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover + sigcache *utils.SigLRU // Cache of recent block signatures to speed up ecrecover Number uint64 `json:"number"` // Block number where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created @@ -45,7 +44,7 @@ type SnapshotV1 struct { // newSnapshot creates a new snapshot with the specified startup parameters. This // method does not initialize the set of recent signers, so only ever use if for // the genesis block. -func newSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *SnapshotV1 { +func newSnapshot(config *params.XDPoSConfig, sigcache *utils.SigLRU, number uint64, hash common.Hash, signers []common.Address) *SnapshotV1 { snap := &SnapshotV1{ config: config, sigcache: sigcache, @@ -62,7 +61,7 @@ func newSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, number uint } // loadSnapshot loads an existing snapshot from the database. -func loadSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*SnapshotV1, error) { +func loadSnapshot(config *params.XDPoSConfig, sigcache *utils.SigLRU, db ethdb.Database, hash common.Hash) (*SnapshotV1, error) { blob, err := db.Get(append([]byte("XDPoS-"), hash[:]...)) if err != nil { return nil, err diff --git a/consensus/XDPoS/engines/engine_v1/utils.go b/consensus/XDPoS/engines/engine_v1/utils.go index a0128331220c..fbd7814935d5 100644 --- a/consensus/XDPoS/engines/engine_v1/utils.go +++ b/consensus/XDPoS/engines/engine_v1/utils.go @@ -9,7 +9,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/params" "github.com/XinFinOrg/XDPoSChain/rlp" - lru "github.com/hashicorp/golang-lru" "golang.org/x/crypto/sha3" ) @@ -87,11 +86,11 @@ func sigHash(header *types.Header) (hash common.Hash) { } // ecrecover extracts the Ethereum account address from a signed header. -func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { +func ecrecover(header *types.Header, sigcache *utils.SigLRU) (common.Address, error) { // If the signature's already cached, return that hash := header.Hash() if address, known := sigcache.Get(hash); known { - return address.(common.Address), nil + return address, nil } // Retrieve the signature from the header extra-data if len(header.Extra) < utils.ExtraSeal { diff --git a/consensus/XDPoS/engines/engine_v2/engine.go b/consensus/XDPoS/engines/engine_v2/engine.go index 25515c3f7acb..bcbf4651cb9f 100644 --- a/consensus/XDPoS/engines/engine_v2/engine.go +++ b/consensus/XDPoS/engines/engine_v2/engine.go @@ -13,6 +13,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/accounts" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/countdown" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils" "github.com/XinFinOrg/XDPoSChain/consensus/clique" @@ -21,7 +22,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/params" - lru "github.com/hashicorp/golang-lru" ) type XDPoS_v2 struct { @@ -32,14 +32,14 @@ type XDPoS_v2 struct { isInitilised bool // status of v2 variables whosTurn common.Address // Record waiting for who to mine - snapshots *lru.ARCCache // Snapshots for gap block - signatures *lru.ARCCache // Signatures of recent blocks to speed up mining - epochSwitches *lru.ARCCache // infos of epoch: master nodes, epoch switch block info, parent of that info - verifiedHeaders *lru.ARCCache + snapshots *lru.Cache[common.Hash, *SnapshotV2] // Snapshots for gap block + signatures *utils.SigLRU // Signatures of recent blocks to speed up mining + epochSwitches *lru.Cache[common.Hash, *types.EpochSwitchInfo] // infos of epoch: master nodes, epoch switch block info, parent of that info + verifiedHeaders *lru.Cache[common.Hash, struct{}] // only contains epoch switch block info // input: round, output: infos of epoch switch block and next epoch switch block info - round2epochBlockInfo *lru.ARCCache + round2epochBlockInfo *lru.Cache[types.Round, *types.BlockInfo] signer common.Address // Ethereum address of the signing key signFn clique.SignerFn // Signer function to authorize hashes with @@ -78,12 +78,6 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database, minePeriodCh chan i duration := time.Duration(config.V2.CurrentConfig.TimeoutPeriod) * time.Second timeoutTimer := countdown.NewCountDown(duration) - snapshots, _ := lru.NewARC(utils.InmemorySnapshots) - signatures, _ := lru.NewARC(utils.InmemorySnapshots) - epochSwitches, _ := lru.NewARC(int(utils.InmemoryEpochs)) - verifiedHeaders, _ := lru.NewARC(utils.InmemorySnapshots) - round2epochBlockInfo, _ := lru.NewARC(utils.InmemoryRound2Epochs) - timeoutPool := utils.NewPool() votePool := utils.NewPool() engine := &XDPoS_v2{ @@ -93,17 +87,17 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database, minePeriodCh chan i db: db, isInitilised: false, - signatures: signatures, + signatures: lru.NewCache[common.Hash, common.Address](utils.InmemorySnapshots), - verifiedHeaders: verifiedHeaders, - snapshots: snapshots, - epochSwitches: epochSwitches, + verifiedHeaders: lru.NewCache[common.Hash, struct{}](utils.InmemorySnapshots), + snapshots: lru.NewCache[common.Hash, *SnapshotV2](utils.InmemorySnapshots), + epochSwitches: lru.NewCache[common.Hash, *types.EpochSwitchInfo](int(utils.InmemoryEpochs)), timeoutWorker: timeoutTimer, BroadcastCh: make(chan interface{}), minePeriodCh: minePeriodCh, newRoundCh: newRoundCh, - round2epochBlockInfo: round2epochBlockInfo, + round2epochBlockInfo: lru.NewCache[types.Round, *types.BlockInfo](utils.InmemoryRound2Epochs), timeoutPool: timeoutPool, votePool: votePool, diff --git a/consensus/XDPoS/engines/engine_v2/epochSwitch.go b/consensus/XDPoS/engines/engine_v2/epochSwitch.go index e9d76daa620a..b6c4a0c16808 100644 --- a/consensus/XDPoS/engines/engine_v2/epochSwitch.go +++ b/consensus/XDPoS/engines/engine_v2/epochSwitch.go @@ -30,9 +30,8 @@ func (x *XDPoS_v2) getPreviousEpochSwitchInfoByHash(chain consensus.ChainReader, // Given header and its hash, get epoch switch info from the epoch switch block of that epoch, // header is allow to be nil. func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types.Header, hash common.Hash) (*types.EpochSwitchInfo, error) { - e, ok := x.epochSwitches.Get(hash) - if ok { - epochSwitchInfo := e.(*types.EpochSwitchInfo) + epochSwitchInfo, ok := x.epochSwitches.Get(hash) + if ok && epochSwitchInfo != nil { log.Debug("[getEpochSwitchInfo] cache hit", "number", epochSwitchInfo.EpochSwitchBlockInfo.Number, "hash", hash.Hex()) return epochSwitchInfo, nil } @@ -88,7 +87,7 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types x.epochSwitches.Add(hash, epochSwitchInfo) return epochSwitchInfo, nil } - epochSwitchInfo, err := x.getEpochSwitchInfo(chain, nil, h.ParentHash) + epochSwitchInfo, err = x.getEpochSwitchInfo(chain, nil, h.ParentHash) if err != nil { log.Error("[getEpochSwitchInfo] recursive error", "err", err, "hash", hash.Hex(), "number", h.Number.Uint64()) return nil, err diff --git a/consensus/XDPoS/engines/engine_v2/snapshot.go b/consensus/XDPoS/engines/engine_v2/snapshot.go index ccae59841278..de4fb76d82bf 100644 --- a/consensus/XDPoS/engines/engine_v2/snapshot.go +++ b/consensus/XDPoS/engines/engine_v2/snapshot.go @@ -84,8 +84,7 @@ func (x *XDPoS_v2) getSnapshot(chain consensus.ChainReader, number uint64, isGap log.Debug("get snapshot from gap block", "number", gapBlockNum, "hash", gapBlockHash.Hex()) // If an in-memory SnapshotV2 was found, use that - if s, ok := x.snapshots.Get(gapBlockHash); ok { - snap := s.(*SnapshotV2) + if snap, ok := x.snapshots.Get(gapBlockHash); ok && snap != nil { log.Trace("Loaded snapshot from memory", "number", gapBlockNum, "hash", gapBlockHash) return snap, nil } diff --git a/consensus/XDPoS/engines/engine_v2/utils.go b/consensus/XDPoS/engines/engine_v2/utils.go index b95d12c5f222..49d79177e8c1 100644 --- a/consensus/XDPoS/engines/engine_v2/utils.go +++ b/consensus/XDPoS/engines/engine_v2/utils.go @@ -13,7 +13,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/rlp" - lru "github.com/hashicorp/golang-lru" "golang.org/x/crypto/sha3" ) @@ -47,11 +46,11 @@ func sigHash(header *types.Header) (hash common.Hash) { return hash } -func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { +func ecrecover(header *types.Header, sigcache *utils.SigLRU) (common.Address, error) { // If the signature's already cached, return that hash := header.Hash() if address, known := sigcache.Get(hash); known { - return address.(common.Address), nil + return address, nil } // Recover the public key and the Ethereum address @@ -224,9 +223,8 @@ func (x *XDPoS_v2) CalculateMissingRounds(chain consensus.ChainReader, header *t func (x *XDPoS_v2) getBlockByEpochNumberInCache(chain consensus.ChainReader, estRound types.Round) *types.BlockInfo { epochSwitchInCache := make([]*types.BlockInfo, 0) for r := estRound; r < estRound+types.Round(x.config.Epoch); r++ { - info, ok := x.round2epochBlockInfo.Get(r) - if ok { - blockInfo := info.(*types.BlockInfo) + blockInfo, ok := x.round2epochBlockInfo.Get(r) + if ok && blockInfo != nil { epochSwitchInCache = append(epochSwitchInCache, blockInfo) } } diff --git a/consensus/XDPoS/engines/engine_v2/verifyHeader.go b/consensus/XDPoS/engines/engine_v2/verifyHeader.go index 4e18e2031e68..8341ae1c6be8 100644 --- a/consensus/XDPoS/engines/engine_v2/verifyHeader.go +++ b/consensus/XDPoS/engines/engine_v2/verifyHeader.go @@ -190,6 +190,6 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade return utils.ErrNotItsTurn } - x.verifiedHeaders.Add(header.Hash(), true) + x.verifiedHeaders.Add(header.Hash(), struct{}{}) return nil } diff --git a/consensus/XDPoS/utils/types.go b/consensus/XDPoS/utils/types.go index b5d116834110..fc4aaf0463aa 100644 --- a/consensus/XDPoS/utils/types.go +++ b/consensus/XDPoS/utils/types.go @@ -7,6 +7,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" "github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/common/prque" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/consensus/clique" @@ -79,3 +80,5 @@ type EpochNumInfo struct { EpochFirstBlockNumber *big.Int `json:"firstBlock"` EpochLastBlockNumber *big.Int `json:"lastBlock"` } + +type SigLRU = lru.Cache[common.Hash, common.Address] diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index bb1e8ef1189c..d6c7f42bde2a 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -29,6 +29,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/accounts" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/hexutil" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/consensus/misc" "github.com/XinFinOrg/XDPoSChain/core/state" @@ -39,7 +40,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/params" "github.com/XinFinOrg/XDPoSChain/rlp" "github.com/XinFinOrg/XDPoSChain/rpc" - lru "github.com/hashicorp/golang-lru" "golang.org/x/crypto/sha3" ) @@ -173,11 +173,11 @@ func sigHash(header *types.Header) (hash common.Hash) { } // ecrecover extracts the Ethereum account address from a signed header. -func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { +func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) { // If the signature's already cached, return that hash := header.Hash() if address, known := sigcache.Get(hash); known { - return address.(common.Address), nil + return address, nil } // Retrieve the signature from the header extra-data if len(header.Extra) < extraSeal { @@ -203,8 +203,8 @@ type Clique struct { config *params.CliqueConfig // Consensus engine configuration parameters db ethdb.Database // Database to store and retrieve snapshot checkpoints - recents *lru.ARCCache // Snapshots for recent block to speed up reorgs - signatures *lru.ARCCache // Signatures of recent blocks to speed up mining + recents *lru.Cache[common.Hash, *Snapshot] // Snapshots for recent block to speed up reorgs + signatures *sigLRU // Signatures of recent blocks to speed up mining proposals map[common.Address]bool // Current list of proposals we are pushing @@ -221,15 +221,12 @@ func New(config *params.CliqueConfig, db ethdb.Database) *Clique { if conf.Epoch == 0 { conf.Epoch = epochLength } - // Allocate the snapshot caches and create the engine - recents, _ := lru.NewARC(inmemorySnapshots) - signatures, _ := lru.NewARC(inmemorySignatures) return &Clique{ config: &conf, db: db, - recents: recents, - signatures: signatures, + recents: lru.NewCache[common.Hash, *Snapshot](inmemorySnapshots), + signatures: lru.NewCache[common.Hash, common.Address](inmemorySignatures), proposals: make(map[common.Address]bool), } } @@ -396,8 +393,8 @@ func (c *Clique) snapshot(chain consensus.ChainReader, number uint64, hash commo ) for { // If an in-memory snapshot was found, use that - if s, ok := c.recents.Get(hash); ok { - snap = s.(*Snapshot) + if s, ok := c.recents.Get(hash); ok && s != nil { + snap = s break } // If an on-disk checkpoint snapshot can be found, use that diff --git a/consensus/clique/snapshot.go b/consensus/clique/snapshot.go index bc89168aff0f..ff7c5a4c8e9a 100644 --- a/consensus/clique/snapshot.go +++ b/consensus/clique/snapshot.go @@ -21,10 +21,10 @@ import ( "encoding/json" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/params" - lru "github.com/hashicorp/golang-lru" ) // Vote represents a single vote that an authorized signer made to modify the @@ -43,10 +43,12 @@ type Tally struct { Votes int `json:"votes"` // Number of votes until now wanting to pass the proposal } +type sigLRU = lru.Cache[common.Hash, common.Address] + // Snapshot is the state of the authorization voting at a given point in time. type Snapshot struct { config *params.CliqueConfig // Consensus engine parameters to fine tune behavior - sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover + sigcache *sigLRU // Cache of recent block signatures to speed up ecrecover Number uint64 `json:"number"` // Block number where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created @@ -59,7 +61,7 @@ type Snapshot struct { // newSnapshot creates a new snapshot with the specified startup parameters. This // method does not initialize the set of recent signers, so only ever use if for // the genesis block. -func newSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot { +func newSnapshot(config *params.CliqueConfig, sigcache *sigLRU, number uint64, hash common.Hash, signers []common.Address) *Snapshot { snap := &Snapshot{ config: config, sigcache: sigcache, @@ -76,7 +78,7 @@ func newSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, number uin } // loadSnapshot loads an existing snapshot from the database. -func loadSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) { +func loadSnapshot(config *params.CliqueConfig, sigcache *sigLRU, db ethdb.Database, hash common.Hash) (*Snapshot, error) { blob, err := db.Get(append([]byte("clique-"), hash[:]...)) if err != nil { return nil, err diff --git a/consensus/ethash/ethash.go b/consensus/ethash/ethash.go index 394d495a07e8..96dd5bb68d5d 100644 --- a/consensus/ethash/ethash.go +++ b/consensus/ethash/ethash.go @@ -32,12 +32,12 @@ import ( "time" "unsafe" + lrupkg "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/metrics" "github.com/XinFinOrg/XDPoSChain/rpc" mmap "github.com/edsrzf/mmap-go" - "github.com/hashicorp/golang-lru/simplelru" ) var ErrInvalidDumpMagic = errors.New("invalid dump magic") @@ -144,34 +144,45 @@ func memoryMapAndGenerate(path string, size uint64, generator func(buffer []uint return memoryMap(path) } +type cacheOrDataset interface { + *cache | *dataset +} + // lru tracks caches or datasets by their last use time, keeping at most N of them. -type lru struct { +type lru[T cacheOrDataset] struct { what string - new func(epoch uint64) interface{} + new func(epoch uint64) T mu sync.Mutex // Items are kept in a LRU cache, but there is a special case: // We always keep an item for (highest seen epoch) + 1 as the 'future item'. - cache *simplelru.LRU + cache lrupkg.BasicLRU[uint64, T] future uint64 - futureItem interface{} + futureItem T } -// newlru create a new least-recently-used cache for ither the verification caches +// newlru create a new least-recently-used cache for either the verification caches // or the mining datasets. -func newlru(what string, maxItems int, new func(epoch uint64) interface{}) *lru { - if maxItems <= 0 { - maxItems = 1 +func newlru[T cacheOrDataset](maxItems int, new func(epoch uint64) T) *lru[T] { + var what string + switch any(T(nil)).(type) { + case *cache: + what = "cache" + case *dataset: + what = "dataset" + default: + panic("unknown type") + } + return &lru[T]{ + what: what, + new: new, + cache: lrupkg.NewBasicLRU[uint64, T](maxItems), } - cache, _ := simplelru.NewLRU(maxItems, func(key, value interface{}) { - log.Trace("Evicted ethash "+what, "epoch", key) - }) - return &lru{what: what, new: new, cache: cache} } // get retrieves or creates an item for the given epoch. The first return value is always // non-nil. The second return value is non-nil if lru thinks that an item will be useful in // the near future. -func (lru *lru) get(epoch uint64) (item, future interface{}) { +func (lru *lru[T]) get(epoch uint64) (item, future T) { lru.mu.Lock() defer lru.mu.Unlock() @@ -205,9 +216,8 @@ type cache struct { once sync.Once // Ensures the cache is generated only once } -// newCache creates a new ethash verification cache and returns it as a plain Go -// interface to be usable in an LRU cache. -func newCache(epoch uint64) interface{} { +// newCache creates a new ethash verification cache. +func newCache(epoch uint64) *cache { return &cache{epoch: epoch} } @@ -283,7 +293,7 @@ type dataset struct { // newDataset creates a new ethash mining dataset and returns it as a plain Go // interface to be usable in an LRU cache. -func newDataset(epoch uint64) interface{} { +func newDataset(epoch uint64) *dataset { return &dataset{epoch: epoch} } @@ -394,13 +404,13 @@ type Config struct { type Ethash struct { config Config - caches *lru // In memory caches to avoid regenerating too often - datasets *lru // In memory datasets to avoid regenerating too often + caches *lru[*cache] // In memory caches to avoid regenerating too often + datasets *lru[*dataset] // In memory datasets to avoid regenerating too often // Mining related fields - rand *rand.Rand // Properly seeded random source for nonces - threads int // Number of threads to mine on if mining - update chan struct{} // Notification channel to update mining parameters + rand *rand.Rand // Properly seeded random source for nonces + threads int // Number of threads to mine on if mining + update chan struct{} // Notification channel to update mining parameters hashrate *metrics.Meter // Meter tracking the average hashrate // The fields below are hooks for testing @@ -425,8 +435,8 @@ func New(config Config) *Ethash { } return &Ethash{ config: config, - caches: newlru("cache", config.CachesInMem, newCache), - datasets: newlru("dataset", config.DatasetsInMem, newDataset), + caches: newlru(config.CachesInMem, newCache), + datasets: newlru(config.DatasetsInMem, newDataset), update: make(chan struct{}), hashrate: metrics.NewMeter(), } @@ -494,15 +504,13 @@ func NewShared() *Ethash { // stored on disk, and finally generating one if none can be found. func (ethash *Ethash) cache(block uint64) *cache { epoch := block / epochLength - currentI, futureI := ethash.caches.get(epoch) - current := currentI.(*cache) + current, future := ethash.caches.get(epoch) // Wait for generation finish. current.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.PowMode == ModeTest) // If we need a new future cache, now's a good time to regenerate it. - if futureI != nil { - future := futureI.(*cache) + if future != nil { go future.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.PowMode == ModeTest) } return current @@ -513,15 +521,13 @@ func (ethash *Ethash) cache(block uint64) *cache { // stored on disk, and finally generating one if none can be found. func (ethash *Ethash) dataset(block uint64) *dataset { epoch := block / epochLength - currentI, futureI := ethash.datasets.get(epoch) - current := currentI.(*dataset) + current, future := ethash.datasets.get(epoch) // Wait for generation finish. current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.PowMode == ModeTest) // If we need a new future dataset, now's a good time to regenerate it. - if futureI != nil { - future := futureI.(*dataset) + if future != nil { go future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.PowMode == ModeTest) } diff --git a/contracts/utils.go b/contracts/utils.go index 5e236743ea27..b309e5bdd24e 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -331,20 +331,19 @@ func GetRewardForCheckpoint(c *XDPoS.XDPoS, chain consensus.ChainReader, header for i := prevCheckpoint + (rCheckpoint * 2) - 1; i >= startBlockNumber; i-- { header = chain.GetHeader(header.ParentHash, i) mapBlkHash[i] = header.Hash() - signData, ok := c.GetCachedSigningTxs(header.Hash()) + signingTxs, ok := c.GetCachedSigningTxs(header.Hash()) if !ok { log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i) block := chain.GetBlock(header.Hash(), i) txs := block.Transactions() if !chain.Config().IsTIPSigning(header.Number) { receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i) - signData = c.CacheNoneTIPSigningTxs(header, txs, receipts) + signingTxs = c.CacheNoneTIPSigningTxs(header, txs, receipts) } else { - signData = c.CacheSigningTxs(header.Hash(), txs) + signingTxs = c.CacheSigningTxs(header.Hash(), txs) } } - txs := signData.([]*types.Transaction) - for _, tx := range txs { + for _, tx := range signingTxs { blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) from := *tx.From() data[blkHash] = append(data[blkHash], from) diff --git a/core/state/trc21_reader.go b/core/state/trc21_reader.go index af5fd25b1390..561cebb5c766 100644 --- a/core/state/trc21_reader.go +++ b/core/state/trc21_reader.go @@ -5,8 +5,7 @@ import ( "math/big" "github.com/XinFinOrg/XDPoSChain/common" - lru "github.com/hashicorp/golang-lru" - + "github.com/XinFinOrg/XDPoSChain/common/lru" ) var ( @@ -22,21 +21,18 @@ var ( } transferFuncHex = common.Hex2Bytes("0xa9059cbb") transferFromFuncHex = common.Hex2Bytes("0x23b872dd") - cache, _ = lru.NewARC(128) + cache = lru.NewCache[common.Hash, map[common.Address]*big.Int](128) ) func GetTRC21FeeCapacityFromStateWithCache(trieRoot common.Hash, statedb *StateDB) map[common.Address]*big.Int { if statedb == nil { return map[common.Address]*big.Int{} } - data, _ := cache.Get(trieRoot) - var info map[common.Address]*big.Int - if data != nil { - info = data.(map[common.Address]*big.Int) - } else { + info, ok := cache.Get(trieRoot) + if !ok || info == nil { info = GetTRC21FeeCapacityFromState(statedb) + cache.Add(trieRoot, info) } - cache.Add(trieRoot, info) tokensFee := map[common.Address]*big.Int{} for key, value := range info { tokensFee[key] = big.NewInt(0).SetBytes(value.Bytes()) diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index ed362f027635..259781a6bb11 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -22,9 +22,8 @@ import ( "math/rand" "time" - lru "github.com/hashicorp/golang-lru" - "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/common/prque" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/core/types" @@ -135,7 +134,8 @@ type Fetcher struct { queue *prque.Prque // Queue containing the import operations (block number sorted) queues map[string]int // Per peer block counts to prevent memory exhaustion queued map[common.Hash]*inject // Set of already queued blocks (to dedup imports) - knowns *lru.ARCCache + knowns *lru.Cache[common.Hash, struct{}] + // Callbacks getBlock blockRetrievalFn // Retrieves a block from the local chain verifyHeader headerVerifierFn // Checks if a block's headers have a valid proof of work @@ -157,7 +157,6 @@ type Fetcher struct { // New creates a block fetcher to retrieve blocks based on hash announcements. func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, handleProposedBlock proposeBlockHandlerFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertBlock blockInsertFn, prepareBlock blockPrepareFn, dropPeer peerDropFn) *Fetcher { - knownBlocks, _ := lru.NewARC(blockLimit) return &Fetcher{ notify: make(chan *announce), inject: make(chan *inject), @@ -174,7 +173,7 @@ func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, handlePropose queue: prque.New(nil), queues: make(map[string]int), queued: make(map[common.Hash]*inject), - knowns: knownBlocks, + knowns: lru.NewCache[common.Hash, struct{}](blockLimit), getBlock: getBlock, verifyHeader: verifyHeader, handleProposedBlock: handleProposedBlock, @@ -641,7 +640,7 @@ func (f *Fetcher) enqueue(peer string, block *types.Block) { } f.queues[peer] = count f.queued[hash] = op - f.knowns.Add(hash, true) + f.knowns.Add(hash, struct{}{}) f.queue.Push(op, -int64(block.NumberU64())) if f.queueChangeHook != nil { f.queueChangeHook(op.block.Hash(), true) diff --git a/eth/handler.go b/eth/handler.go index 503671eb5280..7ac5c633f720 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -25,9 +25,8 @@ import ( "sync/atomic" "time" - lru "github.com/hashicorp/golang-lru" - "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS" "github.com/XinFinOrg/XDPoSChain/consensus/misc" @@ -104,14 +103,14 @@ type ProtocolManager struct { // wait group is used for graceful shutdowns during downloading // and processing wg sync.WaitGroup - knownTxs *lru.Cache - knowOrderTxs *lru.Cache - knowLendingTxs *lru.Cache + knownTxs *lru.Cache[common.Hash, struct{}] + knowOrderTxs *lru.Cache[common.Hash, struct{}] + knowLendingTxs *lru.Cache[common.Hash, struct{}] // V2 messages - knownVotes *lru.Cache - knownSyncInfos *lru.Cache - knownTimeouts *lru.Cache + knownVotes *lru.Cache[common.Hash, struct{}] + knownSyncInfos *lru.Cache[common.Hash, struct{}] + knownTimeouts *lru.Cache[common.Hash, struct{}] } // NewProtocolManagerEx add order pool to protocol @@ -128,14 +127,6 @@ func NewProtocolManagerEx(config *params.ChainConfig, mode downloader.SyncMode, // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // with the ethereum network. func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkID uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) { - knownTxs, _ := lru.New(maxKnownTxs) - knowOrderTxs, _ := lru.New(maxKnownOrderTxs) - knowLendingTxs, _ := lru.New(maxKnownLendingTxs) - - knownVotes, _ := lru.New(maxKnownVote) - knownSyncInfos, _ := lru.New(maxKnownSyncInfo) - knownTimeouts, _ := lru.New(maxKnownTimeout) - // Create the protocol manager with the base fields manager := &ProtocolManager{ networkId: networkID, @@ -148,12 +139,12 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne noMorePeers: make(chan struct{}), txsyncCh: make(chan *txsync), quitSync: make(chan struct{}), - knownTxs: knownTxs, - knowOrderTxs: knowOrderTxs, - knowLendingTxs: knowLendingTxs, - knownVotes: knownVotes, - knownSyncInfos: knownSyncInfos, - knownTimeouts: knownTimeouts, + knownTxs: lru.NewCache[common.Hash, struct{}](maxKnownTxs), + knowOrderTxs: lru.NewCache[common.Hash, struct{}](maxKnownOrderTxs), + knowLendingTxs: lru.NewCache[common.Hash, struct{}](maxKnownLendingTxs), + knownVotes: lru.NewCache[common.Hash, struct{}](maxKnownVote), + knownSyncInfos: lru.NewCache[common.Hash, struct{}](maxKnownSyncInfo), + knownTimeouts: lru.NewCache[common.Hash, struct{}](maxKnownTimeout), orderpool: nil, lendingpool: nil, orderTxSub: nil, @@ -776,9 +767,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { return errResp(ErrDecode, "transaction %d is nil", i) } p.MarkTransaction(tx.Hash()) - exist, _ := pm.knownTxs.ContainsOrAdd(tx.Hash(), true) - if exist { + if pm.knownTxs.Contains(tx.Hash()) { log.Trace("Discard known tx", "hash", tx.Hash(), "nonce", tx.Nonce(), "to", tx.To()) + } else { + pm.knownTxs.Add(tx.Hash(), struct{}{}) } } @@ -801,11 +793,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { return errResp(ErrDecode, "transaction %d is nil", i) } p.MarkOrderTransaction(tx.Hash()) - exist, _ := pm.knowOrderTxs.ContainsOrAdd(tx.Hash(), true) - if exist { + if pm.knowOrderTxs.Contains(tx.Hash()) { log.Trace("Discard known tx", "hash", tx.Hash(), "nonce", tx.Nonce()) + } else { + pm.knowOrderTxs.Add(tx.Hash(), struct{}{}) } - } if pm.orderpool != nil { @@ -829,11 +821,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { return errResp(ErrDecode, "transaction %d is nil", i) } p.MarkLendingTransaction(tx.Hash()) - exist, _ := pm.knowLendingTxs.ContainsOrAdd(tx.Hash(), true) - if exist { + if pm.knowLendingTxs.Contains(tx.Hash()) { log.Trace("Discard known tx", "hash", tx.Hash(), "nonce", tx.Nonce()) + } else { + pm.knowLendingTxs.Add(tx.Hash(), struct{}{}) } - } if pm.lendingpool != nil { @@ -850,11 +842,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { } p.MarkVote(vote.Hash()) - exist, _ := pm.knownVotes.ContainsOrAdd(vote.Hash(), true) - if !exist { - go pm.bft.Vote(p.id, &vote) - } else { + if pm.knownVotes.Contains(vote.Hash()) { log.Trace("Discarded vote, known vote", "vote hash", vote.Hash(), "voted block hash", vote.ProposedBlockInfo.Hash.Hex(), "number", vote.ProposedBlockInfo.Number, "round", vote.ProposedBlockInfo.Round) + } else { + pm.knownVotes.Add(vote.Hash(), struct{}{}) + go pm.bft.Vote(p.id, &vote) } case msg.Code == TimeoutMsg: @@ -868,12 +860,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { } p.MarkTimeout(timeout.Hash()) - exist, _ := pm.knownTimeouts.ContainsOrAdd(timeout.Hash(), true) - - if !exist { - go pm.bft.Timeout(p.id, &timeout) - } else { + if pm.knownTimeouts.Contains(timeout.Hash()) { log.Trace("Discarded Timeout, known Timeout", "Signature", timeout.Signature, "hash", timeout.Hash(), "round", timeout.Round) + } else { + pm.knownTimeouts.Add(timeout.Hash(), struct{}{}) + go pm.bft.Timeout(p.id, &timeout) } case msg.Code == SyncInfoMsg: @@ -887,11 +878,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { } p.MarkSyncInfo(syncInfo.Hash()) - exist, _ := pm.knownSyncInfos.ContainsOrAdd(syncInfo.Hash(), true) - if !exist { - go pm.bft.SyncInfo(p.id, &syncInfo) - } else { + if pm.knownSyncInfos.Contains(syncInfo.Hash()) { log.Trace("Discarded SyncInfo, known SyncInfo", "hash", syncInfo.Hash()) + } else { + pm.knownSyncInfos.Add(syncInfo.Hash(), struct{}{}) + go pm.bft.SyncInfo(p.id, &syncInfo) } default: diff --git a/eth/hooks/engine_v1_hooks.go b/eth/hooks/engine_v1_hooks.go index 553ffc591671..74f55ed278a9 100644 --- a/eth/hooks/engine_v1_hooks.go +++ b/eth/hooks/engine_v1_hooks.go @@ -141,15 +141,14 @@ func AttachConsensusV1Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf if blockNumber%common.MergeSignRange == 0 { mapBlockHash[bhash] = true } - signData, ok := adaptor.GetCachedSigningTxs(bhash) + signingTxs, ok := adaptor.GetCachedSigningTxs(bhash) if !ok { block := chain.GetBlock(bhash, blockNumber) txs := block.Transactions() - signData = adaptor.CacheSigningTxs(bhash, txs) + signingTxs = adaptor.CacheSigningTxs(bhash, txs) } - txs := signData.([]*types.Transaction) // Check signer signed? - for _, tx := range txs { + for _, tx := range signingTxs { blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) from := *tx.From() if mapBlockHash[blkHash] { diff --git a/eth/hooks/engine_v2_hooks.go b/eth/hooks/engine_v2_hooks.go index fde8e924879f..bd5b0ffdd1df 100644 --- a/eth/hooks/engine_v2_hooks.go +++ b/eth/hooks/engine_v2_hooks.go @@ -115,15 +115,14 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf if blockNumber%common.MergeSignRange == 0 { mapBlockHash[bhash] = true } - signData, ok := adaptor.GetCachedSigningTxs(bhash) + signingTxs, ok := adaptor.GetCachedSigningTxs(bhash) if !ok { block := chain.GetBlock(bhash, blockNumber) txs := block.Transactions() - signData = adaptor.CacheSigningTxs(bhash, txs) + signingTxs = adaptor.CacheSigningTxs(bhash, txs) } - txs := signData.([]*types.Transaction) // Check signer signed? - for _, tx := range txs { + for _, tx := range signingTxs { blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) from := *tx.From() if mapBlockHash[blkHash] { @@ -245,15 +244,14 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type } } mapBlkHash[i] = header.Hash() - signData, ok := c.GetCachedSigningTxs(header.Hash()) + signingTxs, ok := c.GetCachedSigningTxs(header.Hash()) if !ok { log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i) block := chain.GetBlock(header.Hash(), i) txs := block.Transactions() - signData = c.CacheSigningTxs(header.Hash(), txs) + signingTxs = c.CacheSigningTxs(header.Hash(), txs) } - txs := signData.([]*types.Transaction) - for _, tx := range txs { + for _, tx := range signingTxs { blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) from := *tx.From() data[blkHash] = append(data[blkHash], from) diff --git a/go.mod b/go.mod index 28a24f8b6b38..d948f4cea3b8 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,6 @@ require ( github.com/golang/protobuf v1.5.3 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/gorilla/websocket v1.4.2 - github.com/hashicorp/golang-lru v0.5.4 github.com/holiman/uint256 v1.2.4 github.com/huin/goupnp v1.3.0 github.com/jackpal/go-nat-pmp v1.0.2 diff --git a/go.sum b/go.sum index 68019c92aba9..bb2ab2b777cb 100644 --- a/go.sum +++ b/go.sum @@ -92,8 +92,6 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= diff --git a/light/lightchain.go b/light/lightchain.go index 236d1ed85bf9..26b5df09172b 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -25,6 +25,7 @@ import ( "time" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/common/lru" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/core" "github.com/XinFinOrg/XDPoSChain/core/rawdb" @@ -35,7 +36,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/params" "github.com/XinFinOrg/XDPoSChain/rlp" - lru "github.com/hashicorp/golang-lru" ) var ( @@ -59,9 +59,9 @@ type LightChain struct { mu sync.RWMutex chainmu sync.RWMutex - bodyCache *lru.Cache // Cache for the most recent block bodies - bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format - blockCache *lru.Cache // Cache for the most recent entire blocks + bodyCache *lru.Cache[common.Hash, *types.Body] + bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] + blockCache *lru.Cache[common.Hash, *types.Block] quit chan struct{} running int32 // running must be called automically @@ -76,17 +76,13 @@ type LightChain struct { // available in the database. It initialises the default Ethereum header // validator. func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.Engine) (*LightChain, error) { - bodyCache, _ := lru.New(bodyCacheLimit) - bodyRLPCache, _ := lru.New(bodyCacheLimit) - blockCache, _ := lru.New(blockCacheLimit) - bc := &LightChain{ chainDb: odr.Database(), odr: odr, quit: make(chan struct{}), - bodyCache: bodyCache, - bodyRLPCache: bodyRLPCache, - blockCache: blockCache, + bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit), + bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit), + blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit), engine: engine, } var err error @@ -218,9 +214,8 @@ func (lc *LightChain) State() (*state.StateDB, error) { // or ODR service by hash, caching it if found. func (lc *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) { // Short circuit if the body's already in the cache, retrieve otherwise - if cached, ok := lc.bodyCache.Get(hash); ok { - body := cached.(*types.Body) - return body, nil + if cached, ok := lc.bodyCache.Get(hash); ok && cached != nil { + return cached, nil } body, err := GetBody(ctx, lc.odr, hash, lc.hc.GetBlockNumber(hash)) if err != nil { @@ -236,7 +231,7 @@ func (lc *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Bod func (lc *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.RawValue, error) { // Short circuit if the body's already in the cache, retrieve otherwise if cached, ok := lc.bodyRLPCache.Get(hash); ok { - return cached.(rlp.RawValue), nil + return cached, nil } body, err := GetBodyRLP(ctx, lc.odr, hash, lc.hc.GetBlockNumber(hash)) if err != nil { @@ -258,8 +253,8 @@ func (lc *LightChain) HasBlock(hash common.Hash, number uint64) bool { // caching it if found. func (lc *LightChain) GetBlock(ctx context.Context, hash common.Hash, number uint64) (*types.Block, error) { // Short circuit if the block's already in the cache, retrieve otherwise - if block, ok := lc.blockCache.Get(hash); ok { - return block.(*types.Block), nil + if block, ok := lc.blockCache.Get(hash); ok && block != nil { + return block, nil } block, err := GetBlock(ctx, lc.odr, hash, number) if err != nil {