github.com/chainopen/ethchaincode@v0.0.0-20190924072703-d975acdaa1c6/core/state/statedb_test.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package state 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "fmt" 23 "math" 24 "math/big" 25 "math/rand" 26 "reflect" 27 "strings" 28 "testing" 29 "testing/quick" 30 31 check "gopkg.in/check.v1" 32 33 "github.com/ethereum/go-ethereum/common" 34 "github.com/ethereum/go-ethereum/core/rawdb" 35 "github.com/ethereum/go-ethereum/core/types" 36 ) 37 38 // Tests that updating a state trie does not leak any database writes prior to 39 // actually committing the state. 40 func TestUpdateLeaks(t *testing.T) { 41 // Create an empty state database 42 db := rawdb.NewMemoryDatabase() 43 state, _ := New(common.Hash{}, NewDatabase(db)) 44 45 // Update it with some accounts 46 for i := byte(0); i < 255; i++ { 47 addr := common.BytesToAddress([]byte{i}) 48 state.AddBalance(addr, big.NewInt(int64(11*i))) 49 state.SetNonce(addr, uint64(42*i)) 50 if i%2 == 0 { 51 state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) 52 } 53 if i%3 == 0 { 54 state.SetCode(addr, []byte{i, i, i, i, i}) 55 } 56 state.IntermediateRoot(false) 57 } 58 // Ensure that no data was leaked into the database 59 it := db.NewIterator() 60 for it.Next() { 61 t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value()) 62 } 63 it.Release() 64 } 65 66 // Tests that no intermediate state of an object is stored into the database, 67 // only the one right before the commit. 68 func TestIntermediateLeaks(t *testing.T) { 69 // Create two state databases, one transitioning to the final state, the other final from the beginning 70 transDb := rawdb.NewMemoryDatabase() 71 finalDb := rawdb.NewMemoryDatabase() 72 transState, _ := New(common.Hash{}, NewDatabase(transDb)) 73 finalState, _ := New(common.Hash{}, NewDatabase(finalDb)) 74 75 modify := func(state *StateDB, addr common.Address, i, tweak byte) { 76 state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak))) 77 state.SetNonce(addr, uint64(42*i+tweak)) 78 if i%2 == 0 { 79 state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{}) 80 state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak}) 81 } 82 if i%3 == 0 { 83 state.SetCode(addr, []byte{i, i, i, i, i, tweak}) 84 } 85 } 86 87 // Modify the transient state. 88 for i := byte(0); i < 255; i++ { 89 modify(transState, common.Address{i}, i, 0) 90 } 91 // Write modifications to trie. 92 transState.IntermediateRoot(false) 93 94 // Overwrite all the data with new values in the transient database. 95 for i := byte(0); i < 255; i++ { 96 modify(transState, common.Address{i}, i, 99) 97 modify(finalState, common.Address{i}, i, 99) 98 } 99 100 // Commit and cross check the databases. 101 if _, err := transState.Commit(false); err != nil { 102 t.Fatalf("failed to commit transition state: %v", err) 103 } 104 if _, err := finalState.Commit(false); err != nil { 105 t.Fatalf("failed to commit final state: %v", err) 106 } 107 it := finalDb.NewIterator() 108 for it.Next() { 109 key := it.Key() 110 if _, err := transDb.Get(key); err != nil { 111 t.Errorf("entry missing from the transition database: %x -> %x", key, it.Value()) 112 } 113 } 114 it.Release() 115 116 it = transDb.NewIterator() 117 for it.Next() { 118 key := it.Key() 119 if _, err := finalDb.Get(key); err != nil { 120 t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value()) 121 } 122 } 123 } 124 125 // TestCopy tests that copying a statedb object indeed makes the original and 126 // the copy independent of each other. This test is a regression test against 127 // https://github.com/ethereum/go-ethereum/pull/15549. 128 func TestCopy(t *testing.T) { 129 // Create a random state test to copy and modify "independently" 130 orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 131 132 for i := byte(0); i < 255; i++ { 133 obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 134 obj.AddBalance(big.NewInt(int64(i))) 135 orig.updateStateObject(obj) 136 } 137 orig.Finalise(false) 138 139 // Copy the state, modify both in-memory 140 copy := orig.Copy() 141 142 for i := byte(0); i < 255; i++ { 143 origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 144 copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 145 146 origObj.AddBalance(big.NewInt(2 * int64(i))) 147 copyObj.AddBalance(big.NewInt(3 * int64(i))) 148 149 orig.updateStateObject(origObj) 150 copy.updateStateObject(copyObj) 151 } 152 // Finalise the changes on both concurrently 153 done := make(chan struct{}) 154 go func() { 155 orig.Finalise(true) 156 close(done) 157 }() 158 copy.Finalise(true) 159 <-done 160 161 // Verify that the two states have been updated independently 162 for i := byte(0); i < 255; i++ { 163 origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 164 copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 165 166 if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 { 167 t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want) 168 } 169 if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 { 170 t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want) 171 } 172 } 173 } 174 175 func TestSnapshotRandom(t *testing.T) { 176 config := &quick.Config{MaxCount: 1000} 177 err := quick.Check((*snapshotTest).run, config) 178 if cerr, ok := err.(*quick.CheckError); ok { 179 test := cerr.In[0].(*snapshotTest) 180 t.Errorf("%v:\n%s", test.err, test) 181 } else if err != nil { 182 t.Error(err) 183 } 184 } 185 186 // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes 187 // captured by the snapshot. Instances of this test with pseudorandom content are created 188 // by Generate. 189 // 190 // The test works as follows: 191 // 192 // A new state is created and all actions are applied to it. Several snapshots are taken 193 // in between actions. The test then reverts each snapshot. For each snapshot the actions 194 // leading up to it are replayed on a fresh, empty state. The behaviour of all public 195 // accessor methods on the reverted state must match the return value of the equivalent 196 // methods on the replayed state. 197 type snapshotTest struct { 198 addrs []common.Address // all account addresses 199 actions []testAction // modifications to the state 200 snapshots []int // actions indexes at which snapshot is taken 201 err error // failure details are reported through this field 202 } 203 204 type testAction struct { 205 name string 206 fn func(testAction, *StateDB) 207 args []int64 208 noAddr bool 209 } 210 211 // newTestAction creates a random action that changes state. 212 func newTestAction(addr common.Address, r *rand.Rand) testAction { 213 actions := []testAction{ 214 { 215 name: "SetBalance", 216 fn: func(a testAction, s *StateDB) { 217 s.SetBalance(addr, big.NewInt(a.args[0])) 218 }, 219 args: make([]int64, 1), 220 }, 221 { 222 name: "AddBalance", 223 fn: func(a testAction, s *StateDB) { 224 s.AddBalance(addr, big.NewInt(a.args[0])) 225 }, 226 args: make([]int64, 1), 227 }, 228 { 229 name: "SetNonce", 230 fn: func(a testAction, s *StateDB) { 231 s.SetNonce(addr, uint64(a.args[0])) 232 }, 233 args: make([]int64, 1), 234 }, 235 { 236 name: "SetState", 237 fn: func(a testAction, s *StateDB) { 238 var key, val common.Hash 239 binary.BigEndian.PutUint16(key[:], uint16(a.args[0])) 240 binary.BigEndian.PutUint16(val[:], uint16(a.args[1])) 241 s.SetState(addr, key, val) 242 }, 243 args: make([]int64, 2), 244 }, 245 { 246 name: "SetCode", 247 fn: func(a testAction, s *StateDB) { 248 code := make([]byte, 16) 249 binary.BigEndian.PutUint64(code, uint64(a.args[0])) 250 binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) 251 s.SetCode(addr, code) 252 }, 253 args: make([]int64, 2), 254 }, 255 { 256 name: "CreateAccount", 257 fn: func(a testAction, s *StateDB) { 258 s.CreateAccount(addr) 259 }, 260 }, 261 { 262 name: "Suicide", 263 fn: func(a testAction, s *StateDB) { 264 s.Suicide(addr) 265 }, 266 }, 267 { 268 name: "AddRefund", 269 fn: func(a testAction, s *StateDB) { 270 s.AddRefund(uint64(a.args[0])) 271 }, 272 args: make([]int64, 1), 273 noAddr: true, 274 }, 275 { 276 name: "AddLog", 277 fn: func(a testAction, s *StateDB) { 278 data := make([]byte, 2) 279 binary.BigEndian.PutUint16(data, uint16(a.args[0])) 280 s.AddLog(&types.Log{Address: addr, Data: data}) 281 }, 282 args: make([]int64, 1), 283 }, 284 { 285 name: "AddPreimage", 286 fn: func(a testAction, s *StateDB) { 287 preimage := []byte{1} 288 hash := common.BytesToHash(preimage) 289 s.AddPreimage(hash, preimage) 290 }, 291 args: make([]int64, 1), 292 }, 293 } 294 action := actions[r.Intn(len(actions))] 295 var nameargs []string 296 if !action.noAddr { 297 nameargs = append(nameargs, addr.Hex()) 298 } 299 for i := range action.args { 300 action.args[i] = rand.Int63n(100) 301 nameargs = append(nameargs, fmt.Sprint(action.args[i])) 302 } 303 action.name += strings.Join(nameargs, ", ") 304 return action 305 } 306 307 // Generate returns a new snapshot test of the given size. All randomness is 308 // derived from r. 309 func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value { 310 // Generate random actions. 311 addrs := make([]common.Address, 50) 312 for i := range addrs { 313 addrs[i][0] = byte(i) 314 } 315 actions := make([]testAction, size) 316 for i := range actions { 317 addr := addrs[r.Intn(len(addrs))] 318 actions[i] = newTestAction(addr, r) 319 } 320 // Generate snapshot indexes. 321 nsnapshots := int(math.Sqrt(float64(size))) 322 if size > 0 && nsnapshots == 0 { 323 nsnapshots = 1 324 } 325 snapshots := make([]int, nsnapshots) 326 snaplen := len(actions) / nsnapshots 327 for i := range snapshots { 328 // Try to place the snapshots some number of actions apart from each other. 329 snapshots[i] = (i * snaplen) + r.Intn(snaplen) 330 } 331 return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil}) 332 } 333 334 func (test *snapshotTest) String() string { 335 out := new(bytes.Buffer) 336 sindex := 0 337 for i, action := range test.actions { 338 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 339 fmt.Fprintf(out, "---- snapshot %d ----\n", sindex) 340 sindex++ 341 } 342 fmt.Fprintf(out, "%4d: %s\n", i, action.name) 343 } 344 return out.String() 345 } 346 347 func (test *snapshotTest) run() bool { 348 // Run all actions and create snapshots. 349 var ( 350 state, _ = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 351 snapshotRevs = make([]int, len(test.snapshots)) 352 sindex = 0 353 ) 354 for i, action := range test.actions { 355 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 356 snapshotRevs[sindex] = state.Snapshot() 357 sindex++ 358 } 359 action.fn(action, state) 360 } 361 // Revert all snapshots in reverse order. Each revert must yield a state 362 // that is equivalent to fresh state with all actions up the snapshot applied. 363 for sindex--; sindex >= 0; sindex-- { 364 checkstate, _ := New(common.Hash{}, state.Database()) 365 for _, action := range test.actions[:test.snapshots[sindex]] { 366 action.fn(action, checkstate) 367 } 368 state.RevertToSnapshot(snapshotRevs[sindex]) 369 if err := test.checkEqual(state, checkstate); err != nil { 370 test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err) 371 return false 372 } 373 } 374 return true 375 } 376 377 // checkEqual checks that methods of state and checkstate return the same values. 378 func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { 379 for _, addr := range test.addrs { 380 var err error 381 checkeq := func(op string, a, b interface{}) bool { 382 if err == nil && !reflect.DeepEqual(a, b) { 383 err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b) 384 return false 385 } 386 return true 387 } 388 // Check basic accessor methods. 389 checkeq("Exist", state.Exist(addr), checkstate.Exist(addr)) 390 checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr)) 391 checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr)) 392 checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) 393 checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) 394 checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) 395 checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) 396 // Check storage. 397 if obj := state.getStateObject(addr); obj != nil { 398 state.ForEachStorage(addr, func(key, value common.Hash) bool { 399 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 400 }) 401 checkstate.ForEachStorage(addr, func(key, value common.Hash) bool { 402 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 403 }) 404 } 405 if err != nil { 406 return err 407 } 408 } 409 410 if state.GetRefund() != checkstate.GetRefund() { 411 return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", 412 state.GetRefund(), checkstate.GetRefund()) 413 } 414 if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) { 415 return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", 416 state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) 417 } 418 return nil 419 } 420 421 func (s *StateSuite) TestTouchDelete(c *check.C) { 422 s.state.GetOrNewStateObject(common.Address{}) 423 root, _ := s.state.Commit(false) 424 s.state.Reset(root) 425 426 snapshot := s.state.Snapshot() 427 s.state.AddBalance(common.Address{}, new(big.Int)) 428 429 if len(s.state.journal.dirties) != 1 { 430 c.Fatal("expected one dirty state object") 431 } 432 s.state.RevertToSnapshot(snapshot) 433 if len(s.state.journal.dirties) != 0 { 434 c.Fatal("expected no dirty state object") 435 } 436 } 437 438 // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy. 439 // See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512 440 func TestCopyOfCopy(t *testing.T) { 441 sdb, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 442 addr := common.HexToAddress("aaaa") 443 sdb.SetBalance(addr, big.NewInt(42)) 444 445 if got := sdb.Copy().GetBalance(addr).Uint64(); got != 42 { 446 t.Fatalf("1st copy fail, expected 42, got %v", got) 447 } 448 if got := sdb.Copy().Copy().GetBalance(addr).Uint64(); got != 42 { 449 t.Fatalf("2nd copy fail, expected 42, got %v", got) 450 } 451 } 452 453 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 454 // while changing the internals of statedb. The workflow is that a contract is 455 // self destructed, then in a followup transaction (but same block) it's created 456 // again and the transaction reverted. 457 // 458 // The original statedb implementation flushed dirty objects to the tries after 459 // each transaction, so this works ok. The rework accumulated writes in memory 460 // first, but the journal wiped the entire state object on create-revert. 461 func TestDeleteCreateRevert(t *testing.T) { 462 // Create an initial state with a single contract 463 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase())) 464 465 addr := toAddr([]byte("so")) 466 state.SetBalance(addr, big.NewInt(1)) 467 468 root, _ := state.Commit(false) 469 state.Reset(root) 470 471 // Simulate self-destructing in one transaction, then create-reverting in another 472 state.Suicide(addr) 473 state.Finalise(true) 474 475 id := state.Snapshot() 476 state.SetBalance(addr, big.NewInt(2)) 477 state.RevertToSnapshot(id) 478 479 // Commit the entire state and make sure we don't crash and have the correct state 480 root, _ = state.Commit(true) 481 state.Reset(root) 482 483 if state.getStateObject(addr) != nil { 484 t.Fatalf("self-destructed contract came alive") 485 } 486 }