mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
core/state: ensure originStorage is committed
I see, the `stateObject.updateTrie` all invoked by the miner, and there exists two stack trace:
1. By `StateDB.Finalise`, and the full stack trace as below:
```
goroutine 83 [running]:
github.com/ethereum/go-ethereum/core/state.(*stateObject).updateTrie(0xc009c46e00, 0x11d9ae0, 0xc000209ad0, 0xc000ce6f1c, 0x33b1d98976d74501)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/core/state/state_object.go:223 +0xcf
github.com/ethereum/go-ethereum/core/state.(*stateObject).updateRoot(0xc009c46e00, 0x11d9ae0, 0xc000209ad0)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/core/state/state_object.go:258 +0x43
github.com/ethereum/go-ethereum/core/state.(*StateDB).Finalise(0xc009c46c40, 0xc018596901)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/core/state/statedb.go:569 +0x1a2
github.com/ethereum/go-ethereum/core.ApplyTransaction(0xc0001e2180, 0x11ce740, 0xc000382000, 0xc00a8b3558, 0xc0001d8ff0, 0xc009c46c40, 0xc00a75c240, 0xc018578900, 0xc00a75c410, 0x0, ...)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/core/state_processor.go:106 +0x32a
github.com/ethereum/go-ethereum/miner.(*worker).commitTransaction(0xc0004da1c0, 0xc018578900, 0x0, 0x0, 0x73e9da8b01000000, 0xc0512796de, 0x0, 0x0, 0x440ee1, 0x100e9c8)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/miner/worker.go:695 +0x13a
github.com/ethereum/go-ethereum/miner.(*worker).commitTransactions(0xc0004da1c0, 0xc00035fd10, 0x0, 0x0, 0x1000000, 0xc0001d8fe0, 0xb1)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/miner/worker.go:765 +0x294
github.com/ethereum/go-ethereum/miner.(*worker).commitNewWork(0xc0004da1c0, 0xc0001d8fe0, 0x1, 0x5baf3a7d)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/miner/worker.go:933 +0xb75
github.com/ethereum/go-ethereum/miner.(*worker).mainLoop(0xc0004da1c0)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/miner/worker.go:411 +0xba1
created by github.com/ethereum/go-ethereum/miner.newWorker
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/miner/worker.go:219 +0x506
```
which uses `w.current.state`, and after the `updateTrie` was
invoked, the `stateObject.dirtyStorage` turned out to be an empty map, and the items are updated to the SecureTrie.
**You only update the Trie, but not commited it, some metadata are only in SecureTrie's cache, not persistenced.**
2. By `StateDB.CommitTrie`, and the full stack trace as below:
```
goroutine 85 [running]:
github.com/ethereum/go-ethereum/core/state.(*stateObject).updateTrie(0xc009c47260, 0x11d9ae0, 0xc000209ad0, 0x177614d290fdfd56, 0xcb009d0df74936b9)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/core/state/state_object.go:223 +0xcf
github.com/ethereum/go-ethereum/core/state.(*stateObject).CommitTrie(0xc009c47260, 0x11d9ae0, 0xc000209ad0, 0xaa71a542df75c534, 0xc2398056166a4ff7)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/core/state/state_object.go:265 +0x5a
github.com/ethereum/go-ethereum/core/state.(*StateDB).Commit(0xc009c46fc0, 0xc002031a01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/core/state/statedb.go:622 +0x30b
github.com/ethereum/go-ethereum/core.(*BlockChain).WriteBlockWithState(0xc000382000, 0xc000d8c240, 0xc01855a0c8, 0x1, 0x1, 0xc009c46fc0, 0x0, 0x0, 0x0)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/core/blockchain.go:909 +0x502
github.com/ethereum/go-ethereum/miner.(*worker).resultLoop(0xc0004da1c0)
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/miner/worker.go:580 +0x628
created by github.com/ethereum/go-ethereum/miner.newWorker
/root/.go/src/github.com/ethereum/go-ethereum/build/_workspace/src/github.com/ethereum/go-ethereum/miner/worker.go:221 +0x557
```
which uses `w.current.state.Copy()`, a deep copy of `w.current.state`. So there exists two objects of `StateDB`.
So far so good. After the 2th `CommitTrie` invoked, I want to use `debug.dumpBlock` to find the storage of deployed contract, but it
failed to print only one no key value, seems I'm missing the preimages
of all the storage key.
After digging into the implement of SecureTrie, inside the `SecureTrie.Commit`, it will insert the preimages down to Database, but it didn't do it.
Finds it depends on `len(t.getSecKeyCache())`, which will decide to use the old `secKeyCache`(copyed from the `w.current.state`) or make a new map by the `t.secKeyCacheOwner`.
But after you copyed a new StateDB, the owner is changed, in the meanwhile, you want to Commit the Trie, only the trie is saved to DB, the preimages are abandoned.
This commit is contained in:
parent
efa11fe534
commit
9bdbdf5e18
1 changed files with 14 additions and 2 deletions
|
|
@ -217,6 +217,18 @@ func (self *stateObject) setState(key, value common.Hash) {
|
||||||
// updateTrie writes cached storage modifications into the object's storage trie.
|
// updateTrie writes cached storage modifications into the object's storage trie.
|
||||||
func (self *stateObject) updateTrie(db Database) Trie {
|
func (self *stateObject) updateTrie(db Database) Trie {
|
||||||
tr := self.getTrie(db)
|
tr := self.getTrie(db)
|
||||||
|
|
||||||
|
// save the originStorage first, ensure all non empty keys in originStorage saved to trie.
|
||||||
|
// if the object is copyed from another one,
|
||||||
|
// the dirtyStorage is empty and the originStorage is not empty.
|
||||||
|
for key, value := range self.originStorage {
|
||||||
|
if value != (common.Hash{}) {
|
||||||
|
// Encoding []byte cannot fail, ok to ignore the error.
|
||||||
|
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
|
||||||
|
self.setError(tr.TryUpdate(key[:], v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for key, value := range self.dirtyStorage {
|
for key, value := range self.dirtyStorage {
|
||||||
delete(self.dirtyStorage, key)
|
delete(self.dirtyStorage, key)
|
||||||
|
|
||||||
|
|
@ -226,7 +238,7 @@ func (self *stateObject) updateTrie(db Database) Trie {
|
||||||
}
|
}
|
||||||
self.originStorage[key] = value
|
self.originStorage[key] = value
|
||||||
|
|
||||||
if (value == common.Hash{}) {
|
if value == (common.Hash{}) {
|
||||||
self.setError(tr.TryDelete(key[:]))
|
self.setError(tr.TryDelete(key[:]))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -237,7 +249,7 @@ func (self *stateObject) updateTrie(db Database) Trie {
|
||||||
return tr
|
return tr
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateRoot sets the trie root to the current root hash of
|
// updateRoot sets the trie root to the current root hash of
|
||||||
func (self *stateObject) updateRoot(db Database) {
|
func (self *stateObject) updateRoot(db Database) {
|
||||||
self.updateTrie(db)
|
self.updateTrie(db)
|
||||||
self.data.Root = self.trie.Hash()
|
self.data.Root = self.trie.Hash()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue