forked from cerc-io/plugeth
core/state: deleted field in StateObject Copy() and unit test
This commit is contained in:
parent
edaea69817
commit
004ed786b4
@ -263,6 +263,7 @@ func (self *StateObject) Copy() *StateObject {
|
|||||||
stateObject.gasPool.Set(self.gasPool)
|
stateObject.gasPool.Set(self.gasPool)
|
||||||
stateObject.remove = self.remove
|
stateObject.remove = self.remove
|
||||||
stateObject.dirty = self.dirty
|
stateObject.dirty = self.dirty
|
||||||
|
stateObject.deleted = self.deleted
|
||||||
|
|
||||||
return stateObject
|
return stateObject
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -117,3 +118,106 @@ func (s *StateSuite) TestSnapshot(c *checker.C) {
|
|||||||
|
|
||||||
c.Assert(data1, checker.DeepEquals, res)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user