github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/core/state/statedb_test.go (about)

     1  //  Copyright 2018 The go-ethereum Authors
     2  //  Copyright 2019 The go-aigar Authors
     3  //  This file is part of the go-aigar library.
     4  //
     5  //  The go-aigar library is free software: you can redistribute it and/or modify
     6  //  it under the terms of the GNU Lesser General Public License as published by
     7  //  the Free Software Foundation, either version 3 of the License, or
     8  //  (at your option) any later version.
     9  //
    10  //  The go-aigar library is distributed in the hope that it will be useful,
    11  //  but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  //  GNU Lesser General Public License for more details.
    14  //
    15  //  You should have received a copy of the GNU Lesser General Public License
    16  //  along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package state
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/binary"
    23  	"fmt"
    24  	"math"
    25  	"math/big"
    26  	"math/rand"
    27  	"reflect"
    28  	"strings"
    29  	"sync"
    30  	"testing"
    31  	"testing/quick"
    32  
    33  	"gopkg.in/check.v1"
    34  
    35  	"github.com/AigarNetwork/aigar/common"
    36  	"github.com/AigarNetwork/aigar/core/rawdb"
    37  	"github.com/AigarNetwork/aigar/core/types"
    38  )
    39  
    40  // Tests that updating a state trie does not leak any database writes prior to
    41  // actually committing the state.
    42  func TestUpdateLeaks(t *testing.T) {
    43  	// Create an empty state database
    44  	db := rawdb.NewMemoryDatabase()
    45  	state, _ := New(common.Hash{}, NewDatabase(db))
    46  
    47  	// Update it with some accounts
    48  	for i := byte(0); i < 255; i++ {
    49  		addr := common.BytesToAddress([]byte{i})
    50  		state.AddBalance(addr, big.NewInt(int64(11*i)))
    51  		state.SetNonce(addr, uint64(42*i))
    52  		if i%2 == 0 {
    53  			state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
    54  		}
    55  		if i%3 == 0 {
    56  			state.SetCode(addr, []byte{i, i, i, i, i})
    57  		}
    58  	}
    59  
    60  	root := state.IntermediateRoot(false)
    61  	if err := state.Database().TrieDB().Commit(root, false); err != nil {
    62  		t.Errorf("can not commit trie %v to persistent database", root.Hex())
    63  	}
    64  
    65  	// Ensure that no data was leaked into the database
    66  	it := db.NewIterator()
    67  	for it.Next() {
    68  		t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value())
    69  	}
    70  	it.Release()
    71  }
    72  
    73  // Tests that no intermediate state of an object is stored into the database,
    74  // only the one right before the commit.
    75  func TestIntermediateLeaks(t *testing.T) {
    76  	// Create two state databases, one transitioning to the final state, the other final from the beginning
    77  	transDb := rawdb.NewMemoryDatabase()
    78  	finalDb := rawdb.NewMemoryDatabase()
    79  	transState, _ := New(common.Hash{}, NewDatabase(transDb))
    80  	finalState, _ := New(common.Hash{}, NewDatabase(finalDb))
    81  
    82  	modify := func(state *StateDB, addr common.Address, i, tweak byte) {
    83  		state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak)))
    84  		state.SetNonce(addr, uint64(42*i+tweak))
    85  		if i%2 == 0 {
    86  			state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{})
    87  			state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak})
    88  		}
    89  		if i%3 == 0 {
    90  			state.SetCode(addr, []byte{i, i, i, i, i, tweak})
    91  		}
    92  	}
    93  
    94  	// Modify the transient state.
    95  	for i := byte(0); i < 255; i++ {
    96  		modify(transState, common.Address{i}, i, 0)
    97  	}
    98  	// Write modifications to trie.
    99  	transState.IntermediateRoot(false)
   100  
   101  	// Overwrite all the data with new values in the transient database.
   102  	for i := byte(0); i < 255; i++ {
   103  		modify(transState, common.Address{i}, i, 99)
   104  		modify(finalState, common.Address{i}, i, 99)
   105  	}
   106  
   107  	// Commit and cross check the databases.
   108  	transRoot, err := transState.Commit(false)
   109  	if err != nil {
   110  		t.Fatalf("failed to commit transition state: %v", err)
   111  	}
   112  	if err = transState.Database().TrieDB().Commit(transRoot, false); err != nil {
   113  		t.Errorf("can not commit trie %v to persistent database", transRoot.Hex())
   114  	}
   115  
   116  	finalRoot, err := finalState.Commit(false)
   117  	if err != nil {
   118  		t.Fatalf("failed to commit final state: %v", err)
   119  	}
   120  	if err = finalState.Database().TrieDB().Commit(finalRoot, false); err != nil {
   121  		t.Errorf("can not commit trie %v to persistent database", finalRoot.Hex())
   122  	}
   123  
   124  	it := finalDb.NewIterator()
   125  	for it.Next() {
   126  		key, fvalue := it.Key(), it.Value()
   127  		tvalue, err := transDb.Get(key)
   128  		if err != nil {
   129  			t.Errorf("entry missing from the transition database: %x -> %x", key, fvalue)
   130  		}
   131  		if !bytes.Equal(fvalue, tvalue) {
   132  			t.Errorf("the value associate key %x is mismatch,: %x in transition database ,%x in final database", key, tvalue, fvalue)
   133  		}
   134  	}
   135  	it.Release()
   136  
   137  	it = transDb.NewIterator()
   138  	for it.Next() {
   139  		key, tvalue := it.Key(), it.Value()
   140  		fvalue, err := finalDb.Get(key)
   141  		if err != nil {
   142  			t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value())
   143  		}
   144  		if !bytes.Equal(fvalue, tvalue) {
   145  			t.Errorf("the value associate key %x is mismatch,: %x in transition database ,%x in final database", key, tvalue, fvalue)
   146  		}
   147  	}
   148  }
   149  
   150  // TestCopy tests that copying a statedb object indeed makes the original and
   151  // the copy independent of each other. This test is a regression test against
   152  // https://github.com/AigarNetwork/aigar/pull/15549.
   153  func TestCopy(t *testing.T) {
   154  	// Create a random state test to copy and modify "independently"
   155  	orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   156  
   157  	for i := byte(0); i < 255; i++ {
   158  		obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   159  		obj.AddBalance(big.NewInt(int64(i)))
   160  		orig.updateStateObject(obj)
   161  	}
   162  	orig.Finalise(false)
   163  
   164  	// Copy the state
   165  	copy := orig.Copy()
   166  
   167  	// Copy the copy state
   168  	ccopy := copy.Copy()
   169  
   170  	// modify all in memory
   171  	for i := byte(0); i < 255; i++ {
   172  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   173  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   174  		ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   175  
   176  		origObj.AddBalance(big.NewInt(2 * int64(i)))
   177  		copyObj.AddBalance(big.NewInt(3 * int64(i)))
   178  		ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
   179  
   180  		orig.updateStateObject(origObj)
   181  		copy.updateStateObject(copyObj)
   182  		ccopy.updateStateObject(copyObj)
   183  	}
   184  
   185  	// Finalise the changes on all concurrently
   186  	finalise := func(wg *sync.WaitGroup, db *StateDB) {
   187  		defer wg.Done()
   188  		db.Finalise(true)
   189  	}
   190  
   191  	var wg sync.WaitGroup
   192  	wg.Add(3)
   193  	go finalise(&wg, orig)
   194  	go finalise(&wg, copy)
   195  	go finalise(&wg, ccopy)
   196  	wg.Wait()
   197  
   198  	// Verify that the three states have been updated independently
   199  	for i := byte(0); i < 255; i++ {
   200  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   201  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   202  		ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   203  
   204  		if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 {
   205  			t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want)
   206  		}
   207  		if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 {
   208  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want)
   209  		}
   210  		if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 {
   211  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want)
   212  		}
   213  	}
   214  }
   215  
   216  func TestSnapshotRandom(t *testing.T) {
   217  	config := &quick.Config{MaxCount: 1000}
   218  	err := quick.Check((*snapshotTest).run, config)
   219  	if cerr, ok := err.(*quick.CheckError); ok {
   220  		test := cerr.In[0].(*snapshotTest)
   221  		t.Errorf("%v:\n%s", test.err, test)
   222  	} else if err != nil {
   223  		t.Error(err)
   224  	}
   225  }
   226  
   227  // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes
   228  // captured by the snapshot. Instances of this test with pseudorandom content are created
   229  // by Generate.
   230  //
   231  // The test works as follows:
   232  //
   233  // A new state is created and all actions are applied to it. Several snapshots are taken
   234  // in between actions. The test then reverts each snapshot. For each snapshot the actions
   235  // leading up to it are replayed on a fresh, empty state. The behaviour of all public
   236  // accessor methods on the reverted state must match the return value of the equivalent
   237  // methods on the replayed state.
   238  type snapshotTest struct {
   239  	addrs     []common.Address // all account addresses
   240  	actions   []testAction     // modifications to the state
   241  	snapshots []int            // actions indexes at which snapshot is taken
   242  	err       error            // failure details are reported through this field
   243  }
   244  
   245  type testAction struct {
   246  	name   string
   247  	fn     func(testAction, *StateDB)
   248  	args   []int64
   249  	noAddr bool
   250  }
   251  
   252  // newTestAction creates a random action that changes state.
   253  func newTestAction(addr common.Address, r *rand.Rand) testAction {
   254  	actions := []testAction{
   255  		{
   256  			name: "SetBalance",
   257  			fn: func(a testAction, s *StateDB) {
   258  				s.SetBalance(addr, big.NewInt(a.args[0]))
   259  			},
   260  			args: make([]int64, 1),
   261  		},
   262  		{
   263  			name: "AddBalance",
   264  			fn: func(a testAction, s *StateDB) {
   265  				s.AddBalance(addr, big.NewInt(a.args[0]))
   266  			},
   267  			args: make([]int64, 1),
   268  		},
   269  		{
   270  			name: "SetNonce",
   271  			fn: func(a testAction, s *StateDB) {
   272  				s.SetNonce(addr, uint64(a.args[0]))
   273  			},
   274  			args: make([]int64, 1),
   275  		},
   276  		{
   277  			name: "SetState",
   278  			fn: func(a testAction, s *StateDB) {
   279  				var key, val common.Hash
   280  				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
   281  				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))
   282  				s.SetState(addr, key, val)
   283  			},
   284  			args: make([]int64, 2),
   285  		},
   286  		{
   287  			name: "SetCode",
   288  			fn: func(a testAction, s *StateDB) {
   289  				code := make([]byte, 16)
   290  				binary.BigEndian.PutUint64(code, uint64(a.args[0]))
   291  				binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
   292  				s.SetCode(addr, code)
   293  			},
   294  			args: make([]int64, 2),
   295  		},
   296  		{
   297  			name: "CreateAccount",
   298  			fn: func(a testAction, s *StateDB) {
   299  				s.CreateAccount(addr)
   300  			},
   301  		},
   302  		{
   303  			name: "Suicide",
   304  			fn: func(a testAction, s *StateDB) {
   305  				s.Suicide(addr)
   306  			},
   307  		},
   308  		{
   309  			name: "AddRefund",
   310  			fn: func(a testAction, s *StateDB) {
   311  				s.AddRefund(uint64(a.args[0]))
   312  			},
   313  			args:   make([]int64, 1),
   314  			noAddr: true,
   315  		},
   316  		{
   317  			name: "AddLog",
   318  			fn: func(a testAction, s *StateDB) {
   319  				data := make([]byte, 2)
   320  				binary.BigEndian.PutUint16(data, uint16(a.args[0]))
   321  				s.AddLog(&types.Log{Address: addr, Data: data})
   322  			},
   323  			args: make([]int64, 1),
   324  		},
   325  		{
   326  			name: "AddPreimage",
   327  			fn: func(a testAction, s *StateDB) {
   328  				preimage := []byte{1}
   329  				hash := common.BytesToHash(preimage)
   330  				s.AddPreimage(hash, preimage)
   331  			},
   332  			args: make([]int64, 1),
   333  		},
   334  	}
   335  	action := actions[r.Intn(len(actions))]
   336  	var nameargs []string
   337  	if !action.noAddr {
   338  		nameargs = append(nameargs, addr.Hex())
   339  	}
   340  	for i := range action.args {
   341  		action.args[i] = rand.Int63n(100)
   342  		nameargs = append(nameargs, fmt.Sprint(action.args[i]))
   343  	}
   344  	action.name += strings.Join(nameargs, ", ")
   345  	return action
   346  }
   347  
   348  // Generate returns a new snapshot test of the given size. All randomness is
   349  // derived from r.
   350  func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value {
   351  	// Generate random actions.
   352  	addrs := make([]common.Address, 50)
   353  	for i := range addrs {
   354  		addrs[i][0] = byte(i)
   355  	}
   356  	actions := make([]testAction, size)
   357  	for i := range actions {
   358  		addr := addrs[r.Intn(len(addrs))]
   359  		actions[i] = newTestAction(addr, r)
   360  	}
   361  	// Generate snapshot indexes.
   362  	nsnapshots := int(math.Sqrt(float64(size)))
   363  	if size > 0 && nsnapshots == 0 {
   364  		nsnapshots = 1
   365  	}
   366  	snapshots := make([]int, nsnapshots)
   367  	snaplen := len(actions) / nsnapshots
   368  	for i := range snapshots {
   369  		// Try to place the snapshots some number of actions apart from each other.
   370  		snapshots[i] = (i * snaplen) + r.Intn(snaplen)
   371  	}
   372  	return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil})
   373  }
   374  
   375  func (test *snapshotTest) String() string {
   376  	out := new(bytes.Buffer)
   377  	sindex := 0
   378  	for i, action := range test.actions {
   379  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   380  			fmt.Fprintf(out, "---- snapshot %d ----\n", sindex)
   381  			sindex++
   382  		}
   383  		fmt.Fprintf(out, "%4d: %s\n", i, action.name)
   384  	}
   385  	return out.String()
   386  }
   387  
   388  func (test *snapshotTest) run() bool {
   389  	// Run all actions and create snapshots.
   390  	var (
   391  		state, _     = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   392  		snapshotRevs = make([]int, len(test.snapshots))
   393  		sindex       = 0
   394  	)
   395  	for i, action := range test.actions {
   396  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   397  			snapshotRevs[sindex] = state.Snapshot()
   398  			sindex++
   399  		}
   400  		action.fn(action, state)
   401  	}
   402  	// Revert all snapshots in reverse order. Each revert must yield a state
   403  	// that is equivalent to fresh state with all actions up the snapshot applied.
   404  	for sindex--; sindex >= 0; sindex-- {
   405  		checkstate, _ := New(common.Hash{}, state.Database())
   406  		for _, action := range test.actions[:test.snapshots[sindex]] {
   407  			action.fn(action, checkstate)
   408  		}
   409  		state.RevertToSnapshot(snapshotRevs[sindex])
   410  		if err := test.checkEqual(state, checkstate); err != nil {
   411  			test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err)
   412  			return false
   413  		}
   414  	}
   415  	return true
   416  }
   417  
   418  // checkEqual checks that methods of state and checkstate return the same values.
   419  func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
   420  	for _, addr := range test.addrs {
   421  		var err error
   422  		checkeq := func(op string, a, b interface{}) bool {
   423  			if err == nil && !reflect.DeepEqual(a, b) {
   424  				err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b)
   425  				return false
   426  			}
   427  			return true
   428  		}
   429  		// Check basic accessor methods.
   430  		checkeq("Exist", state.Exist(addr), checkstate.Exist(addr))
   431  		checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr))
   432  		checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
   433  		checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
   434  		checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
   435  		checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr))
   436  		checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
   437  		// Check storage.
   438  		if obj := state.getStateObject(addr); obj != nil {
   439  			state.ForEachStorage(addr, func(key, value common.Hash) bool {
   440  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   441  			})
   442  			checkstate.ForEachStorage(addr, func(key, value common.Hash) bool {
   443  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   444  			})
   445  		}
   446  		if err != nil {
   447  			return err
   448  		}
   449  	}
   450  
   451  	if state.GetRefund() != checkstate.GetRefund() {
   452  		return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
   453  			state.GetRefund(), checkstate.GetRefund())
   454  	}
   455  	if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) {
   456  		return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v",
   457  			state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{}))
   458  	}
   459  	return nil
   460  }
   461  
   462  func (s *StateSuite) TestTouchDelete(c *check.C) {
   463  	s.state.GetOrNewStateObject(common.Address{})
   464  	root, _ := s.state.Commit(false)
   465  	s.state.Reset(root)
   466  
   467  	snapshot := s.state.Snapshot()
   468  	s.state.AddBalance(common.Address{}, new(big.Int))
   469  
   470  	if len(s.state.journal.dirties) != 1 {
   471  		c.Fatal("expected one dirty state object")
   472  	}
   473  	s.state.RevertToSnapshot(snapshot)
   474  	if len(s.state.journal.dirties) != 0 {
   475  		c.Fatal("expected no dirty state object")
   476  	}
   477  }
   478  
   479  // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
   480  // See https://github.com/AigarNetwork/aigar/pull/15225#issuecomment-380191512
   481  func TestCopyOfCopy(t *testing.T) {
   482  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   483  	addr := common.HexToAddress("aaaa")
   484  	state.SetBalance(addr, big.NewInt(42))
   485  
   486  	if got := state.Copy().GetBalance(addr).Uint64(); got != 42 {
   487  		t.Fatalf("1st copy fail, expected 42, got %v", got)
   488  	}
   489  	if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 {
   490  		t.Fatalf("2nd copy fail, expected 42, got %v", got)
   491  	}
   492  }
   493  
   494  // Tests a regression where committing a copy lost some internal meta information,
   495  // leading to corrupted subsequent copies.
   496  //
   497  // See https://github.com/AigarNetwork/aigar/issues/20106.
   498  func TestCopyCommitCopy(t *testing.T) {
   499  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   500  
   501  	// Create an account and check if the retrieved balance is correct
   502  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   503  	skey := common.HexToHash("aaa")
   504  	sval := common.HexToHash("bbb")
   505  
   506  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   507  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   508  	state.SetState(addr, skey, sval)       // Change the storage trie
   509  
   510  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   511  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   512  	}
   513  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   514  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   515  	}
   516  	if val := state.GetState(addr, skey); val != sval {
   517  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   518  	}
   519  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   520  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   521  	}
   522  	// Copy the non-committed state database and check pre/post commit balance
   523  	copyOne := state.Copy()
   524  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   525  		t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   526  	}
   527  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   528  		t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   529  	}
   530  	if val := copyOne.GetState(addr, skey); val != sval {
   531  		t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   532  	}
   533  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   534  		t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   535  	}
   536  
   537  	copyOne.Commit(false)
   538  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   539  		t.Fatalf("first copy post-commit balance mismatch: have %v, want %v", balance, 42)
   540  	}
   541  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   542  		t.Fatalf("first copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   543  	}
   544  	if val := copyOne.GetState(addr, skey); val != sval {
   545  		t.Fatalf("first copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   546  	}
   547  	if val := copyOne.GetCommittedState(addr, skey); val != sval {
   548  		t.Fatalf("first copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   549  	}
   550  	// Copy the copy and check the balance once more
   551  	copyTwo := copyOne.Copy()
   552  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   553  		t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42)
   554  	}
   555  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   556  		t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello"))
   557  	}
   558  	if val := copyTwo.GetState(addr, skey); val != sval {
   559  		t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   560  	}
   561  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   562  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   563  	}
   564  }
   565  
   566  // Tests a regression where committing a copy lost some internal meta information,
   567  // leading to corrupted subsequent copies.
   568  //
   569  // See https://github.com/AigarNetwork/aigar/issues/20106.
   570  func TestCopyCopyCommitCopy(t *testing.T) {
   571  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   572  
   573  	// Create an account and check if the retrieved balance is correct
   574  	addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
   575  	skey := common.HexToHash("aaa")
   576  	sval := common.HexToHash("bbb")
   577  
   578  	state.SetBalance(addr, big.NewInt(42)) // Change the account trie
   579  	state.SetCode(addr, []byte("hello"))   // Change an external metadata
   580  	state.SetState(addr, skey, sval)       // Change the storage trie
   581  
   582  	if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   583  		t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
   584  	}
   585  	if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   586  		t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello"))
   587  	}
   588  	if val := state.GetState(addr, skey); val != sval {
   589  		t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval)
   590  	}
   591  	if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) {
   592  		t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   593  	}
   594  	// Copy the non-committed state database and check pre/post commit balance
   595  	copyOne := state.Copy()
   596  	if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   597  		t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42)
   598  	}
   599  	if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   600  		t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello"))
   601  	}
   602  	if val := copyOne.GetState(addr, skey); val != sval {
   603  		t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   604  	}
   605  	if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) {
   606  		t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   607  	}
   608  	// Copy the copy and check the balance once more
   609  	copyTwo := copyOne.Copy()
   610  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   611  		t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
   612  	}
   613  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   614  		t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello"))
   615  	}
   616  	if val := copyTwo.GetState(addr, skey); val != sval {
   617  		t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   618  	}
   619  	if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) {
   620  		t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{})
   621  	}
   622  	copyTwo.Commit(false)
   623  	if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   624  		t.Fatalf("second copy post-commit balance mismatch: have %v, want %v", balance, 42)
   625  	}
   626  	if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   627  		t.Fatalf("second copy post-commit code mismatch: have %x, want %x", code, []byte("hello"))
   628  	}
   629  	if val := copyTwo.GetState(addr, skey); val != sval {
   630  		t.Fatalf("second copy post-commit non-committed storage slot mismatch: have %x, want %x", val, sval)
   631  	}
   632  	if val := copyTwo.GetCommittedState(addr, skey); val != sval {
   633  		t.Fatalf("second copy post-commit committed storage slot mismatch: have %x, want %x", val, sval)
   634  	}
   635  	// Copy the copy-copy and check the balance once more
   636  	copyThree := copyTwo.Copy()
   637  	if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
   638  		t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42)
   639  	}
   640  	if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
   641  		t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello"))
   642  	}
   643  	if val := copyThree.GetState(addr, skey); val != sval {
   644  		t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval)
   645  	}
   646  	if val := copyThree.GetCommittedState(addr, skey); val != sval {
   647  		t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval)
   648  	}
   649  }
   650  
   651  // TestDeleteCreateRevert tests a weird state transition corner case that we hit
   652  // while changing the internals of statedb. The workflow is that a contract is
   653  // self destructed, then in a followup transaction (but same block) it's created
   654  // again and the transaction reverted.
   655  //
   656  // The original statedb implementation flushed dirty objects to the tries after
   657  // each transaction, so this works ok. The rework accumulated writes in memory
   658  // first, but the journal wiped the entire state object on create-revert.
   659  func TestDeleteCreateRevert(t *testing.T) {
   660  	// Create an initial state with a single contract
   661  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   662  
   663  	addr := toAddr([]byte("so"))
   664  	state.SetBalance(addr, big.NewInt(1))
   665  
   666  	root, _ := state.Commit(false)
   667  	state.Reset(root)
   668  
   669  	// Simulate self-destructing in one transaction, then create-reverting in another
   670  	state.Suicide(addr)
   671  	state.Finalise(true)
   672  
   673  	id := state.Snapshot()
   674  	state.SetBalance(addr, big.NewInt(2))
   675  	state.RevertToSnapshot(id)
   676  
   677  	// Commit the entire state and make sure we don't crash and have the correct state
   678  	root, _ = state.Commit(true)
   679  	state.Reset(root)
   680  
   681  	if state.getStateObject(addr) != nil {
   682  		t.Fatalf("self-destructed contract came alive")
   683  	}
   684  }