github.com/core-coin/go-core/v2@v2.1.9/core/state/statedb_test.go (about)

     1  // Copyright 2016 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core 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-core 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-core 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/core-coin/go-core/v2/common"
    33  	"github.com/core-coin/go-core/v2/core/rawdb"
    34  	"github.com/core-coin/go-core/v2/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("the value associate key %x is mismatch,: %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("the value associate key %x is mismatch,: %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/core-coin/go-core/v2/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  	action := actions[r.Intn(len(actions))]
   333  	var nameargs []string
   334  	if !action.noAddr {
   335  		nameargs = append(nameargs, addr.Hex())
   336  	}
   337  	for i := range action.args {
   338  		action.args[i] = rand.Int63n(100)
   339  		nameargs = append(nameargs, fmt.Sprint(action.args[i]))
   340  	}
   341  	action.name += strings.Join(nameargs, ", ")
   342  	return action
   343  }
   344  
   345  // Generate returns a new snapshot test of the given size. All randomness is
   346  // derived from r.
   347  func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value {
   348  	// Generate random actions.
   349  	addrs := make([]common.Address, 50)
   350  	for i := range addrs {
   351  		addrs[i][0] = byte(i)
   352  	}
   353  	actions := make([]testAction, size)
   354  	for i := range actions {
   355  		addr := addrs[r.Intn(len(addrs))]
   356  		actions[i] = newTestAction(addr, r)
   357  	}
   358  	// Generate snapshot indexes.
   359  	nsnapshots := int(math.Sqrt(float64(size)))
   360  	if size > 0 && nsnapshots == 0 {
   361  		nsnapshots = 1
   362  	}
   363  	snapshots := make([]int, nsnapshots)
   364  	snaplen := len(actions) / nsnapshots
   365  	for i := range snapshots {
   366  		// Try to place the snapshots some number of actions apart from each other.
   367  		snapshots[i] = (i * snaplen) + r.Intn(snaplen)
   368  	}
   369  	return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil})
   370  }
   371  
   372  func (test *snapshotTest) String() string {
   373  	out := new(bytes.Buffer)
   374  	sindex := 0
   375  	for i, action := range test.actions {
   376  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   377  			fmt.Fprintf(out, "---- snapshot %d ----\n", sindex)
   378  			sindex++
   379  		}
   380  		fmt.Fprintf(out, "%4d: %s\n", i, action.name)
   381  	}
   382  	return out.String()
   383  }
   384  
   385  func (test *snapshotTest) run() bool {
   386  	// Run all actions and create snapshots.
   387  	var (
   388  		state, _     = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   389  		snapshotRevs = make([]int, len(test.snapshots))
   390  		sindex       = 0
   391  	)
   392  	for i, action := range test.actions {
   393  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   394  			snapshotRevs[sindex] = state.Snapshot()
   395  			sindex++
   396  		}
   397  		action.fn(action, state)
   398  	}
   399  	// Revert all snapshots in reverse order. Each revert must yield a state
   400  	// that is equivalent to fresh state with all actions up the snapshot applied.
   401  	for sindex--; sindex >= 0; sindex-- {
   402  		checkstate, _ := New(common.Hash{}, state.Database(), nil)
   403  		for _, action := range test.actions[:test.snapshots[sindex]] {
   404  			action.fn(action, checkstate)
   405  		}
   406  		state.RevertToSnapshot(snapshotRevs[sindex])
   407  		if err := test.checkEqual(state, checkstate); err != nil {
   408  			test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err)
   409  			return false
   410  		}
   411  	}
   412  	return true
   413  }
   414  
   415  // checkEqual checks that methods of state and checkstate return the same values.
   416  func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
   417  	for _, addr := range test.addrs {
   418  		var err error
   419  		checkeq := func(op string, a, b interface{}) bool {
   420  			if err == nil && !reflect.DeepEqual(a, b) {
   421  				err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b)
   422  				return false
   423  			}
   424  			return true
   425  		}
   426  		// Check basic accessor methods.
   427  		checkeq("Exist", state.Exist(addr), checkstate.Exist(addr))
   428  		checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr))
   429  		checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
   430  		checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
   431  		checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
   432  		checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr))
   433  		checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
   434  		// Check storage.
   435  		if obj := state.getStateObject(addr); obj != nil {
   436  			state.ForEachStorage(addr, func(key, value common.Hash) bool {
   437  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   438  			})
   439  			checkstate.ForEachStorage(addr, func(key, value common.Hash) bool {
   440  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   441  			})
   442  		}
   443  		if err != nil {
   444  			return err
   445  		}
   446  	}
   447  
   448  	if state.GetRefund() != checkstate.GetRefund() {
   449  		return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
   450  			state.GetRefund(), checkstate.GetRefund())
   451  	}
   452  	if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) {
   453  		return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v",
   454  			state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{}))
   455  	}
   456  	return nil
   457  }
   458  
   459  func TestTouchDelete(t *testing.T) {
   460  	s := newStateTest()
   461  	s.state.GetOrNewStateObject(common.Address{})
   462  	root, _ := s.state.Commit(false)
   463  	s.state.Reset(root)
   464  
   465  	snapshot := s.state.Snapshot()
   466  	s.state.AddBalance(common.Address{}, new(big.Int))
   467  
   468  	if len(s.state.journal.dirties) != 1 {
   469  		t.Fatal("expected one dirty state object")
   470  	}
   471  	s.state.RevertToSnapshot(snapshot)
   472  	if len(s.state.journal.dirties) != 0 {
   473  		t.Fatal("expected no dirty state object")
   474  	}
   475  }
   476  
   477  // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
   478  // See https://github.com/core-coin/go-core/v2/pull/15225#issuecomment-380191512
   479  func TestCopyOfCopy(t *testing.T) {
   480  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   481  	addr, err := common.HexToAddress("cb21000000000000000000000000000000000000aaaa")
   482  	if err != nil {
   483  		t.Error(err)
   484  	}
   485  	state.SetBalance(addr, big.NewInt(42))
   486  
   487  	if got := state.Copy().GetBalance(addr).Uint64(); got != 42 {
   488  		t.Fatalf("1st copy fail, expected 42, got %v", got)
   489  	}
   490  	if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 {
   491  		t.Fatalf("2nd copy fail, expected 42, got %v", got)
   492  	}
   493  }
   494  
   495  // Tests a regression where committing a copy lost some internal meta information,
   496  // leading to corrupted subsequent copies.
   497  //
   498  // See https://github.com/core-coin/go-core/v2/issues/20106.
   499  func TestCopyCommitCopy(t *testing.T) {
   500  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   501  
   502  	// Create an account and check if the retrieved balance is correct
   503  	addr, err := common.HexToAddress("cb05affeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   504  	if err != nil {
   505  		t.Error(err)
   506  	}
   507  	skey := common.HexToHash("aaa")
   508  	sval := common.HexToHash("bbb")
   509  
   510  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   511  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   512  	state.SetState(addr, skey, sval)       // Change the storage trie
   513  
   514  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   515  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   516  	}
   517  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   518  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   519  	}
   520  	if val := state.GetState(addr, skey); val != sval {
   521  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   522  	}
   523  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   524  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   525  	}
   526  	// Copy the non-committed state database and check pre/post commit balance
   527  	copyOne := state.Copy()
   528  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   529  		t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   530  	}
   531  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   532  		t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   533  	}
   534  	if val := copyOne.GetState(addr, skey); val != sval {
   535  		t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   536  	}
   537  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   538  		t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   539  	}
   540  
   541  	copyOne.Commit(false)
   542  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   543  		t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42)
   544  	}
   545  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   546  		t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   547  	}
   548  	if val := copyOne.GetState(addr, skey); val != sval {
   549  		t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   550  	}
   551  	if val := copyOne.GetCommittedState(addr, skey); val != sval {
   552  		t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   553  	}
   554  	// Copy the copy and check the balance once more
   555  	copyTwo := copyOne.Copy()
   556  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   557  		t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42)
   558  	}
   559  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   560  		t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello"))
   561  	}
   562  	if val := copyTwo.GetState(addr, skey); val != sval {
   563  		t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   564  	}
   565  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   566  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   567  	}
   568  }
   569  
   570  // Tests a regression where committing a copy lost some internal meta information,
   571  // leading to corrupted subsequent copies.
   572  //
   573  // See https://github.com/core-coin/go-core/v2/issues/20106.
   574  func TestCopyCopyCommitCopy(t *testing.T) {
   575  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   576  
   577  	// Create an account and check if the retrieved balance is correct
   578  	addr, err := common.HexToAddress("cb05affeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   579  	if err != nil {
   580  		t.Error(err)
   581  	}
   582  	skey := common.HexToHash("aaa")
   583  	sval := common.HexToHash("bbb")
   584  
   585  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   586  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   587  	state.SetState(addr, skey, sval)       // Change the storage trie
   588  
   589  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   590  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   591  	}
   592  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   593  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   594  	}
   595  	if val := state.GetState(addr, skey); val != sval {
   596  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   597  	}
   598  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   599  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   600  	}
   601  	// Copy the non-committed state database and check pre/post commit balance
   602  	copyOne := state.Copy()
   603  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   604  		t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42)
   605  	}
   606  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   607  		t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello"))
   608  	}
   609  	if val := copyOne.GetState(addr, skey); val != sval {
   610  		t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   611  	}
   612  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   613  		t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   614  	}
   615  	// Copy the copy and check the balance once more
   616  	copyTwo := copyOne.Copy()
   617  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   618  		t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   619  	}
   620  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   621  		t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   622  	}
   623  	if val := copyTwo.GetState(addr, skey); val != sval {
   624  		t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   625  	}
   626  	if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) {
   627  		t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   628  	}
   629  	copyTwo.Commit(false)
   630  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   631  		t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42)
   632  	}
   633  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   634  		t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   635  	}
   636  	if val := copyTwo.GetState(addr, skey); val != sval {
   637  		t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   638  	}
   639  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   640  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   641  	}
   642  	// Copy the copy-copy and check the balance once more
   643  	copyThree := copyTwo.Copy()
   644  	if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   645  		t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42)
   646  	}
   647  	if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   648  		t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello"))
   649  	}
   650  	if val := copyThree.GetState(addr, skey); val != sval {
   651  		t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   652  	}
   653  	if val := copyThree.GetCommittedState(addr, skey); val != sval {
   654  		t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval)
   655  	}
   656  }
   657  
   658  // TestDeleteCreateRevert tests a weird state transition corner case that we hit
   659  // while changing the internals of StateDB. The workflow is that a contract is
   660  // self-destructed, then in a follow-up transaction (but same block) it's created
   661  // again and the transaction reverted.
   662  //
   663  // The original StateDB implementation flushed dirty objects to the tries after
   664  // each transaction, so this works ok. The rework accumulated writes in memory
   665  // first, but the journal wiped the entire state object on create-revert.
   666  func TestDeleteCreateRevert(t *testing.T) {
   667  	// Create an initial state with a single contract
   668  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   669  
   670  	addr := toAddr([]byte("so"))
   671  	state.SetBalance(addr, big.NewInt(1))
   672  
   673  	root, _ := state.Commit(false)
   674  	state.Reset(root)
   675  
   676  	// Simulate self-destructing in one transaction, then create-reverting in another
   677  	state.Suicide(addr)
   678  	state.Finalise(true)
   679  
   680  	id := state.Snapshot()
   681  	state.SetBalance(addr, big.NewInt(2))
   682  	state.RevertToSnapshot(id)
   683  
   684  	// Commit the entire state and make sure we don't crash and have the correct state
   685  	root, _ = state.Commit(true)
   686  	state.Reset(root)
   687  
   688  	if state.getStateObject(addr) != nil {
   689  		t.Fatalf("self-destructed contract came alive")
   690  	}
   691  }
   692  
   693  // TestMissingTrieNodes tests that if the StateDB fails to load parts of the trie,
   694  // the Commit operation fails with an error
   695  // If we are missing trie nodes, we should not continue writing to the trie
   696  func TestMissingTrieNodes(t *testing.T) {
   697  
   698  	// Create an initial state with a few accounts
   699  	memDb := rawdb.NewMemoryDatabase()
   700  	db := NewDatabase(memDb)
   701  	var root common.Hash
   702  	state, _ := New(common.Hash{}, db, nil)
   703  	addr := toAddr([]byte("so"))
   704  	{
   705  		state.SetBalance(addr, big.NewInt(1))
   706  		state.SetCode(addr, []byte{1, 2, 3})
   707  		a2 := toAddr([]byte("another"))
   708  		state.SetBalance(a2, big.NewInt(100))
   709  		state.SetCode(a2, []byte{1, 2, 4})
   710  		root, _ = state.Commit(false)
   711  		t.Logf("root: %x", root)
   712  		// force-flush
   713  		state.Database().TrieDB().Cap(0)
   714  	}
   715  	// Create a new state on the old root
   716  	state, _ = New(root, db, nil)
   717  	// Now we clear out the memdb
   718  	it := memDb.NewIterator(nil, nil)
   719  	for it.Next() {
   720  		k := it.Key()
   721  		// Leave the root intact
   722  		if !bytes.Equal(k, root[:]) {
   723  			t.Logf("key: %x", k)
   724  			memDb.Delete(k)
   725  		}
   726  	}
   727  	balance := state.GetBalance(addr)
   728  	// The removed elem should lead to it returning zero balance
   729  	if exp, got := uint64(0), balance.Uint64(); got != exp {
   730  		t.Errorf("expected %d, got %d", exp, got)
   731  	}
   732  	// Modify the state
   733  	state.SetBalance(addr, big.NewInt(2))
   734  	root, err := state.Commit(false)
   735  	if err == nil {
   736  		t.Fatalf("expected error, got root :%x", root)
   737  	}
   738  }