Compare commits

..

93 Commits

Author SHA1 Message Date
joeycli
facbe6a886 chore: add mgasps metrics 2024-08-29 20:35:58 +08:00
joeycli
84da730eed chore: add pprof service 2024-08-29 20:35:36 +08:00
joeycli
85a6b17ab0 chore: add reopen same tree error debug info 2024-08-22 15:05:42 +08:00
joeycli
8db789b2c0 fix: update trie error 2024-08-22 14:14:29 +08:00
joeycli
36044b05f3 chore: add open state version 2024-08-21 16:39:28 +08:00
joeycli
d5e38ad81e chore: adjust log confidition 2024-08-21 14:23:51 +08:00
joeycli
d5a438a06d chore: add diff and disk version log 2024-08-20 18:02:45 +08:00
Fynn
b585984e32 fix: remove enable hash check 2024-08-20 11:23:26 +08:00
joeycli
a1d4b06707 feat: check ca changeable 2024-08-20 09:01:18 +08:00
joeycli
ea76d5f359 chore: add debug inof for get trie version mismatch error 2024-08-20 08:24:57 +08:00
joeycli
b8fa4761b8 fix: get ca trie 2024-08-20 08:02:58 +08:00
joeycli
3ad7c4e63b fix: panic for updating code 2024-08-20 07:44:17 +08:00
joeycli
74ab9ab248 fix: changte the confidition for open storage tree 2024-08-20 07:38:00 +08:00
joeycli
9c239db9d9 fix: compare func 2024-08-19 16:52:42 +08:00
joeycli
d3854b41ec fix: compare funx 2024-08-19 16:51:13 +08:00
joeycli
30b371daf2 chore: compatable empty hash 2024-08-19 16:45:22 +08:00
joeycli
4764fdb47f fix: the timing release debug state instance 2024-08-19 16:23:01 +08:00
joeycli
fa7a43a2df fix: add calc hash point 2024-08-19 16:14:14 +08:00
joeycli
1a40f79ade fix: set path mode breakpoint 2024-08-19 16:08:56 +08:00
joeycli
3ad4700907 fix: diff debug state error 2024-08-19 16:04:41 +08:00
joeycli
f724941948 fix: add protection for debug hash state 2024-08-19 15:33:06 +08:00
joeycli
ef3f9dfaa7 fix: repeated cmd error 2024-08-19 15:11:27 +08:00
joeycli
aa9d5182c1 fix: panic bug 2024-08-19 15:05:55 +08:00
joeycli
a0daf107f9 fix: genesis init panic 2024-08-19 14:58:54 +08:00
joeycli
55cdcfaff3 fix: repeat cmd error 2024-08-19 14:52:06 +08:00
joeycli
7d5e6ce2d7 feat: add version and hash state diff system 2024-08-19 14:08:40 +08:00
joeycli
1cbdf0a4c9 feat: add hash state db debug system 2024-08-19 12:55:24 +08:00
joeycli
997d7b5bba chore: delete debug log 2024-08-18 16:50:32 +08:00
joeycli
90aa2e137c fix: change pebble to default db 2024-08-18 16:45:25 +08:00
joeycli
e940e28f6c fix: access nil pointer 2024-08-18 16:39:25 +08:00
joeycli
23c60a38a4 feat: add version state debug system 2024-08-18 16:21:06 +08:00
joeycli
f67f494346 chore: add 373559 debug breakpoint 2024-08-16 22:28:44 +08:00
joeycli
84767d1957 chore: add update storage debug info 2024-08-16 21:17:28 +08:00
joeycli
bf808915f0 chore: add update storage debug info 2024-08-16 21:10:46 +08:00
joeycli
b80d78701a chore: add update storage debug info 2024-08-16 21:04:43 +08:00
joeycli
3c4b452ee2 fix: chang condition for ca 2024-08-16 20:45:37 +08:00
joeycli
8197064e91 fix: chang condition for ca 2024-08-16 20:30:18 +08:00
joeycli
90de1d7ff8 fix: version mismatch that add contract balance without update storage tree 2024-08-16 20:16:01 +08:00
joeycli
77dea68afd chore: add detete key debug log 2024-08-16 16:51:10 +08:00
joeycli
9d20658f8d chore: debug 24611 2024-08-16 14:59:57 +08:00
joeycli
dc510033c0 feat: return version for repeat search account tree 2024-08-16 14:43:23 +08:00
joeycli
7bce07abdf chore: adjust state reset 2024-08-16 14:08:55 +08:00
joeycli
2e4ec39e52 chore: add owner and hash log 2024-08-15 17:26:40 +08:00
joeycli
0a901183b9 chore: delete part log 2024-08-15 16:53:16 +08:00
joeycli
2e38d0662c chore: change panic to log error 2024-08-15 16:09:37 +08:00
joeycli
ac2d1a8ada chore: add versa db error log 2024-08-15 15:46:22 +08:00
joeycli
c6d8d6355d fix: get code error 2024-08-15 15:13:21 +08:00
joeycli
7462078caa chore: add system tx log 2024-08-15 14:47:54 +08:00
joeycli
cf04af0cc1 chore: add tx execute log 2024-08-15 14:25:34 +08:00
joeycli
dec27d1b52 fix: add address check for get versa tree 2024-08-15 12:06:24 +08:00
joeycli
bbef39738d chore:add tree get debug info 2024-08-15 09:54:18 +08:00
joeycli
6dfcbc6519 fix lint error 2024-08-14 17:10:35 +08:00
joeycli
42b72feed1 chore: add debug state after tx execute 2024-08-14 16:49:02 +08:00
joeycli
8d7ee3aeb6 chore: add parse state obj 2024-08-14 16:32:58 +08:00
joeycli
a3f8c707e6 chore: fix build error 2024-08-14 16:05:21 +08:00
joeycli
bd9c2ae465 chore: add tx hash log 2024-08-14 16:03:14 +08:00
joeycli
023b092e95 chore: delete storage pool 2024-08-14 15:35:04 +08:00
joeycli
0941eb6ccf chore: panic for snap 2024-08-14 15:21:05 +08:00
joeycli
b73a98cd65 chore: forbid prefetcher 2024-08-14 15:02:20 +08:00
joeycli
26d7f62caa chore: forbid prefetcher 2024-08-14 15:00:33 +08:00
joeycli
be0a305251 chore: add delete obj debug info 2024-08-14 14:46:51 +08:00
joeycli
bfe07c5a83 chore: adjust state obj debug info 2024-08-14 14:33:31 +08:00
joeycli
412c5ee791 chore: add state obj debug info 2024-08-14 12:03:27 +08:00
joeycli
3a70b35ea2 chore: dadd debug log for tx diff 2024-08-14 11:10:51 +08:00
joeycli
f284358f8f chore: delete redundant code 2024-08-14 09:32:57 +08:00
joeycli
5b4e00c905 fix: decode storage val 2024-08-13 20:35:17 +08:00
joeycli
c572535693 chore: add reset panic 2024-08-13 20:25:33 +08:00
joeycli
324e4a4af7 chore: add panic log 2024-08-13 20:07:17 +08:00
joeycli
58dabc990e chore: add apply tx debug log 2024-08-13 20:03:20 +08:00
joeycli
2f0f91dbf8 chore: delete debug log 2024-08-13 18:21:32 +08:00
joeycli
657eced3b7 chore: delete panic code 2024-08-13 18:02:33 +08:00
joeycli
f69ff95e77 fix: blockchain stateat use rw state 2024-08-13 17:54:37 +08:00
joeycli
04e5c1732c chore: add debug panic 2024-08-13 17:36:18 +08:00
joeycli
ec2384aca4 fix: change check from tree root to tree handler 2024-08-13 17:06:23 +08:00
joeycli
83287cec5c chore: add debug log 2024-08-13 16:22:41 +08:00
joeycli
d162a63438 chore: change panic to log 2024-08-13 15:35:02 +08:00
joeycli
b00582cb8a chore: add state info debug log 2024-08-13 15:10:16 +08:00
joeycli
d8c3726154 fix: state object trie expire 2024-08-13 14:26:36 +08:00
joeycli
e8309adedc chore: delete debug print code 2024-08-13 11:05:17 +08:00
joeycli
ed7aa3e3b9 fix: storage tree value encode 2024-08-13 10:57:42 +08:00
joeycli
6188aaec48 chore: add debug print statedb 2024-08-13 10:20:08 +08:00
joeycli
60df2fa712 fix: open strorage trie param error 2024-08-13 08:53:12 +08:00
joeycli
bb167a9af6 chore: add stack debug 2024-08-12 19:35:26 +08:00
joeycli
66bd59013f chore: delete debug code and add log 2024-08-12 18:20:27 +08:00
joeycli
6b7c807e86 chore: add debug code 2024-08-12 18:15:32 +08:00
joeycli
3a34c737dc feat: support has state on statedb and must fullsync under version 2024-08-12 17:58:22 +08:00
joeycli
4635a457c1 feat: add caching db and trie copy 2024-08-12 17:30:21 +08:00
joeycli
e1a2b8e8d6 feat: init genesis 2024-08-12 16:00:06 +08:00
joeycli
6cf5169ce1 feat: add version scheme for startup 2024-08-12 11:46:32 +08:00
joeycli
7f3aac35e4 feat: add mode for new caching db 2024-08-12 11:07:45 +08:00
joeycli
435410f6f3 chore: forbid versiondb rewind 2024-08-12 10:50:49 +08:00
joeycli
d2e5c03965 feat: add version commit 2024-08-12 10:35:13 +08:00
joeycli
41ab497c22 feat: setup versa db 2024-08-09 17:29:47 +08:00
28 changed files with 488 additions and 725 deletions

