diff options
author | Péter Szilágyi <peterke@gmail.com> | 2016-09-27 18:13:13 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2016-09-28 16:27:31 +0800 |
commit | 710435b51b97b4c688b70bda35ab9d1aa704a988 (patch) | |
tree | 154eb1fc771c9d809dc537a5ae45418263ad0770 /core | |
parent | cd791bd855b55b95afc8a5c8f56b8bf67863d099 (diff) | |
download | dexon-710435b51b97b4c688b70bda35ab9d1aa704a988.tar dexon-710435b51b97b4c688b70bda35ab9d1aa704a988.tar.gz dexon-710435b51b97b4c688b70bda35ab9d1aa704a988.tar.bz2 dexon-710435b51b97b4c688b70bda35ab9d1aa704a988.tar.lz dexon-710435b51b97b4c688b70bda35ab9d1aa704a988.tar.xz 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.go | 7 | ||||
-rw-r--r-- | core/state/statedb.go | 51 |
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 |