github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/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/stretchr/testify/assert" 33 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/core/blockstm" 36 "github.com/ethereum/go-ethereum/core/rawdb" 37 "github.com/ethereum/go-ethereum/core/types" 38 ) 39 40 // Tests that updating a state trie does not leak any database writes prior to 41 // actually committing the state. 42 func TestUpdateLeaks(t *testing.T) { 43 // Create an empty state database 44 db := rawdb.NewMemoryDatabase() 45 state, _ := New(common.Hash{}, NewDatabase(db), nil) 46 47 // Update it with some accounts 48 for i := byte(0); i < 255; i++ { 49 addr := common.BytesToAddress([]byte{i}) 50 state.AddBalance(addr, big.NewInt(int64(11*i))) 51 state.SetNonce(addr, uint64(42*i)) 52 if i%2 == 0 { 53 state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) 54 } 55 if i%3 == 0 { 56 state.SetCode(addr, []byte{i, i, i, i, i}) 57 } 58 } 59 60 root := state.IntermediateRoot(false) 61 if err := state.Database().TrieDB().Commit(root, false, nil); err != nil { 62 t.Errorf("can not commit trie %v to persistent database", root.Hex()) 63 } 64 65 // Ensure that no data was leaked into the database 66 it := db.NewIterator(nil, nil) 67 for it.Next() { 68 t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value()) 69 } 70 it.Release() 71 } 72 73 // Tests that no intermediate state of an object is stored into the database, 74 // only the one right before the commit. 75 func TestIntermediateLeaks(t *testing.T) { 76 // Create two state databases, one transitioning to the final state, the other final from the beginning 77 transDb := rawdb.NewMemoryDatabase() 78 finalDb := rawdb.NewMemoryDatabase() 79 transState, _ := New(common.Hash{}, NewDatabase(transDb), nil) 80 finalState, _ := New(common.Hash{}, NewDatabase(finalDb), nil) 81 82 modify := func(state *StateDB, addr common.Address, i, tweak byte) { 83 state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak))) 84 state.SetNonce(addr, uint64(42*i+tweak)) 85 if i%2 == 0 { 86 state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{}) 87 state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak}) 88 } 89 if i%3 == 0 { 90 state.SetCode(addr, []byte{i, i, i, i, i, tweak}) 91 } 92 } 93 94 // Modify the transient state. 95 for i := byte(0); i < 255; i++ { 96 modify(transState, common.Address{i}, i, 0) 97 } 98 // Write modifications to trie. 99 transState.IntermediateRoot(false) 100 101 // Overwrite all the data with new values in the transient database. 102 for i := byte(0); i < 255; i++ { 103 modify(transState, common.Address{i}, i, 99) 104 modify(finalState, common.Address{i}, i, 99) 105 } 106 107 // Commit and cross check the databases. 108 transRoot, err := transState.Commit(false) 109 if err != nil { 110 t.Fatalf("failed to commit transition state: %v", err) 111 } 112 if err = transState.Database().TrieDB().Commit(transRoot, false, nil); err != nil { 113 t.Errorf("can not commit trie %v to persistent database", transRoot.Hex()) 114 } 115 116 finalRoot, err := finalState.Commit(false) 117 if err != nil { 118 t.Fatalf("failed to commit final state: %v", err) 119 } 120 if err = finalState.Database().TrieDB().Commit(finalRoot, false, nil); err != nil { 121 t.Errorf("can not commit trie %v to persistent database", finalRoot.Hex()) 122 } 123 124 it := finalDb.NewIterator(nil, nil) 125 for it.Next() { 126 key, fvalue := it.Key(), it.Value() 127 tvalue, err := transDb.Get(key) 128 if err != nil { 129 t.Errorf("entry missing from the transition database: %x -> %x", key, fvalue) 130 } 131 if !bytes.Equal(fvalue, tvalue) { 132 t.Errorf("value mismatch at key %x: %x in transition database, %x in final database", key, tvalue, fvalue) 133 } 134 } 135 it.Release() 136 137 it = transDb.NewIterator(nil, nil) 138 for it.Next() { 139 key, tvalue := it.Key(), it.Value() 140 fvalue, err := finalDb.Get(key) 141 if err != nil { 142 t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value()) 143 } 144 if !bytes.Equal(fvalue, tvalue) { 145 t.Errorf("value mismatch at key %x: %x in transition database, %x in final database", key, tvalue, fvalue) 146 } 147 } 148 } 149 150 // TestCopy tests that copying a StateDB object indeed makes the original and 151 // the copy independent of each other. This test is a regression test against 152 // https://github.com/ethereum/go-ethereum/pull/15549. 153 func TestCopy(t *testing.T) { 154 // Create a random state test to copy and modify "independently" 155 orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 156 157 for i := byte(0); i < 255; i++ { 158 obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 159 obj.AddBalance(big.NewInt(int64(i))) 160 orig.updateStateObject(obj) 161 } 162 orig.Finalise(false) 163 164 // Copy the state 165 copy := orig.Copy() 166 167 // Copy the copy state 168 ccopy := copy.Copy() 169 170 // modify all in memory 171 for i := byte(0); i < 255; i++ { 172 origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 173 copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 174 ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 175 176 origObj.AddBalance(big.NewInt(2 * int64(i))) 177 copyObj.AddBalance(big.NewInt(3 * int64(i))) 178 ccopyObj.AddBalance(big.NewInt(4 * int64(i))) 179 180 orig.updateStateObject(origObj) 181 copy.updateStateObject(copyObj) 182 ccopy.updateStateObject(copyObj) 183 } 184 185 // Finalise the changes on all concurrently 186 finalise := func(wg *sync.WaitGroup, db *StateDB) { 187 defer wg.Done() 188 db.Finalise(true) 189 } 190 191 var wg sync.WaitGroup 192 wg.Add(3) 193 go finalise(&wg, orig) 194 go finalise(&wg, copy) 195 go finalise(&wg, ccopy) 196 wg.Wait() 197 198 // Verify that the three states have been updated independently 199 for i := byte(0); i < 255; i++ { 200 origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 201 copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 202 ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) 203 204 if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 { 205 t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want) 206 } 207 if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 { 208 t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want) 209 } 210 if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 { 211 t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want) 212 } 213 } 214 } 215 216 func TestSnapshotRandom(t *testing.T) { 217 config := &quick.Config{MaxCount: 1000} 218 err := quick.Check((*snapshotTest).run, config) 219 if cerr, ok := err.(*quick.CheckError); ok { 220 test := cerr.In[0].(*snapshotTest) 221 t.Errorf("%v:\n%s", test.err, test) 222 } else if err != nil { 223 t.Error(err) 224 } 225 } 226 227 // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes 228 // captured by the snapshot. Instances of this test with pseudorandom content are created 229 // by Generate. 230 // 231 // The test works as follows: 232 // 233 // A new state is created and all actions are applied to it. Several snapshots are taken 234 // in between actions. The test then reverts each snapshot. For each snapshot the actions 235 // leading up to it are replayed on a fresh, empty state. The behaviour of all public 236 // accessor methods on the reverted state must match the return value of the equivalent 237 // methods on the replayed state. 238 type snapshotTest struct { 239 addrs []common.Address // all account addresses 240 actions []testAction // modifications to the state 241 snapshots []int // actions indexes at which snapshot is taken 242 err error // failure details are reported through this field 243 } 244 245 type testAction struct { 246 name string 247 fn func(testAction, *StateDB) 248 args []int64 249 noAddr bool 250 } 251 252 // newTestAction creates a random action that changes state. 253 func newTestAction(addr common.Address, r *rand.Rand) testAction { 254 actions := []testAction{ 255 { 256 name: "SetBalance", 257 fn: func(a testAction, s *StateDB) { 258 s.SetBalance(addr, big.NewInt(a.args[0])) 259 }, 260 args: make([]int64, 1), 261 }, 262 { 263 name: "AddBalance", 264 fn: func(a testAction, s *StateDB) { 265 s.AddBalance(addr, big.NewInt(a.args[0])) 266 }, 267 args: make([]int64, 1), 268 }, 269 { 270 name: "SetNonce", 271 fn: func(a testAction, s *StateDB) { 272 s.SetNonce(addr, uint64(a.args[0])) 273 }, 274 args: make([]int64, 1), 275 }, 276 { 277 name: "SetState", 278 fn: func(a testAction, s *StateDB) { 279 var key, val common.Hash 280 binary.BigEndian.PutUint16(key[:], uint16(a.args[0])) 281 binary.BigEndian.PutUint16(val[:], uint16(a.args[1])) 282 s.SetState(addr, key, val) 283 }, 284 args: make([]int64, 2), 285 }, 286 { 287 name: "SetCode", 288 fn: func(a testAction, s *StateDB) { 289 code := make([]byte, 16) 290 binary.BigEndian.PutUint64(code, uint64(a.args[0])) 291 binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) 292 s.SetCode(addr, code) 293 }, 294 args: make([]int64, 2), 295 }, 296 { 297 name: "CreateAccount", 298 fn: func(a testAction, s *StateDB) { 299 s.CreateAccount(addr) 300 }, 301 }, 302 { 303 name: "Suicide", 304 fn: func(a testAction, s *StateDB) { 305 s.Suicide(addr) 306 }, 307 }, 308 { 309 name: "AddRefund", 310 fn: func(a testAction, s *StateDB) { 311 s.AddRefund(uint64(a.args[0])) 312 }, 313 args: make([]int64, 1), 314 noAddr: true, 315 }, 316 { 317 name: "AddLog", 318 fn: func(a testAction, s *StateDB) { 319 data := make([]byte, 2) 320 binary.BigEndian.PutUint16(data, uint16(a.args[0])) 321 s.AddLog(&types.Log{Address: addr, Data: data}) 322 }, 323 args: make([]int64, 1), 324 }, 325 { 326 name: "AddPreimage", 327 fn: func(a testAction, s *StateDB) { 328 preimage := []byte{1} 329 hash := common.BytesToHash(preimage) 330 s.AddPreimage(hash, preimage) 331 }, 332 args: make([]int64, 1), 333 }, 334 { 335 name: "AddAddressToAccessList", 336 fn: func(a testAction, s *StateDB) { 337 s.AddAddressToAccessList(addr) 338 }, 339 }, 340 { 341 name: "AddSlotToAccessList", 342 fn: func(a testAction, s *StateDB) { 343 s.AddSlotToAccessList(addr, 344 common.Hash{byte(a.args[0])}) 345 }, 346 args: make([]int64, 1), 347 }, 348 } 349 action := actions[r.Intn(len(actions))] 350 var nameargs []string 351 if !action.noAddr { 352 nameargs = append(nameargs, addr.Hex()) 353 } 354 for i := range action.args { 355 action.args[i] = rand.Int63n(100) 356 nameargs = append(nameargs, fmt.Sprint(action.args[i])) 357 } 358 action.name += strings.Join(nameargs, ", ") 359 return action 360 } 361 362 // Generate returns a new snapshot test of the given size. All randomness is 363 // derived from r. 364 func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value { 365 // Generate random actions. 366 addrs := make([]common.Address, 50) 367 for i := range addrs { 368 addrs[i][0] = byte(i) 369 } 370 actions := make([]testAction, size) 371 for i := range actions { 372 addr := addrs[r.Intn(len(addrs))] 373 actions[i] = newTestAction(addr, r) 374 } 375 // Generate snapshot indexes. 376 nsnapshots := int(math.Sqrt(float64(size))) 377 if size > 0 && nsnapshots == 0 { 378 nsnapshots = 1 379 } 380 snapshots := make([]int, nsnapshots) 381 snaplen := len(actions) / nsnapshots 382 for i := range snapshots { 383 // Try to place the snapshots some number of actions apart from each other. 384 snapshots[i] = (i * snaplen) + r.Intn(snaplen) 385 } 386 return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil}) 387 } 388 389 func (test *snapshotTest) String() string { 390 out := new(bytes.Buffer) 391 sindex := 0 392 for i, action := range test.actions { 393 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 394 fmt.Fprintf(out, "---- snapshot %d ----\n", sindex) 395 sindex++ 396 } 397 fmt.Fprintf(out, "%4d: %s\n", i, action.name) 398 } 399 return out.String() 400 } 401 402 func (test *snapshotTest) run() bool { 403 // Run all actions and create snapshots. 404 var ( 405 state, _ = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 406 snapshotRevs = make([]int, len(test.snapshots)) 407 sindex = 0 408 ) 409 for i, action := range test.actions { 410 if len(test.snapshots) > sindex && i == test.snapshots[sindex] { 411 snapshotRevs[sindex] = state.Snapshot() 412 sindex++ 413 } 414 action.fn(action, state) 415 } 416 // Revert all snapshots in reverse order. Each revert must yield a state 417 // that is equivalent to fresh state with all actions up the snapshot applied. 418 for sindex--; sindex >= 0; sindex-- { 419 checkstate, _ := New(common.Hash{}, state.Database(), nil) 420 for _, action := range test.actions[:test.snapshots[sindex]] { 421 action.fn(action, checkstate) 422 } 423 state.RevertToSnapshot(snapshotRevs[sindex]) 424 if err := test.checkEqual(state, checkstate); err != nil { 425 test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err) 426 return false 427 } 428 } 429 return true 430 } 431 432 // checkEqual checks that methods of state and checkstate return the same values. 433 func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { 434 for _, addr := range test.addrs { 435 var err error 436 checkeq := func(op string, a, b interface{}) bool { 437 if err == nil && !reflect.DeepEqual(a, b) { 438 err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b) 439 return false 440 } 441 return true 442 } 443 // Check basic accessor methods. 444 checkeq("Exist", state.Exist(addr), checkstate.Exist(addr)) 445 checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr)) 446 checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr)) 447 checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) 448 checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) 449 checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) 450 checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) 451 // Check storage. 452 if obj := state.getStateObject(addr); obj != nil { 453 state.ForEachStorage(addr, func(key, value common.Hash) bool { 454 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 455 }) 456 checkstate.ForEachStorage(addr, func(key, value common.Hash) bool { 457 return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) 458 }) 459 } 460 if err != nil { 461 return err 462 } 463 } 464 465 if state.GetRefund() != checkstate.GetRefund() { 466 return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", 467 state.GetRefund(), checkstate.GetRefund()) 468 } 469 if !reflect.DeepEqual(state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{})) { 470 return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", 471 state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{})) 472 } 473 return nil 474 } 475 476 func TestTouchDelete(t *testing.T) { 477 s := newStateTest() 478 s.state.GetOrNewStateObject(common.Address{}) 479 root, _ := s.state.Commit(false) 480 s.state, _ = New(root, s.state.db, s.state.snaps) 481 482 snapshot := s.state.Snapshot() 483 s.state.AddBalance(common.Address{}, new(big.Int)) 484 485 if len(s.state.journal.dirties) != 1 { 486 t.Fatal("expected one dirty state object") 487 } 488 s.state.RevertToSnapshot(snapshot) 489 if len(s.state.journal.dirties) != 0 { 490 t.Fatal("expected no dirty state object") 491 } 492 } 493 494 func TestMVHashMapReadWriteDelete(t *testing.T) { 495 t.Parallel() 496 497 db := NewDatabase(rawdb.NewMemoryDatabase()) 498 mvhm := blockstm.MakeMVHashMap() 499 s, _ := NewWithMVHashmap(common.Hash{}, db, nil, mvhm) 500 501 states := []*StateDB{s} 502 503 // Create copies of the original state for each transition 504 for i := 1; i <= 4; i++ { 505 sCopy := s.Copy() 506 sCopy.txIndex = i 507 states = append(states, sCopy) 508 } 509 510 addr := common.HexToAddress("0x01") 511 key := common.HexToHash("0x01") 512 val := common.HexToHash("0x01") 513 balance := new(big.Int).SetUint64(uint64(100)) 514 515 // Tx0 read 516 v := states[0].GetState(addr, key) 517 518 assert.Equal(t, common.Hash{}, v) 519 520 // Tx1 write 521 states[1].GetOrNewStateObject(addr) 522 states[1].SetState(addr, key, val) 523 states[1].SetBalance(addr, balance) 524 states[1].FlushMVWriteSet() 525 526 // Tx1 read 527 v = states[1].GetState(addr, key) 528 b := states[1].GetBalance(addr) 529 530 assert.Equal(t, val, v) 531 assert.Equal(t, balance, b) 532 533 // Tx2 read 534 v = states[2].GetState(addr, key) 535 b = states[2].GetBalance(addr) 536 537 assert.Equal(t, val, v) 538 assert.Equal(t, balance, b) 539 540 // Tx3 delete 541 states[3].Suicide(addr) 542 543 // Within Tx 3, the state should not change before finalize 544 v = states[3].GetState(addr, key) 545 assert.Equal(t, val, v) 546 547 // After finalizing Tx 3, the state will change 548 states[3].Finalise(false) 549 v = states[3].GetState(addr, key) 550 assert.Equal(t, common.Hash{}, v) 551 states[3].FlushMVWriteSet() 552 553 // Tx4 read 554 v = states[4].GetState(addr, key) 555 b = states[4].GetBalance(addr) 556 557 assert.Equal(t, common.Hash{}, v) 558 assert.Equal(t, common.Big0, b) 559 } 560 561 func TestMVHashMapRevert(t *testing.T) { 562 t.Parallel() 563 564 db := NewDatabase(rawdb.NewMemoryDatabase()) 565 mvhm := blockstm.MakeMVHashMap() 566 s, _ := NewWithMVHashmap(common.Hash{}, db, nil, mvhm) 567 568 states := []*StateDB{s} 569 570 // Create copies of the original state for each transition 571 for i := 1; i <= 4; i++ { 572 sCopy := s.Copy() 573 sCopy.txIndex = i 574 states = append(states, sCopy) 575 } 576 577 addr := common.HexToAddress("0x01") 578 key := common.HexToHash("0x01") 579 val := common.HexToHash("0x01") 580 balance := new(big.Int).SetUint64(uint64(100)) 581 582 // Tx0 write 583 states[0].GetOrNewStateObject(addr) 584 states[0].SetState(addr, key, val) 585 states[0].SetBalance(addr, balance) 586 states[0].FlushMVWriteSet() 587 588 // Tx1 perform some ops and then revert 589 snapshot := states[1].Snapshot() 590 states[1].AddBalance(addr, new(big.Int).SetUint64(uint64(100))) 591 states[1].SetState(addr, key, common.HexToHash("0x02")) 592 v := states[1].GetState(addr, key) 593 b := states[1].GetBalance(addr) 594 assert.Equal(t, new(big.Int).SetUint64(uint64(200)), b) 595 assert.Equal(t, common.HexToHash("0x02"), v) 596 597 states[1].Suicide(addr) 598 599 states[1].RevertToSnapshot(snapshot) 600 601 v = states[1].GetState(addr, key) 602 b = states[1].GetBalance(addr) 603 604 assert.Equal(t, val, v) 605 assert.Equal(t, balance, b) 606 states[1].Finalise(false) 607 states[1].FlushMVWriteSet() 608 609 // Tx2 check the state and balance 610 v = states[2].GetState(addr, key) 611 b = states[2].GetBalance(addr) 612 613 assert.Equal(t, val, v) 614 assert.Equal(t, balance, b) 615 } 616 617 func TestMVHashMapMarkEstimate(t *testing.T) { 618 t.Parallel() 619 620 db := NewDatabase(rawdb.NewMemoryDatabase()) 621 mvhm := blockstm.MakeMVHashMap() 622 s, _ := NewWithMVHashmap(common.Hash{}, db, nil, mvhm) 623 624 states := []*StateDB{s} 625 626 // Create copies of the original state for each transition 627 for i := 1; i <= 4; i++ { 628 sCopy := s.Copy() 629 sCopy.txIndex = i 630 states = append(states, sCopy) 631 } 632 633 addr := common.HexToAddress("0x01") 634 key := common.HexToHash("0x01") 635 val := common.HexToHash("0x01") 636 balance := new(big.Int).SetUint64(uint64(100)) 637 638 // Tx0 read 639 v := states[0].GetState(addr, key) 640 assert.Equal(t, common.Hash{}, v) 641 642 // Tx0 write 643 states[0].SetState(addr, key, val) 644 v = states[0].GetState(addr, key) 645 assert.Equal(t, val, v) 646 states[0].FlushMVWriteSet() 647 648 // Tx1 write 649 states[1].GetOrNewStateObject(addr) 650 states[1].SetState(addr, key, val) 651 states[1].SetBalance(addr, balance) 652 states[1].FlushMVWriteSet() 653 654 // Tx2 read 655 v = states[2].GetState(addr, key) 656 b := states[2].GetBalance(addr) 657 658 assert.Equal(t, val, v) 659 assert.Equal(t, balance, b) 660 661 // Tx1 mark estimate 662 for _, v := range states[1].MVWriteList() { 663 mvhm.MarkEstimate(v.Path, 1) 664 } 665 666 defer func() { 667 if r := recover(); r == nil { 668 t.Errorf("The code did not panic") 669 } else { 670 t.Log("Recovered in f", r) 671 } 672 }() 673 674 // Tx2 read again should get default (empty) vals because its dependency Tx1 is marked as estimate 675 states[2].GetState(addr, key) 676 states[2].GetBalance(addr) 677 678 // Tx1 read again should get Tx0 vals 679 v = states[1].GetState(addr, key) 680 assert.Equal(t, val, v) 681 } 682 683 func TestMVHashMapOverwrite(t *testing.T) { 684 t.Parallel() 685 686 db := NewDatabase(rawdb.NewMemoryDatabase()) 687 mvhm := blockstm.MakeMVHashMap() 688 s, _ := NewWithMVHashmap(common.Hash{}, db, nil, mvhm) 689 690 states := []*StateDB{s} 691 692 // Create copies of the original state for each transition 693 for i := 1; i <= 4; i++ { 694 sCopy := s.Copy() 695 sCopy.txIndex = i 696 states = append(states, sCopy) 697 } 698 699 addr := common.HexToAddress("0x01") 700 key := common.HexToHash("0x01") 701 val1 := common.HexToHash("0x01") 702 balance1 := new(big.Int).SetUint64(uint64(100)) 703 val2 := common.HexToHash("0x02") 704 balance2 := new(big.Int).SetUint64(uint64(200)) 705 706 // Tx0 write 707 states[0].GetOrNewStateObject(addr) 708 states[0].SetState(addr, key, val1) 709 states[0].SetBalance(addr, balance1) 710 states[0].FlushMVWriteSet() 711 712 // Tx1 write 713 states[1].SetState(addr, key, val2) 714 states[1].SetBalance(addr, balance2) 715 v := states[1].GetState(addr, key) 716 b := states[1].GetBalance(addr) 717 states[1].FlushMVWriteSet() 718 719 assert.Equal(t, val2, v) 720 assert.Equal(t, balance2, b) 721 722 // Tx2 read should get Tx1's value 723 v = states[2].GetState(addr, key) 724 b = states[2].GetBalance(addr) 725 726 assert.Equal(t, val2, v) 727 assert.Equal(t, balance2, b) 728 729 // Tx1 delete 730 for _, v := range states[1].writeMap { 731 mvhm.Delete(v.Path, 1) 732 733 states[1].writeMap = nil 734 } 735 736 // Tx2 read should get Tx0's value 737 v = states[2].GetState(addr, key) 738 b = states[2].GetBalance(addr) 739 740 assert.Equal(t, val1, v) 741 assert.Equal(t, balance1, b) 742 743 // Tx1 read should get Tx0's value 744 v = states[1].GetState(addr, key) 745 b = states[1].GetBalance(addr) 746 747 assert.Equal(t, val1, v) 748 assert.Equal(t, balance1, b) 749 750 // Tx0 delete 751 for _, v := range states[0].writeMap { 752 mvhm.Delete(v.Path, 0) 753 754 states[0].writeMap = nil 755 } 756 757 // Tx2 read again should get default vals 758 v = states[2].GetState(addr, key) 759 b = states[2].GetBalance(addr) 760 761 assert.Equal(t, common.Hash{}, v) 762 assert.Equal(t, common.Big0, b) 763 } 764 765 func TestMVHashMapWriteNoConflict(t *testing.T) { 766 t.Parallel() 767 768 db := NewDatabase(rawdb.NewMemoryDatabase()) 769 mvhm := blockstm.MakeMVHashMap() 770 s, _ := NewWithMVHashmap(common.Hash{}, db, nil, mvhm) 771 772 states := []*StateDB{s} 773 774 // Create copies of the original state for each transition 775 for i := 1; i <= 4; i++ { 776 sCopy := s.Copy() 777 sCopy.txIndex = i 778 states = append(states, sCopy) 779 } 780 781 addr := common.HexToAddress("0x01") 782 key1 := common.HexToHash("0x01") 783 key2 := common.HexToHash("0x02") 784 val1 := common.HexToHash("0x01") 785 balance1 := new(big.Int).SetUint64(uint64(100)) 786 val2 := common.HexToHash("0x02") 787 788 // Tx0 write 789 states[0].GetOrNewStateObject(addr) 790 states[0].FlushMVWriteSet() 791 792 // Tx2 write 793 states[2].SetState(addr, key2, val2) 794 states[2].FlushMVWriteSet() 795 796 // Tx1 write 797 tx1Snapshot := states[1].Snapshot() 798 states[1].SetState(addr, key1, val1) 799 states[1].SetBalance(addr, balance1) 800 states[1].FlushMVWriteSet() 801 802 // Tx1 read 803 assert.Equal(t, val1, states[1].GetState(addr, key1)) 804 assert.Equal(t, balance1, states[1].GetBalance(addr)) 805 // Tx1 should see empty value in key2 806 assert.Equal(t, common.Hash{}, states[1].GetState(addr, key2)) 807 808 // Tx2 read 809 assert.Equal(t, val2, states[2].GetState(addr, key2)) 810 // Tx2 should see values written by Tx1 811 assert.Equal(t, val1, states[2].GetState(addr, key1)) 812 assert.Equal(t, balance1, states[2].GetBalance(addr)) 813 814 // Tx3 read 815 assert.Equal(t, val1, states[3].GetState(addr, key1)) 816 assert.Equal(t, val2, states[3].GetState(addr, key2)) 817 assert.Equal(t, balance1, states[3].GetBalance(addr)) 818 819 // Tx2 delete 820 for _, v := range states[2].writeMap { 821 mvhm.Delete(v.Path, 2) 822 823 states[2].writeMap = nil 824 } 825 826 assert.Equal(t, val1, states[3].GetState(addr, key1)) 827 assert.Equal(t, balance1, states[3].GetBalance(addr)) 828 assert.Equal(t, common.Hash{}, states[3].GetState(addr, key2)) 829 830 // Tx1 revert 831 states[1].RevertToSnapshot(tx1Snapshot) 832 states[1].FlushMVWriteSet() 833 834 assert.Equal(t, common.Hash{}, states[3].GetState(addr, key1)) 835 assert.Equal(t, common.Hash{}, states[3].GetState(addr, key2)) 836 assert.Equal(t, common.Big0, states[3].GetBalance(addr)) 837 838 // Tx1 delete 839 for _, v := range states[1].writeMap { 840 mvhm.Delete(v.Path, 1) 841 842 states[1].writeMap = nil 843 } 844 845 assert.Equal(t, common.Hash{}, states[3].GetState(addr, key1)) 846 assert.Equal(t, common.Hash{}, states[3].GetState(addr, key2)) 847 assert.Equal(t, common.Big0, states[3].GetBalance(addr)) 848 } 849 850 func TestApplyMVWriteSet(t *testing.T) { 851 t.Parallel() 852 853 db := NewDatabase(rawdb.NewMemoryDatabase()) 854 mvhm := blockstm.MakeMVHashMap() 855 s, _ := NewWithMVHashmap(common.Hash{}, db, nil, mvhm) 856 857 sClean := s.Copy() 858 sClean.mvHashmap = nil 859 860 sSingleProcess := sClean.Copy() 861 862 states := []*StateDB{s} 863 864 // Create copies of the original state for each transition 865 for i := 1; i <= 4; i++ { 866 sCopy := s.Copy() 867 sCopy.txIndex = i 868 states = append(states, sCopy) 869 } 870 871 addr1 := common.HexToAddress("0x01") 872 addr2 := common.HexToAddress("0x02") 873 addr3 := common.HexToAddress("0x03") 874 key1 := common.HexToHash("0x01") 875 key2 := common.HexToHash("0x02") 876 val1 := common.HexToHash("0x01") 877 balance1 := new(big.Int).SetUint64(uint64(100)) 878 val2 := common.HexToHash("0x02") 879 balance2 := new(big.Int).SetUint64(uint64(200)) 880 code := []byte{1, 2, 3} 881 882 // Tx0 write 883 states[0].GetOrNewStateObject(addr1) 884 states[0].SetState(addr1, key1, val1) 885 states[0].SetBalance(addr1, balance1) 886 states[0].SetState(addr2, key2, val2) 887 states[0].GetOrNewStateObject(addr3) 888 states[0].Finalise(true) 889 states[0].FlushMVWriteSet() 890 891 sSingleProcess.GetOrNewStateObject(addr1) 892 sSingleProcess.SetState(addr1, key1, val1) 893 sSingleProcess.SetBalance(addr1, balance1) 894 sSingleProcess.SetState(addr2, key2, val2) 895 sSingleProcess.GetOrNewStateObject(addr3) 896 897 sClean.ApplyMVWriteSet(states[0].MVWriteList()) 898 899 assert.Equal(t, sSingleProcess.IntermediateRoot(true), sClean.IntermediateRoot(true)) 900 901 // Tx1 write 902 states[1].SetState(addr1, key2, val2) 903 states[1].SetBalance(addr1, balance2) 904 states[1].SetNonce(addr1, 1) 905 states[1].Finalise(true) 906 states[1].FlushMVWriteSet() 907 908 sSingleProcess.SetState(addr1, key2, val2) 909 sSingleProcess.SetBalance(addr1, balance2) 910 sSingleProcess.SetNonce(addr1, 1) 911 912 sClean.ApplyMVWriteSet(states[1].MVWriteList()) 913 914 assert.Equal(t, sSingleProcess.IntermediateRoot(true), sClean.IntermediateRoot(true)) 915 916 // Tx2 write 917 states[2].SetState(addr1, key1, val2) 918 states[2].SetBalance(addr1, balance2) 919 states[2].SetNonce(addr1, 2) 920 states[2].Finalise(true) 921 states[2].FlushMVWriteSet() 922 923 sSingleProcess.SetState(addr1, key1, val2) 924 sSingleProcess.SetBalance(addr1, balance2) 925 sSingleProcess.SetNonce(addr1, 2) 926 927 sClean.ApplyMVWriteSet(states[2].MVWriteList()) 928 929 assert.Equal(t, sSingleProcess.IntermediateRoot(true), sClean.IntermediateRoot(true)) 930 931 // Tx3 write 932 states[3].Suicide(addr2) 933 states[3].SetCode(addr1, code) 934 states[3].Finalise(true) 935 states[3].FlushMVWriteSet() 936 937 sSingleProcess.Suicide(addr2) 938 sSingleProcess.SetCode(addr1, code) 939 940 sClean.ApplyMVWriteSet(states[3].MVWriteList()) 941 942 assert.Equal(t, sSingleProcess.IntermediateRoot(true), sClean.IntermediateRoot(true)) 943 } 944 945 // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy. 946 // See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512 947 func TestCopyOfCopy(t *testing.T) { 948 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 949 addr := common.HexToAddress("aaaa") 950 state.SetBalance(addr, big.NewInt(42)) 951 952 if got := state.Copy().GetBalance(addr).Uint64(); got != 42 { 953 t.Fatalf("1st copy fail, expected 42, got %v", got) 954 } 955 if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 { 956 t.Fatalf("2nd copy fail, expected 42, got %v", got) 957 } 958 } 959 960 // Tests a regression where committing a copy lost some internal meta information, 961 // leading to corrupted subsequent copies. 962 // 963 // See https://github.com/ethereum/go-ethereum/issues/20106. 964 func TestCopyCommitCopy(t *testing.T) { 965 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 966 967 // Create an account and check if the retrieved balance is correct 968 addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 969 skey := common.HexToHash("aaa") 970 sval := common.HexToHash("bbb") 971 972 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 973 state.SetCode(addr, []byte("hello")) // Change an external metadata 974 state.SetState(addr, skey, sval) // Change the storage trie 975 976 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 977 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 978 } 979 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 980 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 981 } 982 if val := state.GetState(addr, skey); val != sval { 983 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 984 } 985 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 986 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 987 } 988 // Copy the non-committed state database and check pre/post commit balance 989 copyOne := state.Copy() 990 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 991 t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42) 992 } 993 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 994 t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 995 } 996 if val := copyOne.GetState(addr, skey); val != sval { 997 t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 998 } 999 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 1000 t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 1001 } 1002 1003 copyOne.Commit(false) 1004 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 1005 t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42) 1006 } 1007 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 1008 t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 1009 } 1010 if val := copyOne.GetState(addr, skey); val != sval { 1011 t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 1012 } 1013 if val := copyOne.GetCommittedState(addr, skey); val != sval { 1014 t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 1015 } 1016 // Copy the copy and check the balance once more 1017 copyTwo := copyOne.Copy() 1018 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 1019 t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42) 1020 } 1021 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 1022 t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello")) 1023 } 1024 if val := copyTwo.GetState(addr, skey); val != sval { 1025 t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval) 1026 } 1027 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 1028 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 1029 } 1030 } 1031 1032 // Tests a regression where committing a copy lost some internal meta information, 1033 // leading to corrupted subsequent copies. 1034 // 1035 // See https://github.com/ethereum/go-ethereum/issues/20106. 1036 func TestCopyCopyCommitCopy(t *testing.T) { 1037 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 1038 1039 // Create an account and check if the retrieved balance is correct 1040 addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") 1041 skey := common.HexToHash("aaa") 1042 sval := common.HexToHash("bbb") 1043 1044 state.SetBalance(addr, big.NewInt(42)) // Change the account trie 1045 state.SetCode(addr, []byte("hello")) // Change an external metadata 1046 state.SetState(addr, skey, sval) // Change the storage trie 1047 1048 if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 1049 t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) 1050 } 1051 if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 1052 t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) 1053 } 1054 if val := state.GetState(addr, skey); val != sval { 1055 t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) 1056 } 1057 if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { 1058 t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 1059 } 1060 // Copy the non-committed state database and check pre/post commit balance 1061 copyOne := state.Copy() 1062 if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 1063 t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42) 1064 } 1065 if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 1066 t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello")) 1067 } 1068 if val := copyOne.GetState(addr, skey); val != sval { 1069 t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval) 1070 } 1071 if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { 1072 t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 1073 } 1074 // Copy the copy and check the balance once more 1075 copyTwo := copyOne.Copy() 1076 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 1077 t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42) 1078 } 1079 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 1080 t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) 1081 } 1082 if val := copyTwo.GetState(addr, skey); val != sval { 1083 t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 1084 } 1085 if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) { 1086 t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) 1087 } 1088 copyTwo.Commit(false) 1089 if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 1090 t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42) 1091 } 1092 if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 1093 t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello")) 1094 } 1095 if val := copyTwo.GetState(addr, skey); val != sval { 1096 t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) 1097 } 1098 if val := copyTwo.GetCommittedState(addr, skey); val != sval { 1099 t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval) 1100 } 1101 // Copy the copy-copy and check the balance once more 1102 copyThree := copyTwo.Copy() 1103 if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { 1104 t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42) 1105 } 1106 if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) { 1107 t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello")) 1108 } 1109 if val := copyThree.GetState(addr, skey); val != sval { 1110 t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval) 1111 } 1112 if val := copyThree.GetCommittedState(addr, skey); val != sval { 1113 t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval) 1114 } 1115 } 1116 1117 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 1118 // while changing the internals of StateDB. The workflow is that a contract is 1119 // self-destructed, then in a follow-up transaction (but same block) it's created 1120 // again and the transaction reverted. 1121 // 1122 // The original StateDB implementation flushed dirty objects to the tries after 1123 // each transaction, so this works ok. The rework accumulated writes in memory 1124 // first, but the journal wiped the entire state object on create-revert. 1125 func TestDeleteCreateRevert(t *testing.T) { 1126 // Create an initial state with a single contract 1127 state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil) 1128 1129 addr := common.BytesToAddress([]byte("so")) 1130 state.SetBalance(addr, big.NewInt(1)) 1131 1132 root, _ := state.Commit(false) 1133 state, _ = New(root, state.db, state.snaps) 1134 1135 // Simulate self-destructing in one transaction, then create-reverting in another 1136 state.Suicide(addr) 1137 state.Finalise(true) 1138 1139 id := state.Snapshot() 1140 state.SetBalance(addr, big.NewInt(2)) 1141 state.RevertToSnapshot(id) 1142 1143 // Commit the entire state and make sure we don't crash and have the correct state 1144 root, _ = state.Commit(true) 1145 state, _ = New(root, state.db, state.snaps) 1146 1147 if state.getStateObject(addr) != nil { 1148 t.Fatalf("self-destructed contract came alive") 1149 } 1150 } 1151 1152 // TestMissingTrieNodes tests that if the StateDB fails to load parts of the trie, 1153 // the Commit operation fails with an error 1154 // If we are missing trie nodes, we should not continue writing to the trie 1155 func TestMissingTrieNodes(t *testing.T) { 1156 1157 // Create an initial state with a few accounts 1158 memDb := rawdb.NewMemoryDatabase() 1159 db := NewDatabase(memDb) 1160 var root common.Hash 1161 state, _ := New(common.Hash{}, db, nil) 1162 addr := common.BytesToAddress([]byte("so")) 1163 { 1164 state.SetBalance(addr, big.NewInt(1)) 1165 state.SetCode(addr, []byte{1, 2, 3}) 1166 a2 := common.BytesToAddress([]byte("another")) 1167 state.SetBalance(a2, big.NewInt(100)) 1168 state.SetCode(a2, []byte{1, 2, 4}) 1169 root, _ = state.Commit(false) 1170 t.Logf("root: %x", root) 1171 // force-flush 1172 state.Database().TrieDB().Cap(0) 1173 } 1174 // Create a new state on the old root 1175 state, _ = New(root, db, nil) 1176 // Now we clear out the memdb 1177 it := memDb.NewIterator(nil, nil) 1178 for it.Next() { 1179 k := it.Key() 1180 // Leave the root intact 1181 if !bytes.Equal(k, root[:]) { 1182 t.Logf("key: %x", k) 1183 memDb.Delete(k) 1184 } 1185 } 1186 balance := state.GetBalance(addr) 1187 // The removed elem should lead to it returning zero balance 1188 if exp, got := uint64(0), balance.Uint64(); got != exp { 1189 t.Errorf("expected %d, got %d", exp, got) 1190 } 1191 // Modify the state 1192 state.SetBalance(addr, big.NewInt(2)) 1193 root, err := state.Commit(false) 1194 if err == nil { 1195 t.Fatalf("expected error, got root :%x", root) 1196 } 1197 } 1198 1199 func TestStateDBAccessList(t *testing.T) { 1200 // Some helpers 1201 addr := func(a string) common.Address { 1202 return common.HexToAddress(a) 1203 } 1204 slot := func(a string) common.Hash { 1205 return common.HexToHash(a) 1206 } 1207 1208 memDb := rawdb.NewMemoryDatabase() 1209 db := NewDatabase(memDb) 1210 state, _ := New(common.Hash{}, db, nil) 1211 state.accessList = newAccessList() 1212 1213 verifyAddrs := func(astrings ...string) { 1214 t.Helper() 1215 // convert to common.Address form 1216 var addresses []common.Address 1217 var addressMap = make(map[common.Address]struct{}) 1218 for _, astring := range astrings { 1219 address := addr(astring) 1220 addresses = append(addresses, address) 1221 addressMap[address] = struct{}{} 1222 } 1223 // Check that the given addresses are in the access list 1224 for _, address := range addresses { 1225 if !state.AddressInAccessList(address) { 1226 t.Fatalf("expected %x to be in access list", address) 1227 } 1228 } 1229 // Check that only the expected addresses are present in the acesslist 1230 for address := range state.accessList.addresses { 1231 if _, exist := addressMap[address]; !exist { 1232 t.Fatalf("extra address %x in access list", address) 1233 } 1234 } 1235 } 1236 verifySlots := func(addrString string, slotStrings ...string) { 1237 if !state.AddressInAccessList(addr(addrString)) { 1238 t.Fatalf("scope missing address/slots %v", addrString) 1239 } 1240 var address = addr(addrString) 1241 // convert to common.Hash form 1242 var slots []common.Hash 1243 var slotMap = make(map[common.Hash]struct{}) 1244 for _, slotString := range slotStrings { 1245 s := slot(slotString) 1246 slots = append(slots, s) 1247 slotMap[s] = struct{}{} 1248 } 1249 // Check that the expected items are in the access list 1250 for i, s := range slots { 1251 if _, slotPresent := state.SlotInAccessList(address, s); !slotPresent { 1252 t.Fatalf("input %d: scope missing slot %v (address %v)", i, s, addrString) 1253 } 1254 } 1255 // Check that no extra elements are in the access list 1256 index := state.accessList.addresses[address] 1257 if index >= 0 { 1258 stateSlots := state.accessList.slots[index] 1259 for s := range stateSlots { 1260 if _, slotPresent := slotMap[s]; !slotPresent { 1261 t.Fatalf("scope has extra slot %v (address %v)", s, addrString) 1262 } 1263 } 1264 } 1265 } 1266 1267 state.AddAddressToAccessList(addr("aa")) // 1 1268 state.AddSlotToAccessList(addr("bb"), slot("01")) // 2,3 1269 state.AddSlotToAccessList(addr("bb"), slot("02")) // 4 1270 verifyAddrs("aa", "bb") 1271 verifySlots("bb", "01", "02") 1272 1273 // Make a copy 1274 stateCopy1 := state.Copy() 1275 if exp, got := 4, state.journal.length(); exp != got { 1276 t.Fatalf("journal length mismatch: have %d, want %d", got, exp) 1277 } 1278 1279 // same again, should cause no journal entries 1280 state.AddSlotToAccessList(addr("bb"), slot("01")) 1281 state.AddSlotToAccessList(addr("bb"), slot("02")) 1282 state.AddAddressToAccessList(addr("aa")) 1283 if exp, got := 4, state.journal.length(); exp != got { 1284 t.Fatalf("journal length mismatch: have %d, want %d", got, exp) 1285 } 1286 // some new ones 1287 state.AddSlotToAccessList(addr("bb"), slot("03")) // 5 1288 state.AddSlotToAccessList(addr("aa"), slot("01")) // 6 1289 state.AddSlotToAccessList(addr("cc"), slot("01")) // 7,8 1290 state.AddAddressToAccessList(addr("cc")) 1291 if exp, got := 8, state.journal.length(); exp != got { 1292 t.Fatalf("journal length mismatch: have %d, want %d", got, exp) 1293 } 1294 1295 verifyAddrs("aa", "bb", "cc") 1296 verifySlots("aa", "01") 1297 verifySlots("bb", "01", "02", "03") 1298 verifySlots("cc", "01") 1299 1300 // now start rolling back changes 1301 state.journal.revert(state, 7) 1302 if _, ok := state.SlotInAccessList(addr("cc"), slot("01")); ok { 1303 t.Fatalf("slot present, expected missing") 1304 } 1305 verifyAddrs("aa", "bb", "cc") 1306 verifySlots("aa", "01") 1307 verifySlots("bb", "01", "02", "03") 1308 1309 state.journal.revert(state, 6) 1310 if state.AddressInAccessList(addr("cc")) { 1311 t.Fatalf("addr present, expected missing") 1312 } 1313 verifyAddrs("aa", "bb") 1314 verifySlots("aa", "01") 1315 verifySlots("bb", "01", "02", "03") 1316 1317 state.journal.revert(state, 5) 1318 if _, ok := state.SlotInAccessList(addr("aa"), slot("01")); ok { 1319 t.Fatalf("slot present, expected missing") 1320 } 1321 verifyAddrs("aa", "bb") 1322 verifySlots("bb", "01", "02", "03") 1323 1324 state.journal.revert(state, 4) 1325 if _, ok := state.SlotInAccessList(addr("bb"), slot("03")); ok { 1326 t.Fatalf("slot present, expected missing") 1327 } 1328 verifyAddrs("aa", "bb") 1329 verifySlots("bb", "01", "02") 1330 1331 state.journal.revert(state, 3) 1332 if _, ok := state.SlotInAccessList(addr("bb"), slot("02")); ok { 1333 t.Fatalf("slot present, expected missing") 1334 } 1335 verifyAddrs("aa", "bb") 1336 verifySlots("bb", "01") 1337 1338 state.journal.revert(state, 2) 1339 if _, ok := state.SlotInAccessList(addr("bb"), slot("01")); ok { 1340 t.Fatalf("slot present, expected missing") 1341 } 1342 verifyAddrs("aa", "bb") 1343 1344 state.journal.revert(state, 1) 1345 if state.AddressInAccessList(addr("bb")) { 1346 t.Fatalf("addr present, expected missing") 1347 } 1348 verifyAddrs("aa") 1349 1350 state.journal.revert(state, 0) 1351 if state.AddressInAccessList(addr("aa")) { 1352 t.Fatalf("addr present, expected missing") 1353 } 1354 if got, exp := len(state.accessList.addresses), 0; got != exp { 1355 t.Fatalf("expected empty, got %d", got) 1356 } 1357 if got, exp := len(state.accessList.slots), 0; got != exp { 1358 t.Fatalf("expected empty, got %d", got) 1359 } 1360 // Check the copy 1361 // Make a copy 1362 state = stateCopy1 1363 verifyAddrs("aa", "bb") 1364 verifySlots("bb", "01", "02") 1365 if got, exp := len(state.accessList.addresses), 2; got != exp { 1366 t.Fatalf("expected empty, got %d", got) 1367 } 1368 if got, exp := len(state.accessList.slots), 1; got != exp { 1369 t.Fatalf("expected empty, got %d", got) 1370 } 1371 }