Răsfoiți Sursa

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

Gustav Simonsson 10 ani în urmă
părinte
comite
004ed786b4
2 a modificat fișierele cu 105 adăugiri și 0 ștergeri
  1. 1 0
      core/state/state_object.go
  2. 104 0
      core/state/state_test.go

+ 1 - 0
core/state/state_object.go

@@ -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
 }

+ 104 - 0
core/state/state_test.go

@@ -17,6 +17,7 @@
 package state
 
 import (
+	"bytes"
 	"math/big"
 	"testing"
 
@@ -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(so0, so0Restored, 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("\nexpected %v\ngot %v", so0.address, so1.address)
+	}
+	if so0.balance.Cmp(so1.balance) != 0 {
+		t.Fatalf("\nexpected %v\ngot %v", so0.balance, so1.balance)
+	}
+	if so0.nonce != so1.nonce {
+		t.Fatalf("\nexpected %v\ngot %v", so0.nonce, so1.nonce)
+	}
+	if !bytes.Equal(so0.codeHash, so1.codeHash) {
+		t.Fatalf("\nexpected %v\ngot %v", so0.codeHash, so1.codeHash)
+	}
+	if !bytes.Equal(so0.code, so1.code) {
+		t.Fatalf("\nexpected %v\ngot %v", so0.code, so1.code)
+	}
+	if !bytes.Equal(so0.initCode, so1.initCode) {
+		t.Fatalf("\nexpected %v\ngot %v", so0.initCode, so1.initCode)
+	}
+
+	for k, v := range so0.storage {
+		if so1.storage[k] != v {
+			t.Fatalf("\nstorage key %s:\nexpected %v\ngot %v", k, v, so1.storage[k])
+		}
+	}
+	for k, v := range so1.storage {
+		if so0.storage[k] != v {
+			t.Fatalf("\nunexpected k,v : %v, %v", k, v)
+		}
+	}
+
+	if so0.gasPool.Cmp(so1.gasPool) != 0 {
+		t.Fatalf("\nexpected %v\ngot %v", so0.gasPool, so1.gasPool)
+	}
+	if so0.remove != so1.remove {
+		t.Fatalf("\nexpected %v\ngot %v", so0.remove, so1.remove)
+	}
+	if so0.deleted != so1.deleted {
+		t.Fatalf("\nexpected %v\ngot %v", so0.deleted, so1.deleted)
+	}
+	if so0.dirty != so1.dirty {
+		t.Fatalf("\nexpected %v\ngot %v", so0.dirty, so1.dirty)
+	}
+}