diff --git a/core/state/state_object.go b/core/state/state_object.go index 97d9cd4ebb..872b175d77 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "math/big" + "sync" "time" "github.com/ethereum/go-ethereum/common" @@ -73,6 +74,7 @@ type stateObject struct { trie Trie // storage trie, which becomes non-nil on first access code Code // contract bytecode, which gets set when code is loaded + storageMutex sync.Mutex originStorage Storage // Storage cache of original entries to dedup rewrites pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block dirtyStorage Storage // Storage entries that have been modified in the current transaction execution, reset for every transaction @@ -175,6 +177,8 @@ func (s *stateObject) GetState(key common.Hash) common.Hash { // GetCommittedState retrieves a value from the committed account storage trie. func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { + s.storageMutex.Lock() + defer s.storageMutex.Unlock() // If we have a pending write or clean cached, return that if value, pending := s.pendingStorage[key]; pending { return value @@ -183,6 +187,7 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { if value, cached := s.originStorage[key]; cached { return value } + // If the object was destructed in *this* block (and potentially resurrected), // the storage has been cleared out, and we should *not* consult the previous // database about any storage values. The only possible alternatives are: