aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2016-09-27 18:13:13 +0800
committerPéter Szilágyi <peterke@gmail.com>2016-09-28 16:27:31 +0800
commit710435b51b97b4c688b70bda35ab9d1aa704a988 (patch)
tree154eb1fc771c9d809dc537a5ae45418263ad0770 /core
parentcd791bd855b55b95afc8a5c8f56b8bf67863d099 (diff)
downloaddexon-710435b51b97b4c688b70bda35ab9d1aa704a988.tar.gz
dexon-710435b51b97b4c688b70bda35ab9d1aa704a988.tar.zst
dexon-710435b51b97b4c688b70bda35ab9d1aa704a988.zip
core, eth, trie: reuse trie journals in all our code
Diffstat (limited to 'core')
-rw-r--r--core/blockchain.go7
-rw-r--r--core/state/statedb.go51
2 files changed, 48 insertions, 10 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index a5f146a2d..1fbcdfc6f 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -357,7 +357,12 @@ func (self *BlockChain) AuxValidator() pow.PoW { return self.pow }
// State returns a new mutable state based on the current HEAD block.
func (self *BlockChain) State() (*state.StateDB, error) {
- return state.New(self.CurrentBlock().Root(), self.chainDb)
+ return self.StateAt(self.CurrentBlock().Root())
+}
+
+// StateAt returns a new mutable state based on a particular point in time.
+func (self *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
+ return self.stateCache.New(root)
}
// Reset purges the entire blockchain, restoring it to its genesis state.
diff --git a/core/state/statedb.go b/core/state/statedb.go
index 802f37ba0..5c51e3b59 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -20,6 +20,7 @@ package state
import (
"fmt"
"math/big"
+ "sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
@@ -66,6 +67,8 @@ type StateDB struct {
txIndex int
logs map[common.Hash]vm.Logs
logSize uint
+
+ lock sync.Mutex
}
// Create a new state from a given trie
@@ -86,32 +89,53 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
}, nil
}
-// Reset clears out all emphemeral state objects from the state db, but keeps
-// the underlying state trie to avoid reloading data for the next operations.
-func (self *StateDB) Reset(root common.Hash) error {
+// New creates a new statedb by reusing any journalled tries to avoid costly
+// disk io.
+func (self *StateDB) New(root common.Hash) (*StateDB, error) {
+ self.lock.Lock()
+ defer self.lock.Unlock()
+
tr, err := self.openTrie(root)
if err != nil {
- return err
+ return nil, err
}
- *self = StateDB{
+ return &StateDB{
db: self.db,
trie: tr,
- pastTries: self.pastTries,
codeSizeCache: self.codeSizeCache,
stateObjects: make(map[common.Address]*StateObject),
stateObjectsDirty: make(map[common.Address]struct{}),
refund: new(big.Int),
logs: make(map[common.Hash]vm.Logs),
+ }, nil
+}
+
+// Reset clears out all emphemeral state objects from the state db, but keeps
+// the underlying state trie to avoid reloading data for the next operations.
+func (self *StateDB) Reset(root common.Hash) error {
+ self.lock.Lock()
+ defer self.lock.Unlock()
+
+ tr, err := self.openTrie(root)
+ if err != nil {
+ return err
}
+ self.trie = tr
+ self.stateObjects = make(map[common.Address]*StateObject)
+ self.stateObjectsDirty = make(map[common.Address]struct{})
+ self.refund = new(big.Int)
+ self.thash = common.Hash{}
+ self.bhash = common.Hash{}
+ self.txIndex = 0
+ self.logs = make(map[common.Hash]vm.Logs)
+ self.logSize = 0
+
return nil
}
// openTrie creates a trie. It uses an existing trie if one is available
// from the journal if available.
func (self *StateDB) openTrie(root common.Hash) (*trie.SecureTrie, error) {
- if self.trie != nil && self.trie.Hash() == root {
- return self.trie, nil
- }
for i := len(self.pastTries) - 1; i >= 0; i-- {
if self.pastTries[i].Hash() == root {
tr := *self.pastTries[i]
@@ -122,6 +146,9 @@ func (self *StateDB) openTrie(root common.Hash) (*trie.SecureTrie, error) {
}
func (self *StateDB) pushTrie(t *trie.SecureTrie) {
+ self.lock.Lock()
+ defer self.lock.Unlock()
+
if len(self.pastTries) >= maxJournalLength {
copy(self.pastTries, self.pastTries[1:])
self.pastTries[len(self.pastTries)-1] = t
@@ -381,6 +408,9 @@ func (self *StateDB) CreateAccount(addr common.Address) vm.Account {
//
func (self *StateDB) Copy() *StateDB {
+ self.lock.Lock()
+ defer self.lock.Unlock()
+
// Copy all the basic fields, initialize the memory ones
state := &StateDB{
db: self.db,
@@ -406,6 +436,9 @@ func (self *StateDB) Copy() *StateDB {
}
func (self *StateDB) Set(state *StateDB) {
+ self.lock.Lock()
+ defer self.lock.Unlock()
+
self.db = state.db
self.trie = state.trie
self.pastTries = state.pastTries