Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
eff7cfbb
Unverified
Commit
eff7cfbb
authored
5 years ago
by
Martin Holst Swende
Committed by
GitHub
5 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/state/snapshot: handle deleted accounts in fast iterator
parent
328de180
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
78 additions
and
9 deletions
+78
-9
iterator_fast.go
core/state/snapshot/iterator_fast.go
+26
-8
iterator_test.go
core/state/snapshot/iterator_test.go
+52
-1
No files found.
core/state/snapshot/iterator_fast.go
View file @
eff7cfbb
...
...
@@ -164,17 +164,35 @@ func (fi *fastAccountIterator) Next() bool {
fi
.
curAccount
=
fi
.
iterators
[
0
]
.
it
.
Account
()
if
innerErr
:=
fi
.
iterators
[
0
]
.
it
.
Error
();
innerErr
!=
nil
{
fi
.
fail
=
innerErr
return
false
}
return
fi
.
Error
()
==
nil
}
if
!
fi
.
next
(
0
)
{
return
false
if
fi
.
curAccount
!=
nil
{
return
true
}
// Implicit else: we've hit a nil-account, and need to fall through to the
// loop below to land on something non-nil
}
fi
.
curAccount
=
fi
.
iterators
[
0
]
.
it
.
Account
()
if
innerErr
:=
fi
.
iterators
[
0
]
.
it
.
Error
();
innerErr
!=
nil
{
fi
.
fail
=
innerErr
// If an account is deleted in one of the layers, the key will still be there,
// but the actual value will be nil. However, the iterator should not
// export nil-values (but instead simply omit the key), so we need to loop
// here until we either
// - get a non-nil value,
// - hit an error,
// - or exhaust the iterator
for
{
if
!
fi
.
next
(
0
)
{
return
false
// exhausted
}
fi
.
curAccount
=
fi
.
iterators
[
0
]
.
it
.
Account
()
if
innerErr
:=
fi
.
iterators
[
0
]
.
it
.
Error
();
innerErr
!=
nil
{
fi
.
fail
=
innerErr
return
false
// error
}
if
fi
.
curAccount
!=
nil
{
break
// non-nil value found
}
}
return
fi
.
Error
()
==
nil
return
true
}
// next handles the next operation internally and should be invoked when we know
...
...
This diff is collapsed.
Click to expand it.
core/state/snapshot/iterator_test.go
View file @
eff7cfbb
...
...
@@ -130,9 +130,13 @@ func verifyIterator(t *testing.T, expCount int, it AccountIterator) {
last
=
common
.
Hash
{}
)
for
it
.
Next
()
{
if
hash
:=
it
.
Hash
();
bytes
.
Compare
(
last
[
:
],
hash
[
:
])
>=
0
{
hash
:=
it
.
Hash
()
if
bytes
.
Compare
(
last
[
:
],
hash
[
:
])
>=
0
{
t
.
Errorf
(
"wrong order: %x >= %x"
,
last
,
hash
)
}
if
it
.
Account
()
==
nil
{
t
.
Errorf
(
"iterator returned nil-value for hash %x"
,
hash
)
}
count
++
}
if
count
!=
expCount
{
...
...
@@ -377,6 +381,53 @@ func TestAccountIteratorSeek(t *testing.T) {
verifyIterator
(
t
,
0
,
it
)
// expected: nothing
}
// TestIteratorDeletions tests that the iterator behaves correct when there are
// deleted accounts (where the Account() value is nil). The iterator
// should not output any accounts or nil-values for those cases.
func
TestIteratorDeletions
(
t
*
testing
.
T
)
{
// Create an empty base layer and a snapshot tree out of it
base
:=
&
diskLayer
{
diskdb
:
rawdb
.
NewMemoryDatabase
(),
root
:
common
.
HexToHash
(
"0x01"
),
cache
:
fastcache
.
New
(
1024
*
500
),
}
snaps
:=
&
Tree
{
layers
:
map
[
common
.
Hash
]
snapshot
{
base
.
root
:
base
,
},
}
// Stack three diff layers on top with various overlaps
snaps
.
Update
(
common
.
HexToHash
(
"0x02"
),
common
.
HexToHash
(
"0x01"
),
randomAccountSet
(
"0x11"
,
"0x22"
,
"0x33"
),
nil
)
set
:=
randomAccountSet
(
"0x11"
,
"0x22"
,
"0x33"
)
deleted
:=
common
.
HexToHash
(
"0x22"
)
set
[
deleted
]
=
nil
snaps
.
Update
(
common
.
HexToHash
(
"0x03"
),
common
.
HexToHash
(
"0x02"
),
set
,
nil
)
snaps
.
Update
(
common
.
HexToHash
(
"0x04"
),
common
.
HexToHash
(
"0x03"
),
randomAccountSet
(
"0x33"
,
"0x44"
,
"0x55"
),
nil
)
// The output should be 11,33,44,55
it
,
_
:=
snaps
.
AccountIterator
(
common
.
HexToHash
(
"0x04"
),
common
.
Hash
{})
// Do a quick check
verifyIterator
(
t
,
4
,
it
)
it
.
Release
()
// And a more detailed verification that we indeed do not see '0x22'
it
,
_
=
snaps
.
AccountIterator
(
common
.
HexToHash
(
"0x04"
),
common
.
Hash
{})
defer
it
.
Release
()
for
it
.
Next
()
{
hash
:=
it
.
Hash
()
if
it
.
Account
()
==
nil
{
t
.
Errorf
(
"iterator returned nil-value for hash %x"
,
hash
)
}
if
hash
==
deleted
{
t
.
Errorf
(
"expected deleted elem %x to not be returned by iterator"
,
deleted
)
}
}
}
// BenchmarkAccountIteratorTraversal is a bit a bit notorious -- all layers contain the
// exact same 200 accounts. That means that we need to process 2000 items, but
// only spit out 200 values eventually.
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment