Compare commits

..

3 Commits

Author SHA1 Message Date
joeycli
0af2fb4324 feat: support rewind for versa db
fix: rewind ancient store
2024-09-02 17:32:56 +08:00
joeycli
3e8e74d5c2 feat: delete statedb debug system 2024-08-27 09:29:24 +08:00
joeycli
d20bbb4799 feat: integrate versa db
feat: add version commit

chore: forbid versiondb rewind

feat: add mode for new caching db

feat: add version scheme for startup

feat: init genesis for versa db

feat: add caching db and trie copy

feat: support HasState on versa db and must fullsync under versa db

fix: append open strorage trie error to statedb

fix: storage tree value encode

fix: add state object trie expire interface

fix: blockchain stateat use rw state

chore: forbid prefetcher

chore: delete storage pool

feat: hold version in state objet for repeat search account tree

fix: version mismatch that add contract balance without update storage tree

fix: 373559 blocks issue add breakpoint

feat: add version state debug system

feat: add hash state db debug system

feat: add version and hash state diff system

fix: the timing release debug state instance
2024-08-27 09:01:25 +08:00
8 changed files with 468 additions and 404 deletions

View File

@@ -361,8 +361,6 @@ func geth(ctx *cli.Context) error {
defer stack.Close() defer stack.Close()
startNode(ctx, stack, backend, false) startNode(ctx, stack, backend, false)
// TODO:: debug code , will be deleted in the future
debug.StartPProf("127.0.0.1:7060", !ctx.IsSet("metrics.addr"))
stack.Wait() stack.Wait()
return nil return nil
} }

View File

