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