Skip to content

Commit 62cce0c

Browse files
holimanrjl493456442
andcommitted
core/state: tests on the binary iterator (#30754)
Fixes an error in the binary iterator, adds additional testcases --------- Co-authored-by: Gary Rong <[email protected]>
1 parent c8f6d24 commit 62cce0c

File tree

2 files changed

+172
-74
lines changed

2 files changed

+172
-74
lines changed

core/state/snapshot/iterator_binary.go

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,21 @@ type binaryIterator struct {
3939
// initBinaryAccountIterator creates a simplistic iterator to step over all the
4040
// accounts in a slow, but easily verifiable way. Note this function is used for
4141
// initialization, use `newBinaryAccountIterator` as the API.
42-
func (dl *diffLayer) initBinaryAccountIterator() Iterator {
42+
func (dl *diffLayer) initBinaryAccountIterator(seek common.Hash) Iterator {
4343
parent, ok := dl.parent.(*diffLayer)
4444
if !ok {
4545
l := &binaryIterator{
46-
a: dl.AccountIterator(common.Hash{}),
47-
b: dl.Parent().AccountIterator(common.Hash{}),
46+
a: dl.AccountIterator(seek),
47+
b: dl.Parent().AccountIterator(seek),
4848
accountIterator: true,
4949
}
5050
l.aDone = !l.a.Next()
5151
l.bDone = !l.b.Next()
5252
return l
5353
}
5454
l := &binaryIterator{
55-
a: dl.AccountIterator(common.Hash{}),
56-
b: parent.initBinaryAccountIterator(),
55+
a: dl.AccountIterator(seek),
56+
b: parent.initBinaryAccountIterator(seek),
5757
accountIterator: true,
5858
}
5959
l.aDone = !l.a.Next()
@@ -64,12 +64,12 @@ func (dl *diffLayer) initBinaryAccountIterator() Iterator {
6464
// initBinaryStorageIterator creates a simplistic iterator to step over all the
6565
// storage slots in a slow, but easily verifiable way. Note this function is used
6666
// for initialization, use `newBinaryStorageIterator` as the API.
67-
func (dl *diffLayer) initBinaryStorageIterator(account common.Hash) Iterator {
67+
func (dl *diffLayer) initBinaryStorageIterator(account, seek common.Hash) Iterator {
6868
parent, ok := dl.parent.(*diffLayer)
6969
if !ok {
7070
// If the storage in this layer is already destructed, discard all
7171
// deeper layers but still return a valid single-branch iterator.
72-
a, destructed := dl.StorageIterator(account, common.Hash{})
72+
a, destructed := dl.StorageIterator(account, seek)
7373
if destructed {
7474
l := &binaryIterator{
7575
a: a,
@@ -81,7 +81,7 @@ func (dl *diffLayer) initBinaryStorageIterator(account common.Hash) Iterator {
8181
}
8282
// The parent is disk layer, don't need to take care "destructed"
8383
// anymore.
84-
b, _ := dl.Parent().StorageIterator(account, common.Hash{})
84+
b, _ := dl.Parent().StorageIterator(account, seek)
8585
l := &binaryIterator{
8686
a: a,
8787
b: b,
@@ -93,7 +93,7 @@ func (dl *diffLayer) initBinaryStorageIterator(account common.Hash) Iterator {
9393
}
9494
// If the storage in this layer is already destructed, discard all
9595
// deeper layers but still return a valid single-branch iterator.
96-
a, destructed := dl.StorageIterator(account, common.Hash{})
96+
a, destructed := dl.StorageIterator(account, seek)
9797
if destructed {
9898
l := &binaryIterator{
9999
a: a,
@@ -105,7 +105,7 @@ func (dl *diffLayer) initBinaryStorageIterator(account common.Hash) Iterator {
105105
}
106106
l := &binaryIterator{
107107
a: a,
108-
b: parent.initBinaryStorageIterator(account),
108+
b: parent.initBinaryStorageIterator(account, seek),
109109
account: account,
110110
}
111111
l.aDone = !l.a.Next()
@@ -117,33 +117,50 @@ func (dl *diffLayer) initBinaryStorageIterator(account common.Hash) Iterator {
117117
// or an error if iteration failed for some reason (e.g. root being iterated
118118
// becomes stale and garbage collected).
119119
func (it *binaryIterator) Next() bool {
120+
for {
121+
if !it.next() {
122+
return false
123+
}
124+
if len(it.Account()) != 0 || len(it.Slot()) != 0 {
125+
return true
126+
}
127+
// it.fail might be set if error occurs by calling
128+
// it.Account() or it.Slot(), stop iteration if so.
129+
if it.fail != nil {
130+
return false
131+
}
132+
}
133+
}
134+
135+
func (it *binaryIterator) next() bool {
120136
if it.aDone && it.bDone {
121137
return false
122138
}
123-
first:
124-
if it.aDone {
125-
it.k = it.b.Hash()
139+
for {
140+
if it.aDone {
141+
it.k = it.b.Hash()
142+
it.bDone = !it.b.Next()
143+
return true
144+
}
145+
if it.bDone {
146+
it.k = it.a.Hash()
147+
it.aDone = !it.a.Next()
148+
return true
149+
}
150+
nextA, nextB := it.a.Hash(), it.b.Hash()
151+
if diff := bytes.Compare(nextA[:], nextB[:]); diff < 0 {
152+
it.aDone = !it.a.Next()
153+
it.k = nextA
154+
return true
155+
} else if diff == 0 {
156+
// Now we need to advance one of them
157+
it.aDone = !it.a.Next()
158+
continue
159+
}
126160
it.bDone = !it.b.Next()
161+
it.k = nextB
127162
return true
128163
}
129-
if it.bDone {
130-
it.k = it.a.Hash()
131-
it.aDone = !it.a.Next()
132-
return true
133-
}
134-
nextA, nextB := it.a.Hash(), it.b.Hash()
135-
if diff := bytes.Compare(nextA[:], nextB[:]); diff < 0 {
136-
it.aDone = !it.a.Next()
137-
it.k = nextA
138-
return true
139-
} else if diff == 0 {
140-
// Now we need to advance one of them
141-
it.aDone = !it.a.Next()
142-
goto first
143-
}
144-
it.bDone = !it.b.Next()
145-
it.k = nextB
146-
return true
147164
}
148165

149166
// Error returns any failure that occurred during iteration, which might have
@@ -195,19 +212,21 @@ func (it *binaryIterator) Slot() []byte {
195212
// Release recursively releases all the iterators in the stack.
196213
func (it *binaryIterator) Release() {
197214
it.a.Release()
198-
it.b.Release()
215+
if it.b != nil {
216+
it.b.Release()
217+
}
199218
}
200219

201220
// newBinaryAccountIterator creates a simplistic account iterator to step over
202221
// all the accounts in a slow, but easily verifiable way.
203-
func (dl *diffLayer) newBinaryAccountIterator() AccountIterator {
204-
iter := dl.initBinaryAccountIterator()
222+
func (dl *diffLayer) newBinaryAccountIterator(seek common.Hash) AccountIterator {
223+
iter := dl.initBinaryAccountIterator(seek)
205224
return iter.(AccountIterator)
206225
}
207226

208227
// newBinaryStorageIterator creates a simplistic account iterator to step over
209228
// all the storage slots in a slow, but easily verifiable way.
210-
func (dl *diffLayer) newBinaryStorageIterator(account common.Hash) StorageIterator {
211-
iter := dl.initBinaryStorageIterator(account)
229+
func (dl *diffLayer) newBinaryStorageIterator(account, seek common.Hash) StorageIterator {
230+
iter := dl.initBinaryStorageIterator(account, seek)
212231
return iter.(StorageIterator)
213232
}

0 commit comments

Comments
 (0)