View File

@@ -343,7 +343,7 @@ func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block
continue continue
} }
// If we're above the chain head, state availability is a must // If we're above the chain head, state availability is a must
if !chain.HasBlockAndState(block.Hash(), block.Number().Int64()) { if !chain.HasBlockAndState(block.Hash(), block.NumberU64()) {
return blocks[i:] return blocks[i:]
} }
} }

View File

@@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
@@ -41,12 +40,6 @@ func EnableRemoteVerifyManager(remoteValidator *remoteVerifyManager) BlockValida
} }
} }
var (
validateBloomTimer = metrics.NewRegisteredTimer("validate/bloom/time", nil)
validateReceiptTimer = metrics.NewRegisteredTimer("validate/receipt/time", nil)
validateRootTimer = metrics.NewRegisteredTimer("validate/root/time", nil)
)
// BlockValidator is responsible for validating block headers, uncles and // BlockValidator is responsible for validating block headers, uncles and
// processed state. // processed state.
// //
@@ -103,7 +96,7 @@ func ValidateListsInBody(block *types.Block) error {
// validated at this point. // validated at this point.
func (v *BlockValidator) ValidateBody(block *types.Block) error { func (v *BlockValidator) ValidateBody(block *types.Block) error {
// Check whether the block is already imported. // Check whether the block is already imported.
if v.bc.HasBlockAndState(block.Hash(), block.Number().Int64()) { if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
return ErrKnownBlock return ErrKnownBlock
} }
if v.bc.isCachedBadBlock(block) { if v.bc.isCachedBadBlock(block) {
@@ -149,7 +142,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
return nil return nil
}, },
func() error { func() error {
if !v.bc.HasBlockAndState(block.ParentHash(), block.Number().Int64()-1) { if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
return consensus.ErrUnknownAncestor return consensus.ErrUnknownAncestor
} }
@@ -191,10 +184,6 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
// For valid blocks this should always validate to true. // For valid blocks this should always validate to true.
validateFuns := []func() error{ validateFuns := []func() error{
func() error { func() error {
defer func(start time.Time) {
validateBloomTimer.UpdateSince(start)
}(time.Now())
rbloom := types.CreateBloom(receipts) rbloom := types.CreateBloom(receipts)
if rbloom != header.Bloom { if rbloom != header.Bloom {
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom) return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
@@ -202,9 +191,6 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
return nil return nil
}, },
func() error { func() error {
defer func(start time.Time) {
validateReceiptTimer.UpdateSince(start)
}(time.Now())
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil)) receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
if receiptSha != header.ReceiptHash { if receiptSha != header.ReceiptHash {
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha) return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
@@ -223,9 +209,6 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
}) })
} else { } else {
validateFuns = append(validateFuns, func() error { validateFuns = append(validateFuns, func() error {
defer func(start time.Time) {
validateRootTimer.UpdateSince(start)
}(time.Now())
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root { if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error()) return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error())
} }

View File

@@ -92,13 +92,10 @@ var (
triedbCommitTimer = metrics.NewRegisteredTimer("chain/triedb/commits", nil) triedbCommitTimer = metrics.NewRegisteredTimer("chain/triedb/commits", nil)
blockInsertTimer = metrics.NewRegisteredTimer("chain/inserts", nil) blockInsertTimer = metrics.NewRegisteredTimer("chain/inserts", nil)
blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil) blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil)
blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil) blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil)
blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil) blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil)
blockValidationTotalTimer = metrics.NewRegisteredTimer("chain/total/validation", nil)
blockExecutionTotalTimer = metrics.NewRegisteredTimer("chain/total/execution", nil)
blockWriteTotalTimer = metrics.NewRegisteredTimer("chain/total/write", nil)
blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil) blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil)
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil) blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
@@ -346,15 +343,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
// Open trie database with provided config // Open trie database with provided config
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig()) triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig())
if triedb.Scheme() == rawdb.VersionScheme {
vdb := triedb.VersaDB()
ver, root := vdb.LatestStoreDiskVersionInfo()
if ver == -1 {
rawdb.WriteCanonicalHash(db, common.Hash{}, 0)
}
log.Info("version db latest version info", "version", ver, "root", root.String())
}
// Setup the genesis block, commit the provided genesis specification // Setup the genesis block, commit the provided genesis specification
// to database if the genesis block is not present yet, or load the // to database if the genesis block is not present yet, or load the
// stored one from database. // stored one from database.
@@ -437,138 +425,78 @@ 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.Number.Int64(), 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 // scheme. This situation occurs when the initial state sync is not finished
// scheme. This situation occurs when the initial state sync is not finished // yet, or the chain head is rewound below the pivot point. In both scenarios,
// yet, or the chain head is rewound below the pivot point. In both scenarios, // there is no possible recovery approach except for rerunning a snap sync.
// there is no possible recovery approach except for rerunning a snap sync. // Do nothing here until the state syncer picks it up.
// Do nothing here until the state syncer picks it up. log.Info("Genesis state is missing, wait state sync")
log.Info("Genesis state is missing, wait state sync") } else {
} else { // Head state is missing, before the state recovery, find out the
// Head state is missing, before the state recovery, find out the // disk layer point of snapshot(if it's enabled). Make sure the
// disk layer point of snapshot(if it's enabled). Make sure the // rewound point is lower than disk layer.
// rewound point is lower than disk layer. var diskRoot common.Hash
var diskRoot common.Hash if bc.cacheConfig.SnapshotLimit > 0 {
if bc.cacheConfig.SnapshotLimit > 0 { diskRoot = rawdb.ReadSnapshotRoot(bc.db)
diskRoot = rawdb.ReadSnapshotRoot(bc.db) }
if bc.triedb.Scheme() == rawdb.PathScheme && !bc.NoTries() {
recoverable, _ := bc.triedb.Recoverable(diskRoot)
if !bc.HasState(diskRoot) && !recoverable {
diskRoot = bc.triedb.Head()
} }
if bc.triedb.Scheme() == rawdb.PathScheme && !bc.NoTries() { }
recoverable, _ := bc.triedb.Recoverable(diskRoot) if diskRoot != (common.Hash{}) {
if !bc.HasState(0, diskRoot) && !recoverable { log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "diskRoot", diskRoot)
diskRoot = bc.triedb.Head()
}
}
if diskRoot != (common.Hash{}) {
log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "diskRoot", diskRoot)
snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true) snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true)
if err != nil { if err != nil {
return nil, err return nil, err
}
// Chain rewound, persist old snapshot number to indicate recovery procedure
if snapDisk != 0 {
rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk)
}
} else {
log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash())
if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil {
return nil, err
}
} }
} // Chain rewound, persist old snapshot number to indicate recovery procedure
} if snapDisk != 0 {
} else { rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk)
log.Warn("versa db no recovery, rewind in load state")
}
// 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 {
frozen, err = bc.db.BlockStore().Ancients()
if err != nil {
return nil, err
}
var (
needRewind bool
low uint64
)
// The head full block may be rolled back to a very low height due to
// blockchain repair. If the head full block is even lower than the ancient
// chain, truncate the ancient store.
fullBlock := bc.CurrentBlock()
if fullBlock != nil && fullBlock.Hash() != bc.genesisBlock.Hash() && fullBlock.Number.Uint64() < frozen-1 {
needRewind = true
low = fullBlock.Number.Uint64()
}
// In snap sync, it may happen that ancient data has been written to the
// ancient store, but the LastFastBlock has not been updated, truncate the
// extra data here.
snapBlock := bc.CurrentSnapBlock()
if snapBlock != nil && snapBlock.Number.Uint64() < frozen-1 {
needRewind = true
if snapBlock.Number.Uint64() < low || low == 0 {
low = snapBlock.Number.Uint64()
} }
} } else {
if needRewind { log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash())
log.Error("Truncating ancient chain", "from", bc.CurrentHeader().Number.Uint64(), "to", low) if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil {
if err := bc.SetHead(low); err != nil {
return nil, err return nil, err
} }
} }
} }
} }
// 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 {
return nil, err
}
var (
needRewind bool
low uint64
)
// The head full block may be rolled back to a very low height due to
// blockchain repair. If the head full block is even lower than the ancient
// chain, truncate the ancient store.
fullBlock := bc.CurrentBlock()
if fullBlock != nil && fullBlock.Hash() != bc.genesisBlock.Hash() && fullBlock.Number.Uint64() < frozen-1 {
needRewind = true
low = fullBlock.Number.Uint64()
}
// In snap sync, it may happen that ancient data has been written to the
// ancient store, but the LastFastBlock has not been updated, truncate the
// extra data here.
snapBlock := bc.CurrentSnapBlock()
if snapBlock != nil && snapBlock.Number.Uint64() < frozen-1 {
needRewind = true
if snapBlock.Number.Uint64() < low || low == 0 {
low = snapBlock.Number.Uint64()
}
}
if needRewind {
log.Error("Truncating ancient chain", "from", bc.CurrentHeader().Number.Uint64(), "to", low)
if err := bc.SetHead(low); err != nil {
return nil, err
}
}
}
} 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 { if err != nil {
return nil, err return nil, err
} }
var (
needRewind bool
low uint64
)
// The head full block may be rolled back to a very low height due to
// blockchain repair. If the head full block is even lower than the ancient
// chain, truncate the ancient store.
fullBlock := bc.CurrentBlock() 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 fullBlock != nil && fullBlock.Hash() != bc.genesisBlock.Hash() && fullBlock.Number.Uint64() < frozen-1 {
if frozen >= fullBlock.Number.Uint64() { needRewind = true
if _, err = bc.db.BlockStore().TruncateTail(fullBlock.Number.Uint64()); err != nil { low = fullBlock.Number.Uint64()
}
// In snap sync, it may happen that ancient data has been written to the
// ancient store, but the LastFastBlock has not been updated, truncate the
// extra data here.
snapBlock := bc.CurrentSnapBlock()
if snapBlock != nil && snapBlock.Number.Uint64() < frozen-1 {
needRewind = true
if snapBlock.Number.Uint64() < low || low == 0 {
low = snapBlock.Number.Uint64()
}
}
if needRewind {
log.Error("Truncating ancient chain", "from", bc.CurrentHeader().Number.Uint64(), "to", low)
if err := bc.SetHead(low); err != nil {
return nil, err return nil, err
} }
} }
@@ -775,61 +703,20 @@ 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 // Restore the last known head block
var headBlock *types.Block head := rawdb.ReadHeadBlockHash(bc.db)
if bc.triedb.Scheme() == rawdb.VersionScheme { if head == (common.Hash{}) {
head := rawdb.ReadHeadBlockHash(bc.db) // Corrupt or empty database, init from scratch
headBlock = bc.GetBlockByHash(head) log.Warn("Empty database, resetting chain")
return bc.Reset()
versa := bc.triedb.VersaDB() }
archiveVersion, archiveRoot := versa.LatestStoreDiskVersionInfo() // Make sure the entire head block is available
// first start headBlock := bc.GetBlockByHash(head)
if archiveVersion == -1 { if headBlock == nil {
archiveVersion = 0 // Corrupt or empty database, init from scratch
archiveRoot = bc.genesisBlock.Root() log.Warn("Head block missing, resetting chain", "hash", head)
} return bc.Reset()
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_number", archiveVersion, "target_root", archiveRoot.String(), "head_number", headBlock.NumberU64(), "head_root", headBlock.Root().String())
for {
if int64(headBlock.NumberU64()) == archiveVersion && archiveRoot.Cmp(headBlock.Root()) == 0 {
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
} else if int64(headBlock.NumberU64()) == archiveVersion {
log.Crit("rewinding meet same number", "target_number", archiveVersion, "target_root", archiveRoot.String(), "head_number", headBlock.NumberU64(), "head_root", headBlock.Root().String())
} else if archiveRoot.Cmp(headBlock.Root()) == 0 {
log.Info("rewinding meet same root", "target_number", archiveVersion, "target_root", archiveRoot.String(), "head_number", headBlock.NumberU64(), "head_root", headBlock.Root().String())
}
log.Info("rewinding", "target_number", archiveVersion, "target_root", archiveRoot.String(), "head_number", headBlock.NumberU64(), "head_root", headBlock.Root().String())
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
head := rawdb.ReadHeadBlockHash(bc.db)
if head == (common.Hash{}) {
// Corrupt or empty database, init from scratch
log.Warn("Empty database, resetting chain")
return bc.Reset()
}
// Make sure the entire head block is available
headBlock = bc.GetBlockByHash(head)
if headBlock == nil {
// Corrupt or empty database, init from scratch
log.Warn("Head block missing, resetting chain", "hash", head)
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())
@@ -998,7 +885,7 @@ func (bc *BlockChain) rewindHashHead(head *types.Header, root common.Hash) (*typ
} }
// If the associated state is not reachable, continue searching // If the associated state is not reachable, continue searching
// backwards until an available state is found. // backwards until an available state is found.
if !bc.HasState(head.Number.Int64(), head.Root) { if !bc.HasState(head.Root) {
// If the chain is gapped in the middle, return the genesis // If the chain is gapped in the middle, return the genesis
// block as the new chain head. // block as the new chain head.
parent := bc.GetHeader(head.ParentHash, head.Number.Uint64()-1) parent := bc.GetHeader(head.ParentHash, head.Number.Uint64()-1)
@@ -1038,7 +925,7 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash) (*typ
// noState represents if the target state requested for search // noState represents if the target state requested for search
// is unavailable and impossible to be recovered. // is unavailable and impossible to be recovered.
noState = !bc.HasState(head.Number.Int64(), root) && !bc.stateRecoverable(root) noState = !bc.HasState(root) && !bc.stateRecoverable(root)
start = time.Now() // Timestamp the rewinding is restarted start = time.Now() // Timestamp the rewinding is restarted
logged = time.Now() // Timestamp last progress log was printed logged = time.Now() // Timestamp last progress log was printed
@@ -1059,13 +946,13 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash) (*typ
// If the root threshold hasn't been crossed but the available // If the root threshold hasn't been crossed but the available
// state is reached, quickly determine if the target state is // state is reached, quickly determine if the target state is
// possible to be reached or not. // possible to be reached or not.
if !beyondRoot && noState && bc.HasState(head.Number.Int64(), head.Root) { if !beyondRoot && noState && bc.HasState(head.Root) {
beyondRoot = true beyondRoot = true
log.Info("Disable the search for unattainable state", "root", root) log.Info("Disable the search for unattainable state", "root", root)
} }
// Check if the associated state is available or recoverable if // Check if the associated state is available or recoverable if
// the requested root has already been crossed. // the requested root has already been crossed.
if beyondRoot && (bc.HasState(head.Number.Int64(), head.Root) || bc.stateRecoverable(head.Root)) { if beyondRoot && (bc.HasState(head.Root) || bc.stateRecoverable(head.Root)) {
break break
} }
// If pivot block is reached, return the genesis block as the // If pivot block is reached, return the genesis block as the
@@ -1092,7 +979,7 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash) (*typ
} }
} }
// Recover if the target state if it's not available yet. // Recover if the target state if it's not available yet.
if !bc.HasState(head.Number.Int64(), head.Root) { if !bc.HasState(head.Root) {
if err := bc.triedb.Recover(head.Root); err != nil { if err := bc.triedb.Recover(head.Root); err != nil {
log.Crit("Failed to rollback state", "err", err) log.Crit("Failed to rollback state", "err", err)
} }
@@ -1187,7 +1074,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
// the pivot point. In this scenario, there is no possible recovery // the pivot point. In this scenario, there is no possible recovery
// approach except for rerunning a snap sync. Do nothing here until the // approach except for rerunning a snap sync. Do nothing here until the
// state syncer picks it up. // state syncer picks it up.
if !bc.HasState(newHeadBlock.Number.Int64(), newHeadBlock.Root) { if !bc.HasState(newHeadBlock.Root) {
if newHeadBlock.Number.Uint64() != 0 { if newHeadBlock.Number.Uint64() != 0 {
log.Crit("Chain is stateless at a non-genesis block") log.Crit("Chain is stateless at a non-genesis block")
} }
@@ -1299,7 +1186,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
return err return err
} }
} }
if !bc.NoTries() && !bc.HasState(0, root) { if !bc.NoTries() && !bc.HasState(root) {
return fmt.Errorf("non existent state [%x..]", root[:4]) return fmt.Errorf("non existent state [%x..]", root[:4])
} }
// If all checks out, manually set the head block. // If all checks out, manually set the head block.
@@ -2356,7 +2243,13 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1) parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
} }
bc.stateCache.SetVersion(int64(block.NumberU64()) - 1) if bc.stateCache.Scheme() != rawdb.VersionScheme {
if block.NumberU64() == 2000001 {
log.Crit("exit.... path mode, 200w blocks")
}
}
bc.stateCache.SetVersion(int64(block.NumberU64()))
statedb, err := state.NewWithSharedPool(parent.Root, bc.stateCache, bc.snaps) statedb, err := state.NewWithSharedPool(parent.Root, bc.stateCache, bc.snaps)
if err != nil { if err != nil {
bc.stateCache.Release() bc.stateCache.Release()
@@ -2368,18 +2261,18 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
//statedb.StartPrefetcher("chain") //statedb.StartPrefetcher("chain")
interruptCh := make(chan struct{}) interruptCh := make(chan struct{})
// For diff sync, it may fallback to full sync, so we still do prefetch // For diff sync, it may fallback to full sync, so we still do prefetch
if len(block.Transactions()) >= prefetchTxNumber { //if len(block.Transactions()) >= prefetchTxNumber {
// do Prefetch in a separate goroutine to avoid blocking the critical path // // do Prefetch in a separate goroutine to avoid blocking the critical path
//
//1.do state prefetch for snapshot cache // // 1.do state prefetch for snapshot cache
throwaway := statedb.CopyDoPrefetch() // throwaway := statedb.CopyDoPrefetch()
go bc.prefetcher.Prefetch(block, throwaway, &bc.vmConfig, interruptCh) // go bc.prefetcher.Prefetch(block, throwaway, &bc.vmConfig, interruptCh)
//
// // 2.do trie prefetch for MPT trie node cache // // 2.do trie prefetch for MPT trie node cache
// // it is for the big state trie tree, prefetch based on transaction's From/To address. // // it is for the big state trie tree, prefetch based on transaction's From/To address.
// // trie prefetcher is thread safe now, ok to prefetch in a separate routine // // trie prefetcher is thread safe now, ok to prefetch in a separate routine
// go throwaway.TriePrefetchInAdvance(block, signer) // go throwaway.TriePrefetchInAdvance(block, signer)
} //}
// Process block using the parent state as reference point // Process block using the parent state as reference point
if bc.pipeCommit { if bc.pipeCommit {
@@ -2395,8 +2288,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
statedb.StopPrefetcher() statedb.StopPrefetcher()
return it.index, err return it.index, err
} }
blockExecutionTotalTimer.UpdateSince(pstart)
ptime := time.Since(pstart) ptime := time.Since(pstart)
// Validate the state using the default validator // Validate the state using the default validator
@@ -2407,8 +2298,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
statedb.StopPrefetcher() statedb.StopPrefetcher()
return it.index, err return it.index, err
} }
blockValidationTotalTimer.UpdateSince(vstart)
vtime := time.Since(vstart) vtime := time.Since(vstart)
proctime := time.Since(start) // processing + validation proctime := time.Since(start) // processing + validation
@@ -2444,7 +2333,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
return it.index, err return it.index, err
} }
bc.stateCache.Release() bc.stateCache.Release()
blockWriteTotalTimer.UpdateSince(wstart)
bc.cacheReceipts(block.Hash(), receipts, block) bc.cacheReceipts(block.Hash(), receipts, block)
@@ -2624,7 +2512,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
numbers []uint64 numbers []uint64
) )
parent := it.previous() parent := it.previous()
for parent != nil && !bc.HasState(parent.Number.Int64(), parent.Root) { for parent != nil && !bc.HasState(parent.Root) {
if bc.stateRecoverable(parent.Root) { if bc.stateRecoverable(parent.Root) {
if err := bc.triedb.Recover(parent.Root); err != nil { if err := bc.triedb.Recover(parent.Root); err != nil {
return 0, err return 0, err
@@ -2691,7 +2579,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
numbers []uint64 numbers []uint64
parent = block parent = block
) )
for parent != nil && !bc.HasState(parent.Number().Int64(), parent.Root()) { for parent != nil && !bc.HasState(parent.Root()) {
if bc.stateRecoverable(parent.Root()) { if bc.stateRecoverable(parent.Root()) {
if err := bc.triedb.Recover(parent.Root()); err != nil { if err := bc.triedb.Recover(parent.Root()); err != nil {
return common.Hash{}, err return common.Hash{}, err
@@ -2962,7 +2850,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
defer bc.chainmu.Unlock() defer bc.chainmu.Unlock()
// Re-execute the reorged chain in case the head state is missing. // Re-execute the reorged chain in case the head state is missing.
if !bc.HasState(head.Number().Int64(), head.Root()) { if !bc.HasState(head.Root()) {
if latestValidHash, err := bc.recoverAncestors(head); err != nil { if latestValidHash, err := bc.recoverAncestors(head); err != nil {
return latestValidHash, err return latestValidHash, err
} }

View File

@@ -18,7 +18,6 @@ package core
import ( import (
"errors" "errors"
"fmt"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@@ -339,7 +338,7 @@ func (bc *BlockChain) GetTd(hash common.Hash, number uint64) *big.Int {
} }
// HasState checks if state trie is fully present in the database or not. // HasState checks if state trie is fully present in the database or not.
func (bc *BlockChain) HasState(number int64, hash common.Hash) bool { func (bc *BlockChain) HasState(hash common.Hash) bool {
if bc.NoTries() { if bc.NoTries() {
return bc.snaps != nil && bc.snaps.Snapshot(hash) != nil return bc.snaps != nil && bc.snaps.Snapshot(hash) != nil
} }
@@ -349,24 +348,18 @@ func (bc *BlockChain) HasState(number int64, hash common.Hash) bool {
return true return true
} }
} }
return bc.stateCache.HasState(number, hash) return bc.stateCache.HasState(hash)
} }
// HasBlockAndState checks if a block and associated state trie is fully present // HasBlockAndState checks if a block and associated state trie is fully present
// in the database or not, caching it if present. // in the database or not, caching it if present.
func (bc *BlockChain) HasBlockAndState(hash common.Hash, number int64) bool { func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
// Check first that the block itself is known // Check first that the block itself is known
var root common.Hash block := bc.GetBlock(hash, number)
if number < 0 { if block == nil {
root = types.EmptyRootHash return false
} else {
block := bc.GetBlock(hash, uint64(number))
if block == nil {
return false
}
root = block.Root()
} }
return bc.HasState(number, root) return bc.HasState(block.Root())
} }
// stateRecoverable checks if the specified state is recoverable. // stateRecoverable checks if the specified state is recoverable.
@@ -397,19 +390,13 @@ func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
// State returns a new mutable state based on the current HEAD block. // State returns a new mutable state based on the current HEAD block.
func (bc *BlockChain) State() (*state.StateDB, error) { func (bc *BlockChain) State() (*state.StateDB, error) {
return bc.StateAt(bc.CurrentBlock().Number.Int64(), bc.CurrentBlock().Root) return bc.StateAt(bc.CurrentBlock().Root)
} }
// StateAt returns a new mutable state based on a particular point in time. // StateAt returns a new mutable state based on a particular point in time.
func (bc *BlockChain) StateAt(number int64, root common.Hash) (*state.StateDB, error) { func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
// new state db with no need commit mode // new state db with no need commit mode
has := bc.HasState(number, root) stateDb, err := state.New(root, state.NewDatabaseWithNodeDB(bc.db, bc.triedb, false), bc.snaps)
if !has {
return nil, fmt.Errorf(fmt.Sprintf("do not has state, verison: %d, root: %s", number, root.String()))
}
sdb := state.NewDatabaseWithNodeDB(bc.db, bc.triedb, false)
sdb.SetVersion(number)
stateDb, err := state.New(root, sdb, bc.snaps)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -158,7 +158,7 @@ func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Databa
triedbConfig.NoTries = false triedbConfig.NoTries = false
} }
cachingdb := state.NewDatabaseWithNodeDB(db, triedb, true) cachingdb := state.NewDatabaseWithNodeDB(db, triedb, true)
cachingdb.SetVersion(-1) cachingdb.SetVersion(0)
defer cachingdb.Release() defer cachingdb.Release()
statedb, err := state.New(types.EmptyRootHash, cachingdb, nil) statedb, err := state.New(types.EmptyRootHash, cachingdb, nil)
if err != nil { if err != nil {
@@ -274,8 +274,6 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
log.Info("genesis block hash", "hash", block.Hash()) log.Info("genesis block hash", "hash", block.Hash())
return genesis.Config, block.Hash(), nil return genesis.Config, block.Hash(), nil
} }
log.Info("init genesis", "stored root", stored.String())
// The genesis block is present(perhaps in ancient database) while the // The genesis block is present(perhaps in ancient database) while the
// state database is not initialized yet. It can happen that the node // state database is not initialized yet. It can happen that the node
// is initialized with an external ancient store. Commit genesis state // is initialized with an external ancient store. Commit genesis state

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
@@ -60,16 +60,15 @@ func (cv *cachingVersaDB) Copy() Database {
cp.triedb = cv.triedb cp.triedb = cv.triedb
cp.versionDB = cv.versionDB cp.versionDB = cv.versionDB
cp.codeDB = cv.codeDB cp.codeDB = cv.codeDB
cp.version = cv.version
cp.mode = versa.S_RW // it is important cp.mode = versa.S_RW // it is important
// TODO:: maybe add lock for cv.root // TODO:: maybe add lock for cv.root
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
} }
} }
@@ -91,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
@@ -110,8 +109,8 @@ func (cv *cachingVersaDB) CopyTrie(tr Trie) Trie {
return nil return nil
} }
func (cv *cachingVersaDB) HasState(version int64, root common.Hash) bool { func (cv *cachingVersaDB) HasState(root common.Hash) bool {
return cv.versionDB.HasState(version, root) return cv.versionDB.HasState(root)
} }
func (cv *cachingVersaDB) OpenTrie(root common.Hash) (Trie, error) { func (cv *cachingVersaDB) OpenTrie(root common.Hash) (Trie, error) {
@@ -123,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
} }
@@ -146,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
@@ -154,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
} }
@@ -181,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,
@@ -199,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
} }
@@ -207,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 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 {
@@ -228,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
} }
@@ -271,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
@@ -327,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
@@ -353,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
} }
@@ -380,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
} }
@@ -403,22 +402,18 @@ 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)
} }
func (vt *VersaTree) WriteBatch(values map[string][]byte) error {
return vt.db.WriteBatch(vt.handler, values)
}
func (vt *VersaTree) UpdateStorage(address common.Address, key, value []byte) error { func (vt *VersaTree) UpdateStorage(address common.Address, key, value []byte) error {
if vt.address.Cmp(address) != 0 { if vt.address.Cmp(address) != 0 {
panic(fmt.Sprintf("address mismatch in get storage, expect: %s, actul: %s", vt.address.String(), address.String())) panic(fmt.Sprintf("address mismatch in get storage, expect: %s, actul: %s", vt.address.String(), address.String()))
@@ -427,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
} }
@@ -442,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
} }
@@ -457,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
} }
@@ -475,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

