all: remove uses of untyped golang-lru

This commit is contained in:
Daniel Liu 2024-12-17 17:35:07 +08:00 committed by Daniel Liu
parent 7491a7ba74
commit 82ff8c19a0
29 changed files with 226 additions and 320 deletions

View file

@ -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))

View file

@ -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)

View file

@ -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.

View file

@ -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,
}

View file

@ -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

View file

@ -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))

View file

@ -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.

View file

@ -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)
}

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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,

View file

@ -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

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -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
}

View file

@ -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]

View file

@ -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

View file

@ -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

View file

@ -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)
}

View file

@ -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)

View file

@ -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())

View file

@ -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)

View file

@ -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:

View file

@ -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] {

View file

@ -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)

1
go.mod
View file

@ -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

2
go.sum
View file

@ -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=

View file

@ -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 {