diff --git a/core/state/database.go b/core/state/database.go index 3a0ac422ee..58d0ccfe82 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -302,6 +302,8 @@ func mustCopyTrie(t Trie) Trie { return t.Copy() case *trie.VerkleTrie: return t.Copy() + case *trie.TransitionTrie: + return t.Copy() default: panic(fmt.Errorf("unknown trie type %T", t)) } diff --git a/core/state/state_object.go b/core/state/state_object.go index 2938750503..fdeb4254c1 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie/trienode" "github.com/holiman/uint256" ) @@ -494,8 +495,20 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject { selfDestructed: s.selfDestructed, newContract: s.newContract, } - if s.trie != nil { + + switch s.trie.(type) { + case *trie.VerkleTrie: + // Verkle uses only one tree, and the copy has already been + // made in mustCopyTrie. + obj.trie = db.trie + case *trie.TransitionTrie: + // Same thing for the transition tree, since the MPT is + // read-only. + obj.trie = db.trie + case *trie.StateTrie: obj.trie = mustCopyTrie(s.trie) + case nil: + // do nothing } return obj } diff --git a/trie/transition.go b/trie/transition.go index da49c6cdc2..c6eecd3937 100644 --- a/trie/transition.go +++ b/trie/transition.go @@ -211,7 +211,8 @@ func (t *TransitionTrie) UpdateStem(key []byte, values [][]byte) error { func (t *TransitionTrie) Copy() *TransitionTrie { return &TransitionTrie{ overlay: t.overlay.Copy(), - base: t.base.Copy(), + // base in immutable, so there is no need to copy it + base: t.base, storage: t.storage, } }