github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/core/state/statedb_test.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package state
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"fmt"
    23  	"math"
    24  	"math/big"
    25  	"math/rand"
    26  	"reflect"
    27  	"strings"
    28  	"sync"
    29  	"testing"
    30  	"testing/quick"
    31  
    32  	"github.com/zhiqiangxu/go-ethereum/common"
    33  	"github.com/zhiqiangxu/go-ethereum/core/rawdb"
    34  	"github.com/zhiqiangxu/go-ethereum/core/types"
    35  )
    36  
    37  // Tests that updating a state trie does not leak any database writes prior to
    38  // actually committing the state.
    39  func TestUpdateLeaks(t *testing.T) {
    40  	// Create an empty state database
    41  	db := rawdb.NewMemoryDatabase()
    42  	state, _ := New(common.Hash{}, NewDatabase(db), nil)
    43  
    44  	// Update it with some accounts
    45  	for i := byte(0); i < 255; i++ {
    46  		addr := common.BytesToAddress([]byte{i})
    47  		state.AddBalance(addr, big.NewInt(int64(11*i)))
    48  		state.SetNonce(addr, uint64(42*i))
    49  		if i%2 == 0 {
    50  			state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
    51  		}
    52  		if i%3 == 0 {
    53  			state.SetCode(addr, []byte{i, i, i, i, i})
    54  		}
    55  	}
    56  
    57  	root := state.IntermediateRoot(false)
    58  	if err := state.Database().TrieDB().Commit(root, false); 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); 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); 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/zhiqiangxu/go-ethereum/pull/15549.
   150  func TestCopy(t *testing.T) {
   151  	// Create a random state test to copy and modify "independently"
   152  	orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   153  
   154  	for i := byte(0); i < 255; i++ {
   155  		obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   156  		obj.AddBalance(big.NewInt(int64(i)))
   157  		orig.updateStateObject(obj)
   158  	}
   159  	orig.Finalise(false)
   160  
   161  	// Copy the state
   162  	copy := orig.Copy()
   163  
   164  	// Copy the copy state
   165  	ccopy := copy.Copy()
   166  
   167  	// modify all in memory
   168  	for i := byte(0); i < 255; i++ {
   169  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   170  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   171  		ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   172  
   173  		origObj.AddBalance(big.NewInt(2 * int64(i)))
   174  		copyObj.AddBalance(big.NewInt(3 * int64(i)))
   175  		ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
   176  
   177  		orig.updateStateObject(origObj)
   178  		copy.updateStateObject(copyObj)
   179  		ccopy.updateStateObject(copyObj)
   180  	}
   181  
   182  	// Finalise the changes on all concurrently
   183  	finalise := func(wg *sync.WaitGroup, db *StateDB) {
   184  		defer wg.Done()
   185  		db.Finalise(true)
   186  	}
   187  
   188  	var wg sync.WaitGroup
   189  	wg.Add(3)
   190  	go finalise(&wg, orig)
   191  	go finalise(&wg, copy)
   192  	go finalise(&wg, ccopy)
   193  	wg.Wait()
   194  
   195  	// Verify that the three states have been updated independently
   196  	for i := byte(0); i < 255; i++ {
   197  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   198  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   199  		ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   200  
   201  		if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 {
   202  			t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want)
   203  		}
   204  		if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 {
   205  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want)
   206  		}
   207  		if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 {
   208  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want)
   209  		}
   210  	}
   211  }
   212  
   213  func TestSnapshotRandom(t *testing.T) {
   214  	config := &quick.Config{MaxCount: 1000}
   215  	err := quick.Check((*snapshotTest).run, config)
   216  	if cerr, ok := err.(*quick.CheckError); ok {
   217  		test := cerr.In[0].(*snapshotTest)
   218  		t.Errorf("%v:\n%s", test.err, test)
   219  	} else if err != nil {
   220  		t.Error(err)
   221  	}
   222  }
   223  
   224  // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes
   225  // captured by the snapshot. Instances of this test with pseudorandom content are created
   226  // by Generate.
   227  //
   228  // The test works as follows:
   229  //
   230  // A new state is created and all actions are applied to it. Several snapshots are taken
   231  // in between actions. The test then reverts each snapshot. For each snapshot the actions
   232  // leading up to it are replayed on a fresh, empty state. The behaviour of all public
   233  // accessor methods on the reverted state must match the return value of the equivalent
   234  // methods on the replayed state.
   235  type snapshotTest struct {
   236  	addrs     []common.Address // all account addresses
   237  	actions   []testAction     // modifications to the state
   238  	snapshots []int            // actions indexes at which snapshot is taken
   239  	err       error            // failure details are reported through this field
   240  }
   241  
   242  type testAction struct {
   243  	name   string
   244  	fn     func(testAction, *StateDB)
   245  	args   []int64
   246  	noAddr bool
   247  }
   248  
   249  // newTestAction creates a random action that changes state.
   250  func newTestAction(addr common.Address, r *rand.Rand) testAction {
   251  	actions := []testAction{
   252  		{
   253  			name: "SetBalance",
   254  			fn: func(a testAction, s *StateDB) {
   255  				s.SetBalance(addr, big.NewInt(a.args[0]))
   256  			},
   257  			args: make([]int64, 1),
   258  		},
   259  		{
   260  			name: "AddBalance",
   261  			fn: func(a testAction, s *StateDB) {
   262  				s.AddBalance(addr, big.NewInt(a.args[0]))
   263  			},
   264  			args: make([]int64, 1),
   265  		},
   266  		{
   267  			name: "SetNonce",
   268  			fn: func(a testAction, s *StateDB) {
   269  				s.SetNonce(addr, uint64(a.args[0]))
   270  			},
   271  			args: make([]int64, 1),
   272  		},
   273  		{
   274  			name: "SetState",
   275  			fn: func(a testAction, s *StateDB) {
   276  				var key, val common.Hash
   277  				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
   278  				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))
   279  				s.SetState(addr, key, val)
   280  			},
   281  			args: make([]int64, 2),
   282  		},
   283  		{
   284  			name: "SetCode",
   285  			fn: func(a testAction, s *StateDB) {
   286  				code := make([]byte, 16)
   287  				binary.BigEndian.PutUint64(code, uint64(a.args[0]))
   288  				binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
   289  				s.SetCode(addr, code)
   290  			},
   291  			args: make([]int64, 2),
   292  		},
   293  		{
   294  			name: "CreateAccount",
   295  			fn: func(a testAction, s *StateDB) {
   296  				s.CreateAccount(addr)
   297  			},
   298  		},
   299  		{
   300  			name: "Suicide",
   301  			fn: func(a testAction, s *StateDB) {
   302  				s.Suicide(addr)
   303  			},
   304  		},
   305  		{
   306  			name: "AddRefund",
   307  			fn: func(a testAction, s *StateDB) {
   308  				s.AddRefund(uint64(a.args[0]))
   309  			},
   310  			args:   make([]int64, 1),
   311  			noAddr: true,
   312  		},
   313  		{
   314  			name: "AddLog",
   315  			fn: func(a testAction, s *StateDB) {
   316  				data := make([]byte, 2)
   317  				binary.BigEndian.PutUint16(data, uint16(a.args[0]))
   318  				s.AddLog(&types.Log{Address: addr, Data: data})
   319  			},
   320  			args: make([]int64, 1),
   321  		},
   322  		{
   323  			name: "AddPreimage",
   324  			fn: func(a testAction, s *StateDB) {
   325  				preimage := []byte{1}
   326  				hash := common.BytesToHash(preimage)
   327  				s.AddPreimage(hash, preimage)
   328  			},
   329  			args: make([]int64, 1),
   330  		},
   331  	}
   332  	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/zhiqiangxu/go-ethereum/pull/15225#issuecomment-380191512
   479  func TestCopyOfCopy(t *testing.T) {
   480  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   481  	addr := common.HexToAddress("aaaa")
   482  	state.SetBalance(addr, big.NewInt(42))
   483  
   484  	if got := state.Copy().GetBalance(addr).Uint64(); got != 42 {
   485  		t.Fatalf("1st copy fail, expected 42, got %v", got)
   486  	}
   487  	if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 {
   488  		t.Fatalf("2nd copy fail, expected 42, got %v", got)
   489  	}
   490  }
   491  
   492  // Tests a regression where committing a copy lost some internal meta information,
   493  // leading to corrupted subsequent copies.
   494  //
   495  // See https://github.com/zhiqiangxu/go-ethereum/issues/20106.
   496  func TestCopyCommitCopy(t *testing.T) {
   497  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   498  
   499  	// Create an account and check if the retrieved balance is correct
   500  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   501  	skey := common.HexToHash("aaa")
   502  	sval := common.HexToHash("bbb")
   503  
   504  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   505  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   506  	state.SetState(addr, skey, sval)       // Change the storage trie
   507  
   508  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   509  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   510  	}
   511  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   512  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   513  	}
   514  	if val := state.GetState(addr, skey); val != sval {
   515  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   516  	}
   517  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   518  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   519  	}
   520  	// Copy the non-committed state database and check pre/post commit balance
   521  	copyOne := state.Copy()
   522  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   523  		t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   524  	}
   525  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   526  		t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   527  	}
   528  	if val := copyOne.GetState(addr, skey); val != sval {
   529  		t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   530  	}
   531  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   532  		t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   533  	}
   534  
   535  	copyOne.Commit(false)
   536  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   537  		t.Fatalf("first copy post-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 post-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 post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   544  	}
   545  	if val := copyOne.GetCommittedState(addr, skey); val != sval {
   546  		t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   547  	}
   548  	// Copy the copy and check the balance once more
   549  	copyTwo := copyOne.Copy()
   550  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   551  		t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42)
   552  	}
   553  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   554  		t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello"))
   555  	}
   556  	if val := copyTwo.GetState(addr, skey); val != sval {
   557  		t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   558  	}
   559  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   560  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   561  	}
   562  }
   563  
   564  // Tests a regression where committing a copy lost some internal meta information,
   565  // leading to corrupted subsequent copies.
   566  //
   567  // See https://github.com/zhiqiangxu/go-ethereum/issues/20106.
   568  func TestCopyCopyCommitCopy(t *testing.T) {
   569  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   570  
   571  	// Create an account and check if the retrieved balance is correct
   572  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   573  	skey := common.HexToHash("aaa")
   574  	sval := common.HexToHash("bbb")
   575  
   576  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   577  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   578  	state.SetState(addr, skey, sval)       // Change the storage trie
   579  
   580  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   581  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   582  	}
   583  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   584  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   585  	}
   586  	if val := state.GetState(addr, skey); val != sval {
   587  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   588  	}
   589  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   590  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   591  	}
   592  	// Copy the non-committed state database and check pre/post commit balance
   593  	copyOne := state.Copy()
   594  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   595  		t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42)
   596  	}
   597  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   598  		t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello"))
   599  	}
   600  	if val := copyOne.GetState(addr, skey); val != sval {
   601  		t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   602  	}
   603  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   604  		t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   605  	}
   606  	// Copy the copy and check the balance once more
   607  	copyTwo := copyOne.Copy()
   608  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   609  		t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   610  	}
   611  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   612  		t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   613  	}
   614  	if val := copyTwo.GetState(addr, skey); val != sval {
   615  		t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   616  	}
   617  	if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) {
   618  		t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   619  	}
   620  	copyTwo.Commit(false)
   621  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   622  		t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42)
   623  	}
   624  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   625  		t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   626  	}
   627  	if val := copyTwo.GetState(addr, skey); val != sval {
   628  		t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   629  	}
   630  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   631  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   632  	}
   633  	// Copy the copy-copy and check the balance once more
   634  	copyThree := copyTwo.Copy()
   635  	if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   636  		t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42)
   637  	}
   638  	if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   639  		t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello"))
   640  	}
   641  	if val := copyThree.GetState(addr, skey); val != sval {
   642  		t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   643  	}
   644  	if val := copyThree.GetCommittedState(addr, skey); val != sval {
   645  		t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval)
   646  	}
   647  }
   648  
   649  // TestDeleteCreateRevert tests a weird state transition corner case that we hit
   650  // while changing the internals of statedb. The workflow is that a contract is
   651  // self destructed, then in a followup transaction (but same block) it's created
   652  // again and the transaction reverted.
   653  //
   654  // The original statedb implementation flushed dirty objects to the tries after
   655  // each transaction, so this works ok. The rework accumulated writes in memory
   656  // first, but the journal wiped the entire state object on create-revert.
   657  func TestDeleteCreateRevert(t *testing.T) {
   658  	// Create an initial state with a single contract
   659  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
   660  
   661  	addr := toAddr([]byte("so"))
   662  	state.SetBalance(addr, big.NewInt(1))
   663  
   664  	root, _ := state.Commit(false)
   665  	state.Reset(root)
   666  
   667  	// Simulate self-destructing in one transaction, then create-reverting in another
   668  	state.Suicide(addr)
   669  	state.Finalise(true)
   670  
   671  	id := state.Snapshot()
   672  	state.SetBalance(addr, big.NewInt(2))
   673  	state.RevertToSnapshot(id)
   674  
   675  	// Commit the entire state and make sure we don't crash and have the correct state
   676  	root, _ = state.Commit(true)
   677  	state.Reset(root)
   678  
   679  	if state.getStateObject(addr) != nil {
   680  		t.Fatalf("self-destructed contract came alive")
   681  	}
   682  }
   683  
   684  // TestMissingTrieNodes tests that if the statedb fails to load parts of the trie,
   685  // the Commit operation fails with an error
   686  // If we are missing trie nodes, we should not continue writing to the trie
   687  func TestMissingTrieNodes(t *testing.T) {
   688  
   689  	// Create an initial state with a few accounts
   690  	memDb := rawdb.NewMemoryDatabase()
   691  	db := NewDatabase(memDb)
   692  	var root common.Hash
   693  	state, _ := New(common.Hash{}, db, nil)
   694  	addr := toAddr([]byte("so"))
   695  	{
   696  		state.SetBalance(addr, big.NewInt(1))
   697  		state.SetCode(addr, []byte{1, 2, 3})
   698  		a2 := toAddr([]byte("another"))
   699  		state.SetBalance(a2, big.NewInt(100))
   700  		state.SetCode(a2, []byte{1, 2, 4})
   701  		root, _ = state.Commit(false)
   702  		t.Logf("root: %x", root)
   703  		// force-flush
   704  		state.Database().TrieDB().Cap(0)
   705  	}
   706  	// Create a new state on the old root
   707  	state, _ = New(root, db, nil)
   708  	// Now we clear out the memdb
   709  	it := memDb.NewIterator(nil, nil)
   710  	for it.Next() {
   711  		k := it.Key()
   712  		// Leave the root intact
   713  		if !bytes.Equal(k, root[:]) {
   714  			t.Logf("key: %x", k)
   715  			memDb.Delete(k)
   716  		}
   717  	}
   718  	balance := state.GetBalance(addr)
   719  	// The removed elem should lead to it returning zero balance
   720  	if exp, got := uint64(0), balance.Uint64(); got != exp {
   721  		t.Errorf("expected %d, got %d", exp, got)
   722  	}
   723  	// Modify the state
   724  	state.SetBalance(addr, big.NewInt(2))
   725  	root, err := state.Commit(false)
   726  	if err == nil {
   727  		t.Fatalf("expected error, got root :%x", root)
   728  	}
   729  }