@@ -19,7 +19,6 @@ package trie
19
19
import (
20
20
"fmt"
21
21
"reflect"
22
- "sort"
23
22
"strings"
24
23
25
24
"github.com/ethereum/go-ethereum/common"
@@ -41,8 +40,8 @@ var memoryNodeSize = int(reflect.TypeOf(memoryNode{}).Size())
41
40
42
41
// memorySize returns the total memory size used by this node.
43
42
// nolint:unused
44
- func (n * memoryNode ) memorySize (pathlen int ) int {
45
- return int (n .size ) + memoryNodeSize + pathlen
43
+ func (n * memoryNode ) memorySize (key int ) int {
44
+ return int (n .size ) + memoryNodeSize + key
46
45
}
47
46
48
47
// rlp returns the raw rlp encoded blob of the cached trie node, either directly
@@ -65,107 +64,96 @@ func (n *memoryNode) obj() node {
65
64
return expandNode (n .hash [:], n .node )
66
65
}
67
66
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
-
73
67
// nodeWithPrev wraps the memoryNode with the previous node value.
74
- // nolint: unused
75
68
type nodeWithPrev struct {
76
69
* memoryNode
77
70
prev []byte // RLP-encoded previous value, nil means it's non-existent
78
71
}
79
72
80
73
// unwrap returns the internal memoryNode object.
81
- // nolint: unused
74
+ // nolint:unused
82
75
func (n * nodeWithPrev ) unwrap () * memoryNode {
83
76
return n .memoryNode
84
77
}
85
78
86
79
// memorySize returns the total memory size used by this node. It overloads
87
80
// the function in memoryNode by counting the size of previous value as well.
88
81
// nolint: unused
89
- func (n * nodeWithPrev ) memorySize (pathlen int ) int {
90
- return n .memoryNode .memorySize (pathlen ) + len (n .prev )
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
91
92
}
92
93
93
94
// NodeSet contains all dirty nodes collected during the commit operation.
94
95
// Each node is keyed by path. It's not thread-safe to use.
95
96
type NodeSet struct {
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
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
100
101
}
101
102
102
103
// NewNodeSet initializes an empty node set to be used for tracking dirty nodes
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
- }
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 {
112
107
return & NodeSet {
113
- owner : owner ,
114
- nodes : make (map [string ]* memoryNode ),
115
- accessList : accessList ,
108
+ owner : owner ,
109
+ updates : & nodesWithOrder {
110
+ nodes : make (map [string ]* nodeWithPrev ),
111
+ },
112
+ deletes : make (map [string ][]byte ),
116
113
}
117
114
}
118
115
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 ])
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])
139
122
}
123
+ return set
140
124
}
125
+ */
141
126
142
127
// markUpdated marks the node as dirty(newly-inserted or updated) with provided
143
128
// node path, node object along with its previous value.
144
- func (set * NodeSet ) markUpdated (path []byte , node * memoryNode ) {
145
- set .nodes [string (path )] = node
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
+ }
146
135
}
147
136
148
137
// markDeleted marks the node as deleted with provided path and previous value.
149
- // nolint: unused
150
- func (set * NodeSet ) markDeleted (path []byte ) {
151
- set .nodes [string (path )] = & memoryNode {}
138
+ func (set * NodeSet ) markDeleted (path []byte , prev []byte ) {
139
+ set .deletes [string (path )] = prev
152
140
}
153
141
154
142
// addLeaf collects the provided leaf node into set.
155
143
func (set * NodeSet ) addLeaf (node * leaf ) {
156
144
set .leaves = append (set .leaves , node )
157
145
}
158
146
159
- // Size returns the number of dirty nodes contained in the set.
160
- func (set * NodeSet ) Size () int {
161
- return len (set .nodes )
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 )
162
150
}
163
151
164
152
// Hashes returns the hashes of all updated nodes. TODO(rjl493456442) how can
165
153
// we get rid of it?
166
154
func (set * NodeSet ) Hashes () []common.Hash {
167
155
var ret []common.Hash
168
- for _ , node := range set .nodes {
156
+ for _ , node := range set .updates . nodes {
169
157
ret = append (ret , node .hash )
170
158
}
171
159
return ret
@@ -175,17 +163,19 @@ func (set *NodeSet) Hashes() []common.Hash {
175
163
func (set * NodeSet ) Summary () string {
176
164
var out = new (strings.Builder )
177
165
fmt .Fprintf (out , "nodeset owner: %v\n " , set .owner )
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
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 )
184
173
}
185
- // Update
186
- fmt .Fprintf (out , " [+]: %x -> %v\n " , path , n .hash )
187
174
}
188
175
}
176
+ for k , n := range set .deletes {
177
+ fmt .Fprintf (out , " [-]: %x -> %x\n " , k , n )
178
+ }
189
179
for _ , n := range set .leaves {
190
180
fmt .Fprintf (out , "[leaf]: %v\n " , n )
191
181
}
0 commit comments