github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/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/DxChainNetwork/dxc/common" 33 "github.com/DxChainNetwork/dxc/core/rawdb" 34 "github.com/DxChainNetwork/dxc/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("value mismatch at key %x: %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("value mismatch at key %x: %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/DxChainNetwork/dxc/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 name: "AddAddressToAccessList", 333 fn: func(a testAction, s *StateDB) { 334 s.AddAddressToAccessList(addr) 335 }, 336 }, 337 { 338 name: "AddSlotToAccessList", 339 fn: func(a testAction, s *StateDB) { 340 s.AddSlotToAccessList(addr, 341 common.Hash{byte(a.args[0])}) 342 }, 343 args: make([]int64, 1), 344 }, 345 } 346 action := actions[r.Intn(len(actions))] 347 var nameargs []string 348 if !action.noAddr { 349 nameargs = append(nameargs, addr.Hex()) 350 } 351 for i := range action.args { 352 action.args[i] = rand.Int63n(100) 353 nameargs = append(nameargs, fmt.Sprint(action.args[i])) 354 } 355 action.name += strings.Join(nameargs, ", ") 356 return action 357 } 358 359 // Generate returns a new snapshot test of the given size. All randomness is 360 // derived from r. 361 func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value { 362 // Generate random actions. 363 addrs := make([]common.Address, 50) 364 for i := range addrs { 365 addrs[i][0] = byte(i) 366 } 367 actions := make([]testAction, size) 368 for i := range actions { 369 addr := addrs[r.Intn(len(addrs))] 370 actions[i] = newTestAction(addr, r) 371 } 372 // Generate snapshot indexes. 373 nsnapshots := int(math.Sqrt(float64(size))) 374 if size > 0 && nsnapshots == 0 { 375 nsnapshots = 1 376 } 377 snapshots := make([]int, nsnapshots) 378 snaplen := len(actions) / nsnapshots 379 for i := range snapshots { 380 // Try to place the snapshots some number of actions apart from each other. 381 snapshots[i] = (i * snaplen) + r.Intn(snaplen) 382 } 383 return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil}) 384 } 385 386 func (test *snapshotTest) String() string { 387 out := new(bytes.Buffer) 388 sindex := 0 389 for i, action := range test.actions { 390 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 391 fmt.Fprintf(out, "---- snapshot %d ----\n", sindex) 392 sindex++ 393 } 394 fmt.Fprintf(out, "%4d: %s\n", i, action.name) 395 } 396 return out.String() 397 } 398 399 func (test *snapshotTest) run() bool { 400 // Run all actions and create snapshots. 401 var ( 402 state, _ = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 403 snapshotRevs = make([]int, len(test.snapshots)) 404 sindex = 0 405 ) 406 for i, action := range test.actions { 407 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 408 snapshotRevs[sindex] = state.Snapshot() 409 sindex++ 410 } 411 action.fn(action, state) 412 } 413 // Revert all snapshots in reverse order. Each revert must yield a state 414 // that is equivalent to fresh state with all actions up the snapshot applied. 415 for sindex--; sindex >= 0; sindex-- { 416 checkstate, _ := New(common.Hash{}, state.Database(), nil) 417 for _, action := range test.actions[:test.snapshots[sindex]] { 418 action.fn(action, checkstate) 419 } 420 state.RevertToSnapshot(snapshotRevs[sindex]) 421 if err := test.checkEqual(state, checkstate); err != nil { 422 test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err) 423 return false 424 } 425 } 426 return true 427 } 428 429 // checkEqual checks that methods of state and checkstate return the same values. 430 func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { 431 for _, addr := range test.addrs { 432 var err error 433 checkeq := func(op string, a, b interface{}) bool { 434 if err == nil && !reflect.DeepEqual(a, b) { 435 err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b) 436 return false 437 } 438 return true 439 } 440 // Check basic accessor methods. 441 checkeq("Exist", state.Exist(addr), checkstate.Exist(addr)) 442 checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr)) 443 checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr)) 444 checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) 445 checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) 446 checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) 447 checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) 448 // Check storage. 449 if obj := state.getStateObject(addr); obj != nil { 450 state.ForEachStorage(addr, func(key, value common.Hash) bool { 451 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 452 }) 453 checkstate.ForEachStorage(addr, func(key, value common.Hash) bool { 454 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 455 }) 456 } 457 if err != nil { 458 return err 459 } 460 } 461 462 if state.GetRefund() != checkstate.GetRefund() { 463 return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", 464 state.GetRefund(), checkstate.GetRefund()) 465 } 466 if !reflect.DeepEqual(state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{})) { 467 return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", 468 state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{})) 469 } 470 return nil 471 } 472 473 func TestTouchDelete(t *testing.T) { 474 s := newStateTest() 475 s.state.GetOrNewStateObject(common.Address{}) 476 root, _ := s.state.Commit(false) 477 s.state, _ = New(root, s.state.db, s.state.snaps) 478 479 snapshot := s.state.Snapshot() 480 s.state.AddBalance(common.Address{}, new(big.Int)) 481 482 if len(s.state.journal.dirties) != 1 { 483 t.Fatal("expected one dirty state object") 484 } 485 s.state.RevertToSnapshot(snapshot) 486 if len(s.state.journal.dirties) != 0 { 487 t.Fatal("expected no dirty state object") 488 } 489 } 490 491 // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy. 492 // See https://github.com/DxChainNetwork/dxc/pull/15225#issuecomment-380191512 493 func TestCopyOfCopy(t *testing.T) { 494 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 495 addr := common.HexToAddress("aaaa") 496 state.SetBalance(addr, big.NewInt(42)) 497 498 if got := state.Copy().GetBalance(addr).Uint64(); got != 42 { 499 t.Fatalf("1st copy fail, expected 42, got %v", got) 500 } 501 if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 { 502 t.Fatalf("2nd copy fail, expected 42, got %v", got) 503 } 504 } 505 506 // Tests a regression where committing a copy lost some internal meta information, 507 // leading to corrupted subsequent copies. 508 // 509 // See https://github.com/DxChainNetwork/dxc/issues/20106. 510 func TestCopyCommitCopy(t *testing.T) { 511 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 512 513 // Create an account and check if the retrieved balance is correct 514 addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 515 skey := common.HexToHash("aaa") 516 sval := common.HexToHash("bbb") 517 518 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 519 state.SetCode(addr, []byte("hello")) // Change an external metadata 520 state.SetState(addr, skey, sval) // Change the storage trie 521 522 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 523 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 524 } 525 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 526 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 527 } 528 if val := state.GetState(addr, skey); val != sval { 529 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 530 } 531 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 532 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 533 } 534 // Copy the non-committed state database and check pre/post commit balance 535 copyOne := state.Copy() 536 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 537 t.Fatalf("first copy pre-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 pre-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 pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 544 } 545 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 546 t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 547 } 548 549 copyOne.Commit(false) 550 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 551 t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42) 552 } 553 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 554 t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 555 } 556 if val := copyOne.GetState(addr, skey); val != sval { 557 t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 558 } 559 if val := copyOne.GetCommittedState(addr, skey); val != sval { 560 t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 561 } 562 // Copy the copy and check the balance once more 563 copyTwo := copyOne.Copy() 564 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 565 t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42) 566 } 567 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 568 t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello")) 569 } 570 if val := copyTwo.GetState(addr, skey); val != sval { 571 t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval) 572 } 573 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 574 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 575 } 576 } 577 578 // Tests a regression where committing a copy lost some internal meta information, 579 // leading to corrupted subsequent copies. 580 // 581 // See https://github.com/DxChainNetwork/dxc/issues/20106. 582 func TestCopyCopyCommitCopy(t *testing.T) { 583 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 584 585 // Create an account and check if the retrieved balance is correct 586 addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 587 skey := common.HexToHash("aaa") 588 sval := common.HexToHash("bbb") 589 590 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 591 state.SetCode(addr, []byte("hello")) // Change an external metadata 592 state.SetState(addr, skey, sval) // Change the storage trie 593 594 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 595 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 596 } 597 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 598 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 599 } 600 if val := state.GetState(addr, skey); val != sval { 601 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 602 } 603 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 604 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 605 } 606 // Copy the non-committed state database and check pre/post commit balance 607 copyOne := state.Copy() 608 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 609 t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42) 610 } 611 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 612 t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello")) 613 } 614 if val := copyOne.GetState(addr, skey); val != sval { 615 t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval) 616 } 617 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 618 t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 619 } 620 // Copy the copy and check the balance once more 621 copyTwo := copyOne.Copy() 622 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 623 t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42) 624 } 625 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 626 t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 627 } 628 if val := copyTwo.GetState(addr, skey); val != sval { 629 t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 630 } 631 if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) { 632 t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 633 } 634 copyTwo.Commit(false) 635 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 636 t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42) 637 } 638 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 639 t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 640 } 641 if val := copyTwo.GetState(addr, skey); val != sval { 642 t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 643 } 644 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 645 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 646 } 647 // Copy the copy-copy and check the balance once more 648 copyThree := copyTwo.Copy() 649 if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 650 t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42) 651 } 652 if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 653 t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello")) 654 } 655 if val := copyThree.GetState(addr, skey); val != sval { 656 t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval) 657 } 658 if val := copyThree.GetCommittedState(addr, skey); val != sval { 659 t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval) 660 } 661 } 662 663 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 664 // while changing the internals of StateDB. The workflow is that a contract is 665 // self-destructed, then in a follow-up transaction (but same block) it's created 666 // again and the transaction reverted. 667 // 668 // The original StateDB implementation flushed dirty objects to the tries after 669 // each transaction, so this works ok. The rework accumulated writes in memory 670 // first, but the journal wiped the entire state object on create-revert. 671 func TestDeleteCreateRevert(t *testing.T) { 672 // Create an initial state with a single contract 673 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 674 675 addr := common.BytesToAddress([]byte("so")) 676 state.SetBalance(addr, big.NewInt(1)) 677 678 root, _ := state.Commit(false) 679 state, _ = New(root, state.db, state.snaps) 680 681 // Simulate self-destructing in one transaction, then create-reverting in another 682 state.Suicide(addr) 683 state.Finalise(true) 684 685 id := state.Snapshot() 686 state.SetBalance(addr, big.NewInt(2)) 687 state.RevertToSnapshot(id) 688 689 // Commit the entire state and make sure we don't crash and have the correct state 690 root, _ = state.Commit(true) 691 state, _ = New(root, state.db, state.snaps) 692 693 if state.getStateObject(addr) != nil { 694 t.Fatalf("self-destructed contract came alive") 695 } 696 } 697 698 // TestMissingTrieNodes tests that if the StateDB fails to load parts of the trie, 699 // the Commit operation fails with an error 700 // If we are missing trie nodes, we should not continue writing to the trie 701 func TestMissingTrieNodes(t *testing.T) { 702 703 // Create an initial state with a few accounts 704 memDb := rawdb.NewMemoryDatabase() 705 db := NewDatabase(memDb) 706 var root common.Hash 707 state, _ := New(common.Hash{}, db, nil) 708 addr := common.BytesToAddress([]byte("so")) 709 { 710 state.SetBalance(addr, big.NewInt(1)) 711 state.SetCode(addr, []byte{1, 2, 3}) 712 a2 := common.BytesToAddress([]byte("another")) 713 state.SetBalance(a2, big.NewInt(100)) 714 state.SetCode(a2, []byte{1, 2, 4}) 715 root, _ = state.Commit(false) 716 t.Logf("root: %x", root) 717 // force-flush 718 state.Database().TrieDB().Cap(0) 719 } 720 // Create a new state on the old root 721 state, _ = New(root, db, nil) 722 // Now we clear out the memdb 723 it := memDb.NewIterator(nil, nil) 724 for it.Next() { 725 k := it.Key() 726 // Leave the root intact 727 if !bytes.Equal(k, root[:]) { 728 t.Logf("key: %x", k) 729 memDb.Delete(k) 730 } 731 } 732 balance := state.GetBalance(addr) 733 // The removed elem should lead to it returning zero balance 734 if exp, got := uint64(0), balance.Uint64(); got != exp { 735 t.Errorf("expected %d, got %d", exp, got) 736 } 737 // Modify the state 738 state.SetBalance(addr, big.NewInt(2)) 739 root, err := state.Commit(false) 740 if err == nil { 741 t.Fatalf("expected error, got root :%x", root) 742 } 743 } 744 745 func TestStateDBAccessList(t *testing.T) { 746 // Some helpers 747 addr := func(a string) common.Address { 748 return common.HexToAddress(a) 749 } 750 slot := func(a string) common.Hash { 751 return common.HexToHash(a) 752 } 753 754 memDb := rawdb.NewMemoryDatabase() 755 db := NewDatabase(memDb) 756 state, _ := New(common.Hash{}, db, nil) 757 state.accessList = newAccessList() 758 759 verifyAddrs := func(astrings ...string) { 760 t.Helper() 761 // convert to common.Address form 762 var addresses []common.Address 763 var addressMap = make(map[common.Address]struct{}) 764 for _, astring := range astrings { 765 address := addr(astring) 766 addresses = append(addresses, address) 767 addressMap[address] = struct{}{} 768 } 769 // Check that the given addresses are in the access list 770 for _, address := range addresses { 771 if !state.AddressInAccessList(address) { 772 t.Fatalf("expected %x to be in access list", address) 773 } 774 } 775 // Check that only the expected addresses are present in the acesslist 776 for address := range state.accessList.addresses { 777 if _, exist := addressMap[address]; !exist { 778 t.Fatalf("extra address %x in access list", address) 779 } 780 } 781 } 782 verifySlots := func(addrString string, slotStrings ...string) { 783 if !state.AddressInAccessList(addr(addrString)) { 784 t.Fatalf("scope missing address/slots %v", addrString) 785 } 786 var address = addr(addrString) 787 // convert to common.Hash form 788 var slots []common.Hash 789 var slotMap = make(map[common.Hash]struct{}) 790 for _, slotString := range slotStrings { 791 s := slot(slotString) 792 slots = append(slots, s) 793 slotMap[s] = struct{}{} 794 } 795 // Check that the expected items are in the access list 796 for i, s := range slots { 797 if _, slotPresent := state.SlotInAccessList(address, s); !slotPresent { 798 t.Fatalf("input %d: scope missing slot %v (address %v)", i, s, addrString) 799 } 800 } 801 // Check that no extra elements are in the access list 802 index := state.accessList.addresses[address] 803 if index >= 0 { 804 stateSlots := state.accessList.slots[index] 805 for s := range stateSlots { 806 if _, slotPresent := slotMap[s]; !slotPresent { 807 t.Fatalf("scope has extra slot %v (address %v)", s, addrString) 808 } 809 } 810 } 811 } 812 813 state.AddAddressToAccessList(addr("aa")) // 1 814 state.AddSlotToAccessList(addr("bb"), slot("01")) // 2,3 815 state.AddSlotToAccessList(addr("bb"), slot("02")) // 4 816 verifyAddrs("aa", "bb") 817 verifySlots("bb", "01", "02") 818 819 // Make a copy 820 stateCopy1 := state.Copy() 821 if exp, got := 4, state.journal.length(); exp != got { 822 t.Fatalf("journal length mismatch: have %d, want %d", got, exp) 823 } 824 825 // same again, should cause no journal entries 826 state.AddSlotToAccessList(addr("bb"), slot("01")) 827 state.AddSlotToAccessList(addr("bb"), slot("02")) 828 state.AddAddressToAccessList(addr("aa")) 829 if exp, got := 4, state.journal.length(); exp != got { 830 t.Fatalf("journal length mismatch: have %d, want %d", got, exp) 831 } 832 // some new ones 833 state.AddSlotToAccessList(addr("bb"), slot("03")) // 5 834 state.AddSlotToAccessList(addr("aa"), slot("01")) // 6 835 state.AddSlotToAccessList(addr("cc"), slot("01")) // 7,8 836 state.AddAddressToAccessList(addr("cc")) 837 if exp, got := 8, state.journal.length(); exp != got { 838 t.Fatalf("journal length mismatch: have %d, want %d", got, exp) 839 } 840 841 verifyAddrs("aa", "bb", "cc") 842 verifySlots("aa", "01") 843 verifySlots("bb", "01", "02", "03") 844 verifySlots("cc", "01") 845 846 // now start rolling back changes 847 state.journal.revert(state, 7) 848 if _, ok := state.SlotInAccessList(addr("cc"), slot("01")); ok { 849 t.Fatalf("slot present, expected missing") 850 } 851 verifyAddrs("aa", "bb", "cc") 852 verifySlots("aa", "01") 853 verifySlots("bb", "01", "02", "03") 854 855 state.journal.revert(state, 6) 856 if state.AddressInAccessList(addr("cc")) { 857 t.Fatalf("addr present, expected missing") 858 } 859 verifyAddrs("aa", "bb") 860 verifySlots("aa", "01") 861 verifySlots("bb", "01", "02", "03") 862 863 state.journal.revert(state, 5) 864 if _, ok := state.SlotInAccessList(addr("aa"), slot("01")); ok { 865 t.Fatalf("slot present, expected missing") 866 } 867 verifyAddrs("aa", "bb") 868 verifySlots("bb", "01", "02", "03") 869 870 state.journal.revert(state, 4) 871 if _, ok := state.SlotInAccessList(addr("bb"), slot("03")); ok { 872 t.Fatalf("slot present, expected missing") 873 } 874 verifyAddrs("aa", "bb") 875 verifySlots("bb", "01", "02") 876 877 state.journal.revert(state, 3) 878 if _, ok := state.SlotInAccessList(addr("bb"), slot("02")); ok { 879 t.Fatalf("slot present, expected missing") 880 } 881 verifyAddrs("aa", "bb") 882 verifySlots("bb", "01") 883 884 state.journal.revert(state, 2) 885 if _, ok := state.SlotInAccessList(addr("bb"), slot("01")); ok { 886 t.Fatalf("slot present, expected missing") 887 } 888 verifyAddrs("aa", "bb") 889 890 state.journal.revert(state, 1) 891 if state.AddressInAccessList(addr("bb")) { 892 t.Fatalf("addr present, expected missing") 893 } 894 verifyAddrs("aa") 895 896 state.journal.revert(state, 0) 897 if state.AddressInAccessList(addr("aa")) { 898 t.Fatalf("addr present, expected missing") 899 } 900 if got, exp := len(state.accessList.addresses), 0; got != exp { 901 t.Fatalf("expected empty, got %d", got) 902 } 903 if got, exp := len(state.accessList.slots), 0; got != exp { 904 t.Fatalf("expected empty, got %d", got) 905 } 906 // Check the copy 907 // Make a copy 908 state = stateCopy1 909 verifyAddrs("aa", "bb") 910 verifySlots("bb", "01", "02") 911 if got, exp := len(state.accessList.addresses), 2; got != exp { 912 t.Fatalf("expected empty, got %d", got) 913 } 914 if got, exp := len(state.accessList.slots), 1; got != exp { 915 t.Fatalf("expected empty, got %d", got) 916 } 917 } 918 919 func TestErase(t *testing.T) { 920 // Create an initial state with a single contract 921 db := NewDatabase(rawdb.NewMemoryDatabase()) 922 state, _ := New(common.Hash{}, db, nil) 923 924 addr := common.BytesToAddress([]byte("so")) 925 state.SetBalance(addr, big.NewInt(1)) 926 skey := common.HexToHash("aaa") 927 sval := common.HexToHash("bbb") 928 929 state.SetCode(addr, []byte("hello")) // Change an external metadata 930 state.SetState(addr, skey, sval) // Change the storage trie 931 932 root, _ := state.Commit(false) 933 state, _ = New(root, db, nil) 934 935 // Simulate erase and then revert 936 id := state.Snapshot() 937 state.Erase(addr) 938 state.RevertToSnapshot(id) 939 root, _ = state.Commit(true) 940 state, _ = New(root, db, nil) 941 942 obj := state.getStateObject(addr) 943 if code := obj.Code(state.db); !bytes.Equal(code, []byte("hello")) { 944 t.Fatal("RevertToSnapshot failed after erase, code mismatch") 945 } 946 if val := obj.GetState(state.db, skey); val != sval { 947 t.Fatal("RevertToSnapshot failed after erase, storage mismatch") 948 } 949 950 state.Erase(addr) 951 // Commit the entire state and make sure we don't crash and have the correct state 952 root, _ = state.Commit(true) 953 state, _ = New(root, db, nil) 954 955 obj = state.getStateObject(addr) 956 if obj == nil { 957 t.Fatal("erase should not delete the account") 958 } 959 if code := obj.Code(state.db); len(code) > 0 { 960 t.Fatal("erase failed to clear the code") 961 } 962 if val := obj.GetState(state.db, skey); (val != common.Hash{}) { 963 t.Fatal("erase not clear the storage") 964 } 965 if obj.data.Root != emptyRoot { 966 t.Fatal("erase not clear the storage") 967 } 968 if !bytes.Equal(obj.CodeHash(), emptyCodeHash) { 969 t.Fatal("erase failed to clear the code hash") 970 } 971 if obj.Balance().Uint64() != uint64(1) { 972 t.Fatal("erase should not change balance") 973 } 974 }