From 9aa683442ec7ec291edc9be4ec05ab2c228a0f75 Mon Sep 17 00:00:00 2001 From: prathamesh0 <42446521+prathamesh0@users.noreply.github.com> Date: Fri, 24 Jun 2022 14:12:58 +0530 Subject: [PATCH] Reuse builder from vulcanize-geth (#92) * Reuse builder code from vulcanize-geth * Upgrade geth dependency --- .gitignore | 1 + go.mod | 2 +- go.sum | 4 +- pkg/builder.go | 774 ++------------------------------------------ pkg/builder_test.go | 103 +++--- pkg/service.go | 2 +- 6 files changed, 78 insertions(+), 808 deletions(-) diff --git a/.gitignore b/.gitignore index 0abc11c..b5625db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/ eth-statediff-service +.vscode diff --git a/go.mod b/go.mod index b569c5b..1fa51fe 100644 --- a/go.mod +++ b/go.mod @@ -128,4 +128,4 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) -replace github.com/ethereum/go-ethereum v1.10.19 => github.com/vulcanize/go-ethereum v1.10.19-statediff-4.0.2-alpha +replace github.com/ethereum/go-ethereum v1.10.19 => github.com/vulcanize/go-ethereum v1.10.19-statediff-4.0.3-alpha diff --git a/go.sum b/go.sum index 37d7e8d..f2cf104 100644 --- a/go.sum +++ b/go.sum @@ -727,8 +727,8 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vulcanize/go-eth-state-node-iterator v1.1.1 h1:/9zKsUzF1zlQDriAljdspmp1ixcIpOcbetiyHCPhbU0= github.com/vulcanize/go-eth-state-node-iterator v1.1.1/go.mod h1:pL9jDztI5Yv9OOCKpCyo08/v+27othmbQlggoqH84Zo= -github.com/vulcanize/go-ethereum v1.10.19-statediff-4.0.2-alpha h1:xD4fA2khoAnhBEk84JwrIEGvQCndVXpQGv5n7a9cgwc= -github.com/vulcanize/go-ethereum v1.10.19-statediff-4.0.2-alpha/go.mod h1:5tMN+CDbK/qI2UlfN307HJykDmVIOCB1FM5RcHK9Kp8= +github.com/vulcanize/go-ethereum v1.10.19-statediff-4.0.3-alpha h1:Pr6mSkWM7bobRJ/GzeztH+EOQR5IVLScO57G+N/q20g= +github.com/vulcanize/go-ethereum v1.10.19-statediff-4.0.3-alpha/go.mod h1:5tMN+CDbK/qI2UlfN307HJykDmVIOCB1FM5RcHK9Kp8= github.com/vulcanize/leveldb-ethdb-rpc v0.1.3 h1:R0+2GNMQKPXsKVWjTc6h5khD/aZzSarxxVsPEtBHiHU= github.com/vulcanize/leveldb-ethdb-rpc v0.1.3/go.mod h1:A3aI/tDglAHGpB9/vmtwS/mWOvfGl1UFJ1jCbhIPMAM= github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= diff --git a/pkg/builder.go b/pkg/builder.go index 6d72720..1642006 100644 --- a/pkg/builder.go +++ b/pkg/builder.go @@ -20,93 +20,25 @@ package statediff import ( - "bytes" "fmt" "math/bits" "sync" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" sd "github.com/ethereum/go-ethereum/statediff" - sdtrie "github.com/ethereum/go-ethereum/statediff/trie_helpers" sdtypes "github.com/ethereum/go-ethereum/statediff/types" - "github.com/ethereum/go-ethereum/trie" "github.com/sirupsen/logrus" iter "github.com/vulcanize/go-eth-state-node-iterator" ) -var ( - nullHashBytes = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000") - emptyNode, _ = rlp.EncodeToBytes(&[]byte{}) - emptyContractRoot = crypto.Keccak256Hash(emptyNode) - nullCodeHash = crypto.Keccak256Hash([]byte{}).Bytes() -) - -// Builder interface exposes the method for building a state diff between two blocks -type Builder interface { - BuildStateDiffObject(args sd.Args, params sd.Params) (sdtypes.StateObject, error) - BuildStateTrieObject(current *types.Block) (sdtypes.StateObject, error) - WriteStateDiffObject(args sdtypes.StateRoots, params sd.Params, output sdtypes.StateNodeSink, codeOutput sdtypes.CodeSink) error -} - type builder struct { - stateCache state.Database + sd.StateDiffBuilder numWorkers uint } -type iterPair struct { - older, newer trie.NodeIterator -} - -func resolveNode(it trie.NodeIterator, trieDB *trie.Database) (sdtypes.StateNode, []interface{}, error) { - nodePath := make([]byte, len(it.Path())) - copy(nodePath, it.Path()) - node, err := trieDB.Node(it.Hash()) - if err != nil { - return sdtypes.StateNode{}, nil, err - } - var nodeElements []interface{} - if err := rlp.DecodeBytes(node, &nodeElements); err != nil { - return sdtypes.StateNode{}, nil, err - } - ty, err := sdtrie.CheckKeyType(nodeElements) - if err != nil { - return sdtypes.StateNode{}, nil, err - } - return sdtypes.StateNode{ - NodeType: ty, - Path: nodePath, - NodeValue: node, - }, nodeElements, nil -} - -// convenience -func stateNodeAppender(nodes *[]sdtypes.StateNode) sdtypes.StateNodeSink { - return func(node sdtypes.StateNode) error { - *nodes = append(*nodes, node) - return nil - } -} -func storageNodeAppender(nodes *[]sdtypes.StorageNode) sdtypes.StorageNodeSink { - return func(node sdtypes.StorageNode) error { - *nodes = append(*nodes, node) - return nil - } -} -func codeMappingAppender(data *[]sdtypes.CodeAndCodeHash) sdtypes.CodeSink { - return func(c sdtypes.CodeAndCodeHash) error { - *data = append(*data, c) - return nil - } -} - // NewBuilder is used to create a statediff builder -func NewBuilder(stateCache state.Database, workers uint) (Builder, error) { +func NewBuilder(stateCache state.Database, workers uint) (sd.Builder, error) { if workers == 0 { workers = 1 } @@ -114,88 +46,20 @@ func NewBuilder(stateCache state.Database, workers uint) (Builder, error) { return nil, fmt.Errorf("workers must be a power of 2") } return &builder{ - stateCache: stateCache, // state cache is safe for concurrent reads + StateDiffBuilder: sd.StateDiffBuilder{ + StateCache: stateCache, + }, numWorkers: workers, }, nil } -// BuildStateTrieObject builds a state trie object from the provided block -func (sdb *builder) BuildStateTrieObject(current *types.Block) (sdtypes.StateObject, error) { - currentTrie, err := sdb.stateCache.OpenTrie(current.Root()) - if err != nil { - return sdtypes.StateObject{}, fmt.Errorf("error creating trie for block %d: %v", current.Number(), err) - } - it := currentTrie.NodeIterator([]byte{}) - stateNodes, codeAndCodeHashes, err := sdb.buildStateTrie(it) - if err != nil { - return sdtypes.StateObject{}, fmt.Errorf("error collecting state nodes for block %d: %v", current.Number(), err) - } - return sdtypes.StateObject{ - BlockNumber: current.Number(), - BlockHash: current.Hash(), - Nodes: stateNodes, - CodeAndCodeHashes: codeAndCodeHashes, - }, nil -} - -func (sdb *builder) buildStateTrie(it trie.NodeIterator) ([]sdtypes.StateNode, []sdtypes.CodeAndCodeHash, error) { - stateNodes := make([]sdtypes.StateNode, 0) - codeAndCodeHashes := make([]sdtypes.CodeAndCodeHash, 0) - for it.Next(true) { - // skip value nodes - if it.Leaf() || bytes.Equal(nullHashBytes, it.Hash().Bytes()) { - continue - } - node, nodeElements, err := resolveNode(it, sdb.stateCache.TrieDB()) - if err != nil { - return nil, nil, err - } - switch node.NodeType { - case sdtypes.Leaf: - var account types.StateAccount - if err := rlp.DecodeBytes(nodeElements[1].([]byte), &account); err != nil { - return nil, nil, fmt.Errorf("error decoding account for leaf node at path %x nerror: %v", node.Path, err) - } - partialPath := trie.CompactToHex(nodeElements[0].([]byte)) - valueNodePath := append(node.Path, partialPath...) - encodedPath := trie.HexToCompact(valueNodePath) - leafKey := encodedPath[1:] - node.LeafKey = leafKey - if !bytes.Equal(account.CodeHash, nullCodeHash) { - var storageNodes []sdtypes.StorageNode - err := sdb.buildStorageNodesEventual(account.Root, true, storageNodeAppender(&storageNodes)) - if err != nil { - return nil, nil, fmt.Errorf("failed building eventual storage diffs for account %+v\r\nerror: %v", account, err) - } - node.StorageNodes = storageNodes - // emit codehash => code mappings for code - codeHash := common.BytesToHash(account.CodeHash) - code, err := sdb.stateCache.ContractCode(common.Hash{}, codeHash) - if err != nil { - return nil, nil, fmt.Errorf("failed to retrieve code for codehash %s\r\n error: %v", codeHash.String(), err) - } - codeAndCodeHashes = append(codeAndCodeHashes, sdtypes.CodeAndCodeHash{ - Hash: codeHash, - Code: code, - }) - } - stateNodes = append(stateNodes, node) - case sdtypes.Extension, sdtypes.Branch: - stateNodes = append(stateNodes, node) - default: - return nil, nil, fmt.Errorf("unexpected node type %s", node.NodeType) - } - } - return stateNodes, codeAndCodeHashes, it.Error() -} - // BuildStateDiffObject builds a statediff object from two blocks and the provided parameters func (sdb *builder) BuildStateDiffObject(args sd.Args, params sd.Params) (sdtypes.StateObject, error) { var stateNodes []sdtypes.StateNode var codeAndCodeHashes []sdtypes.CodeAndCodeHash err := sdb.WriteStateDiffObject( sdtypes.StateRoots{OldStateRoot: args.OldStateRoot, NewStateRoot: args.NewStateRoot}, - params, stateNodeAppender(&stateNodes), codeMappingAppender(&codeAndCodeHashes)) + params, sd.StateNodeAppender(&stateNodes), sd.CodeMappingAppender(&codeAndCodeHashes)) if err != nil { return sdtypes.StateObject{}, err } @@ -209,18 +73,12 @@ func (sdb *builder) BuildStateDiffObject(args sd.Args, params sd.Params) (sdtype // WriteStateDiffObject writes a statediff object to output callback func (sdb *builder) WriteStateDiffObject(args sdtypes.StateRoots, params sd.Params, output sdtypes.StateNodeSink, codeOutput sdtypes.CodeSink) error { - if len(params.WatchedAddresses) > 0 { - // if we are watching only specific accounts then we are only diffing leaf nodes - log.Info("Ignoring intermediate state nodes because WatchedAddresses was passed") - params.IntermediateStateNodes = false - } - // Load tries for old and new states - oldTrie, err := sdb.stateCache.OpenTrie(args.OldStateRoot) + oldTrie, err := sdb.StateCache.OpenTrie(args.OldStateRoot) if err != nil { return fmt.Errorf("error creating trie for oldStateRoot: %v", err) } - newTrie, err := sdb.stateCache.OpenTrie(args.NewStateRoot) + newTrie, err := sdb.StateCache.OpenTrie(args.NewStateRoot) if err != nil { return fmt.Errorf("error creating trie for newStateRoot: %v", err) } @@ -234,11 +92,11 @@ func (sdb *builder) WriteStateDiffObject(args sdtypes.StateRoots, params sd.Para // Create iterators ahead of time to avoid race condition in state.Trie access // We do two state iterations per subtrie: one for new/updated nodes, // one for deleted/updated nodes; prepare 2 iterator instances for each task - var iterPairs [][]iterPair + var iterPairs [][]sd.IterPair for i := uint(0); i < sdb.numWorkers; i++ { - iterPairs = append(iterPairs, []iterPair{ - {older: oldIters1[i], newer: newIters1[i]}, - {older: oldIters2[i], newer: newIters2[i]}, + iterPairs = append(iterPairs, []sd.IterPair{ + {Older: oldIters1[i], Newer: newIters1[i]}, + {Older: oldIters2[i], Newer: newIters2[i]}, }) } @@ -255,8 +113,16 @@ func (sdb *builder) WriteStateDiffObject(args sdtypes.StateRoots, params sd.Para wg.Add(1) go func(worker uint) { defer wg.Done() - if err := sdb.buildStateDiff(iterPairs[worker], params, nodeSender, codeSender); err != nil { - logrus.Errorf("buildStateDiff error for worker %d, pparams %+v", worker, params) + var err error + if !params.IntermediateStateNodes || len(params.WatchedAddresses) > 0 { + // if we are watching only specific accounts then we are only diffing leaf nodes + err = sdb.BuildStateDiffWithoutIntermediateStateNodes(iterPairs[worker], params, nodeSender, codeSender) + } else { + err = sdb.BuildStateDiffWithIntermediateStateNodes(iterPairs[worker], params, nodeSender, codeSender) + } + + if err != nil { + logrus.Errorf("buildStateDiff error for worker %d, params %+v", worker, params) } }(w) } @@ -288,599 +154,3 @@ func (sdb *builder) WriteStateDiffObject(args sdtypes.StateRoots, params sd.Para return nil } - -func (sdb *builder) buildStateDiff(args []iterPair, params sd.Params, output sdtypes.StateNodeSink, codeOutput sdtypes.CodeSink) error { - // collect a slice of all the intermediate nodes that were touched and exist at B - // a map of their leafkey to all the accounts that were touched and exist at B - // and a slice of all the paths for the nodes in both of the above sets - var diffAccountsAtB AccountMap - var diffPathsAtB map[string]bool - var err error - if params.IntermediateStateNodes { - diffAccountsAtB, diffPathsAtB, err = sdb.createdAndUpdatedStateWithIntermediateNodes(args[0], output) - } else { - diffAccountsAtB, diffPathsAtB, err = sdb.createdAndUpdatedState(args[0], params.WatchedAddressesLeafKeys()) - } - - if err != nil { - return fmt.Errorf("error collecting createdAndUpdatedNodes: %v", err) - } - - // collect a slice of all the nodes that existed at a path in A that doesn't exist in B - // a map of their leafkey to all the accounts that were touched and exist at A - diffAccountsAtA, err := sdb.deletedOrUpdatedState(args[1], diffAccountsAtB, diffPathsAtB, params.WatchedAddressesLeafKeys(), params.IntermediateStorageNodes, output) - if err != nil { - return fmt.Errorf("error collecting deletedOrUpdatedNodes: %v", err) - } - - // collect and sort the leafkeys for both account mappings into a slice - createKeys := sortKeys(diffAccountsAtB) - deleteKeys := sortKeys(diffAccountsAtA) - - // and then find the intersection of these keys - // these are the leafkeys for the accounts which exist at both A and B but are different - // this also mutates the passed in createKeys and deleteKeys, removing the intersection keys - // and leaving the truly created or deleted keys in place - updatedKeys := findIntersection(createKeys, deleteKeys) - - // build the diff nodes for the updated accounts using the mappings at both A and B as directed by the keys found as the intersection of the two - err = sdb.buildAccountUpdates( - diffAccountsAtB, diffAccountsAtA, updatedKeys, params.IntermediateStorageNodes, output) - if err != nil { - return fmt.Errorf("error building diff for updated accounts: %v", err) - } - // build the diff nodes for created accounts - err = sdb.buildAccountCreations(diffAccountsAtB, params.IntermediateStorageNodes, output, codeOutput) - if err != nil { - return fmt.Errorf("error building diff for created accounts: %v", err) - } - return nil -} - -// createdAndUpdatedState returns -// a mapping of their leafkeys to all the accounts that exist in a different state at B than A -// and a slice of the paths for all of the nodes included in both -func (sdb *builder) createdAndUpdatedState(iters iterPair, watchedAddressesLeafKeys map[common.Hash]struct{}) (AccountMap, map[string]bool, error) { - diffPathsAtB := make(map[string]bool) - diffAcountsAtB := make(AccountMap) - it, _ := trie.NewDifferenceIterator(iters.older, iters.newer) - for it.Next(true) { - if it.Leaf() || bytes.Equal(nullHashBytes, it.Hash().Bytes()) { - continue - } - node, nodeElements, err := sdtrie.ResolveNode(it, sdb.stateCache.TrieDB()) - if err != nil { - return nil, nil, err - } - switch node.NodeType { - case sdtypes.Leaf: - // created vs updated is important for leaf nodes since we need to diff their storage - // so we need to map all changed accounts at B to their leafkey, since account can change pathes but not leafkey - var account types.StateAccount - if err := rlp.DecodeBytes(nodeElements[1].([]byte), &account); err != nil { - return nil, nil, fmt.Errorf("error decoding account for leaf node at path %x nerror: %v", node.Path, err) - } - partialPath := trie.CompactToHex(nodeElements[0].([]byte)) - valueNodePath := append(node.Path, partialPath...) - encodedPath := trie.HexToCompact(valueNodePath) - leafKey := encodedPath[1:] - if isWatchedAddress(watchedAddressesLeafKeys, leafKey) { - diffAcountsAtB[common.Bytes2Hex(leafKey)] = accountWrapper{ - NodeType: node.NodeType, - Path: node.Path, - NodeValue: node.NodeValue, - LeafKey: leafKey, - Account: &account, - } - } - } - // add both intermediate and leaf node paths to the list of diffPathsAtB - diffPathsAtB[common.Bytes2Hex(node.Path)] = true - } - return diffAcountsAtB, diffPathsAtB, it.Error() -} - -// createdAndUpdatedStateWithIntermediateNodes returns -// a slice of all the intermediate nodes that exist in a different state at B than A -// a mapping of their leafkeys to all the accounts that exist in a different state at B than A -// and a slice of the paths for all of the nodes included in both -func (sdb *builder) createdAndUpdatedStateWithIntermediateNodes(iters iterPair, output sdtypes.StateNodeSink) (AccountMap, map[string]bool, error) { - diffPathsAtB := make(map[string]bool) - diffAcountsAtB := make(AccountMap) - it, _ := trie.NewDifferenceIterator(iters.older, iters.newer) - for it.Next(true) { - if it.Leaf() || bytes.Equal(nullHashBytes, it.Hash().Bytes()) { - continue - } - node, nodeElements, err := resolveNode(it, sdb.stateCache.TrieDB()) - if err != nil { - return nil, nil, err - } - switch node.NodeType { - case sdtypes.Leaf: - // created vs updated is important for leaf nodes since we need to diff their storage - // so we need to map all changed accounts at B to their leafkey, since account can change paths but not leafkey - var account types.StateAccount - if err := rlp.DecodeBytes(nodeElements[1].([]byte), &account); err != nil { - return nil, nil, fmt.Errorf("error decoding account for leaf node at path %x nerror: %v", node.Path, err) - } - partialPath := trie.CompactToHex(nodeElements[0].([]byte)) - valueNodePath := append(node.Path, partialPath...) - encodedPath := trie.HexToCompact(valueNodePath) - leafKey := encodedPath[1:] - diffAcountsAtB[common.Bytes2Hex(leafKey)] = accountWrapper{ - NodeType: node.NodeType, - Path: node.Path, - NodeValue: node.NodeValue, - LeafKey: leafKey, - Account: &account, - } - case sdtypes.Extension, sdtypes.Branch: - // create a diff for any intermediate node that has changed at b - // created vs updated makes no difference for intermediate nodes since we do not need to diff storage - if err := output(sdtypes.StateNode{ - NodeType: node.NodeType, - Path: node.Path, - NodeValue: node.NodeValue, - }); err != nil { - return nil, nil, err - } - default: - return nil, nil, fmt.Errorf("unexpected node type %s", node.NodeType) - } - // add both intermediate and leaf node paths to the list of diffPathsAtB - diffPathsAtB[common.Bytes2Hex(node.Path)] = true - } - return diffAcountsAtB, diffPathsAtB, it.Error() -} - -// deletedOrUpdatedState returns a slice of all the paths that are emptied at B -// and a mapping of their leafkeys to all the accounts that exist in a different state at A than B -func (sdb *builder) deletedOrUpdatedState(iters iterPair, diffAccountsAtB AccountMap, diffPathsAtB map[string]bool, watchedAddressesLeafKeys map[common.Hash]struct{}, intermediateStorageNodes bool, output sdtypes.StateNodeSink) (AccountMap, error) { - diffAccountAtA := make(AccountMap) - it, _ := trie.NewDifferenceIterator(iters.newer, iters.older) - for it.Next(true) { - // skip value nodes - if it.Leaf() || bytes.Equal(nullHashBytes, it.Hash().Bytes()) { - continue - } - node, nodeElements, err := sdtrie.ResolveNode(it, sdb.stateCache.TrieDB()) - if err != nil { - return nil, err - } - switch node.NodeType { - case sdtypes.Leaf: - // map all different accounts at A to their leafkey - var account types.StateAccount - if err := rlp.DecodeBytes(nodeElements[1].([]byte), &account); err != nil { - return nil, fmt.Errorf("error decoding account for leaf node at path %x nerror: %v", node.Path, err) - } - partialPath := trie.CompactToHex(nodeElements[0].([]byte)) - valueNodePath := append(node.Path, partialPath...) - encodedPath := trie.HexToCompact(valueNodePath) - leafKey := encodedPath[1:] - if isWatchedAddress(watchedAddressesLeafKeys, leafKey) { - diffAccountAtA[common.Bytes2Hex(leafKey)] = accountWrapper{ - NodeType: node.NodeType, - Path: node.Path, - NodeValue: node.NodeValue, - LeafKey: leafKey, - Account: &account, - } - // if this node's path did not show up in diffPathsAtB - // that means the node at this path was deleted (or moved) in B - if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; !ok { - var diff sdtypes.StateNode - // if this node's leaf key also did not show up in diffAccountsAtB - // that means the node was deleted - // in that case, emit an empty "removed" diff state node - // include empty "removed" diff storage nodes for all the storage slots - if _, ok := diffAccountsAtB[common.Bytes2Hex(leafKey)]; !ok { - diff = sdtypes.StateNode{ - NodeType: sdtypes.Removed, - Path: node.Path, - LeafKey: leafKey, - NodeValue: []byte{}, - } - - var storageDiffs []sdtypes.StorageNode - err := sdb.buildRemovedAccountStorageNodes(account.Root, intermediateStorageNodes, storageNodeAppender(&storageDiffs)) - if err != nil { - return nil, fmt.Errorf("failed building storage diffs for removed node %x\r\nerror: %v", node.Path, err) - } - diff.StorageNodes = storageDiffs - } else { - // emit an empty "removed" diff with empty leaf key if the account was moved - diff = sdtypes.StateNode{ - NodeType: sdtypes.Removed, - Path: node.Path, - NodeValue: []byte{}, - } - } - - if err := output(diff); err != nil { - return nil, err - } - } - } - case sdtypes.Extension, sdtypes.Branch: - // if this node's path did not show up in diffPathsAtB - // that means the node at this path was deleted (or moved) in B - // emit an empty "removed" diff to signify as such - if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; !ok { - if err := output(sdtypes.StateNode{ - Path: node.Path, - NodeValue: []byte{}, - NodeType: sdtypes.Removed, - }); err != nil { - return nil, err - } - } - // fall through, we did everything we need to do with these node types - default: - return nil, fmt.Errorf("unexpected node type %s", node.NodeType) - } - } - return diffAccountAtA, it.Error() -} - -// buildAccountUpdates uses the account diffs maps for A => B and B => A and the known intersection of their leafkeys -// to generate the statediff node objects for all of the accounts that existed at both A and B but in different states -// needs to be called before building account creations and deletions as this mutates -// those account maps to remove the accounts which were updated -func (sdb *builder) buildAccountUpdates(creations, deletions AccountMap, updatedKeys []string, intermediateStorageNodes bool, output sdtypes.StateNodeSink) error { - var err error - for _, key := range updatedKeys { - createdAcc := creations[key] - deletedAcc := deletions[key] - var storageDiffs []sdtypes.StorageNode - if deletedAcc.Account != nil && createdAcc.Account != nil { - oldSR := deletedAcc.Account.Root - newSR := createdAcc.Account.Root - err = sdb.buildStorageNodesIncremental(oldSR, newSR, intermediateStorageNodes, storageNodeAppender(&storageDiffs)) - if err != nil { - return fmt.Errorf("failed building incremental storage diffs for account with leafkey %s\r\nerror: %v", key, err) - } - } - if err = output(sdtypes.StateNode{ - NodeType: createdAcc.NodeType, - Path: createdAcc.Path, - NodeValue: createdAcc.NodeValue, - LeafKey: createdAcc.LeafKey, - StorageNodes: storageDiffs, - }); err != nil { - return err - } - delete(creations, key) - delete(deletions, key) - } - - return nil -} - -// buildAccountCreations returns the statediff node objects for all the accounts that exist at B but not at A -// it also returns the code and codehash for created contract accounts -func (sdb *builder) buildAccountCreations(accounts AccountMap, intermediateStorageNodes bool, output sdtypes.StateNodeSink, codeOutput sdtypes.CodeSink) error { - for _, val := range accounts { - diff := sdtypes.StateNode{ - NodeType: val.NodeType, - Path: val.Path, - LeafKey: val.LeafKey, - NodeValue: val.NodeValue, - } - if !bytes.Equal(val.Account.CodeHash, nullCodeHash) { - // For contract creations, any storage node contained is a diff - var storageDiffs []sdtypes.StorageNode - err := sdb.buildStorageNodesEventual(val.Account.Root, intermediateStorageNodes, storageNodeAppender(&storageDiffs)) - if err != nil { - return fmt.Errorf("failed building eventual storage diffs for node %x\r\nerror: %v", val.Path, err) - } - diff.StorageNodes = storageDiffs - // emit codehash => code mappings for code - codeHash := common.BytesToHash(val.Account.CodeHash) - code, err := sdb.stateCache.ContractCode(common.Hash{}, codeHash) - if err != nil { - return fmt.Errorf("failed to retrieve code for codehash %s\r\n error: %v", codeHash.String(), err) - } - if err := codeOutput(sdtypes.CodeAndCodeHash{ - Hash: codeHash, - Code: code, - }); err != nil { - return err - } - } - if err := output(diff); err != nil { - return err - } - } - - return nil -} - -// buildStorageNodesEventual builds the storage diff node objects for a created account -// i.e. it returns all the storage nodes at this state, since there is no previous state -func (sdb *builder) buildStorageNodesEventual(sr common.Hash, intermediateNodes bool, output sdtypes.StorageNodeSink) error { - if bytes.Equal(sr.Bytes(), emptyContractRoot.Bytes()) { - return nil - } - log.Debug("Storage Root For Eventual Diff", "root", sr.Hex()) - sTrie, err := sdb.stateCache.OpenTrie(sr) - if err != nil { - log.Info("error in build storage diff eventual", "error", err) - return err - } - it := sTrie.NodeIterator(make([]byte, 0)) - err = sdb.buildStorageNodesFromTrie(it, intermediateNodes, output) - if err != nil { - return err - } - return nil -} - -// buildStorageNodesFromTrie returns all the storage diff node objects in the provided node iterator -// if any storage keys are provided it will only return those leaf nodes -// including intermediate nodes can be turned on or off -func (sdb *builder) buildStorageNodesFromTrie(it trie.NodeIterator, intermediateNodes bool, output sdtypes.StorageNodeSink) error { - for it.Next(true) { - if it.Leaf() || bytes.Equal(nullHashBytes, it.Hash().Bytes()) { - continue - } - node, nodeElements, err := resolveNode(it, sdb.stateCache.TrieDB()) - if err != nil { - return err - } - switch node.NodeType { - case sdtypes.Leaf: - partialPath := trie.CompactToHex(nodeElements[0].([]byte)) - valueNodePath := append(node.Path, partialPath...) - encodedPath := trie.HexToCompact(valueNodePath) - leafKey := encodedPath[1:] - if err := output(sdtypes.StorageNode{ - NodeType: node.NodeType, - Path: node.Path, - NodeValue: node.NodeValue, - LeafKey: leafKey, - }); err != nil { - return err - } - case sdtypes.Extension, sdtypes.Branch: - if intermediateNodes { - if err := output(sdtypes.StorageNode{ - NodeType: node.NodeType, - Path: node.Path, - NodeValue: node.NodeValue, - }); err != nil { - return err - } - } - default: - return fmt.Errorf("unexpected node type %s", node.NodeType) - } - } - return it.Error() -} - -// buildRemovedAccountStorageNodes builds the "removed" diffs for all the storage nodes for a destroyed account -func (sdb *builder) buildRemovedAccountStorageNodes(sr common.Hash, intermediateNodes bool, output sdtypes.StorageNodeSink) error { - if bytes.Equal(sr.Bytes(), emptyContractRoot.Bytes()) { - return nil - } - log.Debug("Storage Root For Removed Diffs", "root", sr.Hex()) - sTrie, err := sdb.stateCache.OpenTrie(sr) - if err != nil { - log.Info("error in build removed account storage diffs", "error", err) - return err - } - it := sTrie.NodeIterator(make([]byte, 0)) - err = sdb.buildRemovedStorageNodesFromTrie(it, intermediateNodes, output) - if err != nil { - return err - } - return nil -} - -// buildRemovedStorageNodesFromTrie returns diffs for all the storage nodes in the provided node interator -// including intermediate nodes can be turned on or off -func (sdb *builder) buildRemovedStorageNodesFromTrie(it trie.NodeIterator, intermediateNodes bool, output sdtypes.StorageNodeSink) error { - for it.Next(true) { - // skip value nodes - if it.Leaf() || bytes.Equal(nullHashBytes, it.Hash().Bytes()) { - continue - } - node, nodeElements, err := resolveNode(it, sdb.stateCache.TrieDB()) - if err != nil { - return err - } - switch node.NodeType { - case sdtypes.Leaf: - partialPath := trie.CompactToHex(nodeElements[0].([]byte)) - valueNodePath := append(node.Path, partialPath...) - encodedPath := trie.HexToCompact(valueNodePath) - leafKey := encodedPath[1:] - if err := output(sdtypes.StorageNode{ - NodeType: sdtypes.Removed, - Path: node.Path, - NodeValue: []byte{}, - LeafKey: leafKey, - }); err != nil { - return err - } - case sdtypes.Extension, sdtypes.Branch: - if intermediateNodes { - if err := output(sdtypes.StorageNode{ - NodeType: sdtypes.Removed, - Path: node.Path, - NodeValue: []byte{}, - }); err != nil { - return err - } - } - default: - return fmt.Errorf("unexpected node type %s", node.NodeType) - } - } - return it.Error() -} - -// buildStorageNodesIncremental builds the storage diff node objects for all nodes that exist in a different state at B than A -func (sdb *builder) buildStorageNodesIncremental(oldSR common.Hash, newSR common.Hash, intermediateNodes bool, output sdtypes.StorageNodeSink) error { - if bytes.Equal(newSR.Bytes(), oldSR.Bytes()) { - return nil - } - log.Debug("Storage Roots for Incremental Diff", "old", oldSR.Hex(), "new", newSR.Hex()) - oldTrie, err := sdb.stateCache.OpenTrie(oldSR) - if err != nil { - return err - } - newTrie, err := sdb.stateCache.OpenTrie(newSR) - if err != nil { - return err - } - - diffSlotsAtB, diffPathsAtB, err := sdb.createdAndUpdatedStorage(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}), intermediateNodes, output) - if err != nil { - return err - } - err = sdb.deletedOrUpdatedStorage(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}), diffSlotsAtB, diffPathsAtB, intermediateNodes, output) - if err != nil { - return err - } - return nil -} - -func (sdb *builder) createdAndUpdatedStorage(a, b trie.NodeIterator, intermediateNodes bool, output sdtypes.StorageNodeSink) (map[string]bool, map[string]bool, error) { - diffPathsAtB := make(map[string]bool) - diffSlotsAtB := make(map[string]bool) - it, _ := trie.NewDifferenceIterator(a, b) - for it.Next(true) { - if it.Leaf() || bytes.Equal(nullHashBytes, it.Hash().Bytes()) { - continue - } - node, nodeElements, err := resolveNode(it, sdb.stateCache.TrieDB()) - if err != nil { - return nil, nil, err - } - switch node.NodeType { - case sdtypes.Leaf: - partialPath := trie.CompactToHex(nodeElements[0].([]byte)) - valueNodePath := append(node.Path, partialPath...) - encodedPath := trie.HexToCompact(valueNodePath) - leafKey := encodedPath[1:] - diffSlotsAtB[common.Bytes2Hex(leafKey)] = true - if err := output(sdtypes.StorageNode{ - NodeType: node.NodeType, - Path: node.Path, - NodeValue: node.NodeValue, - LeafKey: leafKey, - }); err != nil { - return nil, nil, err - } - case sdtypes.Extension, sdtypes.Branch: - if intermediateNodes { - if err := output(sdtypes.StorageNode{ - NodeType: node.NodeType, - Path: node.Path, - NodeValue: node.NodeValue, - }); err != nil { - return nil, nil, err - } - } - default: - return nil, nil, fmt.Errorf("unexpected node type %s", node.NodeType) - } - diffPathsAtB[common.Bytes2Hex(node.Path)] = true - } - return diffSlotsAtB, diffPathsAtB, it.Error() -} - -func (sdb *builder) deletedOrUpdatedStorage(a, b trie.NodeIterator, diffSlotsAtB, diffPathsAtB map[string]bool, intermediateNodes bool, output sdtypes.StorageNodeSink) error { - it, _ := trie.NewDifferenceIterator(b, a) - for it.Next(true) { - // skip value nodes - if it.Leaf() || bytes.Equal(nullHashBytes, it.Hash().Bytes()) { - continue - } - node, nodeElements, err := sdtrie.ResolveNode(it, sdb.stateCache.TrieDB()) - if err != nil { - return err - } - - switch node.NodeType { - case sdtypes.Leaf: - partialPath := trie.CompactToHex(nodeElements[0].([]byte)) - valueNodePath := append(node.Path, partialPath...) - encodedPath := trie.HexToCompact(valueNodePath) - leafKey := encodedPath[1:] - - // if this node's path did not show up in diffPathsAtB - // that means the node at this path was deleted (or moved) in B - if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; !ok { - // if this node's leaf key also did not show up in diffSlotsAtB - // that means the node was deleted - // in that case, emit an empty "removed" diff storage node - if _, ok := diffSlotsAtB[common.Bytes2Hex(leafKey)]; !ok { - if err := output(sdtypes.StorageNode{ - NodeType: sdtypes.Removed, - Path: node.Path, - NodeValue: []byte{}, - LeafKey: leafKey, - }); err != nil { - return err - } - } else { - // emit an empty "removed" diff with empty leaf key if the account was moved - if err := output(sdtypes.StorageNode{ - NodeType: sdtypes.Removed, - Path: node.Path, - NodeValue: []byte{}, - }); err != nil { - return err - } - } - } - case sdtypes.Extension, sdtypes.Branch: - // if this node's path did not show up in diffPathsAtB - // that means the node at this path was deleted in B - // in that case, emit an empty "removed" diff storage node - if _, ok := diffPathsAtB[common.Bytes2Hex(node.Path)]; !ok { - if intermediateNodes { - if err := output(sdtypes.StorageNode{ - NodeType: sdtypes.Removed, - Path: node.Path, - NodeValue: []byte{}, - }); err != nil { - return err - } - } - } - default: - return fmt.Errorf("unexpected node type %s", node.NodeType) - } - } - return it.Error() -} - -// isWatchedAddress is used to check if a state account corresponds to one of the addresses the builder is configured to watch -func isWatchedAddress(watchedAddressesLeafKeys map[common.Hash]struct{}, stateLeafKey []byte) bool { - // If we aren't watching any specific addresses, we are watching everything - if len(watchedAddressesLeafKeys) == 0 { - return true - } - - _, ok := watchedAddressesLeafKeys[common.BytesToHash(stateLeafKey)] - return ok -} - -// isWatchedStorageKey is used to check if a storage leaf corresponds to one of the storage slots the builder is configured to watch -func isWatchedStorageKey(watchedKeys []common.Hash, storageLeafKey []byte) bool { - // If we aren't watching any specific addresses, we are watching everything - if len(watchedKeys) == 0 { - return true - } - for _, hashKey := range watchedKeys { - if bytes.Equal(hashKey.Bytes(), storageLeafKey) { - return true - } - } - return false -} diff --git a/pkg/builder_test.go b/pkg/builder_test.go index 54496a8..52c7289 100644 --- a/pkg/builder_test.go +++ b/pkg/builder_test.go @@ -26,20 +26,19 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/statediff" + sd "github.com/ethereum/go-ethereum/statediff" "github.com/ethereum/go-ethereum/statediff/test_helpers" sdtypes "github.com/ethereum/go-ethereum/statediff/types" pkg "github.com/vulcanize/eth-statediff-service/pkg" ) -// TODO: add test that filters on address var ( contractLeafKey []byte emptyDiffs = make([]sdtypes.StateNode, 0) emptyStorage = make([]sdtypes.StorageNode, 0) block0, block1, block2, block3, block4, block5, block6 *types.Block - builder pkg.Builder + builder sd.Builder miningReward = int64(2000000000000000000) minerAddress = common.HexToAddress("0x0") minerLeafKey = test_helpers.AddressToLeafKey(minerAddress) @@ -487,16 +486,16 @@ func TestBuilder(t *testing.T) { block1 = blocks[0] block2 = blocks[1] block3 = blocks[2] - params := statediff.Params{} + params := sd.Params{} var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ { "testEmptyDiff", - statediff.Args{ + sd.Args{ OldStateRoot: block0.Root(), NewStateRoot: block0.Root(), BlockNumber: block0.Number(), @@ -511,7 +510,7 @@ func TestBuilder(t *testing.T) { { "testBlock0", //10000 transferred from testBankAddress to account1Addr - statediff.Args{ + sd.Args{ OldStateRoot: test_helpers.NullHash, NewStateRoot: block0.Root(), BlockNumber: block0.Number(), @@ -534,7 +533,7 @@ func TestBuilder(t *testing.T) { { "testBlock1", //10000 transferred from testBankAddress to account1Addr - statediff.Args{ + sd.Args{ OldStateRoot: block0.Root(), NewStateRoot: block1.Root(), BlockNumber: block1.Number(), @@ -573,7 +572,7 @@ func TestBuilder(t *testing.T) { // 1000 transferred from testBankAddress to account1Addr // 1000 transferred from account1Addr to account2Addr // account1addr creates a new contract - statediff.Args{ + sd.Args{ OldStateRoot: block1.Root(), NewStateRoot: block2.Root(), BlockNumber: block2.Number(), @@ -644,7 +643,7 @@ func TestBuilder(t *testing.T) { "testBlock3", //the contract's storage is changed //and the block is mined by account 2 - statediff.Args{ + sd.Args{ OldStateRoot: block2.Root(), NewStateRoot: block3.Root(), BlockNumber: block3.Number(), @@ -721,19 +720,19 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { block2 = blocks[1] block3 = blocks[2] blocks = append([]*types.Block{block0}, blocks...) - params := statediff.Params{ + params := sd.Params{ IntermediateStateNodes: true, IntermediateStorageNodes: true, } var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ { "testEmptyDiff", - statediff.Args{ + sd.Args{ OldStateRoot: block0.Root(), NewStateRoot: block0.Root(), BlockNumber: block0.Number(), @@ -748,7 +747,7 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { { "testBlock0", //10000 transferred from testBankAddress to account1Addr - statediff.Args{ + sd.Args{ OldStateRoot: test_helpers.NullHash, NewStateRoot: block0.Root(), BlockNumber: block0.Number(), @@ -771,7 +770,7 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { { "testBlock1", //10000 transferred from testBankAddress to account1Addr - statediff.Args{ + sd.Args{ OldStateRoot: block0.Root(), NewStateRoot: block1.Root(), BlockNumber: block1.Number(), @@ -816,7 +815,7 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { // 1000 transferred from testBankAddress to account1Addr // 1000 transferred from account1Addr to account2Addr // account1addr creates a new contract - statediff.Args{ + sd.Args{ OldStateRoot: block1.Root(), NewStateRoot: block2.Root(), BlockNumber: block2.Number(), @@ -898,7 +897,7 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { "testBlock3", //the contract's storage is changed //and the block is mined by account 2 - statediff.Args{ + sd.Args{ OldStateRoot: block2.Root(), NewStateRoot: block3.Root(), BlockNumber: block3.Number(), @@ -999,19 +998,19 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { block1 = blocks[0] block2 = blocks[1] block3 = blocks[2] - params := statediff.Params{ + params := sd.Params{ WatchedAddresses: []common.Address{test_helpers.Account1Addr, test_helpers.ContractAddr}, } params.ComputeWatchedAddressesLeafKeys() var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ { "testEmptyDiff", - statediff.Args{ + sd.Args{ OldStateRoot: block0.Root(), NewStateRoot: block0.Root(), BlockNumber: block0.Number(), @@ -1026,7 +1025,7 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { { "testBlock0", //10000 transferred from testBankAddress to account1Addr - statediff.Args{ + sd.Args{ OldStateRoot: test_helpers.NullHash, NewStateRoot: block0.Root(), BlockNumber: block0.Number(), @@ -1041,7 +1040,7 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { { "testBlock1", //10000 transferred from testBankAddress to account1Addr - statediff.Args{ + sd.Args{ OldStateRoot: block0.Root(), NewStateRoot: block1.Root(), BlockNumber: block1.Number(), @@ -1065,7 +1064,7 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { "testBlock2", //1000 transferred from testBankAddress to account1Addr //1000 transferred from account1Addr to account2Addr - statediff.Args{ + sd.Args{ OldStateRoot: block1.Root(), NewStateRoot: block2.Root(), BlockNumber: block2.Number(), @@ -1115,7 +1114,7 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { "testBlock3", //the contract's storage is changed //and the block is mined by account 2 - statediff.Args{ + sd.Args{ OldStateRoot: block2.Root(), NewStateRoot: block3.Root(), BlockNumber: block3.Number(), @@ -1177,20 +1176,20 @@ func TestBuilderWithRemovedAccountAndStorage(t *testing.T) { block4 = blocks[3] block5 = blocks[4] block6 = blocks[5] - params := statediff.Params{ + params := sd.Params{ IntermediateStateNodes: true, IntermediateStorageNodes: true, } var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ // blocks 0-3 are the same as in TestBuilderWithIntermediateNodes { "testBlock4", - statediff.Args{ + sd.Args{ OldStateRoot: block3.Root(), NewStateRoot: block4.Root(), BlockNumber: block4.Number(), @@ -1256,7 +1255,7 @@ func TestBuilderWithRemovedAccountAndStorage(t *testing.T) { }, { "testBlock5", - statediff.Args{ + sd.Args{ OldStateRoot: block4.Root(), NewStateRoot: block5.Root(), BlockNumber: block5.Number(), @@ -1316,7 +1315,7 @@ func TestBuilderWithRemovedAccountAndStorage(t *testing.T) { }, { "testBlock6", - statediff.Args{ + sd.Args{ OldStateRoot: block5.Root(), NewStateRoot: block6.Root(), BlockNumber: block6.Number(), @@ -1412,20 +1411,20 @@ func TestBuilderWithRemovedAccountAndStorageWithoutIntermediateNodes(t *testing. block4 = blocks[3] block5 = blocks[4] block6 = blocks[5] - params := statediff.Params{ + params := sd.Params{ IntermediateStateNodes: false, IntermediateStorageNodes: false, } var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ // blocks 0-3 are the same as in TestBuilderWithIntermediateNodes { "testBlock4", - statediff.Args{ + sd.Args{ OldStateRoot: block3.Root(), NewStateRoot: block4.Root(), BlockNumber: block4.Number(), @@ -1480,7 +1479,7 @@ func TestBuilderWithRemovedAccountAndStorageWithoutIntermediateNodes(t *testing. }, { "testBlock5", - statediff.Args{ + sd.Args{ OldStateRoot: block4.Root(), NewStateRoot: block5.Root(), BlockNumber: block5.Number(), @@ -1529,7 +1528,7 @@ func TestBuilderWithRemovedAccountAndStorageWithoutIntermediateNodes(t *testing. }, { "testBlock6", - statediff.Args{ + sd.Args{ OldStateRoot: block5.Root(), NewStateRoot: block6.Root(), BlockNumber: block6.Number(), @@ -1611,19 +1610,19 @@ func TestBuilderWithRemovedNonWatchedAccount(t *testing.T) { block4 = blocks[3] block5 = blocks[4] block6 = blocks[5] - params := statediff.Params{ + params := sd.Params{ WatchedAddresses: []common.Address{test_helpers.Account1Addr, test_helpers.Account2Addr}, } params.ComputeWatchedAddressesLeafKeys() var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ { "testBlock4", - statediff.Args{ + sd.Args{ OldStateRoot: block3.Root(), NewStateRoot: block4.Root(), BlockNumber: block4.Number(), @@ -1645,7 +1644,7 @@ func TestBuilderWithRemovedNonWatchedAccount(t *testing.T) { }, { "testBlock5", - statediff.Args{ + sd.Args{ OldStateRoot: block4.Root(), NewStateRoot: block5.Root(), BlockNumber: block5.Number(), @@ -1667,7 +1666,7 @@ func TestBuilderWithRemovedNonWatchedAccount(t *testing.T) { }, { "testBlock6", - statediff.Args{ + sd.Args{ OldStateRoot: block5.Root(), NewStateRoot: block6.Root(), BlockNumber: block6.Number(), @@ -1729,19 +1728,19 @@ func TestBuilderWithRemovedWatchedAccount(t *testing.T) { block4 = blocks[3] block5 = blocks[4] block6 = blocks[5] - params := statediff.Params{ + params := sd.Params{ WatchedAddresses: []common.Address{test_helpers.Account1Addr, test_helpers.ContractAddr}, } params.ComputeWatchedAddressesLeafKeys() var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ { "testBlock4", - statediff.Args{ + sd.Args{ OldStateRoot: block3.Root(), NewStateRoot: block4.Root(), BlockNumber: block4.Number(), @@ -1782,7 +1781,7 @@ func TestBuilderWithRemovedWatchedAccount(t *testing.T) { }, { "testBlock5", - statediff.Args{ + sd.Args{ OldStateRoot: block4.Root(), NewStateRoot: block5.Root(), BlockNumber: block5.Number(), @@ -1824,7 +1823,7 @@ func TestBuilderWithRemovedWatchedAccount(t *testing.T) { }, { "testBlock6", - statediff.Args{ + sd.Args{ OldStateRoot: block5.Root(), NewStateRoot: block6.Root(), BlockNumber: block6.Number(), @@ -1979,19 +1978,19 @@ func TestBuilderWithMovedAccount(t *testing.T) { block0 = test_helpers.Genesis block1 = blocks[0] block2 = blocks[1] - params := statediff.Params{ + params := sd.Params{ IntermediateStateNodes: true, IntermediateStorageNodes: true, } var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ { "testBlock1", - statediff.Args{ + sd.Args{ OldStateRoot: block0.Root(), NewStateRoot: block1.Root(), BlockNumber: block1.Number(), @@ -2050,7 +2049,7 @@ func TestBuilderWithMovedAccount(t *testing.T) { }, { "testBlock2", - statediff.Args{ + sd.Args{ OldStateRoot: block1.Root(), NewStateRoot: block2.Root(), BlockNumber: block2.Number(), @@ -2131,19 +2130,19 @@ func TestBuilderWithMovedAccountOnlyLeafs(t *testing.T) { block0 = test_helpers.Genesis block1 = blocks[0] block2 = blocks[1] - params := statediff.Params{ + params := sd.Params{ IntermediateStateNodes: false, IntermediateStorageNodes: false, } var tests = []struct { name string - startingArguments statediff.Args + startingArguments sd.Args expected *sdtypes.StateObject }{ { "testBlock1", - statediff.Args{ + sd.Args{ OldStateRoot: block0.Root(), NewStateRoot: block1.Root(), BlockNumber: block1.Number(), @@ -2191,7 +2190,7 @@ func TestBuilderWithMovedAccountOnlyLeafs(t *testing.T) { }, { "testBlock2", - statediff.Args{ + sd.Args{ OldStateRoot: block1.Root(), NewStateRoot: block2.Root(), BlockNumber: block2.Number(), diff --git a/pkg/service.go b/pkg/service.go index 7893b76..792bdbc 100644 --- a/pkg/service.go +++ b/pkg/service.go @@ -66,7 +66,7 @@ type StateDiffService interface { // Service is the underlying struct for the state diffing service type Service struct { // Used to build the state diff objects - Builder Builder + Builder sd.Builder // Used to read data from LevelDB lvlDBReader Reader // Used to signal shutdown of the service