@@ -74,7 +74,6 @@ var (
blockInsertMgaspsGauge = metrics.NewRegisteredGauge("chain/insert/mgasps", nil) blockInsertMgaspsGauge = metrics.NewRegisteredGauge("chain/insert/mgasps", nil)
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil) chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
mGasPsGauge = metrics.NewRegisteredGauge("chain/process/gas", nil)
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
@@ -425,6 +424,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
// Make sure the state associated with the block is available, or log out // Make sure the state associated with the block is available, or log out
// if there is no available state, waiting for state sync. // if there is no available state, waiting for state sync.
head := bc.CurrentBlock() head := bc.CurrentBlock()
if bc.triedb.Scheme() != rawdb.VersionScheme {
if !bc.HasState(head.Root) { if !bc.HasState(head.Root) {
if head.Number.Uint64() == 0 { if head.Number.Uint64() == 0 {
// The genesis state is missing, which is only possible in the path-based // The genesis state is missing, which is only possible in the path-based
@@ -466,7 +466,11 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
} }
} }
} }
} else {
log.Warn("versa db no recovery, rewind in load state")
}
// Ensure that a previous crash in SetHead doesn't leave extra ancients // Ensure that a previous crash in SetHead doesn't leave extra ancients
if bc.triedb.Scheme() != rawdb.VersionScheme {
if frozen, err := bc.db.BlockStore().ItemAmountInAncient(); err == nil && frozen > 0 { if frozen, err := bc.db.BlockStore().ItemAmountInAncient(); err == nil && frozen > 0 {
frozen, err = bc.db.BlockStore().Ancients() frozen, err = bc.db.BlockStore().Ancients()
if err != nil { if err != nil {
@@ -501,6 +505,24 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
} }
} }
} }
} else {
//TODO:: need consider the offline and inline prune block
frozen, err := bc.db.BlockStore().Ancients()
if err != nil {
return nil, err
}
items, err := bc.db.BlockStore().ItemAmountInAncient()
if err != nil {
return nil, err
}
fullBlock := bc.CurrentBlock()
log.Info("version mode rewind ancient store", "target", fullBlock.Number.Uint64(), "old head", frozen, "items", items, "offset", bc.db.BlockStore().AncientOffSet())
if frozen >= fullBlock.Number.Uint64() {
if _, err = bc.db.BlockStore().TruncateTail(fullBlock.Number.Uint64()); err != nil {
return nil, err
}
}
}
// The first thing the node will do is reconstruct the verification data for // The first thing the node will do is reconstruct the verification data for
// the head block (ethash cache or clique voting snapshot). Might as well do // the head block (ethash cache or clique voting snapshot). Might as well do
// it in advance. // it in advance.
@@ -703,6 +725,38 @@ func (bc *BlockChain) getFinalizedNumber(header *types.Header) uint64 {
// loadLastState loads the last known chain state from the database. This method // loadLastState loads the last known chain state from the database. This method
// assumes that the chain manager mutex is held. // assumes that the chain manager mutex is held.
func (bc *BlockChain) loadLastState() error { func (bc *BlockChain) loadLastState() error {
// TODO:: before versa db support recovery, only rewind
var headBlock *types.Block
if bc.triedb.Scheme() == rawdb.VersionScheme {
head := rawdb.ReadHeadBlockHash(bc.db)
headBlock = bc.GetBlockByHash(head)
versa := bc.triedb.VersaDB()
archiveVersion, _ := versa.LatestStoreDiskVersionInfo()
// empty chain
if archiveVersion == -1 {
archiveVersion = 0
}
if int64(headBlock.NumberU64()) < archiveVersion {
log.Crit("versa db disk version large than header block", "head number", headBlock.NumberU64(), "versa archive number", archiveVersion)
}
log.Info("begin rewind versa db head", "target", archiveVersion)
for {
if int64(headBlock.NumberU64()) == archiveVersion {
rawdb.WriteCanonicalHash(bc.db, headBlock.Hash(), headBlock.NumberU64())
rawdb.WriteHeadHeaderHash(bc.db, headBlock.Hash())
rawdb.WriteHeadBlockHash(bc.db, headBlock.Hash())
rawdb.WriteHeadFastBlockHash(bc.db, headBlock.Hash())
log.Info("reset versa db head block", "number", headBlock.NumberU64(), "hash", headBlock.Hash())
break
}
headBlock = rawdb.ReadBlock(bc.db, headBlock.ParentHash(), headBlock.NumberU64()-1)
if headBlock == nil {
panic("versa db rewind head is nil")
}
}
} else {
// Restore the last known head block // Restore the last known head block
head := rawdb.ReadHeadBlockHash(bc.db) head := rawdb.ReadHeadBlockHash(bc.db)
if head == (common.Hash{}) { if head == (common.Hash{}) {
@@ -711,12 +765,14 @@ func (bc *BlockChain) loadLastState() error {
return bc.Reset() return bc.Reset()
} }
// Make sure the entire head block is available // Make sure the entire head block is available
headBlock := bc.GetBlockByHash(head) headBlock = bc.GetBlockByHash(head)
if headBlock == nil { if headBlock == nil {
// Corrupt or empty database, init from scratch // Corrupt or empty database, init from scratch
log.Warn("Head block missing, resetting chain", "hash", head) log.Warn("Head block missing, resetting chain", "hash", head)
return bc.Reset() return bc.Reset()
} }
}
log.Info("load state head block", "number", headBlock.NumberU64())
// Everything seems to be fine, set as the head block // Everything seems to be fine, set as the head block
bc.currentBlock.Store(headBlock.Header()) bc.currentBlock.Store(headBlock.Header())

View File

@@ -64,7 +64,6 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn
"blocks", st.processed, "txs", txs, "blobs", blobs, "mgas", float64(st.usedGas) / 1000000, "blocks", st.processed, "txs", txs, "blobs", blobs, "mgas", float64(st.usedGas) / 1000000,
"elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps, "elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps,
} }
mGasPsGauge.Update(int64(mgasps))
blockInsertMgaspsGauge.Update(int64(mgasps)) blockInsertMgaspsGauge.Update(int64(mgasps))
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute { if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)

View File

@@ -36,7 +36,7 @@ type cachingVersaDB struct {
mode versa.StateMode mode versa.StateMode
hasState atomic.Bool hasState atomic.Bool
debug *DebugVersionState //debug *DebugVersionState
} }
// NewVersaDatabase should be call by NewDatabaseWithNodeDB // NewVersaDatabase should be call by NewDatabaseWithNodeDB
@@ -66,9 +66,9 @@ func (cv *cachingVersaDB) Copy() Database {
if cv.hasState.Load() { if cv.hasState.Load() {
_, err := cp.OpenTrie(cv.root) _, err := cp.OpenTrie(cv.root)
if err != nil { if err != nil {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnError(fmt.Errorf("failed to open trie in copy caching versa db, error: %s", err.Error())) // cv.debug.OnError(fmt.Errorf("failed to open trie in copy caching versa db, error: %s", err.Error()))
} //}
return cp return cp
} }
} }
@@ -90,18 +90,18 @@ func (cv *cachingVersaDB) CopyTrie(tr Trie) Trie {
} }
tree, err := cv.OpenTrie(vtr.root) tree, err := cv.OpenTrie(vtr.root)
if err != nil { if err != nil {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnError(fmt.Errorf("failed to open trie in copy versa trie, error: %s", err.Error())) // cv.debug.OnError(fmt.Errorf("failed to open trie in copy versa trie, error: %s", err.Error()))
} //}
return nil return nil
} }
return tree return tree
} else { } else {
tree, err := cv.OpenStorageTrie(vtr.stateRoot, vtr.address, vtr.root, nil) tree, err := cv.OpenStorageTrie(vtr.stateRoot, vtr.address, vtr.root, nil)
if err != nil { if err != nil {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnError(fmt.Errorf("failed to open storage trie in copy versa trie, error: %s", err.Error())) // cv.debug.OnError(fmt.Errorf("failed to open storage trie in copy versa trie, error: %s", err.Error()))
} //}
return nil return nil
} }
return tree return tree
@@ -122,20 +122,20 @@ func (cv *cachingVersaDB) OpenTrie(root common.Hash) (Trie, error) {
// TODO:: if root tree, versa db should ignore check version, temp use -1 // TODO:: if root tree, versa db should ignore check version, temp use -1
state, err := cv.versionDB.OpenState(cv.version, root, cv.mode) state, err := cv.versionDB.OpenState(cv.version, root, cv.mode)
if err != nil { if err != nil {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnError(fmt.Errorf("failed to open state, root:%s, error: %s", root.String(), err.Error())) // cv.debug.OnError(fmt.Errorf("failed to open state, root:%s, error: %s", root.String(), err.Error()))
} //}
return nil, err return nil, err
} }
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnOpenState(state) // cv.debug.OnOpenState(state)
} //}
handler, err := cv.versionDB.OpenTree(state, cv.version, common.Hash{}, root) handler, err := cv.versionDB.OpenTree(state, cv.version, common.Hash{}, root)
if err != nil { if err != nil {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnError(fmt.Errorf("failed to open account trie, root:%s, error: %s", root.String(), err.Error())) // cv.debug.OnError(fmt.Errorf("failed to open account trie, root:%s, error: %s", root.String(), err.Error()))
} //}
return nil, err return nil, err
} }
@@ -145,7 +145,7 @@ func (cv *cachingVersaDB) OpenTrie(root common.Hash) (Trie, error) {
accountTree: true, accountTree: true,
root: root, root: root,
mode: cv.mode, mode: cv.mode,
debug: cv.debug, //debug: cv.debug,
} }
cv.state = state cv.state = state
@@ -153,9 +153,9 @@ func (cv *cachingVersaDB) OpenTrie(root common.Hash) (Trie, error) {
cv.accTree = tree cv.accTree = tree
cv.root = root cv.root = root
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnOpenTree(handler, common.Hash{}, common.Address{}) // cv.debug.OnOpenTree(handler, common.Hash{}, common.Address{})
} //}
return tree, nil return tree, nil
} }
@@ -180,16 +180,16 @@ func (cv *cachingVersaDB) openStorageTreeWithVersion(version int64, stateRoot co
owner := crypto.Keccak256Hash(address.Bytes()) owner := crypto.Keccak256Hash(address.Bytes())
handler, err := cv.versionDB.OpenTree(cv.state, version, owner, root) handler, err := cv.versionDB.OpenTree(cv.state, version, owner, root)
if err != nil { if err != nil {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnError(fmt.Errorf("failed to open storage trie, version: %d,stateRoot:%s, address:%s, root: %s, error: %s", // cv.debug.OnError(fmt.Errorf("failed to open storage trie, version: %d,stateRoot:%s, address:%s, root: %s, error: %s",
version, stateRoot.String(), address.String(), root.String(), err.Error())) // version, stateRoot.String(), address.String(), root.String(), err.Error()))
} //}
return nil, err return nil, err
} }
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnOpenTree(handler, owner, address) // cv.debug.OnOpenTree(handler, owner, address)
} //}
tree := &VersaTree{ tree := &VersaTree{
db: cv.versionDB, db: cv.versionDB,
handler: handler, handler: handler,
@@ -198,7 +198,7 @@ func (cv *cachingVersaDB) openStorageTreeWithVersion(version int64, stateRoot co
stateRoot: root, stateRoot: root,
address: address, address: address,
mode: cv.mode, mode: cv.mode,
debug: cv.debug, //debug: cv.debug,
} }
return tree, nil return tree, nil
} }
@@ -206,17 +206,17 @@ func (cv *cachingVersaDB) openStorageTreeWithVersion(version int64, stateRoot co
// Flush unique to versa // Flush unique to versa
func (cv *cachingVersaDB) Flush() error { func (cv *cachingVersaDB) Flush() error {
err := cv.versionDB.Flush(cv.state) err := cv.versionDB.Flush(cv.state)
if err != nil && cv.debug != nil { //if err != nil && cv.debug != nil {
cv.debug.OnError(fmt.Errorf("failed to flush state, version: %d, root:%s, mode:%d, error: %s", // cv.debug.OnError(fmt.Errorf("failed to flush state, version: %d, root:%s, mode:%d, error: %s",
cv.accTree.version, cv.accTree.root.String(), cv.accTree.mode, err.Error())) // cv.accTree.version, cv.accTree.root.String(), cv.accTree.mode, err.Error()))
} //}
return err return err
} }
func (cv *cachingVersaDB) SetVersion(version int64) { func (cv *cachingVersaDB) SetVersion(version int64) {
cv.version = version - 1 cv.version = version - 1
cv.debug = NewDebugVersionState(cv.codeDB, cv.versionDB) //cv.debug = NewDebugVersionState(cv.codeDB, cv.versionDB)
cv.debug.Version = version //cv.debug.Version = version
} }
func (cv *cachingVersaDB) GetVersion() int64 { func (cv *cachingVersaDB) GetVersion() int64 {
@@ -227,21 +227,21 @@ func (cv *cachingVersaDB) GetVersion() int64 {
func (cv *cachingVersaDB) Release() error { func (cv *cachingVersaDB) Release() error {
//log.Info("close state", "state info", cv.versionDB.ParseStateHandler(cv.state)) //log.Info("close state", "state info", cv.versionDB.ParseStateHandler(cv.state))
if cv.state != versa.ErrStateHandler { if cv.state != versa.ErrStateHandler {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnCloseState(cv.state) // cv.debug.OnCloseState(cv.state)
} //}
if err := cv.versionDB.CloseState(cv.state); err != nil { if err := cv.versionDB.CloseState(cv.state); err != nil {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnError(fmt.Errorf("failed to close state in release, version: %d, root:%s, mode:%d, error: %s", // cv.debug.OnError(fmt.Errorf("failed to close state in release, version: %d, root:%s, mode:%d, error: %s",
cv.accTree.version, cv.accTree.root.String(), cv.accTree.mode, err.Error())) // cv.accTree.version, cv.accTree.root.String(), cv.accTree.mode, err.Error()))
} //}
return err return err
} }
cv.hasState.Store(false) cv.hasState.Store(false)
cv.accTree = nil cv.accTree = nil
cv.state = versa.ErrStateHandler cv.state = versa.ErrStateHandler
cv.root = common.Hash{} cv.root = common.Hash{}
cv.debug = nil //cv.debug = nil
} }
return nil return nil
} }
@@ -270,9 +270,9 @@ func (cv *cachingVersaDB) Scheme() string {
} }
func (cv *cachingVersaDB) ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) { func (cv *cachingVersaDB) ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) {
if cv.debug != nil { //if cv.debug != nil {
cv.debug.OnGetCode(addr, codeHash) // cv.debug.OnGetCode(addr, codeHash)
} //}
code, _ := cv.codeCache.Get(codeHash) code, _ := cv.codeCache.Get(codeHash)
if len(code) > 0 { if len(code) > 0 {
return code, nil return code, nil
@@ -326,7 +326,7 @@ type VersaTree struct {
handler versa.TreeHandler handler versa.TreeHandler
version int64 version int64
accountTree bool accountTree bool
debug *DebugVersionState //debug *DebugVersionState
// TODO:: debugging, used for logging // TODO:: debugging, used for logging
stateRoot common.Hash stateRoot common.Hash
@@ -352,23 +352,23 @@ func (vt *VersaTree) getAccountWithVersion(address common.Address) (int64, *type
vt.CheckAccountTree() vt.CheckAccountTree()
ver, res, err := vt.db.Get(vt.handler, address.Bytes()) ver, res, err := vt.db.Get(vt.handler, address.Bytes())
if res == nil || err != nil { if res == nil || err != nil {
if err != nil && vt.debug != nil { //if err != nil && vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to get account, root: %s, address: %s, error: %s", // vt.debug.OnError(fmt.Errorf("failed to get account, root: %s, address: %s, error: %s",
vt.root.String(), address.String(), err.Error())) // vt.root.String(), address.String(), err.Error()))
} //}
return ver, nil, err return ver, nil, err
} }
ret := new(types.StateAccount) ret := new(types.StateAccount)
err = rlp.DecodeBytes(res, ret) err = rlp.DecodeBytes(res, ret)
if err != nil { if err != nil {
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to rlp decode account, root: %s, address: %s, error: %s", // vt.debug.OnError(fmt.Errorf("failed to rlp decode account, root: %s, address: %s, error: %s",
vt.root.String(), address.String(), err.Error())) // vt.root.String(), address.String(), err.Error()))
} //}
}
if vt.debug != nil {
vt.debug.OnGetAccount(address, ret)
} }
//if vt.debug != nil {
// vt.debug.OnGetAccount(address, ret)
//}
return ver, ret, err return ver, ret, err
} }
@@ -379,22 +379,22 @@ func (vt *VersaTree) GetStorage(address common.Address, key []byte) ([]byte, err
vt.CheckStorageTree() vt.CheckStorageTree()
_, enc, err := vt.db.Get(vt.handler, key) _, enc, err := vt.db.Get(vt.handler, key)
if err != nil || len(enc) == 0 { if err != nil || len(enc) == 0 {
if err != nil && vt.debug != nil { //if err != nil && vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to get storage, root: %s, stateRoot: %s, address:%s, key: %s, error: %s", // vt.debug.OnError(fmt.Errorf("failed to get storage, root: %s, stateRoot: %s, address:%s, key: %s, error: %s",
vt.root.String(), vt.stateRoot.String(), address.String(), common.Bytes2Hex(key), err.Error())) // vt.root.String(), vt.stateRoot.String(), address.String(), common.Bytes2Hex(key), err.Error()))
} //}
return nil, err return nil, err
} }
_, content, _, err := rlp.Split(enc) _, content, _, err := rlp.Split(enc)
if err != nil { if err != nil {
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to rlp decode storage, root: %s, stateRoot: %s, address: %s, key: %s,error: %s", // vt.debug.OnError(fmt.Errorf("failed to rlp decode storage, root: %s, stateRoot: %s, address: %s, key: %s,error: %s",
vt.root.String(), vt.stateRoot.String(), address.String(), common.Bytes2Hex(key), err.Error())) // vt.root.String(), vt.stateRoot.String(), address.String(), common.Bytes2Hex(key), err.Error()))
} //}
}
if vt.debug != nil {
vt.debug.OnGetStorage(vt.handler, address, key, content)
} }
//if vt.debug != nil {
// vt.debug.OnGetStorage(vt.handler, address, key, content)
//}
return content, err return content, err
} }
@@ -402,15 +402,15 @@ func (vt *VersaTree) UpdateAccount(address common.Address, account *types.StateA
vt.CheckAccountTree() vt.CheckAccountTree()
data, err := rlp.EncodeToBytes(account) data, err := rlp.EncodeToBytes(account)
if err != nil { if err != nil {
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to update account, root: %s, address: %s, account: %s, error: %s", // vt.debug.OnError(fmt.Errorf("failed to update account, root: %s, address: %s, account: %s, error: %s",
vt.root.String(), address.String(), account.String(), err.Error())) // vt.root.String(), address.String(), account.String(), err.Error()))
} //}
return err return err
} }
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnUpdateAccount(address, account) // vt.debug.OnUpdateAccount(address, account)
} //}
return vt.db.Put(vt.handler, address.Bytes(), data) return vt.db.Put(vt.handler, address.Bytes(), data)
} }
@@ -422,14 +422,14 @@ func (vt *VersaTree) UpdateStorage(address common.Address, key, value []byte) er
v, _ := rlp.EncodeToBytes(value) v, _ := rlp.EncodeToBytes(value)
err := vt.db.Put(vt.handler, key, v) err := vt.db.Put(vt.handler, key, v)
if err != nil { if err != nil {
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to update storage, root: %s, stateRoot: %s, address: %s, key: %s, val: %s, error: %s", // vt.debug.OnError(fmt.Errorf("failed to update storage, root: %s, stateRoot: %s, address: %s, key: %s, val: %s, error: %s",
vt.root.String(), vt.stateRoot.String(), address.String(), common.Bytes2Hex(key), common.Bytes2Hex(value), err.Error())) // vt.root.String(), vt.stateRoot.String(), address.String(), common.Bytes2Hex(key), common.Bytes2Hex(value), err.Error()))
} //}
}
if vt.debug != nil {
vt.debug.OnUpdateStorage(vt.handler, address, key, value)
} }
//if vt.debug != nil {
// vt.debug.OnUpdateStorage(vt.handler, address, key, value)
//}
return err return err
} }
@@ -437,14 +437,14 @@ func (vt *VersaTree) DeleteAccount(address common.Address) error {
vt.CheckAccountTree() vt.CheckAccountTree()
err := vt.db.Delete(vt.handler, address.Bytes()) err := vt.db.Delete(vt.handler, address.Bytes())
if err != nil { if err != nil {
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to delete account, root: %s, address: %s, error: %s", // vt.debug.OnError(fmt.Errorf("failed to delete account, root: %s, address: %s, error: %s",
vt.root.String(), address.String(), err.Error())) // vt.root.String(), address.String(), err.Error()))
} //}
}
if vt.debug != nil {
vt.debug.OnDeleteAccount(address)
} }
//if vt.debug != nil {
// vt.debug.OnDeleteAccount(address)
//}
return err return err
} }
@@ -452,14 +452,14 @@ func (vt *VersaTree) DeleteStorage(address common.Address, key []byte) error {
vt.CheckStorageTree() vt.CheckStorageTree()
err := vt.db.Delete(vt.handler, key) err := vt.db.Delete(vt.handler, key)
if err != nil { if err != nil {
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to delete storage, root: %s, stateRoot: %s, address: %s, key: %s, error: %s", // vt.debug.OnError(fmt.Errorf("failed to delete storage, root: %s, stateRoot: %s, address: %s, key: %s, error: %s",
vt.root.String(), vt.stateRoot.String(), address.String(), common.Bytes2Hex(key), err.Error())) // vt.root.String(), vt.stateRoot.String(), address.String(), common.Bytes2Hex(key), err.Error()))
} //}
}
if vt.debug != nil {
vt.debug.OnDeleteStorage(vt.handler, address, key)
} }
//if vt.debug != nil {
// vt.debug.OnDeleteStorage(vt.handler, address, key)
//}
return err return err
} }
@@ -470,29 +470,29 @@ func (vt *VersaTree) UpdateContractCode(address common.Address, codeHash common.
func (vt *VersaTree) Hash() common.Hash { func (vt *VersaTree) Hash() common.Hash {
hash, err := vt.db.CalcRootHash(vt.handler) hash, err := vt.db.CalcRootHash(vt.handler)
if err != nil { if err != nil {
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to calc root, root: %s, stateRoot%s, error:%s", // vt.debug.OnError(fmt.Errorf("failed to calc root, root: %s, stateRoot%s, error:%s",
vt.root.String(), vt.stateRoot.String(), err.Error())) // vt.root.String(), vt.stateRoot.String(), err.Error()))
} //}
}
if vt.debug != nil {
vt.debug.OnCalcHash(vt.address, hash)
} }
//if vt.debug != nil {
// vt.debug.OnCalcHash(vt.address, hash)
//}
return hash return hash
} }
func (vt *VersaTree) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) { func (vt *VersaTree) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) {
hash, err := vt.db.Commit(vt.handler) hash, err := vt.db.Commit(vt.handler)
if err != nil { if err != nil {
if vt.debug != nil { //if vt.debug != nil {
vt.debug.OnError(fmt.Errorf("failed to commit versa tree, root: %s, stateRoot: %s, error: %s", // vt.debug.OnError(fmt.Errorf("failed to commit versa tree, root: %s, stateRoot: %s, error: %s",
vt.root.String(), vt.stateRoot.String(), err.Error())) // vt.root.String(), vt.stateRoot.String(), err.Error()))
} //}
}
if vt.debug != nil {
vt.debug.OnCalcHash(vt.address, hash)
vt.debug.OnCommitTree(vt.address, vt.handler)
} }
//if vt.debug != nil {
// vt.debug.OnCalcHash(vt.address, hash)
// vt.debug.OnCommitTree(vt.address, vt.handler)
//}
return hash, nil, err return hash, nil, err
} }

