github.com/core-coin/go-core/v2@v2.1.9/trie/trie_test.go (about)

     1  // Copyright 2014 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package trie
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"errors"
    23  	"fmt"
    24  	"hash"
    25  	"io/ioutil"
    26  	"math/big"
    27  	"math/rand"
    28  	"os"
    29  	"reflect"
    30  	"testing"
    31  	"testing/quick"
    32  
    33  	"github.com/davecgh/go-spew/spew"
    34  	"golang.org/x/crypto/sha3"
    35  
    36  	"github.com/core-coin/go-core/v2/xcbdb"
    37  	"github.com/core-coin/go-core/v2/xcbdb/leveldb"
    38  	"github.com/core-coin/go-core/v2/xcbdb/memorydb"
    39  
    40  	"github.com/core-coin/go-core/v2/common"
    41  	"github.com/core-coin/go-core/v2/crypto"
    42  	"github.com/core-coin/go-core/v2/rlp"
    43  )
    44  
    45  func init() {
    46  	spew.Config.Indent = "    "
    47  	spew.Config.DisableMethods = false
    48  }
    49  
    50  // Used for testing
    51  func newEmpty() *Trie {
    52  	trie, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
    53  	return trie
    54  }
    55  
    56  func TestEmptyTrie(t *testing.T) {
    57  	var trie Trie
    58  	res := trie.Hash()
    59  	exp := emptyRoot
    60  	if res != exp {
    61  		t.Errorf("expected %x got %x", exp, res)
    62  	}
    63  }
    64  
    65  func TestNull(t *testing.T) {
    66  	var trie Trie
    67  	key := make([]byte, 32)
    68  	value := []byte("test")
    69  	trie.Update(key, value)
    70  	if !bytes.Equal(trie.Get(key), value) {
    71  		t.Fatal("wrong value")
    72  	}
    73  }
    74  
    75  func TestMissingRoot(t *testing.T) {
    76  	trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), NewDatabase(memorydb.New()))
    77  	if trie != nil {
    78  		t.Error("New returned non-nil trie for invalid root")
    79  	}
    80  	if _, ok := err.(*MissingNodeError); !ok {
    81  		t.Errorf("New returned wrong error: %v", err)
    82  	}
    83  }
    84  
    85  func TestMissingNodeDisk(t *testing.T)    { testMissingNode(t, false) }
    86  func TestMissingNodeMemonly(t *testing.T) { testMissingNode(t, true) }
    87  
    88  func testMissingNode(t *testing.T, memonly bool) {
    89  	diskdb := memorydb.New()
    90  	triedb := NewDatabase(diskdb)
    91  
    92  	trie, _ := New(common.Hash{}, triedb)
    93  	updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
    94  	updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
    95  	root, _ := trie.Commit(nil)
    96  	if !memonly {
    97  		triedb.Commit(root, true, nil)
    98  	}
    99  
   100  	trie, _ = New(root, triedb)
   101  	_, err := trie.TryGet([]byte("120000"))
   102  	if err != nil {
   103  		t.Errorf("Unexpected error: %v", err)
   104  	}
   105  	trie, _ = New(root, triedb)
   106  	_, err = trie.TryGet([]byte("120099"))
   107  	if err != nil {
   108  		t.Errorf("Unexpected error: %v", err)
   109  	}
   110  	trie, _ = New(root, triedb)
   111  	_, err = trie.TryGet([]byte("123456"))
   112  	if err != nil {
   113  		t.Errorf("Unexpected error: %v", err)
   114  	}
   115  	trie, _ = New(root, triedb)
   116  	err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv"))
   117  	if err != nil {
   118  		t.Errorf("Unexpected error: %v", err)
   119  	}
   120  	trie, _ = New(root, triedb)
   121  	err = trie.TryDelete([]byte("123456"))
   122  	if err != nil {
   123  		t.Errorf("Unexpected error: %v", err)
   124  	}
   125  
   126  	hash := common.HexToHash("0x441104088924b2e5c7cad1f84c1489cef750baefc107201334de5aa75f05541a")
   127  	if memonly {
   128  		delete(triedb.dirties, hash)
   129  	} else {
   130  		diskdb.Delete(hash[:])
   131  	}
   132  
   133  	trie, _ = New(root, triedb)
   134  	_, err = trie.TryGet([]byte("120000"))
   135  	if _, ok := err.(*MissingNodeError); !ok {
   136  		t.Errorf("Wrong error: %v", err)
   137  	}
   138  	trie, _ = New(root, triedb)
   139  	_, err = trie.TryGet([]byte("120099"))
   140  	if _, ok := err.(*MissingNodeError); !ok {
   141  		t.Errorf("Wrong error: %v", err)
   142  	}
   143  	trie, _ = New(root, triedb)
   144  	_, err = trie.TryGet([]byte("123456"))
   145  	if err != nil {
   146  		t.Errorf("Unexpected error: %v", err)
   147  	}
   148  	trie, _ = New(root, triedb)
   149  	err = trie.TryUpdate([]byte("120099"), []byte("zxcv"))
   150  	if _, ok := err.(*MissingNodeError); !ok {
   151  		t.Errorf("Wrong error: %v", err)
   152  	}
   153  	trie, _ = New(root, triedb)
   154  	err = trie.TryDelete([]byte("123456"))
   155  	if _, ok := err.(*MissingNodeError); !ok {
   156  		t.Errorf("Wrong error: %v", err)
   157  	}
   158  }
   159  
   160  func TestInsert(t *testing.T) {
   161  	trie := newEmpty()
   162  
   163  	updateString(trie, "doe", "reindeer")
   164  	updateString(trie, "dog", "puppy")
   165  	updateString(trie, "dogglesworth", "cat")
   166  
   167  	exp := common.HexToHash("c33dc4124235214a96518fc8bfdef30a6c1462a08e423c29f7b08513829c551f")
   168  	root := trie.Hash()
   169  	if root != exp {
   170  		t.Errorf("case 1: exp %x got %x", exp, root)
   171  	}
   172  
   173  	trie = newEmpty()
   174  	updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
   175  
   176  	exp = common.HexToHash("84ec0052caf94dc2df953a1a77ed86c20b401cff8e9b85c1c68511bc3d9259a6")
   177  	root, err := trie.Commit(nil)
   178  	if err != nil {
   179  		t.Fatalf("commit error: %v", err)
   180  	}
   181  	if root != exp {
   182  		t.Errorf("case 2: exp %x got %x", exp, root)
   183  	}
   184  }
   185  
   186  func TestGet(t *testing.T) {
   187  	trie := newEmpty()
   188  	updateString(trie, "doe", "reindeer")
   189  	updateString(trie, "dog", "puppy")
   190  	updateString(trie, "dogglesworth", "cat")
   191  
   192  	for i := 0; i < 2; i++ {
   193  		res := getString(trie, "dog")
   194  		if !bytes.Equal(res, []byte("puppy")) {
   195  			t.Errorf("expected puppy got %x", res)
   196  		}
   197  
   198  		unknown := getString(trie, "unknown")
   199  		if unknown != nil {
   200  			t.Errorf("expected nil got %x", unknown)
   201  		}
   202  
   203  		if i == 1 {
   204  			return
   205  		}
   206  		trie.Commit(nil)
   207  	}
   208  }
   209  
   210  func TestDelete(t *testing.T) {
   211  	trie := newEmpty()
   212  	vals := []struct{ k, v string }{
   213  		{"do", "verb"},
   214  		{"core", "wookiedoo"},
   215  		{"horse", "stallion"},
   216  		{"shaman", "horse"},
   217  		{"doge", "coin"},
   218  		{"core", ""},
   219  		{"dog", "puppy"},
   220  		{"shaman", ""},
   221  	}
   222  	for _, val := range vals {
   223  		if val.v != "" {
   224  			updateString(trie, val.k, val.v)
   225  		} else {
   226  			deleteString(trie, val.k)
   227  		}
   228  	}
   229  
   230  	hash := trie.Hash()
   231  	exp := common.HexToHash("422a17a872ce2e062b0998b85bee742dfa98f429c49bb22b81495d23fd3ce841")
   232  	if hash != exp {
   233  		t.Errorf("expected %x got %x", exp, hash)
   234  	}
   235  }
   236  
   237  func TestEmptyValues(t *testing.T) {
   238  	trie := newEmpty()
   239  
   240  	vals := []struct{ k, v string }{
   241  		{"do", "verb"},
   242  		{"core", "wookiedoo"},
   243  		{"horse", "stallion"},
   244  		{"shaman", "horse"},
   245  		{"doge", "coin"},
   246  		{"core", ""},
   247  		{"dog", "puppy"},
   248  		{"shaman", ""},
   249  	}
   250  	for _, val := range vals {
   251  		updateString(trie, val.k, val.v)
   252  	}
   253  
   254  	hash := trie.Hash()
   255  	exp := common.HexToHash("422a17a872ce2e062b0998b85bee742dfa98f429c49bb22b81495d23fd3ce841")
   256  	if hash != exp {
   257  		t.Errorf("expected %x got %x", exp, hash)
   258  	}
   259  }
   260  
   261  func TestReplication(t *testing.T) {
   262  	trie := newEmpty()
   263  	vals := []struct{ k, v string }{
   264  		{"do", "verb"},
   265  		{"core", "wookiedoo"},
   266  		{"horse", "stallion"},
   267  		{"shaman", "horse"},
   268  		{"doge", "coin"},
   269  		{"dog", "puppy"},
   270  		{"somethingveryoddindeedthis is", "myothernodedata"},
   271  	}
   272  	for _, val := range vals {
   273  		updateString(trie, val.k, val.v)
   274  	}
   275  	exp, err := trie.Commit(nil)
   276  	if err != nil {
   277  		t.Fatalf("commit error: %v", err)
   278  	}
   279  
   280  	// create a new trie on top of the database and check that lookups work.
   281  	trie2, err := New(exp, trie.db)
   282  	if err != nil {
   283  		t.Fatalf("can't recreate trie at %x: %v", exp, err)
   284  	}
   285  	for _, kv := range vals {
   286  		if string(getString(trie2, kv.k)) != kv.v {
   287  			t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
   288  		}
   289  	}
   290  	hash, err := trie2.Commit(nil)
   291  	if err != nil {
   292  		t.Fatalf("commit error: %v", err)
   293  	}
   294  	if hash != exp {
   295  		t.Errorf("root failure. expected %x got %x", exp, hash)
   296  	}
   297  
   298  	// perform some insertions on the new trie.
   299  	vals2 := []struct{ k, v string }{
   300  		{"do", "verb"},
   301  		{"core", "wookiedoo"},
   302  		{"horse", "stallion"},
   303  		// {"shaman", "horse"},
   304  		// {"doge", "coin"},
   305  		// {"core", ""},
   306  		// {"dog", "puppy"},
   307  		// {"somethingveryoddindeedthis is", "myothernodedata"},
   308  		// {"shaman", ""},
   309  	}
   310  	for _, val := range vals2 {
   311  		updateString(trie2, val.k, val.v)
   312  	}
   313  	if hash := trie2.Hash(); hash != exp {
   314  		t.Errorf("root failure. expected %x got %x", exp, hash)
   315  	}
   316  }
   317  
   318  func TestLargeValue(t *testing.T) {
   319  	trie := newEmpty()
   320  	trie.Update([]byte("key1"), []byte{99, 99, 99, 99})
   321  	trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32))
   322  	trie.Hash()
   323  }
   324  
   325  // TestRandomCases tests som cases that were found via random fuzzing
   326  func TestRandomCases(t *testing.T) {
   327  	var rt []randTestStep = []randTestStep{
   328  		{op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 0
   329  		{op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 1
   330  		{op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000002")},           // step 2
   331  		{op: 2, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("")},                         // step 3
   332  		{op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 4
   333  		{op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 5
   334  		{op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 6
   335  		{op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 7
   336  		{op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000008")},         // step 8
   337  		{op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000009")},           // step 9
   338  		{op: 2, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")},                                                                                               // step 10
   339  		{op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 11
   340  		{op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 12
   341  		{op: 0, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("000000000000000d")},                                                                               // step 13
   342  		{op: 6, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 14
   343  		{op: 1, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("")},                         // step 15
   344  		{op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 16
   345  		{op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000011")},         // step 17
   346  		{op: 5, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 18
   347  		{op: 3, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 19
   348  		{op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000014")},           // step 20
   349  		{op: 0, key: common.Hex2Bytes("d51b182b95d677e5f1c82508c0228de96b73092d78ce78b2230cd948674f66fd1483bd"), value: common.Hex2Bytes("0000000000000015")},           // step 21
   350  		{op: 0, key: common.Hex2Bytes("c2a38512b83107d665c65235b0250002882ac2022eb00711552354832c5f1d030d0e408e"), value: common.Hex2Bytes("0000000000000016")},         // step 22
   351  		{op: 5, key: common.Hex2Bytes(""), value: common.Hex2Bytes("")},                                                                                                 // step 23
   352  		{op: 1, key: common.Hex2Bytes("980c393656413a15c8da01978ed9f89feb80b502f58f2d640e3a2f5f7a99a7018f1b573befd92053ac6f78fca4a87268"), value: common.Hex2Bytes("")}, // step 24
   353  		{op: 1, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")},                                                                                               // step 25
   354  	}
   355  	runRandTest(rt)
   356  
   357  }
   358  
   359  // randTest performs random trie operations.
   360  // Instances of this test are created by Generate.
   361  type randTest []randTestStep
   362  
   363  type randTestStep struct {
   364  	op    int
   365  	key   []byte // for opUpdate, opDelete, opGet
   366  	value []byte // for opUpdate
   367  	err   error  // for debugging
   368  }
   369  
   370  const (
   371  	opUpdate = iota
   372  	opDelete
   373  	opGet
   374  	opCommit
   375  	opHash
   376  	opReset
   377  	opItercheckhash
   378  	opMax // boundary value, not an actual op
   379  )
   380  
   381  func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
   382  	var allKeys [][]byte
   383  	genKey := func() []byte {
   384  		if len(allKeys) < 2 || r.Intn(100) < 10 {
   385  			// new key
   386  			key := make([]byte, r.Intn(50))
   387  			r.Read(key)
   388  			allKeys = append(allKeys, key)
   389  			return key
   390  		}
   391  		// use existing key
   392  		return allKeys[r.Intn(len(allKeys))]
   393  	}
   394  
   395  	var steps randTest
   396  	for i := 0; i < size; i++ {
   397  		step := randTestStep{op: r.Intn(opMax)}
   398  		switch step.op {
   399  		case opUpdate:
   400  			step.key = genKey()
   401  			step.value = make([]byte, 8)
   402  			binary.BigEndian.PutUint64(step.value, uint64(i))
   403  		case opGet, opDelete:
   404  			step.key = genKey()
   405  		}
   406  		steps = append(steps, step)
   407  	}
   408  	return reflect.ValueOf(steps)
   409  }
   410  
   411  func runRandTest(rt randTest) bool {
   412  	triedb := NewDatabase(memorydb.New())
   413  
   414  	tr, _ := New(common.Hash{}, triedb)
   415  	values := make(map[string]string) // tracks content of the trie
   416  
   417  	for i, step := range rt {
   418  		fmt.Printf("{op: %d, key: common.Hex2Bytes(\"%x\"), value: common.Hex2Bytes(\"%x\")}, // step %d\n",
   419  			step.op, step.key, step.value, i)
   420  		switch step.op {
   421  		case opUpdate:
   422  			tr.Update(step.key, step.value)
   423  			values[string(step.key)] = string(step.value)
   424  		case opDelete:
   425  			tr.Delete(step.key)
   426  			delete(values, string(step.key))
   427  		case opGet:
   428  			v := tr.Get(step.key)
   429  			want := values[string(step.key)]
   430  			if string(v) != want {
   431  				rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
   432  			}
   433  		case opCommit:
   434  			_, rt[i].err = tr.Commit(nil)
   435  		case opHash:
   436  			tr.Hash()
   437  		case opReset:
   438  			hash, err := tr.Commit(nil)
   439  			if err != nil {
   440  				rt[i].err = err
   441  				return false
   442  			}
   443  			newtr, err := New(hash, triedb)
   444  			if err != nil {
   445  				rt[i].err = err
   446  				return false
   447  			}
   448  			tr = newtr
   449  		case opItercheckhash:
   450  			checktr, _ := New(common.Hash{}, triedb)
   451  			it := NewIterator(tr.NodeIterator(nil))
   452  			for it.Next() {
   453  				checktr.Update(it.Key, it.Value)
   454  			}
   455  			if tr.Hash() != checktr.Hash() {
   456  				rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash")
   457  			}
   458  		}
   459  		// Abort the test on error.
   460  		if rt[i].err != nil {
   461  			return false
   462  		}
   463  	}
   464  	return true
   465  }
   466  
   467  func TestRandom(t *testing.T) {
   468  	if err := quick.Check(runRandTest, nil); err != nil {
   469  		if cerr, ok := err.(*quick.CheckError); ok {
   470  			t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
   471  		}
   472  		t.Fatal(err)
   473  	}
   474  }
   475  
   476  func BenchmarkGet(b *testing.B)      { benchGet(b, false) }
   477  func BenchmarkGetDB(b *testing.B)    { benchGet(b, true) }
   478  func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) }
   479  func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
   480  
   481  const benchElemCount = 20000
   482  
   483  func benchGet(b *testing.B, commit bool) {
   484  	trie := new(Trie)
   485  	if commit {
   486  		_, tmpdb := tempDB()
   487  		trie, _ = New(common.Hash{}, tmpdb)
   488  	}
   489  	k := make([]byte, 32)
   490  	for i := 0; i < benchElemCount; i++ {
   491  		binary.LittleEndian.PutUint64(k, uint64(i))
   492  		trie.Update(k, k)
   493  	}
   494  	binary.LittleEndian.PutUint64(k, benchElemCount/2)
   495  	if commit {
   496  		trie.Commit(nil)
   497  	}
   498  
   499  	b.ResetTimer()
   500  	for i := 0; i < b.N; i++ {
   501  		trie.Get(k)
   502  	}
   503  	b.StopTimer()
   504  
   505  	if commit {
   506  		ldb := trie.db.diskdb.(*leveldb.Database)
   507  		ldb.Close()
   508  		os.RemoveAll(ldb.Path())
   509  	}
   510  }
   511  
   512  func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
   513  	trie := newEmpty()
   514  	k := make([]byte, 32)
   515  	b.ReportAllocs()
   516  	for i := 0; i < b.N; i++ {
   517  		e.PutUint64(k, uint64(i))
   518  		trie.Update(k, k)
   519  	}
   520  	return trie
   521  }
   522  
   523  // Benchmarks the trie hashing. Since the trie caches the result of any operation,
   524  // we cannot use b.N as the number of hashing rouns, since all rounds apart from
   525  // the first one will be NOOP. As such, we'll use b.N as the number of account to
   526  // insert into the trie before measuring the hashing.
   527  // BenchmarkHash-6   	  288680	      4561 ns/op	     682 B/op	       9 allocs/op
   528  // BenchmarkHash-6   	  275095	      4800 ns/op	     685 B/op	       9 allocs/op
   529  // pure hasher:
   530  // BenchmarkHash-6   	  319362	      4230 ns/op	     675 B/op	       9 allocs/op
   531  // BenchmarkHash-6   	  257460	      4674 ns/op	     689 B/op	       9 allocs/op
   532  // With hashing in-between and pure hasher:
   533  // BenchmarkHash-6   	  225417	      7150 ns/op	     982 B/op	      12 allocs/op
   534  // BenchmarkHash-6   	  220378	      6197 ns/op	     983 B/op	      12 allocs/op
   535  // same with old hasher
   536  // BenchmarkHash-6   	  229758	      6437 ns/op	     981 B/op	      12 allocs/op
   537  // BenchmarkHash-6   	  212610	      7137 ns/op	     986 B/op	      12 allocs/op
   538  func BenchmarkHash(b *testing.B) {
   539  	// Create a realistic account trie to hash. We're first adding and hashing N
   540  	// entries, then adding N more.
   541  	addresses, accounts := makeAccounts(2 * b.N)
   542  	// Insert the accounts into the trie and hash it
   543  	trie := newEmpty()
   544  	i := 0
   545  	for ; i < len(addresses)/2; i++ {
   546  		trie.Update(crypto.SHA3(addresses[i][:]), accounts[i])
   547  	}
   548  	trie.Hash()
   549  	for ; i < len(addresses); i++ {
   550  		trie.Update(crypto.SHA3(addresses[i][:]), accounts[i])
   551  	}
   552  	b.ResetTimer()
   553  	b.ReportAllocs()
   554  	//trie.hashRoot(nil, nil)
   555  	trie.Hash()
   556  }
   557  
   558  type account struct {
   559  	Nonce   uint64
   560  	Balance *big.Int
   561  	Root    common.Hash
   562  	Code    []byte
   563  }
   564  
   565  // Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation,
   566  // we cannot use b.N as the number of hashing rouns, since all rounds apart from
   567  // the first one will be NOOP. As such, we'll use b.N as the number of account to
   568  // insert into the trie before measuring the hashing.
   569  func BenchmarkCommitAfterHash(b *testing.B) {
   570  	b.Run("no-onleaf", func(b *testing.B) {
   571  		benchmarkCommitAfterHash(b, nil)
   572  	})
   573  	var a account
   574  	onleaf := func(path []byte, leaf []byte, parent common.Hash) error {
   575  		rlp.DecodeBytes(leaf, &a)
   576  		return nil
   577  	}
   578  	b.Run("with-onleaf", func(b *testing.B) {
   579  		benchmarkCommitAfterHash(b, onleaf)
   580  	})
   581  }
   582  
   583  func benchmarkCommitAfterHash(b *testing.B, onleaf LeafCallback) {
   584  	// Make the random benchmark deterministic
   585  	addresses, accounts := makeAccounts(b.N)
   586  	trie := newEmpty()
   587  	for i := 0; i < len(addresses); i++ {
   588  		trie.Update(crypto.SHA3(addresses[i][:]), accounts[i])
   589  	}
   590  	// Insert the accounts into the trie and hash it
   591  	trie.Hash()
   592  	b.ResetTimer()
   593  	b.ReportAllocs()
   594  	trie.Commit(onleaf)
   595  }
   596  
   597  func TestTinyTrie(t *testing.T) {
   598  	// Create a realistic account trie to hash
   599  	_, accounts := makeAccounts(5)
   600  	trie := newEmpty()
   601  	trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3])
   602  	if exp, root := common.HexToHash("b98009397ee653ae93cbc4fecc9633b056a3f3edf787afab85e4e17788db0263"), trie.Hash(); exp != root {
   603  		t.Errorf("1: got %x, exp %x", root, exp)
   604  	}
   605  	trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001338"), accounts[4])
   606  	if exp, root := common.HexToHash("8c396b385e8d12e8719f98f05355bec192de8a6a26ac20da00fe017dc686ee53"), trie.Hash(); exp != root {
   607  		t.Errorf("2: got %x, exp %x", root, exp)
   608  	}
   609  	trie.Update(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001339"), accounts[4])
   610  	if exp, root := common.HexToHash("68138b3fd0ce4d8bda74a36cd136e1172e59956769bb8a5782b4ad904bac533c"), trie.Hash(); exp != root {
   611  		t.Errorf("3: got %x, exp %x", root, exp)
   612  	}
   613  	checktr, _ := New(common.Hash{}, trie.db)
   614  	it := NewIterator(trie.NodeIterator(nil))
   615  	for it.Next() {
   616  		checktr.Update(it.Key, it.Value)
   617  	}
   618  	if troot, itroot := trie.Hash(), checktr.Hash(); troot != itroot {
   619  		t.Fatalf("hash mismatch in opItercheckhash, trie: %x, check: %x", troot, itroot)
   620  	}
   621  }
   622  
   623  func TestCommitAfterHash(t *testing.T) {
   624  	// Create a realistic account trie to hash
   625  	addresses, accounts := makeAccounts(1000)
   626  	trie := newEmpty()
   627  	for i := 0; i < len(addresses); i++ {
   628  		trie.Update(crypto.SHA3(addresses[i][:]), accounts[i])
   629  	}
   630  	// Insert the accounts into the trie and hash it
   631  	trie.Hash()
   632  	trie.Commit(nil)
   633  	root := trie.Hash()
   634  	exp := common.HexToHash("281e4ca371ab2f3b9d6a0741bf9deea69a2af773ae172d8294e5492e8fa81499")
   635  	if exp != root {
   636  		t.Errorf("got %x, exp %x", root, exp)
   637  	}
   638  	root, _ = trie.Commit(nil)
   639  	if exp != root {
   640  		t.Errorf("got %x, exp %x", root, exp)
   641  	}
   642  }
   643  
   644  func makeAccounts(size int) (addresses [][22]byte, accounts [][]byte) {
   645  	// Make the random benchmark deterministic
   646  	random := rand.New(rand.NewSource(0))
   647  	// Create a realistic account trie to hash
   648  	addresses = make([][22]byte, size)
   649  	for i := 0; i < len(addresses); i++ {
   650  		for j := 0; j < len(addresses[i]); j++ {
   651  			addresses[i][j] = byte(random.Intn(256))
   652  		}
   653  		checksum := common.CalculateChecksum(addresses[i][1:], common.DefaultNetworkID.Bytes())
   654  		addresses[i][1] = checksum[0]
   655  		addresses[i][0] = common.DefaultNetworkID.Bytes()[0]
   656  	}
   657  	accounts = make([][]byte, len(addresses))
   658  	for i := 0; i < len(accounts); i++ {
   659  		var (
   660  			nonce = uint64(random.Int63())
   661  			root  = emptyRoot
   662  			code  = crypto.SHA3(nil)
   663  		)
   664  		// The big.Rand function is not deterministic with regards to 64 vs 32 bit systems,
   665  		// and will consume different amount of data from the rand source.
   666  		//balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
   667  		// Therefore, we instead just read via byte buffer
   668  		numBytes := random.Uint32() % 33 // [0, 32] bytes
   669  		balanceBytes := make([]byte, numBytes)
   670  		random.Read(balanceBytes)
   671  		balance := new(big.Int).SetBytes(balanceBytes)
   672  		data, _ := rlp.EncodeToBytes(&account{nonce, balance, root, code})
   673  		accounts[i] = data
   674  	}
   675  	return addresses, accounts
   676  }
   677  
   678  // spongeDb is a dummy db backend which accumulates writes in a sponge
   679  type spongeDb struct {
   680  	sponge  hash.Hash
   681  	id      string
   682  	journal []string
   683  }
   684  
   685  func (s *spongeDb) Has(key []byte) (bool, error)             { panic("implement me") }
   686  func (s *spongeDb) Get(key []byte) ([]byte, error)           { return nil, errors.New("no such elem") }
   687  func (s *spongeDb) Delete(key []byte) error                  { panic("implement me") }
   688  func (s *spongeDb) NewBatch() xcbdb.Batch                    { return &spongeBatch{s} }
   689  func (s *spongeDb) Stat(property string) (string, error)     { panic("implement me") }
   690  func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
   691  func (s *spongeDb) Close() error                             { return nil }
   692  func (s *spongeDb) Put(key []byte, value []byte) error {
   693  	valbrief := value
   694  	if len(valbrief) > 8 {
   695  		valbrief = valbrief[:8]
   696  	}
   697  	s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, key[:8], len(value), valbrief))
   698  	s.sponge.Write(key)
   699  	s.sponge.Write(value)
   700  	return nil
   701  }
   702  func (s *spongeDb) NewIterator(prefix []byte, start []byte) xcbdb.Iterator { panic("implement me") }
   703  
   704  // spongeBatch is a dummy batch which immediately writes to the underlying spongedb
   705  type spongeBatch struct {
   706  	db *spongeDb
   707  }
   708  
   709  func (b *spongeBatch) Put(key, value []byte) error {
   710  	b.db.Put(key, value)
   711  	return nil
   712  }
   713  func (b *spongeBatch) Delete(key []byte) error             { panic("implement me") }
   714  func (b *spongeBatch) ValueSize() int                      { return 100 }
   715  func (b *spongeBatch) Write() error                        { return nil }
   716  func (b *spongeBatch) Reset()                              {}
   717  func (b *spongeBatch) Replay(w xcbdb.KeyValueWriter) error { return nil }
   718  
   719  // TestCommitSequence tests that the trie.Commit operation writes the elements of the trie
   720  // in the expected order, and calls the callbacks in the expected order.
   721  // The test data was based on the 'master' code, and is basically random. It can be used
   722  // to check whether changes to the trie modifies the write order or data in any way.
   723  func TestCommitSequence(t *testing.T) {
   724  	for i, tc := range []struct {
   725  		count              int
   726  		expWriteSeqHash    []byte
   727  		expCallbackSeqHash []byte
   728  	}{
   729  		{20, common.FromHex("46423bd007c78e3483682810ef28b57548733055afdd3c3286181cf58a4e81dc"),
   730  			common.FromHex("feb27c258a451ad67fa76f1a0da6b2a870480ceeafb45865293c0eae5337a11a")},
   731  		{200, common.FromHex("698510e1addaa686563f5ee0fb8ee4d0f4fb3c5ed3fc79e357113671d16cf88b"),
   732  			common.FromHex("30aba6fb3f727eb2ef942c18e264e436b775a4892a8701b7d8a2e357930b99fd")},
   733  		{2000, common.FromHex("ac9e2300aa79f4a0c9715e240f11b92c6a3605207113a840ee66f3908415cd37"),
   734  			common.FromHex("f9c5eee0136c9cd9b2d5f4836a2ec8c80f019ddd061653d45da4b5e812a50c1a")},
   735  	} {
   736  		addresses, accounts := makeAccounts(tc.count)
   737  		// This spongeDb is used to check the sequence of disk-db-writes
   738  		s := &spongeDb{sponge: sha3.New256()}
   739  		db := NewDatabase(s)
   740  		trie, _ := New(common.Hash{}, db)
   741  		// Another sponge is used to check the callback-sequence
   742  		callbackSponge := sha3.New256()
   743  		// Fill the trie with elements
   744  		for i := 0; i < tc.count; i++ {
   745  			trie.Update(crypto.SHA3(addresses[i][:]), accounts[i])
   746  		}
   747  		// Flush trie -> database
   748  		root, _ := trie.Commit(nil)
   749  		// Flush memdb -> disk (sponge)
   750  		db.Commit(root, false, func(c common.Hash) {
   751  			// And spongify the callback-order
   752  			callbackSponge.Write(c[:])
   753  		})
   754  		if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) {
   755  			t.Errorf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp)
   756  		}
   757  		if got, exp := callbackSponge.Sum(nil), tc.expCallbackSeqHash; !bytes.Equal(got, exp) {
   758  			t.Errorf("test %d, call back sequence wrong:\ngot: %x exp %x\n", i, got, exp)
   759  		}
   760  	}
   761  }
   762  
   763  // TestCommitSequenceRandomBlobs is identical to TestCommitSequence
   764  // but uses random blobs instead of 'accounts'
   765  func TestCommitSequenceRandomBlobs(t *testing.T) {
   766  	for i, tc := range []struct {
   767  		count              int
   768  		expWriteSeqHash    []byte
   769  		expCallbackSeqHash []byte
   770  	}{
   771  		{20, common.FromHex("37f57697901e5e3e0d8479dbe8e6b69ca36e7d21a0280605fb6dddfe13a392eb"),
   772  			common.FromHex("99ece3f0594aed23351ac60e2beb547dfda21e6188099a9009f165d4a1409e0a")},
   773  		{200, common.FromHex("c6b50dda20cdd03885cf3fed28b01e773d2df98e5947ddb27fbfe058f5947d2c"),
   774  			common.FromHex("16451bd32a69c0d31c16e93628302a805b99269211c8e0e1c1d5642877fe2a72")},
   775  		{2000, common.FromHex("2e6d9e0b15ec296a2540190b5bb22cace6127e69c6dcc3763cf88625da68cf53"),
   776  			common.FromHex("0af251355a1685c383fe5444a604efecac97ae1e93b05a526308c27ffdbd684d")},
   777  	} {
   778  		prng := rand.New(rand.NewSource(int64(i)))
   779  		// This spongeDb is used to check the sequence of disk-db-writes
   780  		s := &spongeDb{sponge: sha3.New256()}
   781  		db := NewDatabase(s)
   782  		trie, _ := New(common.Hash{}, db)
   783  		// Another sponge is used to check the callback-sequence
   784  		callbackSponge := sha3.New256()
   785  		// Fill the trie with elements
   786  		for i := 0; i < tc.count; i++ {
   787  			key := make([]byte, 32)
   788  			var val []byte
   789  			// 50% short elements, 50% large elements
   790  			if prng.Intn(2) == 0 {
   791  				val = make([]byte, 1+prng.Intn(32))
   792  			} else {
   793  				val = make([]byte, 1+prng.Intn(4096))
   794  			}
   795  			prng.Read(key)
   796  			prng.Read(val)
   797  			trie.Update(key, val)
   798  		}
   799  		// Flush trie -> database
   800  		root, _ := trie.Commit(nil)
   801  		// Flush memdb -> disk (sponge)
   802  		db.Commit(root, false, func(c common.Hash) {
   803  			// And spongify the callback-order
   804  			callbackSponge.Write(c[:])
   805  		})
   806  		if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) {
   807  			t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp)
   808  		}
   809  		if got, exp := callbackSponge.Sum(nil), tc.expCallbackSeqHash; !bytes.Equal(got, exp) {
   810  			t.Fatalf("test %d, call back sequence wrong:\ngot: %x exp %x\n", i, got, exp)
   811  		}
   812  	}
   813  }
   814  
   815  func TestCommitSequenceStackTrie(t *testing.T) {
   816  	for count := 1; count < 200; count++ {
   817  		prng := rand.New(rand.NewSource(int64(count)))
   818  		// This spongeDb is used to check the sequence of disk-db-writes
   819  		s := &spongeDb{sponge: sha3.New256(), id: "a"}
   820  		db := NewDatabase(s)
   821  		trie, _ := New(common.Hash{}, db)
   822  		// Another sponge is used for the stacktrie commits
   823  		stackTrieSponge := &spongeDb{sponge: sha3.New256(), id: "b"}
   824  		stTrie := NewStackTrie(stackTrieSponge)
   825  		// Fill the trie with elements
   826  		for i := 1; i < count; i++ {
   827  			// For the stack trie, we need to do inserts in proper order
   828  			key := make([]byte, 32)
   829  			binary.BigEndian.PutUint64(key, uint64(i))
   830  			var val []byte
   831  			// 50% short elements, 50% large elements
   832  			if prng.Intn(2) == 0 {
   833  				val = make([]byte, 1+prng.Intn(32))
   834  			} else {
   835  				val = make([]byte, 1+prng.Intn(1024))
   836  			}
   837  			prng.Read(val)
   838  			trie.TryUpdate(key, common.CopyBytes(val))
   839  			stTrie.TryUpdate(key, common.CopyBytes(val))
   840  		}
   841  		// Flush trie -> database
   842  		root, _ := trie.Commit(nil)
   843  		// Flush memdb -> disk (sponge)
   844  		db.Commit(root, false, nil)
   845  		// And flush stacktrie -> disk
   846  		stRoot, err := stTrie.Commit()
   847  		if err != nil {
   848  			t.Fatalf("Failed to commit stack trie %v", err)
   849  		}
   850  		if stRoot != root {
   851  			t.Fatalf("root wrong, got %x exp %x", stRoot, root)
   852  		}
   853  		if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) {
   854  			// Show the journal
   855  			t.Logf("Expected:")
   856  			for i, v := range s.journal {
   857  				t.Logf("op %d: %v", i, v)
   858  			}
   859  			t.Logf("Stacktrie:")
   860  			for i, v := range stackTrieSponge.journal {
   861  				t.Logf("op %d: %v", i, v)
   862  			}
   863  			t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", count, got, exp)
   864  		}
   865  	}
   866  }
   867  
   868  // TestCommitSequenceSmallRoot tests that a trie which is essentially only a
   869  // small (<32 byte) shortnode with an included value is properly committed to a
   870  // database.
   871  // This case might not matter, since in practice, all keys are 32 bytes, which means
   872  // that even a small trie which contains a leaf will have an extension making it
   873  // not fit into 32 bytes, rlp-encoded. However, it's still the correct thing to do.
   874  func TestCommitSequenceSmallRoot(t *testing.T) {
   875  	s := &spongeDb{sponge: sha3.New256(), id: "a"}
   876  	db := NewDatabase(s)
   877  	trie, _ := New(common.Hash{}, db)
   878  	// Another sponge is used for the stacktrie commits
   879  	stackTrieSponge := &spongeDb{sponge: sha3.New256(), id: "b"}
   880  	stTrie := NewStackTrie(stackTrieSponge)
   881  	// Add a single small-element to the trie(s)
   882  	key := make([]byte, 5)
   883  	key[0] = 1
   884  	trie.TryUpdate(key, []byte{0x1})
   885  	stTrie.TryUpdate(key, []byte{0x1})
   886  	// Flush trie -> database
   887  	root, _ := trie.Commit(nil)
   888  	// Flush memdb -> disk (sponge)
   889  	db.Commit(root, false, nil)
   890  	// And flush stacktrie -> disk
   891  	stRoot, err := stTrie.Commit()
   892  	if err != nil {
   893  		t.Fatalf("Failed to commit stack trie %v", err)
   894  	}
   895  	if stRoot != root {
   896  		t.Fatalf("root wrong, got %x exp %x", stRoot, root)
   897  	}
   898  	fmt.Printf("root: %x\n", stRoot)
   899  	if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) {
   900  		t.Fatalf("test, disk write sequence wrong:\ngot %x exp %x\n", got, exp)
   901  	}
   902  }
   903  
   904  // BenchmarkCommitAfterHashFixedSize benchmarks the Commit (after Hash) of a fixed number of updates to a trie.
   905  // This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically,
   906  // storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple
   907  // of thousand entries)
   908  func BenchmarkHashFixedSize(b *testing.B) {
   909  	b.Run("10", func(b *testing.B) {
   910  		b.StopTimer()
   911  		acc, add := makeAccounts(20)
   912  		for i := 0; i < b.N; i++ {
   913  			benchmarkHashFixedSize(b, acc, add)
   914  		}
   915  	})
   916  	b.Run("100", func(b *testing.B) {
   917  		b.StopTimer()
   918  		acc, add := makeAccounts(100)
   919  		for i := 0; i < b.N; i++ {
   920  			benchmarkHashFixedSize(b, acc, add)
   921  		}
   922  	})
   923  
   924  	b.Run("1K", func(b *testing.B) {
   925  		b.StopTimer()
   926  		acc, add := makeAccounts(1000)
   927  		for i := 0; i < b.N; i++ {
   928  			benchmarkHashFixedSize(b, acc, add)
   929  		}
   930  	})
   931  	b.Run("10K", func(b *testing.B) {
   932  		b.StopTimer()
   933  		acc, add := makeAccounts(10000)
   934  		for i := 0; i < b.N; i++ {
   935  			benchmarkHashFixedSize(b, acc, add)
   936  		}
   937  	})
   938  	b.Run("100K", func(b *testing.B) {
   939  		b.StopTimer()
   940  		acc, add := makeAccounts(100000)
   941  		for i := 0; i < b.N; i++ {
   942  			benchmarkHashFixedSize(b, acc, add)
   943  		}
   944  	})
   945  }
   946  
   947  func benchmarkHashFixedSize(b *testing.B, addresses [][22]byte, accounts [][]byte) {
   948  	b.ReportAllocs()
   949  	trie := newEmpty()
   950  	for i := 0; i < len(addresses); i++ {
   951  		trie.Update(crypto.SHA3(addresses[i][:]), accounts[i])
   952  	}
   953  	// Insert the accounts into the trie and hash it
   954  	b.StartTimer()
   955  	trie.Hash()
   956  	b.StopTimer()
   957  }
   958  
   959  func BenchmarkCommitAfterHashFixedSize(b *testing.B) {
   960  	b.Run("10", func(b *testing.B) {
   961  		b.StopTimer()
   962  		acc, add := makeAccounts(20)
   963  		for i := 0; i < b.N; i++ {
   964  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   965  		}
   966  	})
   967  	b.Run("100", func(b *testing.B) {
   968  		b.StopTimer()
   969  		acc, add := makeAccounts(100)
   970  		for i := 0; i < b.N; i++ {
   971  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   972  		}
   973  	})
   974  
   975  	b.Run("1K", func(b *testing.B) {
   976  		b.StopTimer()
   977  		acc, add := makeAccounts(1000)
   978  		for i := 0; i < b.N; i++ {
   979  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   980  		}
   981  	})
   982  	b.Run("10K", func(b *testing.B) {
   983  		b.StopTimer()
   984  		acc, add := makeAccounts(10000)
   985  		for i := 0; i < b.N; i++ {
   986  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   987  		}
   988  	})
   989  	b.Run("100K", func(b *testing.B) {
   990  		b.StopTimer()
   991  		acc, add := makeAccounts(100000)
   992  		for i := 0; i < b.N; i++ {
   993  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   994  		}
   995  	})
   996  }
   997  
   998  func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][22]byte, accounts [][]byte) {
   999  	b.ReportAllocs()
  1000  	trie := newEmpty()
  1001  	for i := 0; i < len(addresses); i++ {
  1002  		trie.Update(crypto.SHA3(addresses[i][:]), accounts[i])
  1003  	}
  1004  	// Insert the accounts into the trie and hash it
  1005  	trie.Hash()
  1006  	b.StartTimer()
  1007  	trie.Commit(nil)
  1008  	b.StopTimer()
  1009  }
  1010  
  1011  func BenchmarkDerefRootFixedSize(b *testing.B) {
  1012  	b.Run("10", func(b *testing.B) {
  1013  		b.StopTimer()
  1014  		acc, add := makeAccounts(20)
  1015  		for i := 0; i < b.N; i++ {
  1016  			benchmarkDerefRootFixedSize(b, acc, add)
  1017  		}
  1018  	})
  1019  	b.Run("100", func(b *testing.B) {
  1020  		b.StopTimer()
  1021  		acc, add := makeAccounts(100)
  1022  		for i := 0; i < b.N; i++ {
  1023  			benchmarkDerefRootFixedSize(b, acc, add)
  1024  		}
  1025  	})
  1026  
  1027  	b.Run("1K", func(b *testing.B) {
  1028  		b.StopTimer()
  1029  		acc, add := makeAccounts(1000)
  1030  		for i := 0; i < b.N; i++ {
  1031  			benchmarkDerefRootFixedSize(b, acc, add)
  1032  		}
  1033  	})
  1034  	b.Run("10K", func(b *testing.B) {
  1035  		b.StopTimer()
  1036  		acc, add := makeAccounts(10000)
  1037  		for i := 0; i < b.N; i++ {
  1038  			benchmarkDerefRootFixedSize(b, acc, add)
  1039  		}
  1040  	})
  1041  	b.Run("100K", func(b *testing.B) {
  1042  		b.StopTimer()
  1043  		acc, add := makeAccounts(100000)
  1044  		for i := 0; i < b.N; i++ {
  1045  			benchmarkDerefRootFixedSize(b, acc, add)
  1046  		}
  1047  	})
  1048  }
  1049  
  1050  func benchmarkDerefRootFixedSize(b *testing.B, addresses [][22]byte, accounts [][]byte) {
  1051  	b.ReportAllocs()
  1052  	trie := newEmpty()
  1053  	for i := 0; i < len(addresses); i++ {
  1054  		trie.Update(crypto.SHA3(addresses[i][:]), accounts[i])
  1055  	}
  1056  	h := trie.Hash()
  1057  	trie.Commit(nil)
  1058  	b.StartTimer()
  1059  	trie.db.Dereference(h)
  1060  	b.StopTimer()
  1061  }
  1062  
  1063  func tempDB() (string, *Database) {
  1064  	dir, err := ioutil.TempDir("", "trie-bench")
  1065  	if err != nil {
  1066  		panic(fmt.Sprintf("can't create temporary directory: %v", err))
  1067  	}
  1068  	diskdb, err := leveldb.New(dir, 256, 0, "")
  1069  	if err != nil {
  1070  		panic(fmt.Sprintf("can't create temporary database: %v", err))
  1071  	}
  1072  	return dir, NewDatabase(diskdb)
  1073  }
  1074  
  1075  func getString(trie *Trie, k string) []byte {
  1076  	return trie.Get([]byte(k))
  1077  }
  1078  
  1079  func updateString(trie *Trie, k, v string) {
  1080  	trie.Update([]byte(k), []byte(v))
  1081  }
  1082  
  1083  func deleteString(trie *Trie, k string) {
  1084  	trie.Delete([]byte(k))
  1085  }
  1086  
  1087  func TestDecodeNode(t *testing.T) {
  1088  	t.Parallel()
  1089  	var (
  1090  		hash  = make([]byte, 20)
  1091  		elems = make([]byte, 20)
  1092  	)
  1093  	for i := 0; i < 5000000; i++ {
  1094  		rand.Read(hash)
  1095  		rand.Read(elems)
  1096  		decodeNode(hash, elems)
  1097  	}
  1098  }