github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/core/state/state_test.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package state 13 14 import ( 15 "bytes" 16 "math/big" 17 "testing" 18 19 "github.com/Sberex/go-sberex/common" 20 "github.com/Sberex/go-sberex/crypto" 21 "github.com/Sberex/go-sberex/ethdb" 22 checker "gopkg.in/check.v1" 23 ) 24 25 type StateSuite struct { 26 db *ethdb.MemDatabase 27 state *StateDB 28 } 29 30 var _ = checker.Suite(&StateSuite{}) 31 32 var toAddr = common.BytesToAddress 33 34 func (s *StateSuite) TestDump(c *checker.C) { 35 // generate a few entries 36 obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01})) 37 obj1.AddBalance(big.NewInt(22)) 38 obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02})) 39 obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) 40 obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02})) 41 obj3.SetBalance(big.NewInt(44)) 42 43 // write some of them to the trie 44 s.state.updateStateObject(obj1) 45 s.state.updateStateObject(obj2) 46 s.state.Commit(false) 47 48 // check that dump contains the state objects that are in trie 49 got := string(s.state.Dump()) 50 want := `{ 51 "root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2", 52 "accounts": { 53 "0000000000000000000000000000000000000001": { 54 "balance": "22", 55 "nonce": 0, 56 "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 57 "codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 58 "code": "", 59 "storage": {} 60 }, 61 "0000000000000000000000000000000000000002": { 62 "balance": "44", 63 "nonce": 0, 64 "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 65 "codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 66 "code": "", 67 "storage": {} 68 }, 69 "0000000000000000000000000000000000000102": { 70 "balance": "0", 71 "nonce": 0, 72 "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 73 "codeHash": "87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3", 74 "code": "03030303030303", 75 "storage": {} 76 } 77 } 78 }` 79 if got != want { 80 c.Errorf("dump mismatch:\ngot: %s\nwant: %s\n", got, want) 81 } 82 } 83 84 func (s *StateSuite) SetUpTest(c *checker.C) { 85 s.db, _ = ethdb.NewMemDatabase() 86 s.state, _ = New(common.Hash{}, NewDatabase(s.db)) 87 } 88 89 func (s *StateSuite) TestNull(c *checker.C) { 90 address := common.HexToAddress("0x823140710bf13990e4500136726d8b55") 91 s.state.CreateAccount(address) 92 //value := common.FromHex("0x823140710bf13990e4500136726d8b55") 93 var value common.Hash 94 s.state.SetState(address, common.Hash{}, value) 95 s.state.Commit(false) 96 value = s.state.GetState(address, common.Hash{}) 97 if !common.EmptyHash(value) { 98 c.Errorf("expected empty hash. got %x", value) 99 } 100 } 101 102 func (s *StateSuite) TestSnapshot(c *checker.C) { 103 stateobjaddr := toAddr([]byte("aa")) 104 var storageaddr common.Hash 105 data1 := common.BytesToHash([]byte{42}) 106 data2 := common.BytesToHash([]byte{43}) 107 108 // set initial state object value 109 s.state.SetState(stateobjaddr, storageaddr, data1) 110 // get snapshot of current state 111 snapshot := s.state.Snapshot() 112 113 // set new state object value 114 s.state.SetState(stateobjaddr, storageaddr, data2) 115 // restore snapshot 116 s.state.RevertToSnapshot(snapshot) 117 118 // get state storage value 119 res := s.state.GetState(stateobjaddr, storageaddr) 120 121 c.Assert(data1, checker.DeepEquals, res) 122 } 123 124 func (s *StateSuite) TestSnapshotEmpty(c *checker.C) { 125 s.state.RevertToSnapshot(s.state.Snapshot()) 126 } 127 128 // use testing instead of checker because checker does not support 129 // printing/logging in tests (-check.vv does not work) 130 func TestSnapshot2(t *testing.T) { 131 db, _ := ethdb.NewMemDatabase() 132 state, _ := New(common.Hash{}, NewDatabase(db)) 133 134 stateobjaddr0 := toAddr([]byte("so0")) 135 stateobjaddr1 := toAddr([]byte("so1")) 136 var storageaddr common.Hash 137 138 data0 := common.BytesToHash([]byte{17}) 139 data1 := common.BytesToHash([]byte{18}) 140 141 state.SetState(stateobjaddr0, storageaddr, data0) 142 state.SetState(stateobjaddr1, storageaddr, data1) 143 144 // db, trie are already non-empty values 145 so0 := state.getStateObject(stateobjaddr0) 146 so0.SetBalance(big.NewInt(42)) 147 so0.SetNonce(43) 148 so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}) 149 so0.suicided = false 150 so0.deleted = false 151 state.setStateObject(so0) 152 153 root, _ := state.Commit(false) 154 state.Reset(root) 155 156 // and one with deleted == true 157 so1 := state.getStateObject(stateobjaddr1) 158 so1.SetBalance(big.NewInt(52)) 159 so1.SetNonce(53) 160 so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'}) 161 so1.suicided = true 162 so1.deleted = true 163 state.setStateObject(so1) 164 165 so1 = state.getStateObject(stateobjaddr1) 166 if so1 != nil { 167 t.Fatalf("deleted object not nil when getting") 168 } 169 170 snapshot := state.Snapshot() 171 state.RevertToSnapshot(snapshot) 172 173 so0Restored := state.getStateObject(stateobjaddr0) 174 // Update lazily-loaded values before comparing. 175 so0Restored.GetState(state.db, storageaddr) 176 so0Restored.Code(state.db) 177 // non-deleted is equal (restored) 178 compareStateObjects(so0Restored, so0, t) 179 180 // deleted should be nil, both before and after restore of state copy 181 so1Restored := state.getStateObject(stateobjaddr1) 182 if so1Restored != nil { 183 t.Fatalf("deleted object not nil after restoring snapshot: %+v", so1Restored) 184 } 185 } 186 187 func compareStateObjects(so0, so1 *stateObject, t *testing.T) { 188 if so0.Address() != so1.Address() { 189 t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address) 190 } 191 if so0.Balance().Cmp(so1.Balance()) != 0 { 192 t.Fatalf("Balance mismatch: have %v, want %v", so0.Balance(), so1.Balance()) 193 } 194 if so0.Nonce() != so1.Nonce() { 195 t.Fatalf("Nonce mismatch: have %v, want %v", so0.Nonce(), so1.Nonce()) 196 } 197 if so0.data.Root != so1.data.Root { 198 t.Errorf("Root mismatch: have %x, want %x", so0.data.Root[:], so1.data.Root[:]) 199 } 200 if !bytes.Equal(so0.CodeHash(), so1.CodeHash()) { 201 t.Fatalf("CodeHash mismatch: have %v, want %v", so0.CodeHash(), so1.CodeHash()) 202 } 203 if !bytes.Equal(so0.code, so1.code) { 204 t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code) 205 } 206 207 if len(so1.cachedStorage) != len(so0.cachedStorage) { 208 t.Errorf("Storage size mismatch: have %d, want %d", len(so1.cachedStorage), len(so0.cachedStorage)) 209 } 210 for k, v := range so1.cachedStorage { 211 if so0.cachedStorage[k] != v { 212 t.Errorf("Storage key %x mismatch: have %v, want %v", k, so0.cachedStorage[k], v) 213 } 214 } 215 for k, v := range so0.cachedStorage { 216 if so1.cachedStorage[k] != v { 217 t.Errorf("Storage key %x mismatch: have %v, want none.", k, v) 218 } 219 } 220 221 if so0.suicided != so1.suicided { 222 t.Fatalf("suicided mismatch: have %v, want %v", so0.suicided, so1.suicided) 223 } 224 if so0.deleted != so1.deleted { 225 t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted) 226 } 227 }