core: fix two snapshot iterator flaws, decollide snap storage prefix
* core/state/snapshot/iterator: fix two disk iterator flaws * core/rawdb: change SnapshotStoragePrefix to avoid prefix collision with preimagePrefix
This commit is contained in:
committed by
Péter Szilágyi
parent
fab0ee3bfa
commit
074efe6c8d
@ -90,7 +90,8 @@ type (
|
||||
account *common.Address
|
||||
}
|
||||
resetObjectChange struct {
|
||||
prev *stateObject
|
||||
prev *stateObject
|
||||
prevdestruct bool
|
||||
}
|
||||
suicideChange struct {
|
||||
account *common.Address
|
||||
@ -142,6 +143,9 @@ func (ch createObjectChange) dirtied() *common.Address {
|
||||
|
||||
func (ch resetObjectChange) revert(s *StateDB) {
|
||||
s.setStateObject(ch.prev)
|
||||
if !ch.prevdestruct && s.snap != nil {
|
||||
delete(s.snapDestructs, ch.prev.addrHash)
|
||||
}
|
||||
}
|
||||
|
||||
func (ch resetObjectChange) dirtied() *common.Address {
|
||||
|
@ -148,9 +148,10 @@ type diskAccountIterator struct {
|
||||
|
||||
// AccountIterator creates an account iterator over a disk layer.
|
||||
func (dl *diskLayer) AccountIterator(seek common.Hash) AccountIterator {
|
||||
// TODO: Fix seek position, or remove seek parameter
|
||||
return &diskAccountIterator{
|
||||
layer: dl,
|
||||
it: dl.diskdb.NewIteratorWithPrefix(append(rawdb.SnapshotAccountPrefix, seek[:]...)),
|
||||
it: dl.diskdb.NewIteratorWithPrefix(rawdb.SnapshotAccountPrefix),
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,11 +161,16 @@ func (it *diskAccountIterator) Next() bool {
|
||||
if it.it == nil {
|
||||
return false
|
||||
}
|
||||
// Try to advance the iterator and release it if we reahed the end
|
||||
if !it.it.Next() || !bytes.HasPrefix(it.it.Key(), rawdb.SnapshotAccountPrefix) {
|
||||
it.it.Release()
|
||||
it.it = nil
|
||||
return false
|
||||
// Try to advance the iterator and release it if we reached the end
|
||||
for {
|
||||
if !it.it.Next() || !bytes.HasPrefix(it.it.Key(), rawdb.SnapshotAccountPrefix) {
|
||||
it.it.Release()
|
||||
it.it = nil
|
||||
return false
|
||||
}
|
||||
if len(it.it.Key()) == len(rawdb.SnapshotAccountPrefix)+common.HashLength {
|
||||
break
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -569,12 +569,19 @@ func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
|
||||
func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
|
||||
prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that!
|
||||
|
||||
var prevdestruct bool
|
||||
if s.snap != nil && prev != nil {
|
||||
_, prevdestruct = s.snapDestructs[prev.addrHash]
|
||||
if !prevdestruct {
|
||||
s.snapDestructs[prev.addrHash] = struct{}{}
|
||||
}
|
||||
}
|
||||
newobj = newObject(s, addr, Account{})
|
||||
newobj.setNonce(0) // sets the object to dirty
|
||||
if prev == nil {
|
||||
s.journal.append(createObjectChange{account: &addr})
|
||||
} else {
|
||||
s.journal.append(resetObjectChange{prev: prev})
|
||||
s.journal.append(resetObjectChange{prev: prev, prevdestruct: prevdestruct})
|
||||
}
|
||||
s.setStateObject(newobj)
|
||||
return newobj, prev
|
||||
@ -595,9 +602,6 @@ func (s *StateDB) CreateAccount(addr common.Address) {
|
||||
if prev != nil {
|
||||
newObj.setBalance(prev.data.Balance)
|
||||
}
|
||||
if s.snap != nil && prev != nil {
|
||||
s.snapDestructs[prev.addrHash] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error {
|
||||
|
Reference in New Issue
Block a user