@@ -87,7 +87,7 @@ type Database interface {
Copy() Database Copy() Database
// HasState returns the state data whether in the triedb. // HasState returns the state data whether in the triedb.
HasState(version int64, root common.Hash) bool HasState(root common.Hash) bool
// HasTreeExpired used for caching versa db, whether the state where the opened tree resides has been closed // HasTreeExpired used for caching versa db, whether the state where the opened tree resides has been closed
HasTreeExpired(tr Trie) bool HasTreeExpired(tr Trie) bool
@@ -143,8 +143,6 @@ type Trie interface {
// to be moved to the stateWriter interface when the latter is ready. // to be moved to the stateWriter interface when the latter is ready.
UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error
WriteBatch(values map[string][]byte) error
// Hash returns the root hash of the trie. It does not write to the database and // Hash returns the root hash of the trie. It does not write to the database and
// can be used even if the trie doesn't have one. // can be used even if the trie doesn't have one.
Hash() common.Hash Hash() common.Hash
@@ -229,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.
@@ -242,23 +240,22 @@ 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.
@@ -276,25 +273,24 @@ 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 {
@@ -311,8 +307,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))
} }
@@ -320,9 +316,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
@@ -385,26 +381,25 @@ 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 {
return db return db
} }
func (db *cachingDB) HasState(_ int64, root common.Hash) bool { func (db *cachingDB) HasState(root common.Hash) bool {
_, err := db.OpenTrie(root) _, err := db.OpenTrie(root)
return err == nil return err == nil
} }
@@ -413,137 +408,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

