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