View File

@@ -227,7 +227,7 @@ type cachingDB struct {
triedb *triedb.Database triedb *triedb.Database
noTries bool noTries bool
debug *DebugHashState //debug *DebugHashState
} }
// OpenTrie opens the main account trie at a specific root hash. // OpenTrie opens the main account trie at a specific root hash.
@@ -240,22 +240,23 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
} }
tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb) tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
if err != nil { if err != nil {
if db.debug != nil { //if db.debug != nil {
db.debug.OnError(fmt.Errorf("failed to open tree, root: %s, error: %s", root.String(), err.Error())) // db.debug.OnError(fmt.Errorf("failed to open tree, root: %s, error: %s", root.String(), err.Error()))
} //}
return nil, err return nil, err
} }
ht := &HashTrie{ //ht := &HashTrie{
trie: tr, // trie: tr,
root: root, // root: root,
address: common.Address{}, // address: common.Address{},
owner: common.Hash{}, // owner: common.Hash{},
debug: db.debug, // debug: db.debug,
} //}
if db.debug != nil { //if db.debug != nil {
db.debug.OnOpenTree(root, common.Hash{}, common.Address{}) // db.debug.OnOpenTree(root, common.Hash{}, common.Address{})
} //}
return ht, nil //return ht, nil
return tr, nil
} }
// OpenStorageTrie opens the storage trie of an account. // OpenStorageTrie opens the storage trie of an account.
@@ -273,24 +274,25 @@ func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre
owner := crypto.Keccak256Hash(address.Bytes()) owner := crypto.Keccak256Hash(address.Bytes())
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, owner, root), db.triedb) tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, owner, root), db.triedb)
if err != nil { if err != nil {
if db.debug != nil { //if db.debug != nil {
db.debug.OnError(fmt.Errorf("failed to storage open tree, stateRoot: %s, address: %s, root: %s, error: %s", // db.debug.OnError(fmt.Errorf("failed to storage open tree, stateRoot: %s, address: %s, root: %s, error: %s",
stateRoot.String(), address.String(), root.String(), err.Error())) // stateRoot.String(), address.String(), root.String(), err.Error()))
} //}
return nil, err return nil, err
} }
ht := &HashTrie{ //ht := &HashTrie{
trie: tr, // trie: tr,
root: stateRoot, // root: stateRoot,
statRoot: root, // statRoot: root,
address: address, // address: address,
owner: owner, // owner: owner,
debug: db.debug, // debug: db.debug,
} //}
if db.debug != nil { //if db.debug != nil {
db.debug.OnOpenTree(root, owner, address) // db.debug.OnOpenTree(root, owner, address)
} //}
return ht, nil //return ht, nil
return tr, nil
} }
func (db *cachingDB) NoTries() bool { func (db *cachingDB) NoTries() bool {
@@ -307,8 +309,8 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
return t.Copy() return t.Copy()
case *trie.EmptyTrie: case *trie.EmptyTrie:
return t.Copy() return t.Copy()
case *HashTrie: //case *HashTrie:
return db.CopyTrie(t.trie) // return db.CopyTrie(t.trie)
default: default:
panic(fmt.Errorf("unknown trie type %T", t)) panic(fmt.Errorf("unknown trie type %T", t))
} }
@@ -316,9 +318,9 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
// ContractCode retrieves a particular contract's code. // ContractCode retrieves a particular contract's code.
func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) { func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) {
if db.debug != nil { //if db.debug != nil {
db.debug.OnGetCode(address, codeHash) // db.debug.OnGetCode(address, codeHash)
} //}
code, _ := db.codeCache.Get(codeHash) code, _ := db.codeCache.Get(codeHash)
if len(code) > 0 { if len(code) > 0 {
return code, nil return code, nil
@@ -381,18 +383,19 @@ func (db *cachingDB) Flush() error {
} }
func (db *cachingDB) Release() error { func (db *cachingDB) Release() error {
db.debug.flush() //db.debug.flush()
db.debug = nil //db.debug = nil
return nil return nil
} }
func (db *cachingDB) SetVersion(version int64) { func (db *cachingDB) SetVersion(version int64) {
db.debug = NewDebugHashState(db.disk) //db.debug = NewDebugHashState(db.disk)
db.debug.Version = version //db.debug.Version = version
} }
func (db *cachingDB) GetVersion() int64 { func (db *cachingDB) GetVersion() int64 {
return db.debug.Version //return db.debug.Version
return 0
} }
func (db *cachingDB) Copy() Database { func (db *cachingDB) Copy() Database {
@@ -408,137 +411,137 @@ func (db *cachingDB) HasTreeExpired(_ Trie) bool {
return false return false
} }
type HashTrie struct { //type HashTrie struct {
trie Trie // trie Trie
root common.Hash // root common.Hash
statRoot common.Hash // statRoot common.Hash
address common.Address // address common.Address
owner common.Hash // owner common.Hash
//
debug *DebugHashState // debug *DebugHashState
} //}
//
func (ht *HashTrie) GetKey(key []byte) []byte { //func (ht *HashTrie) GetKey(key []byte) []byte {
return ht.trie.GetKey(key) // return ht.trie.GetKey(key)
} //}
//
func (ht *HashTrie) GetAccount(address common.Address) (*types.StateAccount, error) { //func (ht *HashTrie) GetAccount(address common.Address) (*types.StateAccount, error) {
acc, err := ht.trie.GetAccount(address) // acc, err := ht.trie.GetAccount(address)
if err != nil { // if err != nil {
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnError(fmt.Errorf("failed to get account, address: %s, error: %s", address.String(), err.Error())) // ht.debug.OnError(fmt.Errorf("failed to get account, address: %s, error: %s", address.String(), err.Error()))
} // }
return nil, err // return nil, err
} // }
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnGetAccount(address, acc) // ht.debug.OnGetAccount(address, acc)
} // }
return acc, nil // return acc, nil
} //}
//
func (ht *HashTrie) GetStorage(addr common.Address, key []byte) ([]byte, error) { //func (ht *HashTrie) GetStorage(addr common.Address, key []byte) ([]byte, error) {
val, err := ht.trie.GetStorage(addr, key) // val, err := ht.trie.GetStorage(addr, key)
if err != nil { // if err != nil {
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnError(fmt.Errorf("failed to get storage, address: %s, error: %s", addr.String(), err.Error())) // ht.debug.OnError(fmt.Errorf("failed to get storage, address: %s, error: %s", addr.String(), err.Error()))
} // }
return val, err // return val, err
} // }
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnGetStorage(addr, key, val) // ht.debug.OnGetStorage(addr, key, val)
} // }
return val, err // return val, err
} //}
//
func (ht *HashTrie) UpdateAccount(address common.Address, account *types.StateAccount) error { //func (ht *HashTrie) UpdateAccount(address common.Address, account *types.StateAccount) error {
err := ht.trie.UpdateAccount(address, account) // err := ht.trie.UpdateAccount(address, account)
if err != nil { // if err != nil {
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnError(fmt.Errorf("failed to update account, address: %s, account: %s, error: %s", // ht.debug.OnError(fmt.Errorf("failed to update account, address: %s, account: %s, error: %s",
address.String(), account.String(), err.Error())) // address.String(), account.String(), err.Error()))
} // }
return err // return err
} // }
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnUpdateAccount(address, account) // ht.debug.OnUpdateAccount(address, account)
} // }
return nil // return nil
} //}
//
func (ht *HashTrie) UpdateStorage(addr common.Address, key, value []byte) error { //func (ht *HashTrie) UpdateStorage(addr common.Address, key, value []byte) error {
err := ht.trie.UpdateStorage(addr, key, value) // err := ht.trie.UpdateStorage(addr, key, value)
if err != nil { // if err != nil {
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnError(fmt.Errorf("failed to update storage, address: %s, key: %s, val: %s, error: %s", // ht.debug.OnError(fmt.Errorf("failed to update storage, address: %s, key: %s, val: %s, error: %s",
addr.String(), common.Bytes2Hex(key), common.Bytes2Hex(value), err.Error())) // addr.String(), common.Bytes2Hex(key), common.Bytes2Hex(value), err.Error()))
} // }
return err // return err
} // }
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnUpdateStorage(addr, key, value) // ht.debug.OnUpdateStorage(addr, key, value)
} // }
return nil // return nil
} //}
//
func (ht *HashTrie) DeleteAccount(address common.Address) error { //func (ht *HashTrie) DeleteAccount(address common.Address) error {
err := ht.trie.DeleteAccount(address) // err := ht.trie.DeleteAccount(address)
if err != nil { // if err != nil {
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnError(fmt.Errorf("failed to delete account, address: %s, error: %s", address.String(), err.Error())) // ht.debug.OnError(fmt.Errorf("failed to delete account, address: %s, error: %s", address.String(), err.Error()))
} // }
return err // return err
} // }
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnDeleteAccount(address) // ht.debug.OnDeleteAccount(address)
} // }
return nil // return nil
} //}
//
func (ht *HashTrie) DeleteStorage(addr common.Address, key []byte) error { //func (ht *HashTrie) DeleteStorage(addr common.Address, key []byte) error {
err := ht.trie.DeleteStorage(addr, key) // err := ht.trie.DeleteStorage(addr, key)
if err != nil { // if err != nil {
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnError(fmt.Errorf("failed to update storage, address: %s, key: %s, error: %s", // ht.debug.OnError(fmt.Errorf("failed to update storage, address: %s, key: %s, error: %s",
addr.String(), common.Bytes2Hex(key), err.Error())) // addr.String(), common.Bytes2Hex(key), err.Error()))
} // }
return err // return err
} // }
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnDeleteStorage(addr, key) // ht.debug.OnDeleteStorage(addr, key)
} // }
return nil // return nil
} //}
//
func (ht *HashTrie) UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error { //func (ht *HashTrie) UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error {
return ht.trie.UpdateContractCode(address, codeHash, code) // return ht.trie.UpdateContractCode(address, codeHash, code)
} //}
//
func (ht *HashTrie) Hash() common.Hash { //func (ht *HashTrie) Hash() common.Hash {
root := ht.trie.Hash() // root := ht.trie.Hash()
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnCalcHash(ht.address, root) // ht.debug.OnCalcHash(ht.address, root)
} // }
return root // return root
} //}
//
func (ht *HashTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) { //func (ht *HashTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
hash, set, err := ht.trie.Commit(collectLeaf) // hash, set, err := ht.trie.Commit(collectLeaf)
if err != nil { // if err != nil {
ht.debug.OnError(fmt.Errorf("failed to commit tree, address: %s, error: %s", // ht.debug.OnError(fmt.Errorf("failed to commit tree, address: %s, error: %s",
ht.address.String(), err.Error())) // ht.address.String(), err.Error()))
return hash, set, err // return hash, set, err
} // }
if ht.debug != nil { // if ht.debug != nil {
ht.debug.OnCalcHash(ht.address, hash) // ht.debug.OnCalcHash(ht.address, hash)
ht.debug.OnCommitTree(ht.address, hash) // ht.debug.OnCommitTree(ht.address, hash)
} // }
return hash, set, nil // return hash, set, nil
} //}
//
func (ht *HashTrie) NodeIterator(startKey []byte) (trie.NodeIterator, error) { //func (ht *HashTrie) NodeIterator(startKey []byte) (trie.NodeIterator, error) {
return ht.trie.NodeIterator(startKey) // return ht.trie.NodeIterator(startKey)
} //}
//
func (ht *HashTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error { //func (ht *HashTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
return ht.trie.Prove(key, proofDb) // return ht.trie.Prove(key, proofDb)
} //}

View File

@@ -1713,18 +1713,18 @@ func (s *StateDB) Commit(block uint64, failPostCommitFunc func(), postCommitFunc
// Write any contract code associated with the state object // Write any contract code associated with the state object
if obj.code != nil && obj.dirtyCode { if obj.code != nil && obj.dirtyCode {
rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code) rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
switch d := s.db.(type) { //switch d := s.db.(type) {
case *cachingVersaDB: //case *cachingVersaDB:
if d.debug != nil { // if d.debug != nil {
d.debug.OnUpdateCode(obj.address, common.BytesToHash(obj.CodeHash())) // d.debug.OnUpdateCode(obj.address, common.BytesToHash(obj.CodeHash()))
} // }
case *cachingDB: //case *cachingDB:
if d.debug != nil { // if d.debug != nil {
d.debug.OnUpdateCode(obj.address, common.BytesToHash(obj.CodeHash())) // d.debug.OnUpdateCode(obj.address, common.BytesToHash(obj.CodeHash()))
} // }
default: //default:
panic("caching db type error") // panic("caching db type error")
} //}
obj.dirtyCode = false obj.dirtyCode = false
if s.snap != nil { if s.snap != nil {
panic("snapshot is not nil") panic("snapshot is not nil")

View File

@@ -191,6 +191,8 @@ func peerToSyncOp(mode downloader.SyncMode, p *eth.Peer) *chainSyncOp {
} }
func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) { func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
head := cs.handler.chain.CurrentBlock()
if cs.handler.chain.TrieDB().Scheme() != rawdb.VersionScheme {
// If we're in snap sync mode, return that directly // If we're in snap sync mode, return that directly
if cs.handler.snapSync.Load() { if cs.handler.snapSync.Load() {
block := cs.handler.chain.CurrentSnapBlock() block := cs.handler.chain.CurrentSnapBlock()
@@ -199,7 +201,7 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
} }
// We are probably in full sync, but we might have rewound to before the // We are probably in full sync, but we might have rewound to before the
// snap sync pivot, check if we should re-enable snap sync. // snap sync pivot, check if we should re-enable snap sync.
head := cs.handler.chain.CurrentBlock() head = cs.handler.chain.CurrentBlock()
if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil { if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil {
if head.Number.Uint64() < *pivot { if head.Number.Uint64() < *pivot {
if rawdb.ReadAncientType(cs.handler.database) == rawdb.PruneFreezerType { if rawdb.ReadAncientType(cs.handler.database) == rawdb.PruneFreezerType {
@@ -219,6 +221,11 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
log.Info("Reenabled snap sync as chain is stateless") log.Info("Reenabled snap sync as chain is stateless")
return downloader.SnapSync, td return downloader.SnapSync, td
} }
} else {
if !cs.handler.chain.HasState(head.Root) {
panic("version db not support snap sync")
}
}
// Nope, we're really full syncing // Nope, we're really full syncing
td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64()) td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64())
return downloader.FullSync, td return downloader.FullSync, td

View File

@@ -49,7 +49,8 @@ func (v *VersionDB) Scheme() string {
} }
func (v *VersionDB) Initialized(genesisRoot common.Hash) bool { func (v *VersionDB) Initialized(genesisRoot common.Hash) bool {
return v.db.HasState(genesisRoot) version, _ := v.db.LatestStoreDiskVersionInfo()
return version >= 0
} }
func (v *VersionDB) Size() (common.StorageSize, common.StorageSize, common.StorageSize) { func (v *VersionDB) Size() (common.StorageSize, common.StorageSize, common.StorageSize) {