github.com/chainopen/ethchaincode@v0.0.0-20190924072703-d975acdaa1c6/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  	"testing"
    29  	"testing/quick"
    30  
    31  	check "gopkg.in/check.v1"
    32  
    33  	"github.com/ethereum/go-ethereum/common"
    34  	"github.com/ethereum/go-ethereum/core/rawdb"
    35  	"github.com/ethereum/go-ethereum/core/types"
    36  )
    37  
    38  // Tests that updating a state trie does not leak any database writes prior to
    39  // actually committing the state.
    40  func TestUpdateLeaks(t *testing.T) {
    41  	// Create an empty state database
    42  	db := rawdb.NewMemoryDatabase()
    43  	state, _ := New(common.Hash{}, NewDatabase(db))
    44  
    45  	// Update it with some accounts
    46  	for i := byte(0); i < 255; i++ {
    47  		addr := common.BytesToAddress([]byte{i})
    48  		state.AddBalance(addr, big.NewInt(int64(11*i)))
    49  		state.SetNonce(addr, uint64(42*i))
    50  		if i%2 == 0 {
    51  			state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
    52  		}
    53  		if i%3 == 0 {
    54  			state.SetCode(addr, []byte{i, i, i, i, i})
    55  		}
    56  		state.IntermediateRoot(false)
    57  	}
    58  	// Ensure that no data was leaked into the database
    59  	it := db.NewIterator()
    60  	for it.Next() {
    61  		t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value())
    62  	}
    63  	it.Release()
    64  }
    65  
    66  // Tests that no intermediate state of an object is stored into the database,
    67  // only the one right before the commit.
    68  func TestIntermediateLeaks(t *testing.T) {
    69  	// Create two state databases, one transitioning to the final state, the other final from the beginning
    70  	transDb := rawdb.NewMemoryDatabase()
    71  	finalDb := rawdb.NewMemoryDatabase()
    72  	transState, _ := New(common.Hash{}, NewDatabase(transDb))
    73  	finalState, _ := New(common.Hash{}, NewDatabase(finalDb))
    74  
    75  	modify := func(state *StateDB, addr common.Address, i, tweak byte) {
    76  		state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak)))
    77  		state.SetNonce(addr, uint64(42*i+tweak))
    78  		if i%2 == 0 {
    79  			state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{})
    80  			state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak})
    81  		}
    82  		if i%3 == 0 {
    83  			state.SetCode(addr, []byte{i, i, i, i, i, tweak})
    84  		}
    85  	}
    86  
    87  	// Modify the transient state.
    88  	for i := byte(0); i < 255; i++ {
    89  		modify(transState, common.Address{i}, i, 0)
    90  	}
    91  	// Write modifications to trie.
    92  	transState.IntermediateRoot(false)
    93  
    94  	// Overwrite all the data with new values in the transient database.
    95  	for i := byte(0); i < 255; i++ {
    96  		modify(transState, common.Address{i}, i, 99)
    97  		modify(finalState, common.Address{i}, i, 99)
    98  	}
    99  
   100  	// Commit and cross check the databases.
   101  	if _, err := transState.Commit(false); err != nil {
   102  		t.Fatalf("failed to commit transition state: %v", err)
   103  	}
   104  	if _, err := finalState.Commit(false); err != nil {
   105  		t.Fatalf("failed to commit final state: %v", err)
   106  	}
   107  	it := finalDb.NewIterator()
   108  	for it.Next() {
   109  		key := it.Key()
   110  		if _, err := transDb.Get(key); err != nil {
   111  			t.Errorf("entry missing from the transition database: %x -> %x", key, it.Value())
   112  		}
   113  	}
   114  	it.Release()
   115  
   116  	it = transDb.NewIterator()
   117  	for it.Next() {
   118  		key := it.Key()
   119  		if _, err := finalDb.Get(key); err != nil {
   120  			t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value())
   121  		}
   122  	}
   123  }
   124  
   125  // TestCopy tests that copying a statedb object indeed makes the original and
   126  // the copy independent of each other. This test is a regression test against
   127  // https://github.com/ethereum/go-ethereum/pull/15549.
   128  func TestCopy(t *testing.T) {
   129  	// Create a random state test to copy and modify "independently"
   130  	orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   131  
   132  	for i := byte(0); i < 255; i++ {
   133  		obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   134  		obj.AddBalance(big.NewInt(int64(i)))
   135  		orig.updateStateObject(obj)
   136  	}
   137  	orig.Finalise(false)
   138  
   139  	// Copy the state, modify both in-memory
   140  	copy := orig.Copy()
   141  
   142  	for i := byte(0); i < 255; i++ {
   143  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   144  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   145  
   146  		origObj.AddBalance(big.NewInt(2 * int64(i)))
   147  		copyObj.AddBalance(big.NewInt(3 * int64(i)))
   148  
   149  		orig.updateStateObject(origObj)
   150  		copy.updateStateObject(copyObj)
   151  	}
   152  	// Finalise the changes on both concurrently
   153  	done := make(chan struct{})
   154  	go func() {
   155  		orig.Finalise(true)
   156  		close(done)
   157  	}()
   158  	copy.Finalise(true)
   159  	<-done
   160  
   161  	// Verify that the two states have been updated independently
   162  	for i := byte(0); i < 255; i++ {
   163  		origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   164  		copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
   165  
   166  		if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 {
   167  			t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want)
   168  		}
   169  		if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 {
   170  			t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want)
   171  		}
   172  	}
   173  }
   174  
   175  func TestSnapshotRandom(t *testing.T) {
   176  	config := &quick.Config{MaxCount: 1000}
   177  	err := quick.Check((*snapshotTest).run, config)
   178  	if cerr, ok := err.(*quick.CheckError); ok {
   179  		test := cerr.In[0].(*snapshotTest)
   180  		t.Errorf("%v:\n%s", test.err, test)
   181  	} else if err != nil {
   182  		t.Error(err)
   183  	}
   184  }
   185  
   186  // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes
   187  // captured by the snapshot. Instances of this test with pseudorandom content are created
   188  // by Generate.
   189  //
   190  // The test works as follows:
   191  //
   192  // A new state is created and all actions are applied to it. Several snapshots are taken
   193  // in between actions. The test then reverts each snapshot. For each snapshot the actions
   194  // leading up to it are replayed on a fresh, empty state. The behaviour of all public
   195  // accessor methods on the reverted state must match the return value of the equivalent
   196  // methods on the replayed state.
   197  type snapshotTest struct {
   198  	addrs     []common.Address // all account addresses
   199  	actions   []testAction     // modifications to the state
   200  	snapshots []int            // actions indexes at which snapshot is taken
   201  	err       error            // failure details are reported through this field
   202  }
   203  
   204  type testAction struct {
   205  	name   string
   206  	fn     func(testAction, *StateDB)
   207  	args   []int64
   208  	noAddr bool
   209  }
   210  
   211  // newTestAction creates a random action that changes state.
   212  func newTestAction(addr common.Address, r *rand.Rand) testAction {
   213  	actions := []testAction{
   214  		{
   215  			name: "SetBalance",
   216  			fn: func(a testAction, s *StateDB) {
   217  				s.SetBalance(addr, big.NewInt(a.args[0]))
   218  			},
   219  			args: make([]int64, 1),
   220  		},
   221  		{
   222  			name: "AddBalance",
   223  			fn: func(a testAction, s *StateDB) {
   224  				s.AddBalance(addr, big.NewInt(a.args[0]))
   225  			},
   226  			args: make([]int64, 1),
   227  		},
   228  		{
   229  			name: "SetNonce",
   230  			fn: func(a testAction, s *StateDB) {
   231  				s.SetNonce(addr, uint64(a.args[0]))
   232  			},
   233  			args: make([]int64, 1),
   234  		},
   235  		{
   236  			name: "SetState",
   237  			fn: func(a testAction, s *StateDB) {
   238  				var key, val common.Hash
   239  				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
   240  				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))
   241  				s.SetState(addr, key, val)
   242  			},
   243  			args: make([]int64, 2),
   244  		},
   245  		{
   246  			name: "SetCode",
   247  			fn: func(a testAction, s *StateDB) {
   248  				code := make([]byte, 16)
   249  				binary.BigEndian.PutUint64(code, uint64(a.args[0]))
   250  				binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
   251  				s.SetCode(addr, code)
   252  			},
   253  			args: make([]int64, 2),
   254  		},
   255  		{
   256  			name: "CreateAccount",
   257  			fn: func(a testAction, s *StateDB) {
   258  				s.CreateAccount(addr)
   259  			},
   260  		},
   261  		{
   262  			name: "Suicide",
   263  			fn: func(a testAction, s *StateDB) {
   264  				s.Suicide(addr)
   265  			},
   266  		},
   267  		{
   268  			name: "AddRefund",
   269  			fn: func(a testAction, s *StateDB) {
   270  				s.AddRefund(uint64(a.args[0]))
   271  			},
   272  			args:   make([]int64, 1),
   273  			noAddr: true,
   274  		},
   275  		{
   276  			name: "AddLog",
   277  			fn: func(a testAction, s *StateDB) {
   278  				data := make([]byte, 2)
   279  				binary.BigEndian.PutUint16(data, uint16(a.args[0]))
   280  				s.AddLog(&types.Log{Address: addr, Data: data})
   281  			},
   282  			args: make([]int64, 1),
   283  		},
   284  		{
   285  			name: "AddPreimage",
   286  			fn: func(a testAction, s *StateDB) {
   287  				preimage := []byte{1}
   288  				hash := common.BytesToHash(preimage)
   289  				s.AddPreimage(hash, preimage)
   290  			},
   291  			args: make([]int64, 1),
   292  		},
   293  	}
   294  	action := actions[r.Intn(len(actions))]
   295  	var nameargs []string
   296  	if !action.noAddr {
   297  		nameargs = append(nameargs, addr.Hex())
   298  	}
   299  	for i := range action.args {
   300  		action.args[i] = rand.Int63n(100)
   301  		nameargs = append(nameargs, fmt.Sprint(action.args[i]))
   302  	}
   303  	action.name += strings.Join(nameargs, ", ")
   304  	return action
   305  }
   306  
   307  // Generate returns a new snapshot test of the given size. All randomness is
   308  // derived from r.
   309  func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value {
   310  	// Generate random actions.
   311  	addrs := make([]common.Address, 50)
   312  	for i := range addrs {
   313  		addrs[i][0] = byte(i)
   314  	}
   315  	actions := make([]testAction, size)
   316  	for i := range actions {
   317  		addr := addrs[r.Intn(len(addrs))]
   318  		actions[i] = newTestAction(addr, r)
   319  	}
   320  	// Generate snapshot indexes.
   321  	nsnapshots := int(math.Sqrt(float64(size)))
   322  	if size > 0 && nsnapshots == 0 {
   323  		nsnapshots = 1
   324  	}
   325  	snapshots := make([]int, nsnapshots)
   326  	snaplen := len(actions) / nsnapshots
   327  	for i := range snapshots {
   328  		// Try to place the snapshots some number of actions apart from each other.
   329  		snapshots[i] = (i * snaplen) + r.Intn(snaplen)
   330  	}
   331  	return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil})
   332  }
   333  
   334  func (test *snapshotTest) String() string {
   335  	out := new(bytes.Buffer)
   336  	sindex := 0
   337  	for i, action := range test.actions {
   338  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   339  			fmt.Fprintf(out, "---- snapshot %d ----\n", sindex)
   340  			sindex++
   341  		}
   342  		fmt.Fprintf(out, "%4d: %s\n", i, action.name)
   343  	}
   344  	return out.String()
   345  }
   346  
   347  func (test *snapshotTest) run() bool {
   348  	// Run all actions and create snapshots.
   349  	var (
   350  		state, _     = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   351  		snapshotRevs = make([]int, len(test.snapshots))
   352  		sindex       = 0
   353  	)
   354  	for i, action := range test.actions {
   355  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   356  			snapshotRevs[sindex] = state.Snapshot()
   357  			sindex++
   358  		}
   359  		action.fn(action, state)
   360  	}
   361  	// Revert all snapshots in reverse order. Each revert must yield a state
   362  	// that is equivalent to fresh state with all actions up the snapshot applied.
   363  	for sindex--; sindex >= 0; sindex-- {
   364  		checkstate, _ := New(common.Hash{}, state.Database())
   365  		for _, action := range test.actions[:test.snapshots[sindex]] {
   366  			action.fn(action, checkstate)
   367  		}
   368  		state.RevertToSnapshot(snapshotRevs[sindex])
   369  		if err := test.checkEqual(state, checkstate); err != nil {
   370  			test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err)
   371  			return false
   372  		}
   373  	}
   374  	return true
   375  }
   376  
   377  // checkEqual checks that methods of state and checkstate return the same values.
   378  func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
   379  	for _, addr := range test.addrs {
   380  		var err error
   381  		checkeq := func(op string, a, b interface{}) bool {
   382  			if err == nil && !reflect.DeepEqual(a, b) {
   383  				err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b)
   384  				return false
   385  			}
   386  			return true
   387  		}
   388  		// Check basic accessor methods.
   389  		checkeq("Exist", state.Exist(addr), checkstate.Exist(addr))
   390  		checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr))
   391  		checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
   392  		checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
   393  		checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
   394  		checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr))
   395  		checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
   396  		// Check storage.
   397  		if obj := state.getStateObject(addr); obj != nil {
   398  			state.ForEachStorage(addr, func(key, value common.Hash) bool {
   399  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   400  			})
   401  			checkstate.ForEachStorage(addr, func(key, value common.Hash) bool {
   402  				return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
   403  			})
   404  		}
   405  		if err != nil {
   406  			return err
   407  		}
   408  	}
   409  
   410  	if state.GetRefund() != checkstate.GetRefund() {
   411  		return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
   412  			state.GetRefund(), checkstate.GetRefund())
   413  	}
   414  	if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) {
   415  		return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v",
   416  			state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{}))
   417  	}
   418  	return nil
   419  }
   420  
   421  func (s *StateSuite) TestTouchDelete(c *check.C) {
   422  	s.state.GetOrNewStateObject(common.Address{})
   423  	root, _ := s.state.Commit(false)
   424  	s.state.Reset(root)
   425  
   426  	snapshot := s.state.Snapshot()
   427  	s.state.AddBalance(common.Address{}, new(big.Int))
   428  
   429  	if len(s.state.journal.dirties) != 1 {
   430  		c.Fatal("expected one dirty state object")
   431  	}
   432  	s.state.RevertToSnapshot(snapshot)
   433  	if len(s.state.journal.dirties) != 0 {
   434  		c.Fatal("expected no dirty state object")
   435  	}
   436  }
   437  
   438  // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
   439  // See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512
   440  func TestCopyOfCopy(t *testing.T) {
   441  	sdb, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   442  	addr := common.HexToAddress("aaaa")
   443  	sdb.SetBalance(addr, big.NewInt(42))
   444  
   445  	if got := sdb.Copy().GetBalance(addr).Uint64(); got != 42 {
   446  		t.Fatalf("1st copy fail, expected 42, got %v", got)
   447  	}
   448  	if got := sdb.Copy().Copy().GetBalance(addr).Uint64(); got != 42 {
   449  		t.Fatalf("2nd copy fail, expected 42, got %v", got)
   450  	}
   451  }
   452  
   453  // TestDeleteCreateRevert tests a weird state transition corner case that we hit
   454  // while changing the internals of statedb. The workflow is that a contract is
   455  // self destructed, then in a followup transaction (but same block) it's created
   456  // again and the transaction reverted.
   457  //
   458  // The original statedb implementation flushed dirty objects to the tries after
   459  // each transaction, so this works ok. The rework accumulated writes in memory
   460  // first, but the journal wiped the entire state object on create-revert.
   461  func TestDeleteCreateRevert(t *testing.T) {
   462  	// Create an initial state with a single contract
   463  	state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
   464  
   465  	addr := toAddr([]byte("so"))
   466  	state.SetBalance(addr, big.NewInt(1))
   467  
   468  	root, _ := state.Commit(false)
   469  	state.Reset(root)
   470  
   471  	// Simulate self-destructing in one transaction, then create-reverting in another
   472  	state.Suicide(addr)
   473  	state.Finalise(true)
   474  
   475  	id := state.Snapshot()
   476  	state.SetBalance(addr, big.NewInt(2))
   477  	state.RevertToSnapshot(id)
   478  
   479  	// Commit the entire state and make sure we don't crash and have the correct state
   480  	root, _ = state.Commit(true)
   481  	state.Reset(root)
   482  
   483  	if state.getStateObject(addr) != nil {
   484  		t.Fatalf("self-destructed contract came alive")
   485  	}
   486  }