github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/core/state/statedb_test.go (about)

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