github.com/halybang/go-ethereum@v1.0.5-0.20180325041310-3b262bc1367c/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/wanchain/go-wanchain/common"
    34  	"github.com/wanchain/go-wanchain/core/types"
    35  	"github.com/wanchain/go-wanchain/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  		if i%4 == 0 {
    57  			hash := common.BytesToHash([]byte{i, i, i, i, i, i, i})
    58  			byteArray := append(hash[0:], hash[0:]...)
    59  			state.SetStateByteArray(addr, common.BytesToHash([]byte{i, i, i, i, i, i}), byteArray)
    60  		}
    61  		state.IntermediateRoot(false)
    62  	}
    63  	// Ensure that no data was leaked into the database
    64  	for _, key := range db.Keys() {
    65  		value, _ := db.Get(key)
    66  		t.Errorf("State leaked into database: %x -> %x", key, value)
    67  	}
    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, _ := ethdb.NewMemDatabase()
    75  	finalDb, _ := ethdb.NewMemDatabase()
    76  	transState, _ := New(common.Hash{}, NewDatabase(transDb))
    77  	finalState, _ := New(common.Hash{}, NewDatabase(finalDb))
    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  		if i%4 == 0 {
    90  			hash := common.BytesToHash([]byte{i, i, i, i, i, i, i})
    91  			byteArray := append(hash[0:], hash[0:]...)
    92  			state.SetStateByteArray(addr, common.BytesToHash([]byte{i, i, i, i, i, i}), byteArray)
    93  		}
    94  	}
    95  
    96  	// Modify the transient state.
    97  	for i := byte(0); i < 255; i++ {
    98  		modify(transState, common.Address{byte(i)}, i, 0)
    99  	}
   100  	// Write modifications to trie.
   101  	transState.IntermediateRoot(false)
   102  
   103  	// Overwrite all the data with new values in the transient database.
   104  	for i := byte(0); i < 255; i++ {
   105  		modify(transState, common.Address{byte(i)}, i, 99)
   106  		modify(finalState, common.Address{byte(i)}, i, 99)
   107  	}
   108  
   109  	// Commit and cross check the databases.
   110  	if _, err := transState.CommitTo(transDb, false); err != nil {
   111  		t.Fatalf("failed to commit transition state: %v", err)
   112  	}
   113  	if _, err := finalState.CommitTo(finalDb, false); err != nil {
   114  		t.Fatalf("failed to commit final state: %v", err)
   115  	}
   116  	for _, key := range finalDb.Keys() {
   117  		if _, err := transDb.Get(key); err != nil {
   118  			val, _ := finalDb.Get(key)
   119  			t.Errorf("entry missing from the transition database: %x -> %x", key, val)
   120  		}
   121  	}
   122  	for _, key := range transDb.Keys() {
   123  		if _, err := finalDb.Get(key); err != nil {
   124  			val, _ := transDb.Get(key)
   125  			t.Errorf("extra entry in the transition database: %x -> %x", key, val)
   126  		}
   127  	}
   128  }
   129  
   130  func TestSnapshotRandom(t *testing.T) {
   131  	config := &quick.Config{MaxCount: 1000}
   132  	err := quick.Check((*snapshotTest).run, config)
   133  	if cerr, ok := err.(*quick.CheckError); ok {
   134  		test := cerr.In[0].(*snapshotTest)
   135  		t.Errorf("%v:\n%s", test.err, test)
   136  	} else if err != nil {
   137  		t.Error(err)
   138  	}
   139  }
   140  
   141  // A snapshotTest checks that reverting StateDB snapshots properly undoes all changes
   142  // captured by the snapshot. Instances of this test with pseudorandom content are created
   143  // by Generate.
   144  //
   145  // The test works as follows:
   146  //
   147  // A new state is created and all actions are applied to it. Several snapshots are taken
   148  // in between actions. The test then reverts each snapshot. For each snapshot the actions
   149  // leading up to it are replayed on a fresh, empty state. The behaviour of all public
   150  // accessor methods on the reverted state must match the return value of the equivalent
   151  // methods on the replayed state.
   152  type snapshotTest struct {
   153  	addrs     []common.Address // all account addresses
   154  	actions   []testAction     // modifications to the state
   155  	snapshots []int            // actions indexes at which snapshot is taken
   156  	err       error            // failure details are reported through this field
   157  }
   158  
   159  type testAction struct {
   160  	name   string
   161  	fn     func(testAction, *StateDB)
   162  	args   []int64
   163  	noAddr bool
   164  }
   165  
   166  // newTestAction creates a random action that changes state.
   167  func newTestAction(addr common.Address, r *rand.Rand) testAction {
   168  	actions := []testAction{
   169  		{
   170  			name: "SetBalance",
   171  			fn: func(a testAction, s *StateDB) {
   172  				s.SetBalance(addr, big.NewInt(a.args[0]))
   173  			},
   174  			args: make([]int64, 1),
   175  		},
   176  		{
   177  			name: "AddBalance",
   178  			fn: func(a testAction, s *StateDB) {
   179  				s.AddBalance(addr, big.NewInt(a.args[0]))
   180  			},
   181  			args: make([]int64, 1),
   182  		},
   183  		{
   184  			name: "SetNonce",
   185  			fn: func(a testAction, s *StateDB) {
   186  				s.SetNonce(addr, uint64(a.args[0]))
   187  			},
   188  			args: make([]int64, 1),
   189  		},
   190  		{
   191  			name: "SetState",
   192  			fn: func(a testAction, s *StateDB) {
   193  				var key, val common.Hash
   194  				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
   195  				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))
   196  				s.SetState(addr, key, val)
   197  			},
   198  			args: make([]int64, 2),
   199  		},
   200  		{
   201  			name: "SetStateByteArray",
   202  			fn: func(a testAction, s *StateDB) {
   203  				var key common.Hash
   204  				var val [common.HashLength * 2]byte
   205  				binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
   206  				binary.BigEndian.PutUint16(val[:], uint16(a.args[1]))
   207  				s.SetStateByteArray(addr, key, val[:])
   208  			},
   209  			args: make([]int64, 2),
   210  		},
   211  		{
   212  			name: "SetCode",
   213  			fn: func(a testAction, s *StateDB) {
   214  				code := make([]byte, 16)
   215  				binary.BigEndian.PutUint64(code, uint64(a.args[0]))
   216  				binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
   217  				s.SetCode(addr, code)
   218  			},
   219  			args: make([]int64, 2),
   220  		},
   221  		{
   222  			name: "CreateAccount",
   223  			fn: func(a testAction, s *StateDB) {
   224  				s.CreateAccount(addr)
   225  			},
   226  		},
   227  		{
   228  			name: "Suicide",
   229  			fn: func(a testAction, s *StateDB) {
   230  				s.Suicide(addr)
   231  			},
   232  		},
   233  		{
   234  			name: "AddRefund",
   235  			fn: func(a testAction, s *StateDB) {
   236  				s.AddRefund(big.NewInt(a.args[0]))
   237  			},
   238  			args:   make([]int64, 1),
   239  			noAddr: true,
   240  		},
   241  		{
   242  			name: "AddLog",
   243  			fn: func(a testAction, s *StateDB) {
   244  				data := make([]byte, 2)
   245  				binary.BigEndian.PutUint16(data, uint16(a.args[0]))
   246  				s.AddLog(&types.Log{Address: addr, Data: data})
   247  			},
   248  			args: make([]int64, 1),
   249  		},
   250  	}
   251  	action := actions[r.Intn(len(actions))]
   252  	var nameargs []string
   253  	if !action.noAddr {
   254  		nameargs = append(nameargs, addr.Hex())
   255  	}
   256  	for _, i := range action.args {
   257  		action.args[i] = rand.Int63n(100)
   258  		nameargs = append(nameargs, fmt.Sprint(action.args[i]))
   259  	}
   260  	action.name += strings.Join(nameargs, ", ")
   261  	return action
   262  }
   263  
   264  // Generate returns a new snapshot test of the given size. All randomness is
   265  // derived from r.
   266  func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value {
   267  	// Generate random actions.
   268  	addrs := make([]common.Address, 50)
   269  	for i := range addrs {
   270  		addrs[i][0] = byte(i)
   271  	}
   272  	actions := make([]testAction, size)
   273  	for i := range actions {
   274  		addr := addrs[r.Intn(len(addrs))]
   275  		actions[i] = newTestAction(addr, r)
   276  	}
   277  	// Generate snapshot indexes.
   278  	nsnapshots := int(math.Sqrt(float64(size)))
   279  	if size > 0 && nsnapshots == 0 {
   280  		nsnapshots = 1
   281  	}
   282  	snapshots := make([]int, nsnapshots)
   283  	snaplen := len(actions) / nsnapshots
   284  	for i := range snapshots {
   285  		// Try to place the snapshots some number of actions apart from each other.
   286  		snapshots[i] = (i * snaplen) + r.Intn(snaplen)
   287  	}
   288  	return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil})
   289  }
   290  
   291  func (test *snapshotTest) String() string {
   292  	out := new(bytes.Buffer)
   293  	sindex := 0
   294  	for i, action := range test.actions {
   295  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   296  			fmt.Fprintf(out, "---- snapshot %d ----\n", sindex)
   297  			sindex++
   298  		}
   299  		fmt.Fprintf(out, "%4d: %s\n", i, action.name)
   300  	}
   301  	return out.String()
   302  }
   303  
   304  func (test *snapshotTest) run() bool {
   305  	// Run all actions and create snapshots.
   306  	var (
   307  		db, _        = ethdb.NewMemDatabase()
   308  		state, _     = New(common.Hash{}, NewDatabase(db))
   309  		snapshotRevs = make([]int, len(test.snapshots))
   310  		sindex       = 0
   311  	)
   312  	for i, action := range test.actions {
   313  		if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
   314  			snapshotRevs[sindex] = state.Snapshot()
   315  			sindex++
   316  		}
   317  		action.fn(action, state)
   318  	}
   319  
   320  	// Revert all snapshots in reverse order. Each revert must yield a state
   321  	// that is equivalent to fresh state with all actions up the snapshot applied.
   322  	for sindex--; sindex >= 0; sindex-- {
   323  		checkstate, _ := New(common.Hash{}, NewDatabase(db))
   324  		for _, action := range test.actions[:test.snapshots[sindex]] {
   325  			action.fn(action, checkstate)
   326  		}
   327  		state.RevertToSnapshot(snapshotRevs[sindex])
   328  		if err := test.checkEqual(state, checkstate); err != nil {
   329  			test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err)
   330  			return false
   331  		}
   332  	}
   333  	return true
   334  }
   335  
   336  // checkEqual checks that methods of state and checkstate return the same values.
   337  func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
   338  	for _, addr := range test.addrs {
   339  		var err error
   340  		checkeq := func(op string, a, b interface{}) bool {
   341  			if err == nil && !reflect.DeepEqual(a, b) {
   342  				err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b)
   343  				return false
   344  			}
   345  			return true
   346  		}
   347  		// Check basic accessor methods.
   348  		checkeq("Exist", state.Exist(addr), checkstate.Exist(addr))
   349  		checkeq("HasSuicided", state.HasSuicided(addr), checkstate.HasSuicided(addr))
   350  		checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr))
   351  		checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr))
   352  		checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr))
   353  		checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr))
   354  		checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
   355  		// Check storage.
   356  		if obj := state.getStateObject(addr); obj != nil {
   357  			state.ForEachStorage(addr, func(key, val common.Hash) bool {
   358  				return checkeq("GetState("+key.Hex()+")", val, checkstate.GetState(addr, key))
   359  			})
   360  			checkstate.ForEachStorage(addr, func(key, checkval common.Hash) bool {
   361  				return checkeq("GetState("+key.Hex()+")", state.GetState(addr, key), checkval)
   362  			})
   363  		}
   364  		if err != nil {
   365  			return err
   366  		}
   367  	}
   368  
   369  	if state.GetRefund().Cmp(checkstate.GetRefund()) != 0 {
   370  		return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
   371  			state.GetRefund(), checkstate.GetRefund())
   372  	}
   373  	if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) {
   374  		return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v",
   375  			state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{}))
   376  	}
   377  	return nil
   378  }
   379  
   380  func (s *StateSuite) TestTouchDelete(c *check.C) {
   381  	s.state.GetOrNewStateObject(common.Address{})
   382  	root, _ := s.state.CommitTo(s.db, false)
   383  	s.state.Reset(root)
   384  
   385  	snapshot := s.state.Snapshot()
   386  	s.state.AddBalance(common.Address{}, new(big.Int))
   387  	if len(s.state.stateObjectsDirty) != 1 {
   388  		c.Fatal("expected one dirty state object")
   389  	}
   390  
   391  	s.state.RevertToSnapshot(snapshot)
   392  	if len(s.state.stateObjectsDirty) != 0 {
   393  		c.Fatal("expected no dirty state object")
   394  	}
   395  }