github.com/MetalBlockchain/subnet-evm@v0.4.9/core/state/statedb_test.go (about)

     1  // (c) 2019-2021, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2016 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package state
    28  
    29  import (
    30  	"bytes"
    31  	"encoding/binary"
    32  	"fmt"
    33  	"math"
    34  	"math/big"
    35  	"math/rand"
    36  	"reflect"
    37  	"strings"
    38  	"sync"
    39  	"testing"
    40  	"testing/quick"
    41  
    42  	"github.com/MetalBlockchain/subnet-evm/core/rawdb"
    43  	"github.com/ethereum/go-ethereum/common"
    44  )
    45  
    46  // Tests that updating a state trie does not leak any database writes prior to
    47  // actually committing the state.
    48  func TestUpdateLeaks(t *testing.T) {
    49  	// Create an empty state database
    50  	db := rawdb.NewMemoryDatabase()
    51  	state, _ := New(common.Hash{}, NewDatabase(db), nil)
    52  
    53  	// Update it with some accounts
    54  	for i := byte(0); i < 255; i++ {
    55  		addr := common.BytesToAddress([]byte{i})
    56  		state.AddBalance(addr, big.NewInt(int64(11*i)))
    57  		state.SetNonce(addr, uint64(42*i))
    58  		if i%2 == 0 {
    59  			state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
    60  		}
    61  		if i%3 == 0 {
    62  			state.SetCode(addr, []byte{i, i, i, i, i})
    63  		}
    64  	}
    65  
    66  	root := state.IntermediateRoot(false)
    67  	if err := state.Database().TrieDB().Commit(root, false, nil); err != nil {
    68  		t.Errorf("can not commit trie %v to persistent database", root.Hex())
    69  	}
    70  
    71  	// Ensure that no data was leaked into the database
    72  	it := db.NewIterator(nil, nil)
    73  	for it.Next() {
    74  		t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value())
    75  	}
    76  	it.Release()
    77  }
    78  
    79  // Tests that no intermediate state of an object is stored into the database,
    80  // only the one right before the commit.
    81  func TestIntermediateLeaks(t *testing.T) {
    82  	// Create two state databases, one transitioning to the final state, the other final from the beginning
    83  	transDb := rawdb.NewMemoryDatabase()
    84  	finalDb := rawdb.NewMemoryDatabase()
    85  	transState, _ := New(common.Hash{}, NewDatabase(transDb), nil)
    86  	finalState, _ := New(common.Hash{}, NewDatabase(finalDb), nil)
    87  
    88  	modify := func(state *StateDB, addr common.Address, i, tweak byte) {
    89  		state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak)))
    90  		state.SetNonce(addr, uint64(42*i+tweak))
    91  		if i%2 == 0 {
    92  			state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{})
    93  			state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak})
    94  		}
    95  		if i%3 == 0 {
    96  			state.SetCode(addr, []byte{i, i, i, i, i, tweak})
    97  		}
    98  	}
    99  
   100  	// Modify the transient state.
   101  	for i := byte(0); i < 255; i++ {
   102  		modify(transState, common.Address{i}, i, 0)
   103  	}
   104  	// Write modifications to trie.
   105  	transState.IntermediateRoot(false)
   106  
   107  	// Overwrite all the data with new values in the transient database.
   108  	for i := byte(0); i < 255; i++ {
   109  		modify(transState, common.Address{i}, i, 99)
   110  		modify(finalState, common.Address{i}, i, 99)
   111  	}
   112  
   113  	// Commit and cross check the databases.
   114  	transRoot, err := transState.Commit(false, false)
   115  	if err != nil {
   116  		t.Fatalf("failed to commit transition state: %v", err)
   117  	}
   118  	if err = transState.Database().TrieDB().Commit(transRoot, false, nil); err != nil {
   119  		t.Errorf("can not commit trie %v to persistent database", transRoot.Hex())
   120  	}
   121  
   122  	finalRoot, err := finalState.Commit(false, false)
   123  	if err != nil {
   124  		t.Fatalf("failed to commit final state: %v", err)
   125  	}
   126  	if err = finalState.Database().TrieDB().Commit(finalRoot, false, nil); err != nil {
   127  		t.Errorf("can not commit trie %v to persistent database", finalRoot.Hex())
   128  	}
   129  
   130  	it := finalDb.NewIterator(nil, nil)
   131  	for it.Next() {
   132  		key, fvalue := it.Key(), it.Value()
   133  		tvalue, err := transDb.Get(key)
   134  		if err != nil {
   135  			t.Errorf("entry missing from the transition database: %x -> %x", key, fvalue)
   136  		}
   137  		if !bytes.Equal(fvalue, tvalue) {
   138  			t.Errorf("value mismatch at key %x: %x in transition database, %x in final database", key, tvalue, fvalue)
   139  		}
   140  	}
   141  	it.Release()
   142  
   143  	it = transDb.NewIterator(nil, nil)
   144  	for it.Next() {
   145  		key, tvalue := it.Key(), it.Value()
   146  		fvalue, err := finalDb.Get(key)
   147  		if err != nil {
   148  			t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value())
   149  		}
   150  		if !bytes.Equal(fvalue, tvalue) {
   151  			t.Errorf("value mismatch at key %x: %x in transition database, %x in final database", key, tvalue, fvalue)
   152  		}
   153  	}
   154  }
   155  
   156  // TestCopy tests that copying a StateDB object indeed makes the original and
   157  // the copy independent of each other. This test is a regression test against
   158  // https://github.com/ethereum/go-ethereum/pull/15549.
   159  func TestCopy(t *testing.T) {
   160  	// Create a random state test to copy and modify "independently"
   161  	orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   162  
   163  	for i := byte(0); i < 255; i++ {
   164  		obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   165  		obj.AddBalance(big.NewInt(int64(i)))
   166  		orig.updateStateObject(obj)
   167  	}
   168  	orig.Finalise(false)
   169  
   170  	// Copy the state
   171  	copy := orig.Copy()
   172  
   173  	// Copy the copy state
   174  	ccopy := copy.Copy()
   175  
   176  	// modify all in memory
   177  	for i := byte(0); i < 255; i++ {
   178  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   179  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   180  		ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   181  
   182  		origObj.AddBalance(big.NewInt(2 * int64(i)))
   183  		copyObj.AddBalance(big.NewInt(3 * int64(i)))
   184  		ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
   185  
   186  		orig.updateStateObject(origObj)
   187  		copy.updateStateObject(copyObj)
   188  		ccopy.updateStateObject(copyObj)
   189  	}
   190  
   191  	// Finalise the changes on all concurrently
   192  	finalise := func(wg *sync.WaitGroup, db *StateDB) {
   193  		defer wg.Done()
   194  		db.Finalise(true)
   195  	}
   196  
   197  	var wg sync.WaitGroup
   198  	wg.Add(3)
   199  	go finalise(&wg, orig)
   200  	go finalise(&wg, copy)
   201  	go finalise(&wg, ccopy)
   202  	wg.Wait()
   203  
   204  	// Verify that the three states have been updated independently
   205  	for i := byte(0); i < 255; i++ {
   206  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   207  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   208  		ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   209  
   210  		if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 {
   211  			t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want)
   212  		}
   213  		if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 {
   214  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want)
   215  		}
   216  		if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 {
   217  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want)
   218  		}
   219  	}
   220  }
   221  
   222  func TestSnapshotRandom(t *testing.T) {
   223  	config := &quick.Config{MaxCount: 1000}
   224  	err := quick.Check((*snapshotTest).run, config)
   225  	if cerr, ok := err.(*quick.CheckError); ok {
   226  		test := cerr.In[0].(*snapshotTest)
   227  		t.Errorf("%v:\n%s", test.err, test)
   228  	} else if err != nil {
   229  		t.Error(err)
   230  	}
   231  }
   232  
   233  // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes
   234  // captured by the snapshot. Instances of this test with pseudorandom content are created
   235  // by Generate.
   236  //
   237  // The test works as follows:
   238  //
   239  // A new state is created and all actions are applied to it. Several snapshots are taken
   240  // in between actions. The test then reverts each snapshot. For each snapshot the actions
   241  // leading up to it are replayed on a fresh, empty state. The behaviour of all public
   242  // accessor methods on the reverted state must match the return value of the equivalent
   243  // methods on the replayed state.
   244  type snapshotTest struct {
   245  	addrs     []common.Address // all account addresses
   246  	actions   []testAction     // modifications to the state
   247  	snapshots []int            // actions indexes at which snapshot is taken
   248  	err       error            // failure details are reported through this field
   249  }
   250  
   251  type testAction struct {
   252  	name   string
   253  	fn     func(testAction, *StateDB)
   254  	args   []int64
   255  	noAddr bool
   256  }
   257  
   258  // newTestAction creates a random action that changes state.
   259  func newTestAction(addr common.Address, r *rand.Rand) testAction {
   260  	actions := []testAction{
   261  		{
   262  			name: "SetBalance",
   263  			fn: func(a testAction, s *StateDB) {
   264  				s.SetBalance(addr, big.NewInt(a.args[0]))
   265  			},
   266  			args: make([]int64, 1),
   267  		},
   268  		{
   269  			name: "AddBalance",
   270  			fn: func(a testAction, s *StateDB) {
   271  				s.AddBalance(addr, big.NewInt(a.args[0]))
   272  			},
   273  			args: make([]int64, 1),
   274  		},
   275  		{
   276  			name: "SetNonce",
   277  			fn: func(a testAction, s *StateDB) {
   278  				s.SetNonce(addr, uint64(a.args[0]))
   279  			},
   280  			args: make([]int64, 1),
   281  		},
   282  		{
   283  			name: "SetState",
   284  			fn: func(a testAction, s *StateDB) {
   285  				var key, val common.Hash
   286  				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
   287  				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))
   288  				s.SetState(addr, key, val)
   289  			},
   290  			args: make([]int64, 2),
   291  		},
   292  		{
   293  			name: "SetCode",
   294  			fn: func(a testAction, s *StateDB) {
   295  				code := make([]byte, 16)
   296  				binary.BigEndian.PutUint64(code, uint64(a.args[0]))
   297  				binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
   298  				s.SetCode(addr, code)
   299  			},
   300  			args: make([]int64, 2),
   301  		},
   302  		{
   303  			name: "CreateAccount",
   304  			fn: func(a testAction, s *StateDB) {
   305  				s.CreateAccount(addr)
   306  			},
   307  		},
   308  		{
   309  			name: "Suicide",
   310  			fn: func(a testAction, s *StateDB) {
   311  				s.Suicide(addr)
   312  			},
   313  		},
   314  		{
   315  			name: "AddRefund",
   316  			fn: func(a testAction, s *StateDB) {
   317  				s.AddRefund(uint64(a.args[0]))
   318  			},
   319  			args:   make([]int64, 1),
   320  			noAddr: true,
   321  		},
   322  		{
   323  			name: "AddLog",
   324  			fn: func(a testAction, s *StateDB) {
   325  				data := make([]byte, 2)
   326  				binary.BigEndian.PutUint16(data, uint16(a.args[0]))
   327  				s.AddLog(addr, nil, data, 0)
   328  			},
   329  			args: make([]int64, 1),
   330  		},
   331  		{
   332  			name: "AddPreimage",
   333  			fn: func(a testAction, s *StateDB) {
   334  				preimage := []byte{1}
   335  				hash := common.BytesToHash(preimage)
   336  				s.AddPreimage(hash, preimage)
   337  			},
   338  			args: make([]int64, 1),
   339  		},
   340  		{
   341  			name: "AddAddressToAccessList",
   342  			fn: func(a testAction, s *StateDB) {
   343  				s.AddAddressToAccessList(addr)
   344  			},
   345  		},
   346  		{
   347  			name: "AddSlotToAccessList",
   348  			fn: func(a testAction, s *StateDB) {
   349  				s.AddSlotToAccessList(addr,
   350  					common.Hash{byte(a.args[0])})
   351  			},
   352  			args: make([]int64, 1),
   353  		},
   354  	}
   355  	action := actions[r.Intn(len(actions))]
   356  	var nameargs []string
   357  	if !action.noAddr {
   358  		nameargs = append(nameargs, addr.Hex())
   359  	}
   360  	for i := range action.args {
   361  		action.args[i] = rand.Int63n(100)
   362  		nameargs = append(nameargs, fmt.Sprint(action.args[i]))
   363  	}
   364  	action.name += strings.Join(nameargs, ", ")
   365  	return action
   366  }
   367  
   368  // Generate returns a new snapshot test of the given size. All randomness is
   369  // derived from r.
   370  func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value {
   371  	// Generate random actions.
   372  	addrs := make([]common.Address, 50)
   373  	for i := range addrs {
   374  		addrs[i][0] = byte(i)
   375  	}
   376  	actions := make([]testAction, size)
   377  	for i := range actions {
   378  		addr := addrs[r.Intn(len(addrs))]
   379  		actions[i] = newTestAction(addr, r)
   380  	}
   381  	// Generate snapshot indexes.
   382  	nsnapshots := int(math.Sqrt(float64(size)))
   383  	if size > 0 && nsnapshots == 0 {
   384  		nsnapshots = 1
   385  	}
   386  	snapshots := make([]int, nsnapshots)
   387  	snaplen := len(actions) / nsnapshots
   388  	for i := range snapshots {
   389  		// Try to place the snapshots some number of actions apart from each other.
   390  		snapshots[i] = (i * snaplen) + r.Intn(snaplen)
   391  	}
   392  	return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil})
   393  }
   394  
   395  func (test *snapshotTest) String() string {
   396  	out := new(bytes.Buffer)
   397  	sindex := 0
   398  	for i, action := range test.actions {
   399  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   400  			fmt.Fprintf(out, "---- snapshot %d ----\n", sindex)
   401  			sindex++
   402  		}
   403  		fmt.Fprintf(out, "%4d: %s\n", i, action.name)
   404  	}
   405  	return out.String()
   406  }
   407  
   408  func (test *snapshotTest) run() bool {
   409  	// Run all actions and create snapshots.
   410  	var (
   411  		state, _     = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   412  		snapshotRevs = make([]int, len(test.snapshots))
   413  		sindex       = 0
   414  	)
   415  	for i, action := range test.actions {
   416  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   417  			snapshotRevs[sindex] = state.Snapshot()
   418  			sindex++
   419  		}
   420  		action.fn(action, state)
   421  	}
   422  	// Revert all snapshots in reverse order. Each revert must yield a state
   423  	// that is equivalent to fresh state with all actions up the snapshot applied.
   424  	for sindex--; sindex >= 0; sindex-- {
   425  		checkstate, _ := New(common.Hash{}, state.Database(), nil)
   426  		for _, action := range test.actions[:test.snapshots[sindex]] {
   427  			action.fn(action, checkstate)
   428  		}
   429  		state.RevertToSnapshot(snapshotRevs[sindex])
   430  		if err := test.checkEqual(state, checkstate); err != nil {
   431  			test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err)
   432  			return false
   433  		}
   434  	}
   435  	return true
   436  }
   437  
   438  // checkEqual checks that methods of state and checkstate return the same values.
   439  func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
   440  	for _, addr := range test.addrs {
   441  		var err error
   442  		checkeq := func(op string, a, b interface{}) bool {
   443  			if err == nil && !reflect.DeepEqual(a, b) {
   444  				err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b)
   445  				return false
   446  			}
   447  			return true
   448  		}
   449  		// Check basic accessor methods.
   450  		checkeq("Exist", state.Exist(addr), checkstate.Exist(addr))
   451  		checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr))
   452  		checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
   453  		checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
   454  		checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
   455  		checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr))
   456  		checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
   457  		// Check storage.
   458  		if obj := state.getStateObject(addr); obj != nil {
   459  			state.ForEachStorage(addr, func(key, value common.Hash) bool {
   460  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   461  			})
   462  			checkstate.ForEachStorage(addr, func(key, value common.Hash) bool {
   463  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   464  			})
   465  		}
   466  		if err != nil {
   467  			return err
   468  		}
   469  	}
   470  
   471  	if state.GetRefund() != checkstate.GetRefund() {
   472  		return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
   473  			state.GetRefund(), checkstate.GetRefund())
   474  	}
   475  	if !reflect.DeepEqual(state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{})) {
   476  		return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v",
   477  			state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{}))
   478  	}
   479  	return nil
   480  }
   481  
   482  func TestTouchDelete(t *testing.T) {
   483  	s := newStateTest()
   484  	s.state.GetOrNewStateObject(common.Address{})
   485  	root, _ := s.state.Commit(false, false)
   486  	s.state, _ = NewWithSnapshot(root, s.state.db, s.state.snap)
   487  
   488  	snapshot := s.state.Snapshot()
   489  	s.state.AddBalance(common.Address{}, new(big.Int))
   490  
   491  	if len(s.state.journal.dirties) != 1 {
   492  		t.Fatal("expected one dirty state object")
   493  	}
   494  	s.state.RevertToSnapshot(snapshot)
   495  	if len(s.state.journal.dirties) != 0 {
   496  		t.Fatal("expected no dirty state object")
   497  	}
   498  }
   499  
   500  // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
   501  // See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512
   502  func TestCopyOfCopy(t *testing.T) {
   503  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   504  	addr := common.HexToAddress("aaaa")
   505  	state.SetBalance(addr, big.NewInt(42))
   506  
   507  	if got := state.Copy().GetBalance(addr).Uint64(); got != 42 {
   508  		t.Fatalf("1st copy fail, expected 42, got %v", got)
   509  	}
   510  	if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 {
   511  		t.Fatalf("2nd copy fail, expected 42, got %v", got)
   512  	}
   513  }
   514  
   515  // Tests a regression where committing a copy lost some internal meta information,
   516  // leading to corrupted subsequent copies.
   517  //
   518  // See https://github.com/ethereum/go-ethereum/issues/20106.
   519  func TestCopyCommitCopy(t *testing.T) {
   520  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   521  
   522  	// Create an account and check if the retrieved balance is correct
   523  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   524  	skey := common.HexToHash("aaa")
   525  	sval := common.HexToHash("bbb")
   526  
   527  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   528  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   529  	state.SetState(addr, skey, sval)       // Change the storage trie
   530  
   531  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   532  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   533  	}
   534  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   535  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   536  	}
   537  	if val := state.GetState(addr, skey); val != sval {
   538  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   539  	}
   540  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   541  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   542  	}
   543  	// Copy the non-committed state database and check pre/post commit balance
   544  	copyOne := state.Copy()
   545  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   546  		t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   547  	}
   548  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   549  		t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   550  	}
   551  	if val := copyOne.GetState(addr, skey); val != sval {
   552  		t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   553  	}
   554  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   555  		t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   556  	}
   557  
   558  	copyOne.Commit(false, false)
   559  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   560  		t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42)
   561  	}
   562  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   563  		t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   564  	}
   565  	if val := copyOne.GetState(addr, skey); val != sval {
   566  		t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   567  	}
   568  	if val := copyOne.GetCommittedState(addr, skey); val != sval {
   569  		t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   570  	}
   571  	// Copy the copy and check the balance once more
   572  	copyTwo := copyOne.Copy()
   573  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   574  		t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42)
   575  	}
   576  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   577  		t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello"))
   578  	}
   579  	if val := copyTwo.GetState(addr, skey); val != sval {
   580  		t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   581  	}
   582  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   583  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   584  	}
   585  }
   586  
   587  // Tests a regression where committing a copy lost some internal meta information,
   588  // leading to corrupted subsequent copies.
   589  //
   590  // See https://github.com/ethereum/go-ethereum/issues/20106.
   591  func TestCopyCopyCommitCopy(t *testing.T) {
   592  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   593  
   594  	// Create an account and check if the retrieved balance is correct
   595  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   596  	skey := common.HexToHash("aaa")
   597  	sval := common.HexToHash("bbb")
   598  
   599  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   600  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   601  	state.SetState(addr, skey, sval)       // Change the storage trie
   602  
   603  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   604  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   605  	}
   606  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   607  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   608  	}
   609  	if val := state.GetState(addr, skey); val != sval {
   610  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   611  	}
   612  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   613  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   614  	}
   615  	// Copy the non-committed state database and check pre/post commit balance
   616  	copyOne := state.Copy()
   617  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   618  		t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42)
   619  	}
   620  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   621  		t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello"))
   622  	}
   623  	if val := copyOne.GetState(addr, skey); val != sval {
   624  		t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   625  	}
   626  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   627  		t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   628  	}
   629  	// Copy the copy and check the balance once more
   630  	copyTwo := copyOne.Copy()
   631  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   632  		t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   633  	}
   634  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   635  		t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   636  	}
   637  	if val := copyTwo.GetState(addr, skey); val != sval {
   638  		t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   639  	}
   640  	if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) {
   641  		t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   642  	}
   643  	copyTwo.Commit(false, false)
   644  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   645  		t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42)
   646  	}
   647  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   648  		t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   649  	}
   650  	if val := copyTwo.GetState(addr, skey); val != sval {
   651  		t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   652  	}
   653  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   654  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   655  	}
   656  	// Copy the copy-copy and check the balance once more
   657  	copyThree := copyTwo.Copy()
   658  	if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   659  		t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42)
   660  	}
   661  	if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   662  		t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello"))
   663  	}
   664  	if val := copyThree.GetState(addr, skey); val != sval {
   665  		t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   666  	}
   667  	if val := copyThree.GetCommittedState(addr, skey); val != sval {
   668  		t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval)
   669  	}
   670  }
   671  
   672  // TestDeleteCreateRevert tests a weird state transition corner case that we hit
   673  // while changing the internals of StateDB. The workflow is that a contract is
   674  // self-destructed, then in a follow-up transaction (but same block) it's created
   675  // again and the transaction reverted.
   676  //
   677  // The original StateDB implementation flushed dirty objects to the tries after
   678  // each transaction, so this works ok. The rework accumulated writes in memory
   679  // first, but the journal wiped the entire state object on create-revert.
   680  func TestDeleteCreateRevert(t *testing.T) {
   681  	// Create an initial state with a single contract
   682  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   683  
   684  	addr := common.BytesToAddress([]byte("so"))
   685  	state.SetBalance(addr, big.NewInt(1))
   686  
   687  	root, _ := state.Commit(false, false)
   688  	state, _ = NewWithSnapshot(root, state.db, state.snap)
   689  
   690  	// Simulate self-destructing in one transaction, then create-reverting in another
   691  	state.Suicide(addr)
   692  	state.Finalise(true)
   693  
   694  	id := state.Snapshot()
   695  	state.SetBalance(addr, big.NewInt(2))
   696  	state.RevertToSnapshot(id)
   697  
   698  	// Commit the entire state and make sure we don't crash and have the correct state
   699  	root, _ = state.Commit(true, false)
   700  	state, _ = NewWithSnapshot(root, state.db, state.snap)
   701  
   702  	if state.getStateObject(addr) != nil {
   703  		t.Fatalf("self-destructed contract came alive")
   704  	}
   705  }
   706  
   707  // TestMissingTrieNodes tests that if the StateDB fails to load parts of the trie,
   708  // the Commit operation fails with an error
   709  // If we are missing trie nodes, we should not continue writing to the trie
   710  func TestMissingTrieNodes(t *testing.T) {
   711  	// Create an initial state with a few accounts
   712  	memDb := rawdb.NewMemoryDatabase()
   713  	db := NewDatabase(memDb)
   714  	var root common.Hash
   715  	state, _ := New(common.Hash{}, db, nil)
   716  	addr := common.BytesToAddress([]byte("so"))
   717  	{
   718  		state.SetBalance(addr, big.NewInt(1))
   719  		state.SetCode(addr, []byte{1, 2, 3})
   720  		a2 := common.BytesToAddress([]byte("another"))
   721  		state.SetBalance(a2, big.NewInt(100))
   722  		state.SetCode(a2, []byte{1, 2, 4})
   723  		root, _ = state.Commit(false, false)
   724  		t.Logf("root: %x", root)
   725  		// force-flush
   726  		state.Database().TrieDB().Cap(0)
   727  	}
   728  	// Create a new state on the old root
   729  	state, _ = New(root, db, nil)
   730  	// Now we clear out the memdb
   731  	it := memDb.NewIterator(nil, nil)
   732  	for it.Next() {
   733  		k := it.Key()
   734  		// Leave the root intact
   735  		if !bytes.Equal(k, root[:]) {
   736  			t.Logf("key: %x", k)
   737  			memDb.Delete(k)
   738  		}
   739  	}
   740  	balance := state.GetBalance(addr)
   741  	// The removed elem should lead to it returning zero balance
   742  	if exp, got := uint64(0), balance.Uint64(); got != exp {
   743  		t.Errorf("expected %d, got %d", exp, got)
   744  	}
   745  	// Modify the state
   746  	state.SetBalance(addr, big.NewInt(2))
   747  	root, err := state.Commit(false, false)
   748  	if err == nil {
   749  		t.Fatalf("expected error, got root :%x", root)
   750  	}
   751  }
   752  
   753  func TestStateDBAccessList(t *testing.T) {
   754  	// Some helpers
   755  	addr := func(a string) common.Address {
   756  		return common.HexToAddress(a)
   757  	}
   758  	slot := func(a string) common.Hash {
   759  		return common.HexToHash(a)
   760  	}
   761  
   762  	memDb := rawdb.NewMemoryDatabase()
   763  	db := NewDatabase(memDb)
   764  	state, _ := New(common.Hash{}, db, nil)
   765  	state.accessList = newAccessList()
   766  
   767  	verifyAddrs := func(astrings ...string) {
   768  		t.Helper()
   769  		// convert to common.Address form
   770  		var addresses []common.Address
   771  		var addressMap = make(map[common.Address]struct{})
   772  		for _, astring := range astrings {
   773  			address := addr(astring)
   774  			addresses = append(addresses, address)
   775  			addressMap[address] = struct{}{}
   776  		}
   777  		// Check that the given addresses are in the access list
   778  		for _, address := range addresses {
   779  			if !state.AddressInAccessList(address) {
   780  				t.Fatalf("expected %x to be in access list", address)
   781  			}
   782  		}
   783  		// Check that only the expected addresses are present in the access list
   784  		for address := range state.accessList.addresses {
   785  			if _, exist := addressMap[address]; !exist {
   786  				t.Fatalf("extra address %x in access list", address)
   787  			}
   788  		}
   789  	}
   790  	verifySlots := func(addrString string, slotStrings ...string) {
   791  		if !state.AddressInAccessList(addr(addrString)) {
   792  			t.Fatalf("scope missing address/slots %v", addrString)
   793  		}
   794  		var address = addr(addrString)
   795  		// convert to common.Hash form
   796  		var slots []common.Hash
   797  		var slotMap = make(map[common.Hash]struct{})
   798  		for _, slotString := range slotStrings {
   799  			s := slot(slotString)
   800  			slots = append(slots, s)
   801  			slotMap[s] = struct{}{}
   802  		}
   803  		// Check that the expected items are in the access list
   804  		for i, s := range slots {
   805  			if _, slotPresent := state.SlotInAccessList(address, s); !slotPresent {
   806  				t.Fatalf("input %d: scope missing slot %v (address %v)", i, s, addrString)
   807  			}
   808  		}
   809  		// Check that no extra elements are in the access list
   810  		index := state.accessList.addresses[address]
   811  		if index >= 0 {
   812  			stateSlots := state.accessList.slots[index]
   813  			for s := range stateSlots {
   814  				if _, slotPresent := slotMap[s]; !slotPresent {
   815  					t.Fatalf("scope has extra slot %v (address %v)", s, addrString)
   816  				}
   817  			}
   818  		}
   819  	}
   820  
   821  	state.AddAddressToAccessList(addr("aa"))          // 1
   822  	state.AddSlotToAccessList(addr("bb"), slot("01")) // 2,3
   823  	state.AddSlotToAccessList(addr("bb"), slot("02")) // 4
   824  	verifyAddrs("aa", "bb")
   825  	verifySlots("bb", "01", "02")
   826  
   827  	// Make a copy
   828  	stateCopy1 := state.Copy()
   829  	if exp, got := 4, state.journal.length(); exp != got {
   830  		t.Fatalf("journal length mismatch: have %d, want %d", got, exp)
   831  	}
   832  
   833  	// same again, should cause no journal entries
   834  	state.AddSlotToAccessList(addr("bb"), slot("01"))
   835  	state.AddSlotToAccessList(addr("bb"), slot("02"))
   836  	state.AddAddressToAccessList(addr("aa"))
   837  	if exp, got := 4, state.journal.length(); exp != got {
   838  		t.Fatalf("journal length mismatch: have %d, want %d", got, exp)
   839  	}
   840  	// some new ones
   841  	state.AddSlotToAccessList(addr("bb"), slot("03")) // 5
   842  	state.AddSlotToAccessList(addr("aa"), slot("01")) // 6
   843  	state.AddSlotToAccessList(addr("cc"), slot("01")) // 7,8
   844  	state.AddAddressToAccessList(addr("cc"))
   845  	if exp, got := 8, state.journal.length(); exp != got {
   846  		t.Fatalf("journal length mismatch: have %d, want %d", got, exp)
   847  	}
   848  
   849  	verifyAddrs("aa", "bb", "cc")
   850  	verifySlots("aa", "01")
   851  	verifySlots("bb", "01", "02", "03")
   852  	verifySlots("cc", "01")
   853  
   854  	// now start rolling back changes
   855  	state.journal.revert(state, 7)
   856  	if _, ok := state.SlotInAccessList(addr("cc"), slot("01")); ok {
   857  		t.Fatalf("slot present, expected missing")
   858  	}
   859  	verifyAddrs("aa", "bb", "cc")
   860  	verifySlots("aa", "01")
   861  	verifySlots("bb", "01", "02", "03")
   862  
   863  	state.journal.revert(state, 6)
   864  	if state.AddressInAccessList(addr("cc")) {
   865  		t.Fatalf("addr present, expected missing")
   866  	}
   867  	verifyAddrs("aa", "bb")
   868  	verifySlots("aa", "01")
   869  	verifySlots("bb", "01", "02", "03")
   870  
   871  	state.journal.revert(state, 5)
   872  	if _, ok := state.SlotInAccessList(addr("aa"), slot("01")); ok {
   873  		t.Fatalf("slot present, expected missing")
   874  	}
   875  	verifyAddrs("aa", "bb")
   876  	verifySlots("bb", "01", "02", "03")
   877  
   878  	state.journal.revert(state, 4)
   879  	if _, ok := state.SlotInAccessList(addr("bb"), slot("03")); ok {
   880  		t.Fatalf("slot present, expected missing")
   881  	}
   882  	verifyAddrs("aa", "bb")
   883  	verifySlots("bb", "01", "02")
   884  
   885  	state.journal.revert(state, 3)
   886  	if _, ok := state.SlotInAccessList(addr("bb"), slot("02")); ok {
   887  		t.Fatalf("slot present, expected missing")
   888  	}
   889  	verifyAddrs("aa", "bb")
   890  	verifySlots("bb", "01")
   891  
   892  	state.journal.revert(state, 2)
   893  	if _, ok := state.SlotInAccessList(addr("bb"), slot("01")); ok {
   894  		t.Fatalf("slot present, expected missing")
   895  	}
   896  	verifyAddrs("aa", "bb")
   897  
   898  	state.journal.revert(state, 1)
   899  	if state.AddressInAccessList(addr("bb")) {
   900  		t.Fatalf("addr present, expected missing")
   901  	}
   902  	verifyAddrs("aa")
   903  
   904  	state.journal.revert(state, 0)
   905  	if state.AddressInAccessList(addr("aa")) {
   906  		t.Fatalf("addr present, expected missing")
   907  	}
   908  	if got, exp := len(state.accessList.addresses), 0; got != exp {
   909  		t.Fatalf("expected empty, got %d", got)
   910  	}
   911  	if got, exp := len(state.accessList.slots), 0; got != exp {
   912  		t.Fatalf("expected empty, got %d", got)
   913  	}
   914  	// Check the copy
   915  	// Make a copy
   916  	state = stateCopy1
   917  	verifyAddrs("aa", "bb")
   918  	verifySlots("bb", "01", "02")
   919  	if got, exp := len(state.accessList.addresses), 2; got != exp {
   920  		t.Fatalf("expected empty, got %d", got)
   921  	}
   922  	if got, exp := len(state.accessList.slots), 1; got != exp {
   923  		t.Fatalf("expected empty, got %d", got)
   924  	}
   925  }
   926  
   927  // Tests that account and storage tries are flushed in the correct order and that
   928  // no data loss occurs.
   929  func TestFlushOrderDataLoss(t *testing.T) {
   930  	// Create a state trie with many accounts and slots
   931  	var (
   932  		memdb    = rawdb.NewMemoryDatabase()
   933  		statedb  = NewDatabase(memdb)
   934  		state, _ = New(common.Hash{}, statedb, nil)
   935  	)
   936  	for a := byte(0); a < 10; a++ {
   937  		state.CreateAccount(common.Address{a})
   938  		for s := byte(0); s < 10; s++ {
   939  			state.SetState(common.Address{a}, common.Hash{a, s}, common.Hash{a, s})
   940  		}
   941  	}
   942  	root, err := state.Commit(false, false)
   943  	if err != nil {
   944  		t.Fatalf("failed to commit state trie: %v", err)
   945  	}
   946  	statedb.TrieDB().Reference(root, common.Hash{})
   947  	if err := statedb.TrieDB().Cap(1024); err != nil {
   948  		t.Fatalf("failed to cap trie dirty cache: %v", err)
   949  	}
   950  	if err := statedb.TrieDB().Commit(root, false, nil); err != nil {
   951  		t.Fatalf("failed to commit state trie: %v", err)
   952  	}
   953  	// Reopen the state trie from flushed disk and verify it
   954  	state, err = New(root, NewDatabase(memdb), nil)
   955  	if err != nil {
   956  		t.Fatalf("failed to reopen state trie: %v", err)
   957  	}
   958  	for a := byte(0); a < 10; a++ {
   959  		for s := byte(0); s < 10; s++ {
   960  			if have := state.GetState(common.Address{a}, common.Hash{a, s}); have != (common.Hash{a, s}) {
   961  				t.Errorf("account %d: slot %d: state mismatch: have %x, want %x", a, s, have, common.Hash{a, s})
   962  			}
   963  		}
   964  	}
   965  }