Skip to content

core/state: deleted field in StateObject Copy() and unit test #1781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 9, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ func (self *StateObject) Copy() *StateObject {
stateObject.gasPool.Set(self.gasPool)
stateObject.remove = self.remove
stateObject.dirty = self.dirty
stateObject.deleted = self.deleted

return stateObject
}
Expand Down
104 changes: 104 additions & 0 deletions core/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package state

import (
"bytes"
"math/big"
"testing"

Expand Down Expand Up @@ -117,3 +118,106 @@ func (s *StateSuite) TestSnapshot(c *checker.C) {

c.Assert(data1, checker.DeepEquals, res)
}

// use testing instead of checker because checker does not support
// printing/logging in tests (-check.vv does not work)
func TestSnapshot2(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
state := New(common.Hash{}, db)

stateobjaddr0 := toAddr([]byte("so0"))
stateobjaddr1 := toAddr([]byte("so1"))
var storageaddr common.Hash

data0 := common.BytesToHash([]byte{17})
data1 := common.BytesToHash([]byte{18})

state.SetState(stateobjaddr0, storageaddr, data0)
state.SetState(stateobjaddr1, storageaddr, data1)

// db, trie are already non-empty values
so0 := state.GetStateObject(stateobjaddr0)
so0.balance = big.NewInt(42)
so0.nonce = 43
so0.gasPool = big.NewInt(44)
so0.code = []byte{'c', 'a', 'f', 'e'}
so0.codeHash = so0.CodeHash()
so0.remove = true
so0.deleted = false
so0.dirty = false
state.SetStateObject(so0)

// and one with deleted == true
so1 := state.GetStateObject(stateobjaddr1)
so1.balance = big.NewInt(52)
so1.nonce = 53
so1.gasPool = big.NewInt(54)
so1.code = []byte{'c', 'a', 'f', 'e', '2'}
so1.codeHash = so1.CodeHash()
so1.remove = true
so1.deleted = true
so1.dirty = true
state.SetStateObject(so1)

so1 = state.GetStateObject(stateobjaddr1)
if so1 != nil {
t.Fatalf("deleted object not nil when getting")
}

snapshot := state.Copy()
state.Set(snapshot)

so0Restored := state.GetStateObject(stateobjaddr0)
so1Restored := state.GetStateObject(stateobjaddr1)
// non-deleted is equal (restored)
compareStateObjects(so0Restored, so0, t)
// deleted should be nil, both before and after restore of state copy
if so1Restored != nil {
t.Fatalf("deleted object not nil after restoring snapshot")
}
}

func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
if so0.address != so1.address {
t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address)
}
if so0.balance.Cmp(so1.balance) != 0 {
t.Fatalf("Balance mismatch: have %v, want %v", so0.balance, so1.balance)
}
if so0.nonce != so1.nonce {
t.Fatalf("Nonce mismatch: have %v, want %v", so0.nonce, so1.nonce)
}
if !bytes.Equal(so0.codeHash, so1.codeHash) {
t.Fatalf("CodeHash mismatch: have %v, want %v", so0.codeHash, so1.codeHash)
}
if !bytes.Equal(so0.code, so1.code) {
t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code)
}
if !bytes.Equal(so0.initCode, so1.initCode) {
t.Fatalf("InitCode mismatch: have %v, want %v", so0.initCode, so1.initCode)
}

for k, v := range so1.storage {
if so0.storage[k] != v {
t.Fatalf("Storage key %s mismatch: have %v, want %v", k, so0.storage[k], v)
}
}
for k, v := range so0.storage {
if so1.storage[k] != v {
t.Fatalf("Storage key %s mismatch: have %v, want none.", k, v)
}
}

if so0.gasPool.Cmp(so1.gasPool) != 0 {
t.Fatalf("GasPool mismatch: have %v, want %v", so0.gasPool, so1.gasPool)
}
if so0.remove != so1.remove {
t.Fatalf("Remove mismatch: have %v, want %v", so0.remove, so1.remove)
}
if so0.deleted != so1.deleted {
t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted)
}
if so0.dirty != so1.dirty {
t.Fatalf("Dirty mismatch: have %v, want %v", so0.dirty, so1.dirty)
}
}