aboutsummaryrefslogtreecommitdiffstats
path: root/core/blockchain.go
diff options
context:
space:
mode:
authorFelix Lange <fjl@users.noreply.github.com>2017-06-27 21:57:06 +0800
committerGitHub <noreply@github.com>2017-06-27 21:57:06 +0800
commit9e5f03b6c487175cc5aa1224e5e12fd573f483a7 (patch)
tree475e573ff6c7e77cd069a2f6238afdb27d4bce43 /core/blockchain.go
parentbb366271fe33cf87b462dc5a25ac6c448ac6d2e1 (diff)
downloaddexon-9e5f03b6c487175cc5aa1224e5e12fd573f483a7.tar.gz
dexon-9e5f03b6c487175cc5aa1224e5e12fd573f483a7.tar.zst
dexon-9e5f03b6c487175cc5aa1224e5e12fd573f483a7.zip
core/state: access trie through Database interface, track errors (#14589)
With this commit, core/state's access to the underlying key/value database is mediated through an interface. Database errors are tracked in StateDB and returned by CommitTo or the new Error method. Motivation for this change: We can remove the light client's duplicated copy of core/state. The light client now supports node iteration, so tracing and storage enumeration can work with the light client (not implemented in this commit).
Diffstat (limited to 'core/blockchain.go')
-rw-r--r--core/blockchain.go38
1 files changed, 16 insertions, 22 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index 073b91bab..aab2e72f3 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -92,7 +92,7 @@ type BlockChain struct {
currentBlock *types.Block // Current head of the block chain
currentFastBlock *types.Block // Current head of the fast-sync chain (may be above the block chain!)
- stateCache *state.StateDB // State database to reuse between imports (contains state cache)
+ stateCache state.Database // State database to reuse between imports (contains state cache)
bodyCache *lru.Cache // Cache for the most recent block bodies
bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format
blockCache *lru.Cache // Cache for the most recent entire blocks
@@ -125,6 +125,7 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, engine co
bc := &BlockChain{
config: config,
chainDb: chainDb,
+ stateCache: state.NewDatabase(chainDb),
eventMux: mux,
quit: make(chan struct{}),
bodyCache: bodyCache,
@@ -190,7 +191,7 @@ func (bc *BlockChain) loadLastState() error {
return bc.Reset()
}
// Make sure the state associated with the block is available
- if _, err := state.New(currentBlock.Root(), bc.chainDb); err != nil {
+ if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil {
// Dangling block without a state associated, init from scratch
log.Warn("Head state missing, resetting chain", "number", currentBlock.Number(), "hash", currentBlock.Hash())
return bc.Reset()
@@ -214,12 +215,6 @@ func (bc *BlockChain) loadLastState() error {
bc.currentFastBlock = block
}
}
- // Initialize a statedb cache to ensure singleton account bloom filter generation
- statedb, err := state.New(bc.currentBlock.Root(), bc.chainDb)
- if err != nil {
- return err
- }
- bc.stateCache = statedb
// Issue a status log for the user
headerTd := bc.GetTd(currentHeader.Hash(), currentHeader.Number.Uint64())
@@ -261,7 +256,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
bc.currentBlock = bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64())
}
if bc.currentBlock != nil {
- if _, err := state.New(bc.currentBlock.Root(), bc.chainDb); err != nil {
+ if _, err := state.New(bc.currentBlock.Root(), bc.stateCache); err != nil {
// Rewound state missing, rolled back to before pivot, reset to genesis
bc.currentBlock = nil
}
@@ -384,7 +379,7 @@ func (bc *BlockChain) State() (*state.StateDB, error) {
// StateAt returns a new mutable state based on a particular point in time.
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
- return bc.stateCache.New(root)
+ return state.New(root, bc.stateCache)
}
// Reset purges the entire blockchain, restoring it to its genesis state.
@@ -531,7 +526,7 @@ func (bc *BlockChain) HasBlockAndState(hash common.Hash) bool {
return false
}
// Ensure the associated state is also present
- _, err := state.New(block.Root(), bc.chainDb)
+ _, err := bc.stateCache.OpenTrie(block.Root())
return err == nil
}
@@ -959,31 +954,30 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
}
// Create a new statedb using the parent block and report an
// error if it fails.
- switch {
- case i == 0:
- err = bc.stateCache.Reset(bc.GetBlock(block.ParentHash(), block.NumberU64()-1).Root())
- default:
- err = bc.stateCache.Reset(chain[i-1].Root())
+ var parent *types.Block
+ if i == 0 {
+ parent = bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
+ } else {
+ parent = chain[i-1]
}
+ state, err := state.New(parent.Root(), bc.stateCache)
if err != nil {
- bc.reportBlock(block, nil, err)
return i, err
}
// Process block using the parent state as reference point.
- receipts, logs, usedGas, err := bc.processor.Process(block, bc.stateCache, bc.vmConfig)
+ receipts, logs, usedGas, err := bc.processor.Process(block, state, bc.vmConfig)
if err != nil {
bc.reportBlock(block, receipts, err)
return i, err
}
// Validate the state using the default validator
- err = bc.Validator().ValidateState(block, bc.GetBlock(block.ParentHash(), block.NumberU64()-1), bc.stateCache, receipts, usedGas)
+ err = bc.Validator().ValidateState(block, parent, state, receipts, usedGas)
if err != nil {
bc.reportBlock(block, receipts, err)
return i, err
}
// Write state changes to database
- _, err = bc.stateCache.Commit(bc.config.IsEIP158(block.Number()))
- if err != nil {
+ if _, err = state.CommitTo(bc.chainDb, bc.config.IsEIP158(block.Number())); err != nil {
return i, err
}
@@ -1021,7 +1015,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
return i, err
}
// Write hash preimages
- if err := WritePreimages(bc.chainDb, block.NumberU64(), bc.stateCache.Preimages()); err != nil {
+ if err := WritePreimages(bc.chainDb, block.NumberU64(), state.Preimages()); err != nil {
return i, err
}
case SideStatTy: