@@ -19,6 +19,7 @@ package trie
1919import (
2020 "fmt"
2121 "reflect"
22+ "sort"
2223 "strings"
2324
2425 "github.com/ethereum/go-ethereum/common"
@@ -40,8 +41,8 @@ var memoryNodeSize = int(reflect.TypeOf(memoryNode{}).Size())
4041
4142// memorySize returns the total memory size used by this node.
4243// nolint:unused
43- func (n * memoryNode ) memorySize (key int ) int {
44- return int (n .size ) + memoryNodeSize + key
44+ func (n * memoryNode ) memorySize (pathlen int ) int {
45+ return int (n .size ) + memoryNodeSize + pathlen
4546}
4647
4748// rlp returns the raw rlp encoded blob of the cached trie node, either directly
@@ -64,96 +65,107 @@ func (n *memoryNode) obj() node {
6465 return expandNode (n .hash [:], n .node )
6566}
6667
68+ // isDeleted returns the indicator if the node is marked as deleted.
69+ func (n * memoryNode ) isDeleted () bool {
70+ return n .hash == (common.Hash {})
71+ }
72+
6773// nodeWithPrev wraps the memoryNode with the previous node value.
74+ // nolint: unused
6875type nodeWithPrev struct {
6976 * memoryNode
7077 prev []byte // RLP-encoded previous value, nil means it's non-existent
7178}
7279
7380// unwrap returns the internal memoryNode object.
74- // nolint:unused
81+ // nolint: unused
7582func (n * nodeWithPrev ) unwrap () * memoryNode {
7683 return n .memoryNode
7784}
7885
7986// memorySize returns the total memory size used by this node. It overloads
8087// the function in memoryNode by counting the size of previous value as well.
8188// nolint: unused
82- func (n * nodeWithPrev ) memorySize (key int ) int {
83- return n .memoryNode .memorySize (key ) + len (n .prev )
84- }
85-
86- // nodesWithOrder represents a collection of dirty nodes which includes
87- // newly-inserted and updated nodes. The modification order of all nodes
88- // is represented by order list.
89- type nodesWithOrder struct {
90- order []string // the path list of dirty nodes, sort by insertion order
91- nodes map [string ]* nodeWithPrev // the map of dirty nodes, keyed by node path
89+ func (n * nodeWithPrev ) memorySize (pathlen int ) int {
90+ return n .memoryNode .memorySize (pathlen ) + len (n .prev )
9291}
9392
9493// NodeSet contains all dirty nodes collected during the commit operation.
9594// Each node is keyed by path. It's not thread-safe to use.
9695type NodeSet struct {
97- owner common.Hash // the identifier of the trie
98- updates * nodesWithOrder // the set of updated nodes(newly inserted, updated)
99- deletes map [ string ][] byte // the map of deleted nodes, keyed by node
100- leaves [] * leaf // the list of dirty leaves
96+ owner common.Hash // the identifier of the trie
97+ nodes map [ string ] * memoryNode // the set of dirty nodes(inserted, updated, deleted )
98+ leaves [] * leaf // the list of dirty leaves
99+ accessList map [ string ][] byte // The list of accessed nodes, which records the original node value
101100}
102101
103102// NewNodeSet initializes an empty node set to be used for tracking dirty nodes
104- // from a specific account or storage trie. The owner is zero for the account
105- // trie and the owning account address hash for storage tries.
106- func NewNodeSet (owner common.Hash ) * NodeSet {
103+ // for a specific account or storage trie. The owner is zero for the account trie
104+ // and the owning account address hash for storage tries. The provided accessList
105+ // represents the original value of accessed nodes, it can be optional but would
106+ // be beneficial for speeding up the construction of trie history.
107+ func NewNodeSet (owner common.Hash , accessList map [string ][]byte ) * NodeSet {
108+ // Don't panic for lazy users
109+ if accessList == nil {
110+ accessList = make (map [string ][]byte )
111+ }
107112 return & NodeSet {
108- owner : owner ,
109- updates : & nodesWithOrder {
110- nodes : make (map [string ]* nodeWithPrev ),
111- },
112- deletes : make (map [string ][]byte ),
113+ owner : owner ,
114+ nodes : make (map [string ]* memoryNode ),
115+ accessList : accessList ,
113116 }
114117}
115118
116- /*
117- // NewNodeSetWithDeletion initializes the nodeset with provided deletion set.
118- func NewNodeSetWithDeletion(owner common.Hash, paths [][]byte, prev [][]byte) *NodeSet {
119- set := NewNodeSet(owner)
120- for i, path := range paths {
121- set.markDeleted(path, prev[i])
119+ // forEachWithOrder iterates the dirty nodes with the specified order.
120+ // If topToBottom is true:
121+ //
122+ // then the order of iteration is top to bottom, left to right.
123+ //
124+ // If topToBottom is false:
125+ //
126+ // then the order of iteration is bottom to top, right to left.
127+ func (set * NodeSet ) forEachWithOrder (topToBottom bool , callback func (path string , n * memoryNode )) {
128+ var paths sort.StringSlice
129+ for path := range set .nodes {
130+ paths = append (paths , path )
131+ }
132+ if topToBottom {
133+ paths .Sort ()
134+ } else {
135+ sort .Sort (sort .Reverse (paths ))
136+ }
137+ for _ , path := range paths {
138+ callback (path , set .nodes [path ])
122139 }
123- return set
124140}
125- */
126141
127142// markUpdated marks the node as dirty(newly-inserted or updated) with provided
128143// node path, node object along with its previous value.
129- func (set * NodeSet ) markUpdated (path []byte , node * memoryNode , prev []byte ) {
130- set .updates .order = append (set .updates .order , string (path ))
131- set .updates .nodes [string (path )] = & nodeWithPrev {
132- memoryNode : node ,
133- prev : prev ,
134- }
144+ func (set * NodeSet ) markUpdated (path []byte , node * memoryNode ) {
145+ set .nodes [string (path )] = node
135146}
136147
137148// markDeleted marks the node as deleted with provided path and previous value.
138- func (set * NodeSet ) markDeleted (path []byte , prev []byte ) {
139- set .deletes [string (path )] = prev
149+ // nolint: unused
150+ func (set * NodeSet ) markDeleted (path []byte ) {
151+ set .nodes [string (path )] = & memoryNode {}
140152}
141153
142154// addLeaf collects the provided leaf node into set.
143155func (set * NodeSet ) addLeaf (node * leaf ) {
144156 set .leaves = append (set .leaves , node )
145157}
146158
147- // Size returns the number of updated and deleted nodes contained in the set.
148- func (set * NodeSet ) Size () ( int , int ) {
149- return len (set .updates . order ), len ( set . deletes )
159+ // Size returns the number of dirty nodes contained in the set.
160+ func (set * NodeSet ) Size () int {
161+ return len (set .nodes )
150162}
151163
152164// Hashes returns the hashes of all updated nodes. TODO(rjl493456442) how can
153165// we get rid of it?
154166func (set * NodeSet ) Hashes () []common.Hash {
155167 var ret []common.Hash
156- for _ , node := range set .updates . nodes {
168+ for _ , node := range set .nodes {
157169 ret = append (ret , node .hash )
158170 }
159171 return ret
@@ -163,19 +175,17 @@ func (set *NodeSet) Hashes() []common.Hash {
163175func (set * NodeSet ) Summary () string {
164176 var out = new (strings.Builder )
165177 fmt .Fprintf (out , "nodeset owner: %v\n " , set .owner )
166- if set .updates != nil {
167- for _ , key := range set .updates .order {
168- updated := set .updates .nodes [key ]
169- if updated .prev != nil {
170- fmt .Fprintf (out , " [*]: %x -> %v prev: %x\n " , key , updated .hash , updated .prev )
171- } else {
172- fmt .Fprintf (out , " [+]: %x -> %v\n " , key , updated .hash )
178+ if set .nodes != nil {
179+ for path , n := range set .nodes {
180+ // Deletion
181+ if n .isDeleted () {
182+ fmt .Fprintf (out , " [-]: %x\n " , path )
183+ continue
173184 }
185+ // Update
186+ fmt .Fprintf (out , " [+]: %x -> %v\n " , path , n .hash )
174187 }
175188 }
176- for k , n := range set .deletes {
177- fmt .Fprintf (out , " [-]: %x -> %x\n " , k , n )
178- }
179189 for _ , n := range set .leaves {
180190 fmt .Fprintf (out , "[leaf]: %v\n " , n )
181191 }
0 commit comments