github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/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 "sync" 29 "testing" 30 "testing/quick" 31 32 "github.com/zhiqiangxu/go-ethereum/common" 33 "github.com/zhiqiangxu/go-ethereum/core/rawdb" 34 "github.com/zhiqiangxu/go-ethereum/core/types" 35 ) 36 37 // Tests that updating a state trie does not leak any database writes prior to 38 // actually committing the state. 39 func TestUpdateLeaks(t *testing.T) { 40 // Create an empty state database 41 db := rawdb.NewMemoryDatabase() 42 state, _ := New(common.Hash{}, NewDatabase(db), nil) 43 44 // Update it with some accounts 45 for i := byte(0); i < 255; i++ { 46 addr := common.BytesToAddress([]byte{i}) 47 state.AddBalance(addr, big.NewInt(int64(11*i))) 48 state.SetNonce(addr, uint64(42*i)) 49 if i%2 == 0 { 50 state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) 51 } 52 if i%3 == 0 { 53 state.SetCode(addr, []byte{i, i, i, i, i}) 54 } 55 } 56 57 root := state.IntermediateRoot(false) 58 if err := state.Database().TrieDB().Commit(root, false); err != nil { 59 t.Errorf("can not commit trie %v to persistent database", root.Hex()) 60 } 61 62 // Ensure that no data was leaked into the database 63 it := db.NewIterator(nil, nil) 64 for it.Next() { 65 t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value()) 66 } 67 it.Release() 68 } 69 70 // Tests that no intermediate state of an object is stored into the database, 71 // only the one right before the commit. 72 func TestIntermediateLeaks(t *testing.T) { 73 // Create two state databases, one transitioning to the final state, the other final from the beginning 74 transDb := rawdb.NewMemoryDatabase() 75 finalDb := rawdb.NewMemoryDatabase() 76 transState, _ := New(common.Hash{}, NewDatabase(transDb), nil) 77 finalState, _ := New(common.Hash{}, NewDatabase(finalDb), nil) 78 79 modify := func(state *StateDB, addr common.Address, i, tweak byte) { 80 state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak))) 81 state.SetNonce(addr, uint64(42*i+tweak)) 82 if i%2 == 0 { 83 state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{}) 84 state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak}) 85 } 86 if i%3 == 0 { 87 state.SetCode(addr, []byte{i, i, i, i, i, tweak}) 88 } 89 } 90 91 // Modify the transient state. 92 for i := byte(0); i < 255; i++ { 93 modify(transState, common.Address{i}, i, 0) 94 } 95 // Write modifications to trie. 96 transState.IntermediateRoot(false) 97 98 // Overwrite all the data with new values in the transient database. 99 for i := byte(0); i < 255; i++ { 100 modify(transState, common.Address{i}, i, 99) 101 modify(finalState, common.Address{i}, i, 99) 102 } 103 104 // Commit and cross check the databases. 105 transRoot, err := transState.Commit(false) 106 if err != nil { 107 t.Fatalf("failed to commit transition state: %v", err) 108 } 109 if err = transState.Database().TrieDB().Commit(transRoot, false); err != nil { 110 t.Errorf("can not commit trie %v to persistent database", transRoot.Hex()) 111 } 112 113 finalRoot, err := finalState.Commit(false) 114 if err != nil { 115 t.Fatalf("failed to commit final state: %v", err) 116 } 117 if err = finalState.Database().TrieDB().Commit(finalRoot, false); err != nil { 118 t.Errorf("can not commit trie %v to persistent database", finalRoot.Hex()) 119 } 120 121 it := finalDb.NewIterator(nil, nil) 122 for it.Next() { 123 key, fvalue := it.Key(), it.Value() 124 tvalue, err := transDb.Get(key) 125 if err != nil { 126 t.Errorf("entry missing from the transition database: %x -> %x", key, fvalue) 127 } 128 if !bytes.Equal(fvalue, tvalue) { 129 t.Errorf("the value associate key %x is mismatch,: %x in transition database ,%x in final database", key, tvalue, fvalue) 130 } 131 } 132 it.Release() 133 134 it = transDb.NewIterator(nil, nil) 135 for it.Next() { 136 key, tvalue := it.Key(), it.Value() 137 fvalue, err := finalDb.Get(key) 138 if err != nil { 139 t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value()) 140 } 141 if !bytes.Equal(fvalue, tvalue) { 142 t.Errorf("the value associate key %x is mismatch,: %x in transition database ,%x in final database", key, tvalue, fvalue) 143 } 144 } 145 } 146 147 // TestCopy tests that copying a statedb object indeed makes the original and 148 // the copy independent of each other. This test is a regression test against 149 // https://github.com/zhiqiangxu/go-ethereum/pull/15549. 150 func TestCopy(t *testing.T) { 151 // Create a random state test to copy and modify "independently" 152 orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 153 154 for i := byte(0); i < 255; i++ { 155 obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 156 obj.AddBalance(big.NewInt(int64(i))) 157 orig.updateStateObject(obj) 158 } 159 orig.Finalise(false) 160 161 // Copy the state 162 copy := orig.Copy() 163 164 // Copy the copy state 165 ccopy := copy.Copy() 166 167 // modify all in memory 168 for i := byte(0); i < 255; i++ { 169 origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 170 copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 171 ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 172 173 origObj.AddBalance(big.NewInt(2 * int64(i))) 174 copyObj.AddBalance(big.NewInt(3 * int64(i))) 175 ccopyObj.AddBalance(big.NewInt(4 * int64(i))) 176 177 orig.updateStateObject(origObj) 178 copy.updateStateObject(copyObj) 179 ccopy.updateStateObject(copyObj) 180 } 181 182 // Finalise the changes on all concurrently 183 finalise := func(wg *sync.WaitGroup, db *StateDB) { 184 defer wg.Done() 185 db.Finalise(true) 186 } 187 188 var wg sync.WaitGroup 189 wg.Add(3) 190 go finalise(&wg, orig) 191 go finalise(&wg, copy) 192 go finalise(&wg, ccopy) 193 wg.Wait() 194 195 // Verify that the three states have been updated independently 196 for i := byte(0); i < 255; i++ { 197 origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 198 copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 199 ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 200 201 if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 { 202 t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want) 203 } 204 if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 { 205 t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want) 206 } 207 if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 { 208 t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want) 209 } 210 } 211 } 212 213 func TestSnapshotRandom(t *testing.T) { 214 config := &quick.Config{MaxCount: 1000} 215 err := quick.Check((*snapshotTest).run, config) 216 if cerr, ok := err.(*quick.CheckError); ok { 217 test := cerr.In[0].(*snapshotTest) 218 t.Errorf("%v:\n%s", test.err, test) 219 } else if err != nil { 220 t.Error(err) 221 } 222 } 223 224 // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes 225 // captured by the snapshot. Instances of this test with pseudorandom content are created 226 // by Generate. 227 // 228 // The test works as follows: 229 // 230 // A new state is created and all actions are applied to it. Several snapshots are taken 231 // in between actions. The test then reverts each snapshot. For each snapshot the actions 232 // leading up to it are replayed on a fresh, empty state. The behaviour of all public 233 // accessor methods on the reverted state must match the return value of the equivalent 234 // methods on the replayed state. 235 type snapshotTest struct { 236 addrs []common.Address // all account addresses 237 actions []testAction // modifications to the state 238 snapshots []int // actions indexes at which snapshot is taken 239 err error // failure details are reported through this field 240 } 241 242 type testAction struct { 243 name string 244 fn func(testAction, *StateDB) 245 args []int64 246 noAddr bool 247 } 248 249 // newTestAction creates a random action that changes state. 250 func newTestAction(addr common.Address, r *rand.Rand) testAction { 251 actions := []testAction{ 252 { 253 name: "SetBalance", 254 fn: func(a testAction, s *StateDB) { 255 s.SetBalance(addr, big.NewInt(a.args[0])) 256 }, 257 args: make([]int64, 1), 258 }, 259 { 260 name: "AddBalance", 261 fn: func(a testAction, s *StateDB) { 262 s.AddBalance(addr, big.NewInt(a.args[0])) 263 }, 264 args: make([]int64, 1), 265 }, 266 { 267 name: "SetNonce", 268 fn: func(a testAction, s *StateDB) { 269 s.SetNonce(addr, uint64(a.args[0])) 270 }, 271 args: make([]int64, 1), 272 }, 273 { 274 name: "SetState", 275 fn: func(a testAction, s *StateDB) { 276 var key, val common.Hash 277 binary.BigEndian.PutUint16(key[:], uint16(a.args[0])) 278 binary.BigEndian.PutUint16(val[:], uint16(a.args[1])) 279 s.SetState(addr, key, val) 280 }, 281 args: make([]int64, 2), 282 }, 283 { 284 name: "SetCode", 285 fn: func(a testAction, s *StateDB) { 286 code := make([]byte, 16) 287 binary.BigEndian.PutUint64(code, uint64(a.args[0])) 288 binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) 289 s.SetCode(addr, code) 290 }, 291 args: make([]int64, 2), 292 }, 293 { 294 name: "CreateAccount", 295 fn: func(a testAction, s *StateDB) { 296 s.CreateAccount(addr) 297 }, 298 }, 299 { 300 name: "Suicide", 301 fn: func(a testAction, s *StateDB) { 302 s.Suicide(addr) 303 }, 304 }, 305 { 306 name: "AddRefund", 307 fn: func(a testAction, s *StateDB) { 308 s.AddRefund(uint64(a.args[0])) 309 }, 310 args: make([]int64, 1), 311 noAddr: true, 312 }, 313 { 314 name: "AddLog", 315 fn: func(a testAction, s *StateDB) { 316 data := make([]byte, 2) 317 binary.BigEndian.PutUint16(data, uint16(a.args[0])) 318 s.AddLog(&types.Log{Address: addr, Data: data}) 319 }, 320 args: make([]int64, 1), 321 }, 322 { 323 name: "AddPreimage", 324 fn: func(a testAction, s *StateDB) { 325 preimage := []byte{1} 326 hash := common.BytesToHash(preimage) 327 s.AddPreimage(hash, preimage) 328 }, 329 args: make([]int64, 1), 330 }, 331 } 332 action := actions[r.Intn(len(actions))] 333 var nameargs []string 334 if !action.noAddr { 335 nameargs = append(nameargs, addr.Hex()) 336 } 337 for i := range action.args { 338 action.args[i] = rand.Int63n(100) 339 nameargs = append(nameargs, fmt.Sprint(action.args[i])) 340 } 341 action.name += strings.Join(nameargs, ", ") 342 return action 343 } 344 345 // Generate returns a new snapshot test of the given size. All randomness is 346 // derived from r. 347 func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value { 348 // Generate random actions. 349 addrs := make([]common.Address, 50) 350 for i := range addrs { 351 addrs[i][0] = byte(i) 352 } 353 actions := make([]testAction, size) 354 for i := range actions { 355 addr := addrs[r.Intn(len(addrs))] 356 actions[i] = newTestAction(addr, r) 357 } 358 // Generate snapshot indexes. 359 nsnapshots := int(math.Sqrt(float64(size))) 360 if size > 0 && nsnapshots == 0 { 361 nsnapshots = 1 362 } 363 snapshots := make([]int, nsnapshots) 364 snaplen := len(actions) / nsnapshots 365 for i := range snapshots { 366 // Try to place the snapshots some number of actions apart from each other. 367 snapshots[i] = (i * snaplen) + r.Intn(snaplen) 368 } 369 return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil}) 370 } 371 372 func (test *snapshotTest) String() string { 373 out := new(bytes.Buffer) 374 sindex := 0 375 for i, action := range test.actions { 376 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 377 fmt.Fprintf(out, "---- snapshot %d ----\n", sindex) 378 sindex++ 379 } 380 fmt.Fprintf(out, "%4d: %s\n", i, action.name) 381 } 382 return out.String() 383 } 384 385 func (test *snapshotTest) run() bool { 386 // Run all actions and create snapshots. 387 var ( 388 state, _ = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 389 snapshotRevs = make([]int, len(test.snapshots)) 390 sindex = 0 391 ) 392 for i, action := range test.actions { 393 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 394 snapshotRevs[sindex] = state.Snapshot() 395 sindex++ 396 } 397 action.fn(action, state) 398 } 399 // Revert all snapshots in reverse order. Each revert must yield a state 400 // that is equivalent to fresh state with all actions up the snapshot applied. 401 for sindex--; sindex >= 0; sindex-- { 402 checkstate, _ := New(common.Hash{}, state.Database(), nil) 403 for _, action := range test.actions[:test.snapshots[sindex]] { 404 action.fn(action, checkstate) 405 } 406 state.RevertToSnapshot(snapshotRevs[sindex]) 407 if err := test.checkEqual(state, checkstate); err != nil { 408 test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err) 409 return false 410 } 411 } 412 return true 413 } 414 415 // checkEqual checks that methods of state and checkstate return the same values. 416 func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { 417 for _, addr := range test.addrs { 418 var err error 419 checkeq := func(op string, a, b interface{}) bool { 420 if err == nil && !reflect.DeepEqual(a, b) { 421 err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b) 422 return false 423 } 424 return true 425 } 426 // Check basic accessor methods. 427 checkeq("Exist", state.Exist(addr), checkstate.Exist(addr)) 428 checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr)) 429 checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr)) 430 checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) 431 checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) 432 checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) 433 checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) 434 // Check storage. 435 if obj := state.getStateObject(addr); obj != nil { 436 state.ForEachStorage(addr, func(key, value common.Hash) bool { 437 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 438 }) 439 checkstate.ForEachStorage(addr, func(key, value common.Hash) bool { 440 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 441 }) 442 } 443 if err != nil { 444 return err 445 } 446 } 447 448 if state.GetRefund() != checkstate.GetRefund() { 449 return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", 450 state.GetRefund(), checkstate.GetRefund()) 451 } 452 if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) { 453 return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", 454 state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) 455 } 456 return nil 457 } 458 459 func TestTouchDelete(t *testing.T) { 460 s := newStateTest() 461 s.state.GetOrNewStateObject(common.Address{}) 462 root, _ := s.state.Commit(false) 463 s.state.Reset(root) 464 465 snapshot := s.state.Snapshot() 466 s.state.AddBalance(common.Address{}, new(big.Int)) 467 468 if len(s.state.journal.dirties) != 1 { 469 t.Fatal("expected one dirty state object") 470 } 471 s.state.RevertToSnapshot(snapshot) 472 if len(s.state.journal.dirties) != 0 { 473 t.Fatal("expected no dirty state object") 474 } 475 } 476 477 // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy. 478 // See https://github.com/zhiqiangxu/go-ethereum/pull/15225#issuecomment-380191512 479 func TestCopyOfCopy(t *testing.T) { 480 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 481 addr := common.HexToAddress("aaaa") 482 state.SetBalance(addr, big.NewInt(42)) 483 484 if got := state.Copy().GetBalance(addr).Uint64(); got != 42 { 485 t.Fatalf("1st copy fail, expected 42, got %v", got) 486 } 487 if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 { 488 t.Fatalf("2nd copy fail, expected 42, got %v", got) 489 } 490 } 491 492 // Tests a regression where committing a copy lost some internal meta information, 493 // leading to corrupted subsequent copies. 494 // 495 // See https://github.com/zhiqiangxu/go-ethereum/issues/20106. 496 func TestCopyCommitCopy(t *testing.T) { 497 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 498 499 // Create an account and check if the retrieved balance is correct 500 addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 501 skey := common.HexToHash("aaa") 502 sval := common.HexToHash("bbb") 503 504 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 505 state.SetCode(addr, []byte("hello")) // Change an external metadata 506 state.SetState(addr, skey, sval) // Change the storage trie 507 508 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 509 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 510 } 511 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 512 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 513 } 514 if val := state.GetState(addr, skey); val != sval { 515 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 516 } 517 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 518 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 519 } 520 // Copy the non-committed state database and check pre/post commit balance 521 copyOne := state.Copy() 522 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 523 t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42) 524 } 525 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 526 t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 527 } 528 if val := copyOne.GetState(addr, skey); val != sval { 529 t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 530 } 531 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 532 t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 533 } 534 535 copyOne.Commit(false) 536 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 537 t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42) 538 } 539 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 540 t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 541 } 542 if val := copyOne.GetState(addr, skey); val != sval { 543 t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 544 } 545 if val := copyOne.GetCommittedState(addr, skey); val != sval { 546 t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 547 } 548 // Copy the copy and check the balance once more 549 copyTwo := copyOne.Copy() 550 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 551 t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42) 552 } 553 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 554 t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello")) 555 } 556 if val := copyTwo.GetState(addr, skey); val != sval { 557 t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval) 558 } 559 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 560 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 561 } 562 } 563 564 // Tests a regression where committing a copy lost some internal meta information, 565 // leading to corrupted subsequent copies. 566 // 567 // See https://github.com/zhiqiangxu/go-ethereum/issues/20106. 568 func TestCopyCopyCommitCopy(t *testing.T) { 569 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 570 571 // Create an account and check if the retrieved balance is correct 572 addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 573 skey := common.HexToHash("aaa") 574 sval := common.HexToHash("bbb") 575 576 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 577 state.SetCode(addr, []byte("hello")) // Change an external metadata 578 state.SetState(addr, skey, sval) // Change the storage trie 579 580 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 581 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 582 } 583 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 584 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 585 } 586 if val := state.GetState(addr, skey); val != sval { 587 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 588 } 589 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 590 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 591 } 592 // Copy the non-committed state database and check pre/post commit balance 593 copyOne := state.Copy() 594 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 595 t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42) 596 } 597 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 598 t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello")) 599 } 600 if val := copyOne.GetState(addr, skey); val != sval { 601 t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval) 602 } 603 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 604 t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 605 } 606 // Copy the copy and check the balance once more 607 copyTwo := copyOne.Copy() 608 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 609 t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42) 610 } 611 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 612 t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 613 } 614 if val := copyTwo.GetState(addr, skey); val != sval { 615 t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 616 } 617 if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) { 618 t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 619 } 620 copyTwo.Commit(false) 621 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 622 t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42) 623 } 624 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 625 t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 626 } 627 if val := copyTwo.GetState(addr, skey); val != sval { 628 t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 629 } 630 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 631 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 632 } 633 // Copy the copy-copy and check the balance once more 634 copyThree := copyTwo.Copy() 635 if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 636 t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42) 637 } 638 if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 639 t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello")) 640 } 641 if val := copyThree.GetState(addr, skey); val != sval { 642 t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval) 643 } 644 if val := copyThree.GetCommittedState(addr, skey); val != sval { 645 t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval) 646 } 647 } 648 649 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 650 // while changing the internals of statedb. The workflow is that a contract is 651 // self destructed, then in a followup transaction (but same block) it's created 652 // again and the transaction reverted. 653 // 654 // The original statedb implementation flushed dirty objects to the tries after 655 // each transaction, so this works ok. The rework accumulated writes in memory 656 // first, but the journal wiped the entire state object on create-revert. 657 func TestDeleteCreateRevert(t *testing.T) { 658 // Create an initial state with a single contract 659 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 660 661 addr := toAddr([]byte("so")) 662 state.SetBalance(addr, big.NewInt(1)) 663 664 root, _ := state.Commit(false) 665 state.Reset(root) 666 667 // Simulate self-destructing in one transaction, then create-reverting in another 668 state.Suicide(addr) 669 state.Finalise(true) 670 671 id := state.Snapshot() 672 state.SetBalance(addr, big.NewInt(2)) 673 state.RevertToSnapshot(id) 674 675 // Commit the entire state and make sure we don't crash and have the correct state 676 root, _ = state.Commit(true) 677 state.Reset(root) 678 679 if state.getStateObject(addr) != nil { 680 t.Fatalf("self-destructed contract came alive") 681 } 682 } 683 684 // TestMissingTrieNodes tests that if the statedb fails to load parts of the trie, 685 // the Commit operation fails with an error 686 // If we are missing trie nodes, we should not continue writing to the trie 687 func TestMissingTrieNodes(t *testing.T) { 688 689 // Create an initial state with a few accounts 690 memDb := rawdb.NewMemoryDatabase() 691 db := NewDatabase(memDb) 692 var root common.Hash 693 state, _ := New(common.Hash{}, db, nil) 694 addr := toAddr([]byte("so")) 695 { 696 state.SetBalance(addr, big.NewInt(1)) 697 state.SetCode(addr, []byte{1, 2, 3}) 698 a2 := toAddr([]byte("another")) 699 state.SetBalance(a2, big.NewInt(100)) 700 state.SetCode(a2, []byte{1, 2, 4}) 701 root, _ = state.Commit(false) 702 t.Logf("root: %x", root) 703 // force-flush 704 state.Database().TrieDB().Cap(0) 705 } 706 // Create a new state on the old root 707 state, _ = New(root, db, nil) 708 // Now we clear out the memdb 709 it := memDb.NewIterator(nil, nil) 710 for it.Next() { 711 k := it.Key() 712 // Leave the root intact 713 if !bytes.Equal(k, root[:]) { 714 t.Logf("key: %x", k) 715 memDb.Delete(k) 716 } 717 } 718 balance := state.GetBalance(addr) 719 // The removed elem should lead to it returning zero balance 720 if exp, got := uint64(0), balance.Uint64(); got != exp { 721 t.Errorf("expected %d, got %d", exp, got) 722 } 723 // Modify the state 724 state.SetBalance(addr, big.NewInt(2)) 725 root, err := state.Commit(false) 726 if err == nil { 727 t.Fatalf("expected error, got root :%x", root) 728 } 729 }