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