@@ -34,7 +34,4 @@ var (
slotDeletionCount = metrics.NewRegisteredMeter("state/delete/storage/slot", nil) slotDeletionCount = metrics.NewRegisteredMeter("state/delete/storage/slot", nil)
slotDeletionSize = metrics.NewRegisteredMeter("state/delete/storage/size", nil) slotDeletionSize = metrics.NewRegisteredMeter("state/delete/storage/size", nil)
slotDeletionSkip = metrics.NewRegisteredGauge("state/delete/storage/skip", nil) slotDeletionSkip = metrics.NewRegisteredGauge("state/delete/storage/skip", nil)
accountIntermediateRootTimer = metrics.NewRegisteredTimer("state/account/intermediate/root/time", nil)
storageIntermediateRootTimer = metrics.NewRegisteredTimer("state/storage/intermediate/root/time", nil)
) )

View File

@@ -235,14 +235,6 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
return common.Hash{} return common.Hash{}
} }
// If no live objects are available, attempt to use snapshots // If no live objects are available, attempt to use snapshots
defer func(start time.Time) {
stateDBGetTimer.UpdateSince(start)
stateDBGetQPS.Mark(1)
stateDBGetStorageTimer.UpdateSince(start)
stateDBGetStorageQPS.Mark(1)
}(time.Now())
var ( var (
enc []byte enc []byte
err error err error
@@ -398,10 +390,6 @@ func (s *stateObject) updateTrie() (Trie, error) {
s.db.setError(err) s.db.setError(err)
return nil, err return nil, err
} }
if len(s.pendingStorage) == 0 {
return s.trie, nil
}
// Insert all the pending storage updates into the trie // Insert all the pending storage updates into the trie
usedStorage := make([][]byte, 0, len(s.pendingStorage)) usedStorage := make([][]byte, 0, len(s.pendingStorage))
dirtyStorage := make(map[common.Hash][]byte) dirtyStorage := make(map[common.Hash][]byte)
@@ -417,14 +405,11 @@ func (s *stateObject) updateTrie() (Trie, error) {
} }
dirtyStorage[key] = v dirtyStorage[key] = v
} }
//storages := make(map[string][]byte)
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
for key, value := range dirtyStorage { for key, value := range dirtyStorage {
//TODO:: add version schema check
if len(value) == 0 { if len(value) == 0 {
if err := tr.DeleteStorage(s.address, key[:]); err != nil { if err := tr.DeleteStorage(s.address, key[:]); err != nil {
s.db.setError(err) s.db.setError(err)
@@ -436,16 +421,6 @@ func (s *stateObject) updateTrie() (Trie, error) {
} }
s.db.StorageUpdated += 1 s.db.StorageUpdated += 1
} }
//if len(value) == 0 {
// storages[string(key[:])] = nil
//} else {
// v, _ := rlp.EncodeToBytes(value)
// storages[string(key[:])] = v
//}
//if err := tr.WriteBatch(storages); err != nil {
// s.db.setError(err)
//}
// Cache the items for preloading // Cache the items for preloading
usedStorage = append(usedStorage, common.CopyBytes(key[:])) usedStorage = append(usedStorage, common.CopyBytes(key[:]))
} }
@@ -532,11 +507,6 @@ func (s *stateObject) updateRoot() {
// The returned set can be nil if nothing to commit. This function assumes all // The returned set can be nil if nothing to commit. This function assumes all
// storage mutations have already been flushed into trie by updateRoot. // storage mutations have already been flushed into trie by updateRoot.
func (s *stateObject) commit() (*trienode.NodeSet, error) { func (s *stateObject) commit() (*trienode.NodeSet, error) {
if s.IsContractAccount() && s.trie == nil && s.db.db.GetVersion() != 0 {
panic(fmt.Sprintf("not open contract account, owner: %s, r_version: %d, c_version: %d, root: %s",
s.address.String(), s.db.db.GetVersion(), s.version, s.Root().String()))
}
// Short circuit if trie is not even loaded, don't bother with committing anything // Short circuit if trie is not even loaded, don't bother with committing anything
if s.trie == nil { if s.trie == nil {
s.origin = s.data.Copy() s.origin = s.data.Copy()

View File

@@ -54,16 +54,6 @@ type revision struct {
journalIndex int journalIndex int
} }
var (
stateDBGetTimer = metrics.NewRegisteredTimer("statedb/get/time", nil)
stateDBGetQPS = metrics.NewRegisteredMeter("statedb/get/qps", nil)
stateDBGetAccountTimer = metrics.NewRegisteredTimer("statedb/account/get/time", nil)
stateDBGetAccountQPS = metrics.NewRegisteredMeter("statedb/account/get/qps", nil)
stateDBGetStorageTimer = metrics.NewRegisteredTimer("statedb/storage/get/time", nil)
stateDBGetStorageQPS = metrics.NewRegisteredMeter("statedb/storage/get/qps", nil)
)
// StateDB structs within the ethereum protocol are used to store anything // StateDB structs within the ethereum protocol are used to store anything
// within the merkle trie. StateDBs take care of caching and storing // within the merkle trie. StateDBs take care of caching and storing
// nested states. It's the general query interface to retrieve: // nested states. It's the general query interface to retrieve:
@@ -692,7 +682,6 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
if err := s.trie.UpdateAccount(addr, &obj.data); err != nil { if err := s.trie.UpdateAccount(addr, &obj.data); err != nil {
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err)) s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))
} }
if obj.dirtyCode { if obj.dirtyCode {
s.trie.UpdateContractCode(obj.Address(), common.BytesToHash(obj.CodeHash()), obj.code) s.trie.UpdateContractCode(obj.Address(), common.BytesToHash(obj.CodeHash()), obj.code)
} }
@@ -720,7 +709,6 @@ func (s *StateDB) deleteStateObject(obj *stateObject) {
} }
// Delete the account from the trie // Delete the account from the trie
addr := obj.Address() addr := obj.Address()
if err := s.trie.DeleteAccount(addr); err != nil { if err := s.trie.DeleteAccount(addr); err != nil {
s.setError(fmt.Errorf("deleteStateObject (%x) error: %v", addr[:], err)) s.setError(fmt.Errorf("deleteStateObject (%x) error: %v", addr[:], err))
} }
@@ -745,14 +733,6 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
if obj := s.stateObjects[addr]; obj != nil { if obj := s.stateObjects[addr]; obj != nil {
return obj return obj
} }
defer func(start time.Time) {
stateDBGetTimer.UpdateSince(start)
stateDBGetQPS.Mark(1)
stateDBGetAccountTimer.UpdateSince(start)
stateDBGetAccountQPS.Mark(1)
}(time.Now())
// If no live objects are available, attempt to use snapshots // If no live objects are available, attempt to use snapshots
var data *types.StateAccount var data *types.StateAccount
if s.snap != nil { if s.snap != nil {
@@ -1197,10 +1177,6 @@ func (s *StateDB) populateSnapStorage(obj *stateObject) bool {
} }
func (s *StateDB) AccountsIntermediateRoot() { func (s *StateDB) AccountsIntermediateRoot() {
defer func(start time.Time) {
storageIntermediateRootTimer.UpdateSince(start)
}(time.Now())
tasks := make(chan func()) tasks := make(chan func())
finishCh := make(chan struct{}) finishCh := make(chan struct{})
defer close(finishCh) defer close(finishCh)
@@ -1228,6 +1204,7 @@ func (s *StateDB) AccountsIntermediateRoot() {
wg.Add(1) wg.Add(1)
tasks <- func() { tasks <- func() {
obj.updateRoot() obj.updateRoot()
// Cache the data until commit. Note, this update mechanism is not symmetric // Cache the data until commit. Note, this update mechanism is not symmetric
// to the deletion, because whereas it is enough to track account updates // to the deletion, because whereas it is enough to track account updates
// at commit time, deletions need tracking at transaction boundary level to // at commit time, deletions need tracking at transaction boundary level to
@@ -1244,9 +1221,6 @@ func (s *StateDB) AccountsIntermediateRoot() {
} }
func (s *StateDB) StateIntermediateRoot() common.Hash { func (s *StateDB) StateIntermediateRoot() common.Hash {
defer func(start time.Time) {
accountIntermediateRootTimer.UpdateSince(start)
}(time.Now())
// If there was a trie prefetcher operating, it gets aborted and irrevocably // If there was a trie prefetcher operating, it gets aborted and irrevocably
// modified after we start retrieving tries. Remove it from the statedb after // modified after we start retrieving tries. Remove it from the statedb after
// this round of use. // this round of use.
@@ -1680,9 +1654,9 @@ func (s *StateDB) Commit(block uint64, failPostCommitFunc func(), postCommitFunc
if err := s.db.Flush(); err != nil { if err := s.db.Flush(); err != nil {
return err return err
} }
//if err := s.db.Release(); err != nil { if err := s.db.Release(); err != nil {
// return err return err
//} }
s.originalRoot = root s.originalRoot = root
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
s.TrieDBCommits += time.Since(start) s.TrieDBCommits += time.Since(start)
@@ -1739,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

@@ -49,6 +49,7 @@ func NewStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine conse
// the transaction messages using the statedb, but any changes are discarded. The // the transaction messages using the statedb, but any changes are discarded. The
// only goal is to pre-cache transaction signatures and state trie nodes. // only goal is to pre-cache transaction signatures and state trie nodes.
func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg *vm.Config, interruptCh <-chan struct{}) { func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg *vm.Config, interruptCh <-chan struct{}) {
panic("prefetcher not support")
var ( var (
header = block.Header() header = block.Header()
signer = types.MakeSigner(p.config, header.Number, header.Time) signer = types.MakeSigner(p.config, header.Number, header.Time)

View File

@@ -366,9 +366,9 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserve txpool.Addres
// Initialize the state with head block, or fallback to empty one in // Initialize the state with head block, or fallback to empty one in
// case the head state is not available (might occur when node is not // case the head state is not available (might occur when node is not
// fully synced). // fully synced).
state, err := p.chain.StateAt(head.Number.Int64(), head.Root) state, err := p.chain.StateAt(head.Root)
if err != nil { if err != nil {
state, err = p.chain.StateAt(-1, types.EmptyRootHash) state, err = p.chain.StateAt(types.EmptyRootHash)
} }
if err != nil { if err != nil {
return err return err
@@ -793,7 +793,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
resettimeHist.Update(time.Since(start).Nanoseconds()) resettimeHist.Update(time.Since(start).Nanoseconds())
}(time.Now()) }(time.Now())
statedb, err := p.chain.StateAt(newHead.Number.Int64(), newHead.Root) statedb, err := p.chain.StateAt(newHead.Root)
if err != nil { if err != nil {
log.Error("Failed to reset blobpool state", "err", err) log.Error("Failed to reset blobpool state", "err", err)
return return

View File

@@ -40,5 +40,5 @@ type BlockChain interface {
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
// StateAt returns a state database for a given root hash (generally the head). // StateAt returns a state database for a given root hash (generally the head).
StateAt(number int64, root common.Hash) (*state.StateDB, error) StateAt(root common.Hash) (*state.StateDB, error)
} }

View File

@@ -120,7 +120,7 @@ type BlockChain interface {
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
// StateAt returns a state database for a given root hash (generally the head). // StateAt returns a state database for a given root hash (generally the head).
StateAt(number int64, root common.Hash) (*state.StateDB, error) StateAt(root common.Hash) (*state.StateDB, error)
} }
// Config are the configuration parameters of the transaction pool. // Config are the configuration parameters of the transaction pool.
@@ -311,9 +311,9 @@ func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserve txpool.A
// Initialize the state with head block, or fallback to empty one in // Initialize the state with head block, or fallback to empty one in
// case the head state is not available (might occur when node is not // case the head state is not available (might occur when node is not
// fully synced). // fully synced).
statedb, err := pool.chain.StateAt(head.Number.Int64(), head.Root) statedb, err := pool.chain.StateAt(head.Root)
if err != nil { if err != nil {
statedb, err = pool.chain.StateAt(-1, types.EmptyRootHash) statedb, err = pool.chain.StateAt(types.EmptyRootHash)
} }
if err != nil { if err != nil {
return err return err
@@ -1492,7 +1492,7 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) {
if newHead == nil { if newHead == nil {
newHead = pool.chain.CurrentBlock() // Special case during testing newHead = pool.chain.CurrentBlock() // Special case during testing
} }
statedb, err := pool.chain.StateAt(newHead.Number.Int64(), newHead.Root) statedb, err := pool.chain.StateAt(newHead.Root)
if err != nil { if err != nil {
log.Error("Failed to reset txpool state", "err", err) log.Error("Failed to reset txpool state", "err", err)
return return

View File

@@ -204,7 +204,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
if header == nil { if header == nil {
return nil, nil, errors.New("header not found") return nil, nil, errors.New("header not found")
} }
stateDb, err := b.eth.BlockChain().StateAt(header.Number.Int64(), header.Root) stateDb, err := b.eth.BlockChain().StateAt(header.Root)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -226,7 +226,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockN
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
return nil, nil, errors.New("hash is not currently canonical") return nil, nil, errors.New("hash is not currently canonical")
} }
stateDb, err := b.eth.BlockChain().StateAt(header.Number.Int64(), header.Root) stateDb, err := b.eth.BlockChain().StateAt(header.Root)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@@ -81,7 +81,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
if header == nil { if header == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
} }
stateDb, err := api.eth.BlockChain().StateAt(header.Number.Int64(), header.Root) stateDb, err := api.eth.BlockChain().StateAt(header.Root)
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
} }
@@ -167,7 +167,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
if header == nil { if header == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", number) return state.Dump{}, fmt.Errorf("block #%d not found", number)
} }
stateDb, err = api.eth.BlockChain().StateAt(header.Number.Int64(), header.Root) stateDb, err = api.eth.BlockChain().StateAt(header.Root)
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
} }
@@ -177,7 +177,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
if block == nil { if block == nil {
return state.Dump{}, fmt.Errorf("block %s not found", hash.Hex()) return state.Dump{}, fmt.Errorf("block %s not found", hash.Hex())
} }
stateDb, err = api.eth.BlockChain().StateAt(block.Number().Int64(), block.Root()) stateDb, err = api.eth.BlockChain().StateAt(block.Root())
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
} }

View File

@@ -220,13 +220,13 @@ func newHandler(config *handlerConfig) (*handler, error) {
} }
h.snapSync.Store(true) h.snapSync.Store(true)
log.Warn("Switch sync mode from full sync to snap sync", "reason", "snap sync incomplete") log.Warn("Switch sync mode from full sync to snap sync", "reason", "snap sync incomplete")
} else if !h.chain.NoTries() && !h.chain.HasState(fullBlock.Number.Int64(), fullBlock.Root) { } else if !h.chain.NoTries() && !h.chain.HasState(fullBlock.Root) {
h.snapSync.Store(true) h.snapSync.Store(true)
log.Warn("Switch sync mode from full sync to snap sync", "reason", "head state missing") log.Warn("Switch sync mode from full sync to snap sync", "reason", "head state missing")
} }
} else { } else {
head := h.chain.CurrentBlock() head := h.chain.CurrentBlock()
if head.Number.Uint64() > 0 && h.chain.HasState(head.Number.Int64(), head.Root) { if head.Number.Uint64() > 0 && h.chain.HasState(head.Root) {
// Print warning log if database is not empty to run snap sync. // Print warning log if database is not empty to run snap sync.
log.Warn("Switch sync mode from snap sync to full sync", "reason", "snap sync complete") log.Warn("Switch sync mode from snap sync to full sync", "reason", "snap sync complete")
} else { } else {

View File

@@ -55,7 +55,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
// The state is available in live database, create a reference // The state is available in live database, create a reference
// on top to prevent garbage collection and return a release // on top to prevent garbage collection and return a release
// function to deref it. // function to deref it.
if statedb, err = eth.blockchain.StateAt(block.Number().Int64(), block.Root()); err == nil { if statedb, err = eth.blockchain.StateAt(block.Root()); err == nil {
eth.blockchain.TrieDB().Reference(block.Root(), common.Hash{}) eth.blockchain.TrieDB().Reference(block.Root(), common.Hash{})
return statedb, func() { return statedb, func() {
eth.blockchain.TrieDB().Dereference(block.Root()) eth.blockchain.TrieDB().Dereference(block.Root())
@@ -185,7 +185,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) { func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) {
// Check if the requested state is available in the live chain. // Check if the requested state is available in the live chain.
statedb, err := eth.blockchain.StateAt(block.Number().Int64(), block.Root()) statedb, err := eth.blockchain.StateAt(block.Root())
if err == nil { if err == nil {
return statedb, noopReleaser, nil return statedb, noopReleaser, nil
} }

View File

@@ -17,7 +17,6 @@
package eth package eth
import ( import (
"fmt"
"math/big" "math/big"
"time" "time"
@@ -192,40 +191,33 @@ 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) {
// If we're in snap sync mode, return that directly
if cs.handler.snapSync.Load() {
block := cs.handler.chain.CurrentSnapBlock()
td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64())
return downloader.SnapSync, td
}
// 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.
head := cs.handler.chain.CurrentBlock() head := cs.handler.chain.CurrentBlock()
if cs.handler.chain.TrieDB().Scheme() != rawdb.VersionScheme { if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil {
// If we're in snap sync mode, return that directly if head.Number.Uint64() < *pivot {
if cs.handler.snapSync.Load() { if rawdb.ReadAncientType(cs.handler.database) == rawdb.PruneFreezerType {
block := cs.handler.chain.CurrentSnapBlock() log.Crit("Current rewound to before the fast sync pivot, can't enable pruneancient mode", "current block number", head.Number.Uint64(), "pivot", *pivot)
td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64())
return downloader.SnapSync, td
}
// 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.
head = cs.handler.chain.CurrentBlock()
if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil {
if head.Number.Uint64() < *pivot {
if rawdb.ReadAncientType(cs.handler.database) == rawdb.PruneFreezerType {
log.Crit("Current rewound to before the fast sync pivot, can't enable pruneancient mode", "current block number", head.Number.Uint64(), "pivot", *pivot)
}
block := cs.handler.chain.CurrentSnapBlock()
td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64())
return downloader.SnapSync, td
} }
}
// We are in a full sync, but the associated head state is missing. To complete
// the head state, forcefully rerun the snap sync. Note it doesn't mean the
// persistent state is corrupted, just mismatch with the head block.
if !cs.handler.chain.NoTries() && !cs.handler.chain.HasState(head.Number.Int64(), head.Root) {
block := cs.handler.chain.CurrentSnapBlock() block := cs.handler.chain.CurrentSnapBlock()
td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64())
log.Info("Reenabled snap sync as chain is stateless")
return downloader.SnapSync, td return downloader.SnapSync, td
} }
} else { }
if !cs.handler.chain.HasState(head.Number.Int64(), head.Root) { // We are in a full sync, but the associated head state is missing. To complete
panic(fmt.Sprintf("version db not support snap sync, version: %d, root: %s", head.Number.Int64(), head.Root)) // the head state, forcefully rerun the snap sync. Note it doesn't mean the
} // persistent state is corrupted, just mismatch with the head block.
if !cs.handler.chain.NoTries() && !cs.handler.chain.HasState(head.Root) {
block := cs.handler.chain.CurrentSnapBlock()
td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64())
log.Info("Reenabled snap sync as chain is stateless")
return downloader.SnapSync, td
} }
// 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())

3
go.mod
View File

@@ -42,7 +42,7 @@ require (
github.com/gorilla/websocket v1.5.1 github.com/gorilla/websocket v1.5.1
github.com/graph-gophers/graphql-go v1.3.0 github.com/graph-gophers/graphql-go v1.3.0
github.com/hashicorp/go-bexpr v0.1.10 github.com/hashicorp/go-bexpr v0.1.10
github.com/hashicorp/golang-lru v1.0.2 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4
github.com/holiman/bloomfilter/v2 v2.0.3 github.com/holiman/bloomfilter/v2 v2.0.3
github.com/holiman/uint256 v1.3.0 github.com/holiman/uint256 v1.3.0
@@ -252,6 +252,7 @@ require (
github.com/spf13/afero v1.10.0 // indirect github.com/spf13/afero v1.10.0 // indirect
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e // indirect github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e // indirect
github.com/tidwall/btree v1.7.0 // indirect
github.com/tidwall/gjson v1.10.2 // indirect github.com/tidwall/gjson v1.10.2 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect

6
go.sum
View File

@@ -598,8 +598,8 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@@ -1152,6 +1152,8 @@ github.com/tendermint/iavl v0.12.0 h1:xcaFAr+ycqCj7WN1RzL2EfcBioRDOHcU1oWcg83K02
github.com/tendermint/iavl v0.12.0/go.mod h1:EoKMMv++tDOL5qKKVnoIqtVPshRrEPeJ0WsgDOLAauM= github.com/tendermint/iavl v0.12.0/go.mod h1:EoKMMv++tDOL5qKKVnoIqtVPshRrEPeJ0WsgDOLAauM=
github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e h1:cR8/SYRgyQCt5cNCMniB/ZScMkhI9nk8U5C7SbISXjo= github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e h1:cR8/SYRgyQCt5cNCMniB/ZScMkhI9nk8U5C7SbISXjo=
github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e/go.mod h1:Tu4lItkATkonrYuvtVjG0/rhy15qrNGNTjPdaphtZ/8= github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e/go.mod h1:Tu4lItkATkonrYuvtVjG0/rhy15qrNGNTjPdaphtZ/8=
github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI=
github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo= github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=

View File

@@ -1367,11 +1367,11 @@ func (s *BlockChainAPI) needToReplay(ctx context.Context, block *types.Block, ac
if err != nil { if err != nil {
return false, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err) return false, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err)
} }
parentState, err := s.b.Chain().StateAt(parent.Number().Int64(), parent.Root()) parentState, err := s.b.Chain().StateAt(parent.Root())
if err != nil { if err != nil {
return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64()-1, err) return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64()-1, err)
} }
currentState, err := s.b.Chain().StateAt(parent.Number().Int64(), block.Root()) currentState, err := s.b.Chain().StateAt(block.Root())
if err != nil { if err != nil {
return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64(), err) return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64(), err)
} }
@@ -1397,7 +1397,7 @@ func (s *BlockChainAPI) replay(ctx context.Context, block *types.Block, accounts
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err) return nil, nil, fmt.Errorf("block not found for block number (%d): %v", block.NumberU64()-1, err)
} }
statedb, err := s.b.Chain().StateAt(parent.Number().Int64(), parent.Root()) statedb, err := s.b.Chain().StateAt(parent.Root())
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("state not found for block number (%d): %v", block.NumberU64()-1, err) return nil, nil, fmt.Errorf("state not found for block number (%d): %v", block.NumberU64()-1, err)
} }

