Use the statedb database to get Tries
The old approach of getting state tries involved instantiating a new state database and using it to instantiate a trie. What we didn't realize was that state database needed to have Close() called on it, which we didn't offer a way for plugins to do, resulting in memory leaking. This approach reuses the primary trie database associated with the blockchain object, albeit a bit indirectly. This will allow access to recent tries that are stored in memory, where previously only tries that had been committed to disk were accessible.
This commit is contained in:
parent
703c3b6b74
commit
bc14d12fd7
@ -358,8 +358,7 @@ func geth(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stack, backend := makeFullNode(ctx)
|
stack, backend := makeFullNode(ctx)
|
||||||
trieCfg := plugethCaptureTrieConfig(ctx, stack, backend)
|
wrapperBackend := backendwrapper.NewBackend(backend)
|
||||||
wrapperBackend := backendwrapper.NewBackend(backend, trieCfg)
|
|
||||||
|
|
||||||
pluginsInitializeNode(stack, wrapperBackend)
|
pluginsInitializeNode(stack, wrapperBackend)
|
||||||
if ok, err := plugins.RunSubcommand(ctx); ok {
|
if ok, err := plugins.RunSubcommand(ctx); ok {
|
||||||
|
@ -1,25 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
||||||
gcore "github.com/ethereum/go-ethereum/core"
|
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
|
||||||
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
|
|
||||||
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/plugins"
|
"github.com/ethereum/go-ethereum/plugins"
|
||||||
"github.com/ethereum/go-ethereum/plugins/wrappers"
|
"github.com/ethereum/go-ethereum/plugins/wrappers"
|
||||||
|
|
||||||
"github.com/openrelayxyz/plugeth-utils/core"
|
"github.com/openrelayxyz/plugeth-utils/core"
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted"
|
"github.com/openrelayxyz/plugeth-utils/restricted"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func apiTranslate(apis []core.API) []rpc.API {
|
func apiTranslate(apis []core.API) []rpc.API {
|
||||||
@ -132,69 +122,3 @@ func pluginBlockChain() {
|
|||||||
}
|
}
|
||||||
BlockChain(plugins.DefaultPluginLoader)
|
BlockChain(plugins.DefaultPluginLoader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func plugethCaptureTrieConfig(ctx *cli.Context, stack *node.Node, backend ethapi.Backend) *trie.Config {
|
|
||||||
|
|
||||||
ethCfg := new(ethconfig.Config)
|
|
||||||
|
|
||||||
if ctx.IsSet(utils.CacheFlag.Name) || ctx.IsSet(utils.CacheTrieFlag.Name) {
|
|
||||||
ethCfg.TrieCleanCache = ctx.Int(utils.CacheFlag.Name) * ctx.Int(utils.CacheTrieFlag.Name) / 100
|
|
||||||
}
|
|
||||||
if ctx.IsSet(utils.CacheNoPrefetchFlag.Name) {
|
|
||||||
ethCfg.NoPrefetch = ctx.Bool(utils.CacheNoPrefetchFlag.Name)
|
|
||||||
}
|
|
||||||
if ctx.IsSet(utils.CacheFlag.Name) || ctx.IsSet(utils.CacheGCFlag.Name) {
|
|
||||||
ethCfg.TrieDirtyCache = ctx.Int(utils.CacheFlag.Name) * ctx.Int(utils.CacheGCFlag.Name) / 100
|
|
||||||
}
|
|
||||||
if ctx.IsSet(utils.GCModeFlag.Name) {
|
|
||||||
ethCfg.NoPruning = ctx.String(utils.GCModeFlag.Name) == "archive"
|
|
||||||
}
|
|
||||||
if ctx.IsSet(utils.CacheFlag.Name) || ctx.IsSet(utils.CacheSnapshotFlag.Name) {
|
|
||||||
ethCfg.SnapshotCache = ctx.Int(utils.CacheFlag.Name) * ctx.Int(utils.CacheSnapshotFlag.Name) / 100
|
|
||||||
}
|
|
||||||
ethCfg.Preimages = ctx.Bool(utils.CachePreimagesFlag.Name)
|
|
||||||
if ethCfg.NoPruning && !ethCfg.Preimages {
|
|
||||||
ethCfg.Preimages = true
|
|
||||||
log.Info("Enabling recording of key preimages since archive mode is used")
|
|
||||||
}
|
|
||||||
if ctx.IsSet(utils.StateHistoryFlag.Name) {
|
|
||||||
ethCfg.StateHistory = ctx.Uint64(utils.StateHistoryFlag.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
chaindb := backend.ChainDb()
|
|
||||||
|
|
||||||
scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), chaindb)
|
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ethCfg.StateScheme = scheme
|
|
||||||
|
|
||||||
cacheCfg := &gcore.CacheConfig{
|
|
||||||
TrieCleanLimit: ethCfg.TrieCleanCache,
|
|
||||||
TrieCleanNoPrefetch: ethCfg.NoPrefetch,
|
|
||||||
TrieDirtyLimit: ethCfg.TrieDirtyCache,
|
|
||||||
TrieDirtyDisabled: ethCfg.NoPruning,
|
|
||||||
TrieTimeLimit: ethconfig.Defaults.TrieTimeout,
|
|
||||||
SnapshotLimit: ethCfg.SnapshotCache,
|
|
||||||
Preimages: ethCfg.Preimages,
|
|
||||||
StateHistory: ethCfg.StateHistory,
|
|
||||||
StateScheme: ethCfg.StateScheme,
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &trie.Config{Preimages: cacheCfg.Preimages}
|
|
||||||
if cacheCfg.StateScheme == rawdb.HashScheme {
|
|
||||||
config.HashDB = &hashdb.Config{
|
|
||||||
CleanCacheSize: cacheCfg.TrieCleanLimit * 1024 * 1024,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cacheCfg.StateScheme == rawdb.PathScheme {
|
|
||||||
config.PathDB = &pathdb.Config{
|
|
||||||
StateHistory: cacheCfg.StateHistory,
|
|
||||||
CleanCacheSize: cacheCfg.TrieCleanLimit * 1024 * 1024,
|
|
||||||
DirtyCacheSize: cacheCfg.TrieDirtyLimit * 1024 * 1024,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
@ -13,12 +13,10 @@ import (
|
|||||||
gcore "github.com/ethereum/go-ethereum/core"
|
gcore "github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
gparams "github.com/ethereum/go-ethereum/params"
|
gparams "github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
@ -29,6 +27,7 @@ import (
|
|||||||
|
|
||||||
type Backend struct {
|
type Backend struct {
|
||||||
b ethapi.Backend
|
b ethapi.Backend
|
||||||
|
db state.Database
|
||||||
newTxsFeed event.Feed
|
newTxsFeed event.Feed
|
||||||
newTxsOnce sync.Once
|
newTxsOnce sync.Once
|
||||||
chainFeed event.Feed
|
chainFeed event.Feed
|
||||||
@ -44,14 +43,17 @@ type Backend struct {
|
|||||||
removedLogsFeed event.Feed
|
removedLogsFeed event.Feed
|
||||||
removedLogsOnce sync.Once
|
removedLogsOnce sync.Once
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
trieConfig *trie.Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBackend(b ethapi.Backend, tc *trie.Config) *Backend {
|
func NewBackend(b ethapi.Backend) *Backend {
|
||||||
|
state, _, err := b.StateAndHeaderByNumber(context.Background(), 0)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
return &Backend{
|
return &Backend{
|
||||||
b: b,
|
b: b,
|
||||||
trieConfig: tc}
|
db: state.Database(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
|
func (b *Backend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
|
||||||
@ -492,7 +494,7 @@ func CloneChainConfig(cf *gparams.ChainConfig) *params.ChainConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) GetTrie(h core.Hash) (core.Trie, error) {
|
func (b *Backend) GetTrie(h core.Hash) (core.Trie, error) {
|
||||||
tr, err := trie.NewStateTrie(trie.TrieID(common.Hash(h)), trie.NewDatabase(b.b.ChainDb(), b.trieConfig))
|
tr, err := b.db.OpenTrie(common.Hash(h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -508,7 +510,7 @@ func (b *Backend) GetAccountTrie(stateRoot core.Hash, account core.Address) (cor
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
acTr, err := trie.NewStateTrie(trie.StorageTrieID(common.Hash(stateRoot), crypto.Keccak256Hash(account[:]), common.Hash(act.Root)), trie.NewDatabase(b.b.ChainDb(), b.trieConfig))
|
acTr, err := b.db.OpenStorageTrie(common.Hash(stateRoot), common.Address(account), common.Hash(act.Root))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,9 @@ func (t *WrappedTrie) Hash() core.Hash {
|
|||||||
|
|
||||||
func (t *WrappedTrie) NodeIterator(startKey []byte) core.NodeIterator {
|
func (t *WrappedTrie) NodeIterator(startKey []byte) core.NodeIterator {
|
||||||
itr, err := t.t.NodeIterator(startKey)
|
itr, err := t.t.NodeIterator(startKey)
|
||||||
|
if err != nil {
|
||||||
log.Error("Error returned from geth side NodeIterator", "err", err)
|
log.Error("Error returned from geth side NodeIterator", "err", err)
|
||||||
|
}
|
||||||
return &WrappedNodeIterator{itr}
|
return &WrappedNodeIterator{itr}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user