github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/core/state/statedb_test.go (about)

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