View File

@@ -245,7 +245,7 @@ func (miner *Miner) Pending() (*types.Block, *state.StateDB) {
if block == nil { if block == nil {
return nil, nil return nil, nil
} }
stateDb, err := miner.worker.chain.StateAt(block.Number.Int64(), block.Root) stateDb, err := miner.worker.chain.StateAt(block.Root)
if err != nil { if err != nil {
return nil, nil return nil, nil
} }

View File

@@ -690,7 +690,7 @@ func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase co
prevEnv *environment) (*environment, error) { prevEnv *environment) (*environment, error) {
// Retrieve the parent state to execute on top and start a prefetcher for // Retrieve the parent state to execute on top and start a prefetcher for
// the miner to speed block sealing up a bit // the miner to speed block sealing up a bit
state, err := w.chain.StateAt(parent.Number.Int64(), parent.Root) state, err := w.chain.StateAt(parent.Root)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -31,11 +31,6 @@ func NewEmptyTrie() *EmptyTrie {
return &EmptyTrie{} return &EmptyTrie{}
} }
func (t *EmptyTrie) WriteBatch(values map[string][]byte) error {
panic("EmptyTrie not support WriteBatch")
return nil
}
func (t *EmptyTrie) GetKey(shaKey []byte) []byte { func (t *EmptyTrie) GetKey(shaKey []byte) []byte {
return nil return nil
} }

