github.com/core-coin/go-core/v2@v2.1.9/core/state/statedb_test.go (about) 1 // Copyright 2016 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core 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-core 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-core 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/core-coin/go-core/v2/common" 33 "github.com/core-coin/go-core/v2/core/rawdb" 34 "github.com/core-coin/go-core/v2/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, nil); 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, nil); 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, nil); 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/core-coin/go-core/v2/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/core-coin/go-core/v2/pull/15225#issuecomment-380191512 479 func TestCopyOfCopy(t *testing.T) { 480 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 481 addr, err := common.HexToAddress("cb21000000000000000000000000000000000000aaaa") 482 if err != nil { 483 t.Error(err) 484 } 485 state.SetBalance(addr, big.NewInt(42)) 486 487 if got := state.Copy().GetBalance(addr).Uint64(); got != 42 { 488 t.Fatalf("1st copy fail, expected 42, got %v", got) 489 } 490 if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 { 491 t.Fatalf("2nd copy fail, expected 42, got %v", got) 492 } 493 } 494 495 // Tests a regression where committing a copy lost some internal meta information, 496 // leading to corrupted subsequent copies. 497 // 498 // See https://github.com/core-coin/go-core/v2/issues/20106. 499 func TestCopyCommitCopy(t *testing.T) { 500 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 501 502 // Create an account and check if the retrieved balance is correct 503 addr, err := common.HexToAddress("cb05affeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 504 if err != nil { 505 t.Error(err) 506 } 507 skey := common.HexToHash("aaa") 508 sval := common.HexToHash("bbb") 509 510 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 511 state.SetCode(addr, []byte("hello")) // Change an external metadata 512 state.SetState(addr, skey, sval) // Change the storage trie 513 514 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 515 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 516 } 517 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 518 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 519 } 520 if val := state.GetState(addr, skey); val != sval { 521 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 522 } 523 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 524 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 525 } 526 // Copy the non-committed state database and check pre/post commit balance 527 copyOne := state.Copy() 528 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 529 t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42) 530 } 531 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 532 t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 533 } 534 if val := copyOne.GetState(addr, skey); val != sval { 535 t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 536 } 537 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 538 t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 539 } 540 541 copyOne.Commit(false) 542 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 543 t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42) 544 } 545 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 546 t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 547 } 548 if val := copyOne.GetState(addr, skey); val != sval { 549 t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 550 } 551 if val := copyOne.GetCommittedState(addr, skey); val != sval { 552 t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 553 } 554 // Copy the copy and check the balance once more 555 copyTwo := copyOne.Copy() 556 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 557 t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42) 558 } 559 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 560 t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello")) 561 } 562 if val := copyTwo.GetState(addr, skey); val != sval { 563 t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval) 564 } 565 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 566 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 567 } 568 } 569 570 // Tests a regression where committing a copy lost some internal meta information, 571 // leading to corrupted subsequent copies. 572 // 573 // See https://github.com/core-coin/go-core/v2/issues/20106. 574 func TestCopyCopyCommitCopy(t *testing.T) { 575 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 576 577 // Create an account and check if the retrieved balance is correct 578 addr, err := common.HexToAddress("cb05affeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 579 if err != nil { 580 t.Error(err) 581 } 582 skey := common.HexToHash("aaa") 583 sval := common.HexToHash("bbb") 584 585 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 586 state.SetCode(addr, []byte("hello")) // Change an external metadata 587 state.SetState(addr, skey, sval) // Change the storage trie 588 589 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 590 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 591 } 592 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 593 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 594 } 595 if val := state.GetState(addr, skey); val != sval { 596 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 597 } 598 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 599 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 600 } 601 // Copy the non-committed state database and check pre/post commit balance 602 copyOne := state.Copy() 603 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 604 t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42) 605 } 606 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 607 t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello")) 608 } 609 if val := copyOne.GetState(addr, skey); val != sval { 610 t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval) 611 } 612 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 613 t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 614 } 615 // Copy the copy and check the balance once more 616 copyTwo := copyOne.Copy() 617 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 618 t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42) 619 } 620 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 621 t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 622 } 623 if val := copyTwo.GetState(addr, skey); val != sval { 624 t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 625 } 626 if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) { 627 t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 628 } 629 copyTwo.Commit(false) 630 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 631 t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42) 632 } 633 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 634 t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 635 } 636 if val := copyTwo.GetState(addr, skey); val != sval { 637 t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 638 } 639 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 640 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 641 } 642 // Copy the copy-copy and check the balance once more 643 copyThree := copyTwo.Copy() 644 if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 645 t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42) 646 } 647 if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 648 t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello")) 649 } 650 if val := copyThree.GetState(addr, skey); val != sval { 651 t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval) 652 } 653 if val := copyThree.GetCommittedState(addr, skey); val != sval { 654 t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval) 655 } 656 } 657 658 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 659 // while changing the internals of StateDB. The workflow is that a contract is 660 // self-destructed, then in a follow-up transaction (but same block) it's created 661 // again and the transaction reverted. 662 // 663 // The original StateDB implementation flushed dirty objects to the tries after 664 // each transaction, so this works ok. The rework accumulated writes in memory 665 // first, but the journal wiped the entire state object on create-revert. 666 func TestDeleteCreateRevert(t *testing.T) { 667 // Create an initial state with a single contract 668 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 669 670 addr := toAddr([]byte("so")) 671 state.SetBalance(addr, big.NewInt(1)) 672 673 root, _ := state.Commit(false) 674 state.Reset(root) 675 676 // Simulate self-destructing in one transaction, then create-reverting in another 677 state.Suicide(addr) 678 state.Finalise(true) 679 680 id := state.Snapshot() 681 state.SetBalance(addr, big.NewInt(2)) 682 state.RevertToSnapshot(id) 683 684 // Commit the entire state and make sure we don't crash and have the correct state 685 root, _ = state.Commit(true) 686 state.Reset(root) 687 688 if state.getStateObject(addr) != nil { 689 t.Fatalf("self-destructed contract came alive") 690 } 691 } 692 693 // TestMissingTrieNodes tests that if the StateDB fails to load parts of the trie, 694 // the Commit operation fails with an error 695 // If we are missing trie nodes, we should not continue writing to the trie 696 func TestMissingTrieNodes(t *testing.T) { 697 698 // Create an initial state with a few accounts 699 memDb := rawdb.NewMemoryDatabase() 700 db := NewDatabase(memDb) 701 var root common.Hash 702 state, _ := New(common.Hash{}, db, nil) 703 addr := toAddr([]byte("so")) 704 { 705 state.SetBalance(addr, big.NewInt(1)) 706 state.SetCode(addr, []byte{1, 2, 3}) 707 a2 := toAddr([]byte("another")) 708 state.SetBalance(a2, big.NewInt(100)) 709 state.SetCode(a2, []byte{1, 2, 4}) 710 root, _ = state.Commit(false) 711 t.Logf("root: %x", root) 712 // force-flush 713 state.Database().TrieDB().Cap(0) 714 } 715 // Create a new state on the old root 716 state, _ = New(root, db, nil) 717 // Now we clear out the memdb 718 it := memDb.NewIterator(nil, nil) 719 for it.Next() { 720 k := it.Key() 721 // Leave the root intact 722 if !bytes.Equal(k, root[:]) { 723 t.Logf("key: %x", k) 724 memDb.Delete(k) 725 } 726 } 727 balance := state.GetBalance(addr) 728 // The removed elem should lead to it returning zero balance 729 if exp, got := uint64(0), balance.Uint64(); got != exp { 730 t.Errorf("expected %d, got %d", exp, got) 731 } 732 // Modify the state 733 state.SetBalance(addr, big.NewInt(2)) 734 root, err := state.Commit(false) 735 if err == nil { 736 t.Fatalf("expected error, got root :%x", root) 737 } 738 }