Skip to content

Commit 5a79aca

Browse files
authored
Merge pull request #16485 from holiman/fixcopycopy
core/state: fix bug in copy of copy State
2 parents e7cc5b4 + 0c7b99b commit 5a79aca

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

core/state/statedb.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,16 @@ func (self *StateDB) Copy() *StateDB {
474474
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state)
475475
state.stateObjectsDirty[addr] = struct{}{}
476476
}
477+
// Above, we don't copy the actual journal. This means that if the copy is copied, the
478+
// loop above will be a no-op, since the copy's journal is empty.
479+
// Thus, here we iterate over stateObjects, to enable copies of copies
480+
for addr := range self.stateObjectsDirty {
481+
if _, exist := state.stateObjects[addr]; !exist {
482+
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state)
483+
state.stateObjectsDirty[addr] = struct{}{}
484+
}
485+
}
486+
477487
for hash, logs := range self.logs {
478488
state.logs[hash] = make([]*types.Log, len(logs))
479489
copy(state.logs[hash], logs)

core/state/statedb_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,19 @@ func (s *StateSuite) TestTouchDelete(c *check.C) {
422422
c.Fatal("expected no dirty state object")
423423
}
424424
}
425+
426+
// TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
427+
// See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512
428+
func TestCopyOfCopy(t *testing.T) {
429+
db, _ := ethdb.NewMemDatabase()
430+
sdb, _ := New(common.Hash{}, NewDatabase(db))
431+
addr := common.HexToAddress("aaaa")
432+
sdb.SetBalance(addr, big.NewInt(42))
433+
434+
if got := sdb.Copy().GetBalance(addr).Uint64(); got != 42 {
435+
t.Fatalf("1st copy fail, expected 42, got %v", got)
436+
}
437+
if got := sdb.Copy().Copy().GetBalance(addr).Uint64(); got != 42 {
438+
t.Fatalf("2nd copy fail, expected 42, got %v", got)
439+
}
440+
}

0 commit comments

Comments
 (0)