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