Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

all: remove remaining uses of untyped golang-lru #26194

Merged
merged 6 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common/lru/basiclru.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type cacheItem[K any, V any] struct {

// NewBasicLRU creates a new LRU cache.
func NewBasicLRU[K comparable, V any](capacity int) BasicLRU[K, V] {
if capacity < 0 {
if capacity <= 0 {
capacity = 1
}
c := BasicLRU[K, V]{
Expand Down
16 changes: 8 additions & 8 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
lru "github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core/state"
Expand All @@ -41,7 +42,6 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
lru "github.com/hashicorp/golang-lru"
"golang.org/x/crypto/sha3"
)

Expand Down Expand Up @@ -143,11 +143,11 @@ var (
type SignerFn func(signer accounts.Account, mimeType string, message []byte) ([]byte, error)

// 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 {
Expand All @@ -173,8 +173,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

Expand All @@ -195,8 +195,8 @@ func New(config *params.CliqueConfig, db ethdb.Database) *Clique {
conf.Epoch = epochLength
}
// Allocate the snapshot caches and create the engine
recents, _ := lru.NewARC(inmemorySnapshots)
signatures, _ := lru.NewARC(inmemorySignatures)
recents := lru.NewCache[common.Hash, *Snapshot](inmemorySnapshots)
signatures := lru.NewCache[common.Hash, common.Address](inmemorySignatures)

return &Clique{
config: &conf,
Expand Down Expand Up @@ -375,7 +375,7 @@ func (c *Clique) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
for snap == nil {
// If an in-memory snapshot was found, use that
if s, ok := c.recents.Get(hash); ok {
snap = s.(*Snapshot)
snap = s
break
}
// If an on-disk checkpoint snapshot can be found, use that
Expand Down
10 changes: 6 additions & 4 deletions consensus/clique/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
lru "github.com/hashicorp/golang-lru"
)

// Vote represents a single vote that an authorized signer made to modify the
Expand All @@ -47,10 +47,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
Expand All @@ -70,7 +72,7 @@ func (s signersAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// 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,
Expand All @@ -87,7 +89,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(rawdb.CliqueSnapshotPrefix, hash[:]...))
if err != nil {
return nil, err
Expand Down
69 changes: 36 additions & 33 deletions consensus/ethash/ethash.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ import (
"unsafe"

"github.com/edsrzf/mmap-go"
lrupkg "github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rpc"
"github.com/hashicorp/golang-lru/simplelru"
)

var ErrInvalidDumpMagic = errors.New("invalid dump magic")
Expand Down Expand Up @@ -165,34 +165,45 @@ func memoryMapAndGenerate(path string, size uint64, lock bool, generator func(bu
return memoryMap(path, lock)
}

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

Expand Down Expand Up @@ -226,9 +237,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}
}

Expand Down Expand Up @@ -308,7 +318,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}
}

Expand Down Expand Up @@ -439,8 +449,8 @@ 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
Expand Down Expand Up @@ -477,8 +487,8 @@ func New(config Config, notify []string, noverify bool) *Ethash {
}
ethash := &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.NewMeterForced(),
}
Expand Down Expand Up @@ -573,15 +583,13 @@ func (ethash *Ethash) StopRemoteSealer() error {
// 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.CachesLockMmap, 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.CachesLockMmap, ethash.config.PowMode == ModeTest)
}
return current
Expand All @@ -596,25 +604,20 @@ func (ethash *Ethash) cache(block uint64) *cache {
func (ethash *Ethash) dataset(block uint64, async bool) *dataset {
// Retrieve the requested ethash dataset
epoch := block / epochLength
currentI, futureI := ethash.datasets.get(epoch)
current := currentI.(*dataset)
current, future := ethash.datasets.get(epoch)

// If async is specified, generate everything in a background thread
if async && !current.generated() {
go func() {
current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest)

if futureI != nil {
future := futureI.(*dataset)
if future != nil {
future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest)
}
}()
} else {
// Either blocking generation was requested, or already done
current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest)

if futureI != nil {
future := futureI.(*dataset)
if future != nil {
go future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.DatasetsLockMmap, ethash.config.PowMode == ModeTest)
}
}
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ require (
github.com/gorilla/websocket v1.4.2
github.com/graph-gophers/graphql-go v1.3.0
github.com/hashicorp/go-bexpr v0.1.10
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e
github.com/holiman/bloomfilter/v2 v2.0.3
github.com/holiman/uint256 v1.2.0
Expand Down
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpx
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw=
github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU=
Expand Down
10 changes: 5 additions & 5 deletions les/vflux/server/clientdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/les/utils"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/rlp"
lru "github.com/hashicorp/golang-lru"
)

const (
Expand Down Expand Up @@ -57,7 +57,7 @@ var (

type nodeDB struct {
db ethdb.KeyValueStore
cache *lru.Cache
cache *lru.Cache[string, utils.ExpiredValue]
auxbuf []byte // 37-byte auxiliary buffer for key encoding
verbuf [2]byte // 2-byte auxiliary buffer for db version
evictCallBack func(mclock.AbsTime, bool, utils.ExpiredValue) bool // Callback to determine whether the balance can be evicted.
Expand All @@ -67,10 +67,9 @@ type nodeDB struct {
}

func newNodeDB(db ethdb.KeyValueStore, clock mclock.Clock) *nodeDB {
cache, _ := lru.New(balanceCacheLimit)
ndb := &nodeDB{
db: db,
cache: cache,
cache: lru.NewCache[string, utils.ExpiredValue](balanceCacheLimit),
auxbuf: make([]byte, 37),
clock: clock,
closeCh: make(chan struct{}),
Expand Down Expand Up @@ -125,8 +124,9 @@ func (db *nodeDB) getOrNewBalance(id []byte, neg bool) utils.ExpiredValue {
key := db.key(id, neg)
item, exist := db.cache.Get(string(key))
if exist {
return item.(utils.ExpiredValue)
return item
}

var b utils.ExpiredValue
enc, err := db.db.Get(key)
if err != nil || len(enc) == 0 {
Expand Down
Loading