View File

@@ -73,11 +73,6 @@ func NewStateTrie(id *ID, db database.Database) (*StateTrie, error) {
return &StateTrie{trie: *trie, db: db}, nil return &StateTrie{trie: *trie, db: db}, nil
} }
func (t *StateTrie) WriteBatch(values map[string][]byte) error {
panic("StateTrie not support WriteBatch")
return nil
}
// MustGet returns the value for key stored in the trie. // MustGet returns the value for key stored in the trie.
// The value bytes must not be modified by the caller. // The value bytes must not be modified by the caller.
// //

View File

@@ -69,11 +69,6 @@ func NewVerkleTrie(root common.Hash, db database.Database, cache *utils.PointCac
}, nil }, nil
} }
func (t *VerkleTrie) WriteBatch(values map[string][]byte) error {
panic("VerkleTrie not support WriteBatch")
return nil
}
// GetKey returns the sha3 preimage of a hashed key that was previously used // GetKey returns the sha3 preimage of a hashed key that was previously used
// to store a value. // to store a value.
func (t *VerkleTrie) GetKey(key []byte) []byte { func (t *VerkleTrie) GetKey(key []byte) []byte {

View File

@@ -22,22 +22,18 @@ type VersionDB struct {
func New(config *Config) *VersionDB { func New(config *Config) *VersionDB {
var ( var (
//cfg *versa.VersaDBConfig cfg *versa.VersaDBConfig
path = "./node/version_db" // TODO:: debug code path = "./node/version_db" // TODO:: debug code
) )
//if config != nil { if config != nil {
// path = config.Path path = config.Path
// cfg = &versa.VersaDBConfig{ cfg = &versa.VersaDBConfig{
// FlushInterval: 2000, FlushInterval: config.FlushInterval,
// MaxStatesInMem: 128, MaxStatesInMem: config.MaxStatesInMem,
// MemLowWaterMark: 10, }
// MemHighWaterMark: 20, }
// MemEvictInternal: 200, db, err := versa.NewVersaDB(path, cfg)
// }
// _ = cfg
//}
db, err := versa.NewVersaDB(path, &versa.VersaDBConfig{})
if err != nil { if err != nil {
log.Crit("failed to new version db", "error", err) log.Crit("failed to new version db", "error", err)
} }
@@ -53,8 +49,7 @@ func (v *VersionDB) Scheme() string {
} }
func (v *VersionDB) Initialized(genesisRoot common.Hash) bool { func (v *VersionDB) Initialized(genesisRoot common.Hash) bool {
version, _ := v.db.LatestStoreDiskVersionInfo() return v.db.HasState(genesisRoot)
return version >= 0
} }
func (v *VersionDB) Size() (common.StorageSize, common.StorageSize, common.StorageSize) { func (v *VersionDB) Size() (common.StorageSize, common.StorageSize, common.StorageSize) {