github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/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/scroll-tech/go-ethereum/common"
    33  	"github.com/scroll-tech/go-ethereum/core/rawdb"
    34  	"github.com/scroll-tech/go-ethereum/core/types"
    35  )
    36  
    37  // Tests that updating a state trie does not leak any database writes prior to
    38  // actually committing the state.
    39  func TestUpdateLeaks(t *testing.T) {
    40  	// Create an empty state database
    41  	db := rawdb.NewMemoryDatabase()
    42  	state, _ := New(common.Hash{}, NewDatabase(db), nil)
    43  
    44  	// Update it with some accounts
    45  	for i := byte(0); i < 255; i++ {
    46  		addr := common.BytesToAddress([]byte{i})
    47  		state.AddBalance(addr, big.NewInt(int64(11*i)))
    48  		state.SetNonce(addr, uint64(42*i))
    49  		if i%2 == 0 {
    50  			state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
    51  		}
    52  		if i%3 == 0 {
    53  			state.SetCode(addr, []byte{i, i, i, i, i})
    54  		}
    55  	}
    56  
    57  	root := state.IntermediateRoot(false)
    58  	if err := state.Database().TrieDB().Commit(root, false, 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/scroll-tech/go-ethereum/pull/15549.
   150  func TestCopy(t *testing.T) {
   151  	// Create a random state test to copy and modify "independently"
   152  	orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   153  
   154  	for i := byte(0); i < 255; i++ {
   155  		obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   156  		obj.AddBalance(big.NewInt(int64(i)))
   157  		orig.updateStateObject(obj)
   158  	}
   159  	orig.Finalise(false)
   160  
   161  	// Copy the state
   162  	copy := orig.Copy()
   163  
   164  	// Copy the copy state
   165  	ccopy := copy.Copy()
   166  
   167  	// modify all in memory
   168  	for i := byte(0); i < 255; i++ {
   169  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   170  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   171  		ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   172  
   173  		origObj.AddBalance(big.NewInt(2 * int64(i)))
   174  		copyObj.AddBalance(big.NewInt(3 * int64(i)))
   175  		ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
   176  
   177  		orig.updateStateObject(origObj)
   178  		copy.updateStateObject(copyObj)
   179  		ccopy.updateStateObject(copyObj)
   180  	}
   181  
   182  	// Finalise the changes on all concurrently
   183  	finalise := func(wg *sync.WaitGroup, db *StateDB) {
   184  		defer wg.Done()
   185  		db.Finalise(true)
   186  	}
   187  
   188  	var wg sync.WaitGroup
   189  	wg.Add(3)
   190  	go finalise(&wg, orig)
   191  	go finalise(&wg, copy)
   192  	go finalise(&wg, ccopy)
   193  	wg.Wait()
   194  
   195  	// Verify that the three states have been updated independently
   196  	for i := byte(0); i < 255; i++ {
   197  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   198  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   199  		ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   200  
   201  		if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 {
   202  			t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want)
   203  		}
   204  		if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 {
   205  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want)
   206  		}
   207  		if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 {
   208  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want)
   209  		}
   210  	}
   211  }
   212  
   213  func TestSnapshotRandom(t *testing.T) {
   214  	config := &quick.Config{MaxCount: 1000}
   215  	err := quick.Check((*snapshotTest).run, config)
   216  	if cerr, ok := err.(*quick.CheckError); ok {
   217  		test := cerr.In[0].(*snapshotTest)
   218  		t.Errorf("%v:\n%s", test.err, test)
   219  	} else if err != nil {
   220  		t.Error(err)
   221  	}
   222  }
   223  
   224  // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes
   225  // captured by the snapshot. Instances of this test with pseudorandom content are created
   226  // by Generate.
   227  //
   228  // The test works as follows:
   229  //
   230  // A new state is created and all actions are applied to it. Several snapshots are taken
   231  // in between actions. The test then reverts each snapshot. For each snapshot the actions
   232  // leading up to it are replayed on a fresh, empty state. The behaviour of all public
   233  // accessor methods on the reverted state must match the return value of the equivalent
   234  // methods on the replayed state.
   235  type snapshotTest struct {
   236  	addrs     []common.Address // all account addresses
   237  	actions   []testAction     // modifications to the state
   238  	snapshots []int            // actions indexes at which snapshot is taken
   239  	err       error            // failure details are reported through this field
   240  }
   241  
   242  type testAction struct {
   243  	name   string
   244  	fn     func(testAction, *StateDB)
   245  	args   []int64
   246  	noAddr bool
   247  }
   248  
   249  // newTestAction creates a random action that changes state.
   250  func newTestAction(addr common.Address, r *rand.Rand) testAction {
   251  	actions := []testAction{
   252  		{
   253  			name: "SetBalance",
   254  			fn: func(a testAction, s *StateDB) {
   255  				s.SetBalance(addr, big.NewInt(a.args[0]))
   256  			},
   257  			args: make([]int64, 1),
   258  		},
   259  		{
   260  			name: "AddBalance",
   261  			fn: func(a testAction, s *StateDB) {
   262  				s.AddBalance(addr, big.NewInt(a.args[0]))
   263  			},
   264  			args: make([]int64, 1),
   265  		},
   266  		{
   267  			name: "SetNonce",
   268  			fn: func(a testAction, s *StateDB) {
   269  				s.SetNonce(addr, uint64(a.args[0]))
   270  			},
   271  			args: make([]int64, 1),
   272  		},
   273  		{
   274  			name: "SetState",
   275  			fn: func(a testAction, s *StateDB) {
   276  				var key, val common.Hash
   277  				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
   278  				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))
   279  				s.SetState(addr, key, val)
   280  			},
   281  			args: make([]int64, 2),
   282  		},
   283  		{
   284  			name: "SetCode",
   285  			fn: func(a testAction, s *StateDB) {
   286  				code := make([]byte, 16)
   287  				binary.BigEndian.PutUint64(code, uint64(a.args[0]))
   288  				binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
   289  				s.SetCode(addr, code)
   290  			},
   291  			args: make([]int64, 2),
   292  		},
   293  		{
   294  			name: "CreateAccount",
   295  			fn: func(a testAction, s *StateDB) {
   296  				s.CreateAccount(addr)
   297  			},
   298  		},
   299  		{
   300  			name: "Suicide",
   301  			fn: func(a testAction, s *StateDB) {
   302  				s.Suicide(addr)
   303  			},
   304  		},
   305  		{
   306  			name: "AddRefund",
   307  			fn: func(a testAction, s *StateDB) {
   308  				s.AddRefund(uint64(a.args[0]))
   309  			},
   310  			args:   make([]int64, 1),
   311  			noAddr: true,
   312  		},
   313  		{
   314  			name: "AddLog",
   315  			fn: func(a testAction, s *StateDB) {
   316  				data := make([]byte, 2)
   317  				binary.BigEndian.PutUint16(data, uint16(a.args[0]))
   318  				s.AddLog(&types.Log{Address: addr, Data: data})
   319  			},
   320  			args: make([]int64, 1),
   321  		},
   322  		{
   323  			name: "AddPreimage",
   324  			fn: func(a testAction, s *StateDB) {
   325  				preimage := []byte{1}
   326  				hash := common.BytesToHash(preimage)
   327  				s.AddPreimage(hash, preimage)
   328  			},
   329  			args: make([]int64, 1),
   330  		},
   331  		{
   332  			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("GetKeccakCodeHash", state.GetKeccakCodeHash(addr), checkstate.GetKeccakCodeHash(addr))
   447  		checkeq("GetPoseidonCodeHash", state.GetPoseidonCodeHash(addr), checkstate.GetPoseidonCodeHash(addr))
   448  		checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
   449  		// Check storage.
   450  		if obj := state.getStateObject(addr); obj != nil {
   451  			state.ForEachStorage(addr, func(key, value common.Hash) bool {
   452  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   453  			})
   454  			checkstate.ForEachStorage(addr, func(key, value common.Hash) bool {
   455  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   456  			})
   457  		}
   458  		if err != nil {
   459  			return err
   460  		}
   461  	}
   462  
   463  	if state.GetRefund() != checkstate.GetRefund() {
   464  		return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
   465  			state.GetRefund(), checkstate.GetRefund())
   466  	}
   467  	if !reflect.DeepEqual(state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{})) {
   468  		return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v",
   469  			state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{}))
   470  	}
   471  	return nil
   472  }
   473  
   474  func TestTouchDelete(t *testing.T) {
   475  	s := newStateTest()
   476  	s.state.GetOrNewStateObject(common.Address{})
   477  	root, _ := s.state.Commit(false)
   478  	s.state, _ = New(root, s.state.db, s.state.snaps)
   479  
   480  	snapshot := s.state.Snapshot()
   481  	s.state.AddBalance(common.Address{}, new(big.Int))
   482  
   483  	if len(s.state.journal.dirties) != 1 {
   484  		t.Fatal("expected one dirty state object")
   485  	}
   486  	s.state.RevertToSnapshot(snapshot)
   487  	if len(s.state.journal.dirties) != 0 {
   488  		t.Fatal("expected no dirty state object")
   489  	}
   490  }
   491  
   492  // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
   493  // See https://github.com/scroll-tech/go-ethereum/pull/15225#issuecomment-380191512
   494  func TestCopyOfCopy(t *testing.T) {
   495  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   496  	addr := common.HexToAddress("aaaa")
   497  	state.SetBalance(addr, big.NewInt(42))
   498  
   499  	if got := state.Copy().GetBalance(addr).Uint64(); got != 42 {
   500  		t.Fatalf("1st copy fail, expected 42, got %v", got)
   501  	}
   502  	if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 {
   503  		t.Fatalf("2nd copy fail, expected 42, got %v", got)
   504  	}
   505  }
   506  
   507  // Tests a regression where committing a copy lost some internal meta information,
   508  // leading to corrupted subsequent copies.
   509  //
   510  // See https://github.com/scroll-tech/go-ethereum/issues/20106.
   511  func TestCopyCommitCopy(t *testing.T) {
   512  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   513  
   514  	// Create an account and check if the retrieved balance is correct
   515  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   516  	skey := common.HexToHash("aaa")
   517  	sval := common.HexToHash("bbb")
   518  
   519  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   520  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   521  	state.SetState(addr, skey, sval)       // Change the storage trie
   522  
   523  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   524  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   525  	}
   526  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   527  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   528  	}
   529  	if val := state.GetState(addr, skey); val != sval {
   530  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   531  	}
   532  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   533  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   534  	}
   535  	// Copy the non-committed state database and check pre/post commit balance
   536  	copyOne := state.Copy()
   537  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   538  		t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   539  	}
   540  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   541  		t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   542  	}
   543  	if val := copyOne.GetState(addr, skey); val != sval {
   544  		t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   545  	}
   546  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   547  		t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   548  	}
   549  
   550  	copyOne.Commit(false)
   551  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   552  		t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42)
   553  	}
   554  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   555  		t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   556  	}
   557  	if val := copyOne.GetState(addr, skey); val != sval {
   558  		t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   559  	}
   560  	if val := copyOne.GetCommittedState(addr, skey); val != sval {
   561  		t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   562  	}
   563  	// Copy the copy and check the balance once more
   564  	copyTwo := copyOne.Copy()
   565  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   566  		t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42)
   567  	}
   568  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   569  		t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello"))
   570  	}
   571  	if val := copyTwo.GetState(addr, skey); val != sval {
   572  		t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   573  	}
   574  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   575  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   576  	}
   577  }
   578  
   579  // Tests a regression where committing a copy lost some internal meta information,
   580  // leading to corrupted subsequent copies.
   581  //
   582  // See https://github.com/scroll-tech/go-ethereum/issues/20106.
   583  func TestCopyCopyCommitCopy(t *testing.T) {
   584  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   585  
   586  	// Create an account and check if the retrieved balance is correct
   587  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   588  	skey := common.HexToHash("aaa")
   589  	sval := common.HexToHash("bbb")
   590  
   591  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   592  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   593  	state.SetState(addr, skey, sval)       // Change the storage trie
   594  
   595  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   596  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   597  	}
   598  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   599  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   600  	}
   601  	if val := state.GetState(addr, skey); val != sval {
   602  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   603  	}
   604  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   605  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   606  	}
   607  	// Copy the non-committed state database and check pre/post commit balance
   608  	copyOne := state.Copy()
   609  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   610  		t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42)
   611  	}
   612  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   613  		t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello"))
   614  	}
   615  	if val := copyOne.GetState(addr, skey); val != sval {
   616  		t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   617  	}
   618  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   619  		t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   620  	}
   621  	// Copy the copy and check the balance once more
   622  	copyTwo := copyOne.Copy()
   623  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   624  		t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   625  	}
   626  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   627  		t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   628  	}
   629  	if val := copyTwo.GetState(addr, skey); val != sval {
   630  		t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   631  	}
   632  	if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) {
   633  		t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   634  	}
   635  	copyTwo.Commit(false)
   636  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   637  		t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42)
   638  	}
   639  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   640  		t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   641  	}
   642  	if val := copyTwo.GetState(addr, skey); val != sval {
   643  		t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   644  	}
   645  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   646  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   647  	}
   648  	// Copy the copy-copy and check the balance once more
   649  	copyThree := copyTwo.Copy()
   650  	if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   651  		t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42)
   652  	}
   653  	if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   654  		t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello"))
   655  	}
   656  	if val := copyThree.GetState(addr, skey); val != sval {
   657  		t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   658  	}
   659  	if val := copyThree.GetCommittedState(addr, skey); val != sval {
   660  		t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval)
   661  	}
   662  }
   663  
   664  // TestDeleteCreateRevert tests a weird state transition corner case that we hit
   665  // while changing the internals of StateDB. The workflow is that a contract is
   666  // self-destructed, then in a follow-up transaction (but same block) it's created
   667  // again and the transaction reverted.
   668  //
   669  // The original StateDB implementation flushed dirty objects to the tries after
   670  // each transaction, so this works ok. The rework accumulated writes in memory
   671  // first, but the journal wiped the entire state object on create-revert.
   672  func TestDeleteCreateRevert(t *testing.T) {
   673  	// Create an initial state with a single contract
   674  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   675  
   676  	addr := common.BytesToAddress([]byte("so"))
   677  	state.SetBalance(addr, big.NewInt(1))
   678  
   679  	root, _ := state.Commit(false)
   680  	state, _ = New(root, state.db, state.snaps)
   681  
   682  	// Simulate self-destructing in one transaction, then create-reverting in another
   683  	state.Suicide(addr)
   684  	state.Finalise(true)
   685  
   686  	id := state.Snapshot()
   687  	state.SetBalance(addr, big.NewInt(2))
   688  	state.RevertToSnapshot(id)
   689  
   690  	// Commit the entire state and make sure we don't crash and have the correct state
   691  	root, _ = state.Commit(true)
   692  	state, _ = New(root, state.db, state.snaps)
   693  
   694  	if state.getStateObject(addr) != nil {
   695  		t.Fatalf("self-destructed contract came alive")
   696  	}
   697  }
   698  
   699  // TestMissingTrieNodes tests that if the StateDB fails to load parts of the trie,
   700  // the Commit operation fails with an error
   701  // If we are missing trie nodes, we should not continue writing to the trie
   702  func TestMissingTrieNodes(t *testing.T) {
   703  
   704  	// Create an initial state with a few accounts
   705  	memDb := rawdb.NewMemoryDatabase()
   706  	db := NewDatabase(memDb)
   707  	var root common.Hash
   708  	state, _ := New(common.Hash{}, db, nil)
   709  	addr := common.BytesToAddress([]byte("so"))
   710  	{
   711  		state.SetBalance(addr, big.NewInt(1))
   712  		state.SetCode(addr, []byte{1, 2, 3})
   713  		a2 := common.BytesToAddress([]byte("another"))
   714  		state.SetBalance(a2, big.NewInt(100))
   715  		state.SetCode(a2, []byte{1, 2, 4})
   716  		root, _ = state.Commit(false)
   717  		t.Logf("root: %x", root)
   718  		// force-flush
   719  		state.Database().TrieDB().Cap(0)
   720  	}
   721  	// Create a new state on the old root
   722  	state, _ = New(root, db, nil)
   723  	// Now we clear out the memdb
   724  	it := memDb.NewIterator(nil, nil)
   725  	for it.Next() {
   726  		k := it.Key()
   727  		// Leave the root intact
   728  		if !bytes.Equal(k, root[:]) {
   729  			t.Logf("key: %x", k)
   730  			memDb.Delete(k)
   731  		}
   732  	}
   733  	balance := state.GetBalance(addr)
   734  	// The removed elem should lead to it returning zero balance
   735  	if exp, got := uint64(0), balance.Uint64(); got != exp {
   736  		t.Errorf("expected %d, got %d", exp, got)
   737  	}
   738  	// Modify the state
   739  	state.SetBalance(addr, big.NewInt(2))
   740  	root, err := state.Commit(false)
   741  	if err == nil {
   742  		t.Fatalf("expected error, got root :%x", root)
   743  	}
   744  }
   745  
   746  func TestStateDBAccessList(t *testing.T) {
   747  	// Some helpers
   748  	addr := func(a string) common.Address {
   749  		return common.HexToAddress(a)
   750  	}
   751  	slot := func(a string) common.Hash {
   752  		return common.HexToHash(a)
   753  	}
   754  
   755  	memDb := rawdb.NewMemoryDatabase()
   756  	db := NewDatabase(memDb)
   757  	state, _ := New(common.Hash{}, db, nil)
   758  	state.accessList = newAccessList()
   759  
   760  	verifyAddrs := func(astrings ...string) {
   761  		t.Helper()
   762  		// convert to common.Address form
   763  		var addresses []common.Address
   764  		var addressMap = make(map[common.Address]struct{})
   765  		for _, astring := range astrings {
   766  			address := addr(astring)
   767  			addresses = append(addresses, address)
   768  			addressMap[address] = struct{}{}
   769  		}
   770  		// Check that the given addresses are in the access list
   771  		for _, address := range addresses {
   772  			if !state.AddressInAccessList(address) {
   773  				t.Fatalf("expected %x to be in access list", address)
   774  			}
   775  		}
   776  		// Check that only the expected addresses are present in the acesslist
   777  		for address := range state.accessList.addresses {
   778  			if _, exist := addressMap[address]; !exist {
   779  				t.Fatalf("extra address %x in access list", address)
   780  			}
   781  		}
   782  	}
   783  	verifySlots := func(addrString string, slotStrings ...string) {
   784  		if !state.AddressInAccessList(addr(addrString)) {
   785  			t.Fatalf("scope missing address/slots %v", addrString)
   786  		}
   787  		var address = addr(addrString)
   788  		// convert to common.Hash form
   789  		var slots []common.Hash
   790  		var slotMap = make(map[common.Hash]struct{})
   791  		for _, slotString := range slotStrings {
   792  			s := slot(slotString)
   793  			slots = append(slots, s)
   794  			slotMap[s] = struct{}{}
   795  		}
   796  		// Check that the expected items are in the access list
   797  		for i, s := range slots {
   798  			if _, slotPresent := state.SlotInAccessList(address, s); !slotPresent {
   799  				t.Fatalf("input %d: scope missing slot %v (address %v)", i, s, addrString)
   800  			}
   801  		}
   802  		// Check that no extra elements are in the access list
   803  		index := state.accessList.addresses[address]
   804  		if index >= 0 {
   805  			stateSlots := state.accessList.slots[index]
   806  			for s := range stateSlots {
   807  				if _, slotPresent := slotMap[s]; !slotPresent {
   808  					t.Fatalf("scope has extra slot %v (address %v)", s, addrString)
   809  				}
   810  			}
   811  		}
   812  	}
   813  
   814  	state.AddAddressToAccessList(addr("aa"))          // 1
   815  	state.AddSlotToAccessList(addr("bb"), slot("01")) // 2,3
   816  	state.AddSlotToAccessList(addr("bb"), slot("02")) // 4
   817  	verifyAddrs("aa", "bb")
   818  	verifySlots("bb", "01", "02")
   819  
   820  	// Make a copy
   821  	stateCopy1 := state.Copy()
   822  	if exp, got := 4, state.journal.length(); exp != got {
   823  		t.Fatalf("journal length mismatch: have %d, want %d", got, exp)
   824  	}
   825  
   826  	// same again, should cause no journal entries
   827  	state.AddSlotToAccessList(addr("bb"), slot("01"))
   828  	state.AddSlotToAccessList(addr("bb"), slot("02"))
   829  	state.AddAddressToAccessList(addr("aa"))
   830  	if exp, got := 4, state.journal.length(); exp != got {
   831  		t.Fatalf("journal length mismatch: have %d, want %d", got, exp)
   832  	}
   833  	// some new ones
   834  	state.AddSlotToAccessList(addr("bb"), slot("03")) // 5
   835  	state.AddSlotToAccessList(addr("aa"), slot("01")) // 6
   836  	state.AddSlotToAccessList(addr("cc"), slot("01")) // 7,8
   837  	state.AddAddressToAccessList(addr("cc"))
   838  	if exp, got := 8, state.journal.length(); exp != got {
   839  		t.Fatalf("journal length mismatch: have %d, want %d", got, exp)
   840  	}
   841  
   842  	verifyAddrs("aa", "bb", "cc")
   843  	verifySlots("aa", "01")
   844  	verifySlots("bb", "01", "02", "03")
   845  	verifySlots("cc", "01")
   846  
   847  	// now start rolling back changes
   848  	state.journal.revert(state, 7)
   849  	if _, ok := state.SlotInAccessList(addr("cc"), slot("01")); ok {
   850  		t.Fatalf("slot present, expected missing")
   851  	}
   852  	verifyAddrs("aa", "bb", "cc")
   853  	verifySlots("aa", "01")
   854  	verifySlots("bb", "01", "02", "03")
   855  
   856  	state.journal.revert(state, 6)
   857  	if state.AddressInAccessList(addr("cc")) {
   858  		t.Fatalf("addr present, expected missing")
   859  	}
   860  	verifyAddrs("aa", "bb")
   861  	verifySlots("aa", "01")
   862  	verifySlots("bb", "01", "02", "03")
   863  
   864  	state.journal.revert(state, 5)
   865  	if _, ok := state.SlotInAccessList(addr("aa"), slot("01")); ok {
   866  		t.Fatalf("slot present, expected missing")
   867  	}
   868  	verifyAddrs("aa", "bb")
   869  	verifySlots("bb", "01", "02", "03")
   870  
   871  	state.journal.revert(state, 4)
   872  	if _, ok := state.SlotInAccessList(addr("bb"), slot("03")); ok {
   873  		t.Fatalf("slot present, expected missing")
   874  	}
   875  	verifyAddrs("aa", "bb")
   876  	verifySlots("bb", "01", "02")
   877  
   878  	state.journal.revert(state, 3)
   879  	if _, ok := state.SlotInAccessList(addr("bb"), slot("02")); ok {
   880  		t.Fatalf("slot present, expected missing")
   881  	}
   882  	verifyAddrs("aa", "bb")
   883  	verifySlots("bb", "01")
   884  
   885  	state.journal.revert(state, 2)
   886  	if _, ok := state.SlotInAccessList(addr("bb"), slot("01")); ok {
   887  		t.Fatalf("slot present, expected missing")
   888  	}
   889  	verifyAddrs("aa", "bb")
   890  
   891  	state.journal.revert(state, 1)
   892  	if state.AddressInAccessList(addr("bb")) {
   893  		t.Fatalf("addr present, expected missing")
   894  	}
   895  	verifyAddrs("aa")
   896  
   897  	state.journal.revert(state, 0)
   898  	if state.AddressInAccessList(addr("aa")) {
   899  		t.Fatalf("addr present, expected missing")
   900  	}
   901  	if got, exp := len(state.accessList.addresses), 0; got != exp {
   902  		t.Fatalf("expected empty, got %d", got)
   903  	}
   904  	if got, exp := len(state.accessList.slots), 0; got != exp {
   905  		t.Fatalf("expected empty, got %d", got)
   906  	}
   907  	// Check the copy
   908  	// Make a copy
   909  	state = stateCopy1
   910  	verifyAddrs("aa", "bb")
   911  	verifySlots("bb", "01", "02")
   912  	if got, exp := len(state.accessList.addresses), 2; got != exp {
   913  		t.Fatalf("expected empty, got %d", got)
   914  	}
   915  	if got, exp := len(state.accessList.slots), 1; got != exp {
   916  		t.Fatalf("expected empty, got %d", got)
   917  	}
   918  }