diff --git a/cmd/geth/main.go b/cmd/geth/main.go index ec8d0fa93..574490830 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -41,6 +41,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/node" "go.uber.org/automaxprocs/maxprocs" + "github.com/ethereum/go-ethereum/plugins" "github.com/ethereum/go-ethereum/plugins/wrappers/backendwrapper" @@ -351,8 +352,11 @@ func geth(ctx *cli.Context) error { return fmt.Errorf("invalid command: %q", args[0]) } } + stack, backend := makeFullNode(ctx) - wrapperBackend := backendwrapper.NewBackend(backend) + tc := plugethCaptureTrieConfig(ctx, stack) + wrapperBackend := backendwrapper.NewBackend(backend, tc) + pluginsInitializeNode(stack, wrapperBackend) if ok, err := plugins.RunSubcommand(ctx); ok { stack.Close() diff --git a/cmd/geth/plugin_hooks.go b/cmd/geth/plugin_hooks.go index 2a1053c3a..dcc4f76e3 100644 --- a/cmd/geth/plugin_hooks.go +++ b/cmd/geth/plugin_hooks.go @@ -1,13 +1,24 @@ package main 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/log" "github.com/ethereum/go-ethereum/node" + "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/wrappers" - "github.com/ethereum/go-ethereum/rpc" + "github.com/openrelayxyz/plugeth-utils/core" "github.com/openrelayxyz/plugeth-utils/restricted" + + "github.com/urfave/cli/v2" ) func apiTranslate(apis []core.API) []rpc.API { @@ -119,4 +130,38 @@ func pluginBlockChain() { return } BlockChain(plugins.DefaultPluginLoader) +} + +func plugethCaptureTrieConfig(ctx *cli.Context, stack *node.Node) *trie.Config { + + ec := new(ethconfig.Config) + utils.SetEthConfig(ctx, stack, ec) + + cc := &gcore.CacheConfig{ + TrieCleanLimit: ec.TrieCleanCache, + TrieCleanNoPrefetch: ec.NoPrefetch, + TrieDirtyLimit: ec.TrieDirtyCache, + TrieDirtyDisabled: ec.NoPruning, + TrieTimeLimit: ec.TrieTimeout, + SnapshotLimit: ec.SnapshotCache, + Preimages: ec.Preimages, + StateHistory: ec.StateHistory, + StateScheme: ec.StateScheme, + } + + config := &trie.Config{Preimages: cc.Preimages} + if cc.StateScheme == rawdb.HashScheme { + config.HashDB = &hashdb.Config{ + CleanCacheSize: cc.TrieCleanLimit * 1024 * 1024, + } + } + if cc.StateScheme == rawdb.PathScheme { + config.PathDB = &pathdb.Config{ + StateHistory: cc.StateHistory, + CleanCacheSize: cc.TrieCleanLimit * 1024 * 1024, + DirtyCacheSize: cc.TrieDirtyLimit * 1024 * 1024, + } + } + + return config } \ No newline at end of file diff --git a/core/state/plugin_hooks.go b/core/state/plugin_hooks.go index d6bad4287..e5dd74490 100644 --- a/core/state/plugin_hooks.go +++ b/core/state/plugin_hooks.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/plugins" - "github.com/ethereum/go-ethereum/core/state/snapshot" + "github.com/ethereum/go-ethereum/core/types" "github.com/openrelayxyz/plugeth-utils/core" ) @@ -17,7 +17,7 @@ func (s *pluginSnapshot) Root() common.Hash { return s.root } -func (s *pluginSnapshot) Account(hash common.Hash) (*snapshot.Account, error) { +func (s *pluginSnapshot) Account(hash common.Hash) (*types.SlimAccount, error) { return nil, fmt.Errorf("not implemented") } diff --git a/core/state/statedb.go b/core/state/statedb.go index e280309a7..e123ca48c 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -173,9 +173,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) if sdb.snap == nil { log.Debug("Snapshots not availble. Using plugin snapshot.") sdb.snap = &pluginSnapshot{root} - sdb.stateObjectsDestruct = make(map[common.Address]struct{}) - sdb.snapAccounts = make(map[common.Hash][]byte) - sdb.snapStorage = make(map[common.Hash]map[common.Hash][]byte) + sdb.stateObjectsDestruct = make(map[common.Address]*types.StateAccount) } // End PluGeth section return sdb, nil @@ -1201,18 +1199,28 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er codeUpdates := make(map[common.Hash][]byte) // end PluGeth injection for addr := range s.stateObjectsDirty { - if obj := s.stateObjects[addr]; !obj.deleted { - // Write any contract code associated with the state object - if obj.code != nil && obj.dirtyCode { - rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code) - // begin PluGeth injection - codeUpdates[common.BytesToHash(obj.CodeHash())] = obj.code - // end PluGeth injection - obj.dirtyCode = false - } - // Write any storage changes in the state object to its storage trie - set, err := obj.commitTrie(s.db) - if err != nil { + obj := s.stateObjects[addr] + if obj.deleted { + continue + } + // Write any contract code associated with the state object + if obj.code != nil && obj.dirtyCode { + rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code) + // begin PluGeth injection + codeUpdates[common.BytesToHash(obj.CodeHash())] = obj.code + // end PluGeth injection + obj.dirtyCode = false + } + // Write any storage changes in the state object to its storage trie + set, err := obj.commit() + if err != nil { + return common.Hash{}, err + } + // Merge the dirty nodes of storage trie into global set. It is possible + // that the account was destructed and then resurrected in the same block. + // In this case, the node set is shared by both accounts. + if set != nil { + if err := nodes.Merge(set); err != nil { return common.Hash{}, err } updates, deleted := set.Size() @@ -1261,10 +1269,10 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er // Only update if there's a state transition (skip empty Clique blocks) if parent := s.snap.Root(); parent != root { //begin PluGeth code injection - pluginStateUpdate(root, parent, s.convertAccountSet(s.stateObjectsDestruct), s.snapAccounts, s.snapStorage, codeUpdates) + pluginStateUpdate(root, parent, s.convertAccountSet(s.stateObjectsDestruct), s.accounts, s.storages, codeUpdates) if _, ok := s.snap.(*pluginSnapshot); !ok && s.snaps != nil { // This if statement (but not its content) was added by PluGeth //end PluGeth injection - if err := s.snaps.Update(root, parent, s.convertAccountSet(s.stateObjectsDestruct), s.snapAccounts, s.snapStorage); err != nil { + if err := s.snaps.Update(root, parent, s.convertAccountSet(s.stateObjectsDestruct), s.accounts, s.storages); err != nil { log.Warn("Failed to update snapshot tree", "from", parent, "to", root, "err", err) } // Keep 128 diff layers in the memory, persistent layer is 129th. diff --git a/plugins/wrappers/backendwrapper/backendwrapper.go b/plugins/wrappers/backendwrapper/backendwrapper.go index 083e070c8..311402186 100644 --- a/plugins/wrappers/backendwrapper/backendwrapper.go +++ b/plugins/wrappers/backendwrapper/backendwrapper.go @@ -19,9 +19,9 @@ import ( "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "github.com/openrelayxyz/plugeth-utils/core" "github.com/openrelayxyz/plugeth-utils/restricted" "github.com/openrelayxyz/plugeth-utils/restricted/params" @@ -44,10 +44,14 @@ type Backend struct { removedLogsFeed event.Feed removedLogsOnce sync.Once chainConfig *params.ChainConfig + trieConfig *trie.Config } -func NewBackend(b ethapi.Backend) *Backend { - return &Backend{b: b} +func NewBackend(b ethapi.Backend, tc *trie.Config) *Backend { + + return &Backend{ + b: b, + trieConfig: tc} } func (b *Backend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { @@ -488,7 +492,7 @@ func CloneChainConfig(cf *gparams.ChainConfig) *params.ChainConfig { } func (b *Backend) GetTrie(h core.Hash) (core.Trie, error) { - tr, err := trie.NewStateTrie(trie.TrieID(common.Hash(h)), trie.NewDatabase(b.b.ChainDb())) + tr, err := trie.NewStateTrie(trie.TrieID(common.Hash(h)), trie.NewDatabase(b.b.ChainDb(), b.trieConfig)) if err != nil { return nil, err } @@ -504,7 +508,7 @@ func (b *Backend) GetAccountTrie(stateRoot core.Hash, account core.Address) (cor if err != nil { return nil, err } - acTr, err := trie.NewStateTrie(trie.StorageTrieID(common.Hash(stateRoot), crypto.Keccak256Hash(account[:]), common.Hash(act.Root)), trie.NewDatabase(b.b.ChainDb())) + acTr, err := trie.NewStateTrie(trie.StorageTrieID(common.Hash(stateRoot), crypto.Keccak256Hash(account[:]), common.Hash(act.Root)), trie.NewDatabase(b.b.ChainDb(), b.trieConfig)) if err != nil { return nil, err } @@ -512,5 +516,5 @@ func (b *Backend) GetAccountTrie(stateRoot core.Hash, account core.Address) (cor } func (b *Backend) GetContractCode(h core.Hash) ([]byte, error) { - return state.NewDatabase(b.b.ChainDb()).ContractCode(common.Hash{}, common.Hash(h)) + return state.NewDatabase(b.b.ChainDb()).ContractCode(common.Address{}, common.Hash(h)) } diff --git a/plugins/wrappers/backendwrapper/triewrapper.go b/plugins/wrappers/backendwrapper/triewrapper.go index c3190fe8e..d4e3b3c1d 100644 --- a/plugins/wrappers/backendwrapper/triewrapper.go +++ b/plugins/wrappers/backendwrapper/triewrapper.go @@ -3,6 +3,7 @@ package backendwrapper import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/trie" "github.com/openrelayxyz/plugeth-utils/core" @@ -38,7 +39,8 @@ func (t *WrappedTrie) Hash() core.Hash { } func (t *WrappedTrie) NodeIterator(startKey []byte) core.NodeIterator { - itr := t.t.NodeIterator(startKey) + itr, err := t.t.NodeIterator(startKey) + log.Error("Error returned from geth side NodeIterator", "err", err) return &WrappedNodeIterator{itr} } diff --git a/plugins/wrappers/wrappers.go b/plugins/wrappers/wrappers.go index e2ca48684..e49dfb1ea 100644 --- a/plugins/wrappers/wrappers.go +++ b/plugins/wrappers/wrappers.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/node" + "github.com/openrelayxyz/plugeth-utils/core" ) @@ -166,8 +167,8 @@ func (w *WrappedStateDB) GetState(addr core.Address, hsh core.Hash) core.Hash { } // HasSuicided(Address) bool -func (w *WrappedStateDB) HasSuicided(addr core.Address) bool { // I figured we'd skip some of the future labor and update the name now - return w.s.HasSuicided(common.Address(addr)) +func (w *WrappedStateDB) HasSuicided(addr core.Address) bool { + return w.s.HasSelfDestructed(common.Address(addr)) } // // Exist reports whether the given account exists in state. @@ -231,7 +232,7 @@ func (n *Node) ResolvePath(x string) string { return n.n.ResolvePath(x) } func (n *Node) Attach() (core.Client, error) { - return n.n.Attach() + return n.n.Attach(), nil } func (n *Node) Close() error { return n.n.Close()