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