diff --git a/pkg/eth/backend.go b/pkg/eth/backend.go index 03688d0f..00f1216d 100644 --- a/pkg/eth/backend.go +++ b/pkg/eth/backend.go @@ -45,8 +45,6 @@ import ( "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" ethServerShared "github.com/ethereum/go-ethereum/statediff/indexer/shared" - 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/jmoiron/sqlx" ) @@ -953,7 +951,7 @@ func (b *Backend) getSliceStem(headPath []byte, t state.Trie, response *GetSlice if depthReached > metaData.maxDepth { metaData.maxDepth = depthReached } - if node.NodeType == sdtypes.Leaf { + if node.NodeType == Leaf { metaData.leafCount++ } leavesFetchTime += leafFetchTime @@ -995,7 +993,7 @@ func (b *Backend) getSliceHead(headPath []byte, t state.Trie, response *GetSlice if depthReached > metaData.maxDepth { metaData.maxDepth = depthReached } - if node.NodeType == sdtypes.Leaf { + if node.NodeType == Leaf { metaData.leafCount++ } @@ -1037,7 +1035,7 @@ func (b *Backend) getSliceTrie(headPath []byte, t state.Trie, response *GetSlice continue } - node, nodeElements, err := sdtrie.ResolveNode(it, b.StateDatabase.TrieDB()) + node, nodeElements, err := ResolveNodeIt(it, b.StateDatabase.TrieDB()) if err != nil { return err } @@ -1052,7 +1050,7 @@ func (b *Backend) getSliceTrie(headPath []byte, t state.Trie, response *GetSlice if depthReached > metaData.maxDepth { metaData.maxDepth = depthReached } - if node.NodeType == sdtypes.Leaf { + if node.NodeType == Leaf { metaData.leafCount++ } leavesFetchTime += leafFetchTime diff --git a/pkg/eth/backend_utils.go b/pkg/eth/backend_utils.go index 68655604..bc200cb3 100644 --- a/pkg/eth/backend_utils.go +++ b/pkg/eth/backend_utils.go @@ -35,8 +35,6 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" - sdtrie "github.com/ethereum/go-ethereum/statediff/trie_helpers" - sdtypes "github.com/ethereum/go-ethereum/statediff/types" "github.com/ethereum/go-ethereum/trie" ) @@ -334,7 +332,7 @@ func fillSliceNodeData( ethDB ethdb.KeyValueReader, nodesMap map[string]string, leavesMap map[string]GetSliceResponseAccount, - node sdtypes.StateNode, + node StateNode, nodeElements []interface{}, storage bool, ) (int64, error) { @@ -344,7 +342,7 @@ func fillSliceNodeData( // Extract account data if it's a Leaf node leafStartTime := makeTimestamp() - if node.NodeType == sdtypes.Leaf && !storage { + if node.NodeType == Leaf && !storage { stateLeafKey, storageRoot, code, err := extractContractAccountInfo(ethDB, node, nodeElements) if err != nil { return 0, fmt.Errorf("GetSlice account lookup error: %s", err.Error()) @@ -362,7 +360,7 @@ func fillSliceNodeData( return makeTimestamp() - leafStartTime, nil } -func extractContractAccountInfo(ethDB ethdb.KeyValueReader, node sdtypes.StateNode, nodeElements []interface{}) (string, string, []byte, error) { +func extractContractAccountInfo(ethDB ethdb.KeyValueReader, node StateNode, nodeElements []interface{}) (string, string, []byte, error) { 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) @@ -387,23 +385,3 @@ func extractContractAccountInfo(ethDB ethdb.KeyValueReader, node sdtypes.StateNo return stateLeafKeyString, storageRootString, codeBytes, nil } - -func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (sdtypes.StateNode, []interface{}, error) { - nodePath := make([]byte, len(path)) - copy(nodePath, path) - - 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 -} diff --git a/pkg/eth/helpers.go b/pkg/eth/helpers.go index cce23579..fcbf3cac 100644 --- a/pkg/eth/helpers.go +++ b/pkg/eth/helpers.go @@ -18,25 +18,8 @@ package eth import ( "time" - - sdtypes "github.com/ethereum/go-ethereum/statediff/types" ) -func ResolveToNodeType(nodeType int) sdtypes.NodeType { - switch nodeType { - case 0: - return sdtypes.Branch - case 1: - return sdtypes.Extension - case 2: - return sdtypes.Leaf - case 3: - return sdtypes.Removed - default: - return sdtypes.Unknown - } -} - // Timestamp in milliseconds func makeTimestamp() int64 { return time.Now().UnixNano() / int64(time.Millisecond) diff --git a/pkg/eth/node_types.go b/pkg/eth/node_types.go new file mode 100644 index 00000000..f0f1ba15 --- /dev/null +++ b/pkg/eth/node_types.go @@ -0,0 +1,116 @@ +package eth + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +// NodeType for explicitly setting type of node +type NodeType string + +const ( + Unknown NodeType = "Unknown" + Branch NodeType = "Branch" + Extension NodeType = "Extension" + Leaf NodeType = "Leaf" + Removed NodeType = "Removed" // used to represent paths which have been emptied +) + +func (n NodeType) Int() int { + switch n { + case Branch: + return 0 + case Extension: + return 1 + case Leaf: + return 2 + case Removed: + return 3 + default: + return -1 + } +} + +// CheckKeyType checks what type of key we have +func CheckKeyType(elements []interface{}) (NodeType, error) { + if len(elements) > 2 { + return Branch, nil + } + if len(elements) < 2 { + return Unknown, fmt.Errorf("node cannot be less than two elements in length") + } + switch elements[0].([]byte)[0] / 16 { + case '\x00': + return Extension, nil + case '\x01': + return Extension, nil + case '\x02': + return Leaf, nil + case '\x03': + return Leaf, nil + default: + return Unknown, fmt.Errorf("unknown hex prefix") + } +} + +// StateNode holds the data for a single state diff node +type StateNode struct { + NodeType NodeType `json:"nodeType" gencodec:"required"` + Path []byte `json:"path" gencodec:"required"` + NodeValue []byte `json:"value" gencodec:"required"` + StorageNodes []StorageNode `json:"storage"` + LeafKey []byte `json:"leafKey"` +} + +// StorageNode holds the data for a single storage diff node +type StorageNode struct { + NodeType NodeType `json:"nodeType" gencodec:"required"` + Path []byte `json:"path" gencodec:"required"` + NodeValue []byte `json:"value" gencodec:"required"` + LeafKey []byte `json:"leafKey"` +} + +func ResolveNode(path []byte, node []byte, trieDB *trie.Database) (StateNode, []interface{}, error) { + nodePath := make([]byte, len(path)) + copy(nodePath, path) + + var nodeElements []interface{} + if err := rlp.DecodeBytes(node, &nodeElements); err != nil { + return StateNode{}, nil, err + } + + ty, err := CheckKeyType(nodeElements) + if err != nil { + return StateNode{}, nil, err + } + return StateNode{ + NodeType: ty, + Path: nodePath, + NodeValue: node, + }, nodeElements, nil +} + +// ResolveNodeIt return the state diff node pointed by the iterator. +func ResolveNodeIt(it trie.NodeIterator, trieDB *trie.Database) (StateNode, []interface{}, error) { + nodePath := make([]byte, len(it.Path())) + copy(nodePath, it.Path()) + node, err := trieDB.Node(it.Hash()) + if err != nil { + return StateNode{}, nil, err + } + var nodeElements []interface{} + if err = rlp.DecodeBytes(node, &nodeElements); err != nil { + return StateNode{}, nil, err + } + ty, err := CheckKeyType(nodeElements) + if err != nil { + return StateNode{}, nil, err + } + return StateNode{ + NodeType: ty, + Path: nodePath, + NodeValue: node, + }, nodeElements, nil +}