mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 14:16:44 +00:00
core/state: add mutex to protect global statedb and trie caches
This commit is contained in:
parent
5cbe71a9c4
commit
c907726d8b
1 changed files with 29 additions and 16 deletions
|
|
@ -20,6 +20,7 @@ package state
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
|
@ -66,6 +67,8 @@ type StateDB struct {
|
||||||
txIndex int
|
txIndex int
|
||||||
logs map[common.Hash]vm.Logs
|
logs map[common.Hash]vm.Logs
|
||||||
logSize uint
|
logSize uint
|
||||||
|
|
||||||
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new state from a given trie
|
// Create a new state from a given trie
|
||||||
|
|
@ -89,15 +92,17 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
|
||||||
// New creates a new statedb by reusing any journalled tries to avoid costly
|
// New creates a new statedb by reusing any journalled tries to avoid costly
|
||||||
// disk io.
|
// disk io.
|
||||||
func (self *StateDB) New(root common.Hash) (*StateDB, error) {
|
func (self *StateDB) New(root common.Hash) (*StateDB, error) {
|
||||||
|
self.lock.Lock()
|
||||||
|
defer self.lock.Unlock()
|
||||||
|
|
||||||
tr, err := self.openTrie(root)
|
tr, err := self.openTrie(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
csc, _ := lru.New(codeSizeCacheSize)
|
|
||||||
return &StateDB{
|
return &StateDB{
|
||||||
db: self.db,
|
db: self.db,
|
||||||
trie: tr,
|
trie: tr,
|
||||||
codeSizeCache: csc,
|
codeSizeCache: self.codeSizeCache,
|
||||||
stateObjects: make(map[common.Address]*StateObject),
|
stateObjects: make(map[common.Address]*StateObject),
|
||||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||||
refund: new(big.Int),
|
refund: new(big.Int),
|
||||||
|
|
@ -108,30 +113,29 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) {
|
||||||
// Reset clears out all emphemeral state objects from the state db, but keeps
|
// 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.
|
// the underlying state trie to avoid reloading data for the next operations.
|
||||||
func (self *StateDB) Reset(root common.Hash) error {
|
func (self *StateDB) Reset(root common.Hash) error {
|
||||||
|
self.lock.Lock()
|
||||||
|
defer self.lock.Unlock()
|
||||||
|
|
||||||
tr, err := self.openTrie(root)
|
tr, err := self.openTrie(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*self = StateDB{
|
self.trie = tr
|
||||||
db: self.db,
|
self.stateObjects = make(map[common.Address]*StateObject)
|
||||||
trie: tr,
|
self.stateObjectsDirty = make(map[common.Address]struct{})
|
||||||
pastTries: self.pastTries,
|
self.refund = new(big.Int)
|
||||||
codeSizeCache: self.codeSizeCache,
|
self.thash = common.Hash{}
|
||||||
stateObjects: make(map[common.Address]*StateObject),
|
self.bhash = common.Hash{}
|
||||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
self.txIndex = 0
|
||||||
refund: new(big.Int),
|
self.logs = make(map[common.Hash]vm.Logs)
|
||||||
logs: make(map[common.Hash]vm.Logs),
|
self.logSize = 0
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// openTrie creates a trie. It uses an existing trie if one is available
|
// openTrie creates a trie. It uses an existing trie if one is available
|
||||||
// from the journal if available.
|
// from the journal if available.
|
||||||
func (self *StateDB) openTrie(root common.Hash) (*trie.SecureTrie, error) {
|
func (self *StateDB) openTrie(root common.Hash) (*trie.SecureTrie, error) {
|
||||||
if self.trie != nil && self.trie.Hash() == root {
|
|
||||||
cpy := *self.trie
|
|
||||||
return &cpy, nil
|
|
||||||
}
|
|
||||||
for i := len(self.pastTries) - 1; i >= 0; i-- {
|
for i := len(self.pastTries) - 1; i >= 0; i-- {
|
||||||
if self.pastTries[i].Hash() == root {
|
if self.pastTries[i].Hash() == root {
|
||||||
tr := *self.pastTries[i]
|
tr := *self.pastTries[i]
|
||||||
|
|
@ -142,6 +146,9 @@ func (self *StateDB) openTrie(root common.Hash) (*trie.SecureTrie, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) pushTrie(t *trie.SecureTrie) {
|
func (self *StateDB) pushTrie(t *trie.SecureTrie) {
|
||||||
|
self.lock.Lock()
|
||||||
|
defer self.lock.Unlock()
|
||||||
|
|
||||||
if len(self.pastTries) >= maxJournalLength {
|
if len(self.pastTries) >= maxJournalLength {
|
||||||
copy(self.pastTries, self.pastTries[1:])
|
copy(self.pastTries, self.pastTries[1:])
|
||||||
self.pastTries[len(self.pastTries)-1] = t
|
self.pastTries[len(self.pastTries)-1] = t
|
||||||
|
|
@ -401,6 +408,9 @@ func (self *StateDB) CreateAccount(addr common.Address) vm.Account {
|
||||||
//
|
//
|
||||||
|
|
||||||
func (self *StateDB) Copy() *StateDB {
|
func (self *StateDB) Copy() *StateDB {
|
||||||
|
self.lock.Lock()
|
||||||
|
defer self.lock.Unlock()
|
||||||
|
|
||||||
// Copy all the basic fields, initialize the memory ones
|
// Copy all the basic fields, initialize the memory ones
|
||||||
state := &StateDB{
|
state := &StateDB{
|
||||||
db: self.db,
|
db: self.db,
|
||||||
|
|
@ -426,6 +436,9 @@ func (self *StateDB) Copy() *StateDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateDB) Set(state *StateDB) {
|
func (self *StateDB) Set(state *StateDB) {
|
||||||
|
self.lock.Lock()
|
||||||
|
defer self.lock.Unlock()
|
||||||
|
|
||||||
self.db = state.db
|
self.db = state.db
|
||||||
self.trie = state.trie
|
self.trie = state.trie
|
||||||
self.pastTries = state.pastTries
|
self.pastTries = state.pastTries
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue