github.com/theQRL/go-zond@v0.2.1/core/state/statedb_test.go (about)

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