diff options
Diffstat (limited to 'core/state/statedb_test.go')
-rw-r--r-- | core/state/statedb_test.go | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index bf073bc94..bb3b87ead 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -449,3 +449,38 @@ func TestCopyOfCopy(t *testing.T) { t.Fatalf("2nd copy fail, expected 42, got %v", got) } } + +// TestDeleteCreateRevert tests a weird state transition corner case that we hit +// while changing the internals of statedb. The workflow is that a contract is +// self destructed, then in a followup transaction (but same block) it's created +// again and the transaction reverted. +// +// The original statedb implementation flushed dirty objects to the tries after +// each transaction, so this works ok. The rework accumulated writes in memory +// first, but the journal wiped the entire state object on create-revert. +func TestDeleteCreateRevert(t *testing.T) { + // Create an initial state with a single contract + state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) + + addr := toAddr([]byte("so")) + state.SetBalance(addr, big.NewInt(1)) + + root, _ := state.Commit(false) + state.Reset(root) + + // Simulate self-destructing in one transaction, then create-reverting in another + state.Suicide(addr) + state.Finalise(true) + + id := state.Snapshot() + state.SetBalance(addr, big.NewInt(2)) + state.RevertToSnapshot(id) + + // Commit the entire state and make sure we don't crash and have the correct state + root, _ = state.Commit(true) + state.Reset(root) + + if state.getStateObject(addr) != nil { + t.Fatalf("self-destructed contract came alive") + } +} |