github.com/klaytn/klaytn@v1.12.1/storage/statedb/trie_test.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2014 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from trie/trie_test.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package statedb
    22  
    23  import (
    24  	"bytes"
    25  	"encoding/binary"
    26  	"fmt"
    27  	"math/big"
    28  	"math/rand"
    29  	"os"
    30  	"reflect"
    31  	"testing"
    32  	"testing/quick"
    33  
    34  	"github.com/davecgh/go-spew/spew"
    35  	"github.com/klaytn/klaytn/blockchain/types/account"
    36  	"github.com/klaytn/klaytn/blockchain/types/accountkey"
    37  	"github.com/klaytn/klaytn/common"
    38  	"github.com/klaytn/klaytn/crypto"
    39  	"github.com/klaytn/klaytn/rlp"
    40  	"github.com/klaytn/klaytn/storage/database"
    41  	"github.com/stretchr/testify/assert"
    42  )
    43  
    44  func init() {
    45  	spew.Config.Indent = "    "
    46  	spew.Config.DisableMethods = false
    47  }
    48  
    49  // Used for testing
    50  func newEmptyTrie() *Trie {
    51  	trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager()), nil)
    52  	return trie
    53  }
    54  
    55  func TestEmptyTrie(t *testing.T) {
    56  	var trie Trie
    57  	res := trie.Hash()
    58  	exp := emptyRoot
    59  	if res != common.Hash(exp) {
    60  		t.Errorf("expected %x got %x", exp, res)
    61  	}
    62  }
    63  
    64  func TestNull(t *testing.T) {
    65  	var trie Trie
    66  	key := make([]byte, 32)
    67  	value := []byte("test")
    68  	trie.Update(key, value)
    69  	if !bytes.Equal(trie.Get(key), value) {
    70  		t.Fatal("wrong value")
    71  	}
    72  }
    73  
    74  func TestMissingRoot(t *testing.T) {
    75  	trie, err := NewTrie(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), NewDatabase(database.NewMemoryDBManager()), nil)
    76  	if trie != nil {
    77  		t.Error("NewTrie returned non-nil trie for invalid root")
    78  	}
    79  	if _, ok := err.(*MissingNodeError); !ok {
    80  		t.Errorf("NewTrie returned wrong error: %v", err)
    81  	}
    82  }
    83  
    84  func TestMissingNodeDisk(t *testing.T)    { testMissingNode(t, false) }
    85  func TestMissingNodeMemonly(t *testing.T) { testMissingNode(t, true) }
    86  
    87  func testMissingNode(t *testing.T, memonly bool) {
    88  	dbm := database.NewMemoryDBManager()
    89  	triedb := NewDatabase(dbm)
    90  
    91  	trie, _ := NewTrie(common.Hash{}, triedb, nil)
    92  	updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
    93  	updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
    94  	root, _ := trie.Commit(nil)
    95  	if !memonly {
    96  		triedb.Commit(root, true, 0)
    97  	}
    98  
    99  	trie, _ = NewTrie(root, triedb, nil)
   100  	_, err := trie.TryGet([]byte("120000"))
   101  	if err != nil {
   102  		t.Errorf("Unexpected error: %v", err)
   103  	}
   104  	trie, _ = NewTrie(root, triedb, nil)
   105  	_, err = trie.TryGet([]byte("120099"))
   106  	if err != nil {
   107  		t.Errorf("Unexpected error: %v", err)
   108  	}
   109  	trie, _ = NewTrie(root, triedb, nil)
   110  	_, err = trie.TryGet([]byte("123456"))
   111  	if err != nil {
   112  		t.Errorf("Unexpected error: %v", err)
   113  	}
   114  	trie, _ = NewTrie(root, triedb, nil)
   115  	err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv"))
   116  	if err != nil {
   117  		t.Errorf("Unexpected error: %v", err)
   118  	}
   119  	trie, _ = NewTrie(root, triedb, nil)
   120  	err = trie.TryDelete([]byte("123456"))
   121  	if err != nil {
   122  		t.Errorf("Unexpected error: %v", err)
   123  	}
   124  
   125  	hash := common.HexToHash("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9").ExtendZero()
   126  	if memonly {
   127  		delete(triedb.nodes, hash)
   128  	} else {
   129  		dbm.DeleteTrieNode(hash)
   130  	}
   131  
   132  	trie, _ = NewTrie(root, triedb, nil)
   133  	_, err = trie.TryGet([]byte("120000"))
   134  	if _, ok := err.(*MissingNodeError); !ok {
   135  		t.Errorf("Wrong error: %v", err)
   136  	}
   137  	trie, _ = NewTrie(root, triedb, nil)
   138  	_, err = trie.TryGet([]byte("120099"))
   139  	if _, ok := err.(*MissingNodeError); !ok {
   140  		t.Errorf("Wrong error: %v", err)
   141  	}
   142  	trie, _ = NewTrie(root, triedb, nil)
   143  	_, err = trie.TryGet([]byte("123456"))
   144  	if err != nil {
   145  		t.Errorf("Unexpected error: %v", err)
   146  	}
   147  	trie, _ = NewTrie(root, triedb, nil)
   148  	err = trie.TryUpdate([]byte("120099"), []byte("zxcv"))
   149  	if _, ok := err.(*MissingNodeError); !ok {
   150  		t.Errorf("Wrong error: %v", err)
   151  	}
   152  	trie, _ = NewTrie(root, triedb, nil)
   153  	err = trie.TryDelete([]byte("123456"))
   154  	if _, ok := err.(*MissingNodeError); !ok {
   155  		t.Errorf("Wrong error: %v", err)
   156  	}
   157  }
   158  
   159  func TestInsert(t *testing.T) {
   160  	trie := newEmptyTrie()
   161  
   162  	updateString(trie, "doe", "reindeer")
   163  	updateString(trie, "dog", "puppy")
   164  	updateString(trie, "dogglesworth", "cat")
   165  
   166  	exp := common.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3")
   167  	root := trie.Hash()
   168  	if root != exp {
   169  		t.Errorf("exp %x got %x", exp, root)
   170  	}
   171  
   172  	trie = newEmptyTrie()
   173  	updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
   174  
   175  	exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
   176  	root, err := trie.Commit(nil)
   177  	if err != nil {
   178  		t.Fatalf("commit error: %v", err)
   179  	}
   180  	if root != exp {
   181  		t.Errorf("exp %x got %x", exp, root)
   182  	}
   183  }
   184  
   185  func TestGet(t *testing.T) {
   186  	trie := newEmptyTrie()
   187  	updateString(trie, "doe", "reindeer")
   188  	updateString(trie, "dog", "puppy")
   189  	updateString(trie, "dogglesworth", "cat")
   190  
   191  	for i := 0; i < 2; i++ {
   192  		res := getString(trie, "dog")
   193  		if !bytes.Equal(res, []byte("puppy")) {
   194  			t.Errorf("expected puppy got %x", res)
   195  		}
   196  
   197  		unknown := getString(trie, "unknown")
   198  		if unknown != nil {
   199  			t.Errorf("expected nil got %x", unknown)
   200  		}
   201  
   202  		if i == 1 {
   203  			return
   204  		}
   205  		trie.Commit(nil)
   206  	}
   207  }
   208  
   209  func TestDelete(t *testing.T) {
   210  	trie := newEmptyTrie()
   211  	vals := []struct{ k, v string }{
   212  		{"do", "verb"},
   213  		{"klaytn", "wookiedoo"},
   214  		{"horse", "stallion"},
   215  		{"shaman", "horse"},
   216  		{"doge", "coin"},
   217  		{"klaytn", ""},
   218  		{"dog", "puppy"},
   219  		{"shaman", ""},
   220  	}
   221  	for _, val := range vals {
   222  		if val.v != "" {
   223  			updateString(trie, val.k, val.v)
   224  		} else {
   225  			deleteString(trie, val.k)
   226  		}
   227  	}
   228  
   229  	hash := trie.Hash()
   230  	exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   231  	if hash != exp {
   232  		t.Errorf("expected %x got %x", exp, hash)
   233  	}
   234  }
   235  
   236  func TestEmptyValues(t *testing.T) {
   237  	trie := newEmptyTrie()
   238  
   239  	vals := []struct{ k, v string }{
   240  		{"do", "verb"},
   241  		{"klaytn", "wookiedoo"},
   242  		{"horse", "stallion"},
   243  		{"shaman", "horse"},
   244  		{"doge", "coin"},
   245  		{"klaytn", ""},
   246  		{"dog", "puppy"},
   247  		{"shaman", ""},
   248  	}
   249  	for _, val := range vals {
   250  		updateString(trie, val.k, val.v)
   251  	}
   252  
   253  	hash := trie.Hash()
   254  	exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   255  	if hash != exp {
   256  		t.Errorf("expected %x got %x", exp, hash)
   257  	}
   258  }
   259  
   260  func TestReplication(t *testing.T) {
   261  	trie := newEmptyTrie()
   262  	vals := []struct{ k, v string }{
   263  		{"do", "verb"},
   264  		{"klaytn", "wookiedoo"},
   265  		{"horse", "stallion"},
   266  		{"shaman", "horse"},
   267  		{"doge", "coin"},
   268  		{"dog", "puppy"},
   269  		{"somethingveryoddindeedthis is", "myothernodedata"},
   270  	}
   271  	for _, val := range vals {
   272  		updateString(trie, val.k, val.v)
   273  	}
   274  	exp, err := trie.Commit(nil)
   275  	if err != nil {
   276  		t.Fatalf("commit error: %v", err)
   277  	}
   278  
   279  	// create a new trie on top of the database and check that lookups work.
   280  	trie2, err := NewTrie(exp, trie.db, nil)
   281  	if err != nil {
   282  		t.Fatalf("can't recreate trie at %x: %v", exp, err)
   283  	}
   284  	for _, kv := range vals {
   285  		if string(getString(trie2, kv.k)) != kv.v {
   286  			t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
   287  		}
   288  	}
   289  	hash, err := trie2.Commit(nil)
   290  	if err != nil {
   291  		t.Fatalf("commit error: %v", err)
   292  	}
   293  	if hash != exp {
   294  		t.Errorf("root failure. expected %x got %x", exp, hash)
   295  	}
   296  
   297  	// perform some insertions on the new trie.
   298  	vals2 := []struct{ k, v string }{
   299  		{"do", "verb"},
   300  		{"klaytn", "wookiedoo"},
   301  		{"horse", "stallion"},
   302  		// {"shaman", "horse"},
   303  		// {"doge", "coin"},
   304  		// {"klaytn", ""},
   305  		// {"dog", "puppy"},
   306  		// {"somethingveryoddindeedthis is", "myothernodedata"},
   307  		// {"shaman", ""},
   308  	}
   309  	for _, val := range vals2 {
   310  		updateString(trie2, val.k, val.v)
   311  	}
   312  	if hash := trie2.Hash(); hash != exp {
   313  		t.Errorf("root failure. expected %x got %x", exp, hash)
   314  	}
   315  }
   316  
   317  func TestLargeValue(t *testing.T) {
   318  	trie := newEmptyTrie()
   319  	trie.Update([]byte("key1"), []byte{99, 99, 99, 99})
   320  	trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32))
   321  	trie.Hash()
   322  }
   323  
   324  func TestStorageTrie(t *testing.T) {
   325  	newStorageTrie := func(pruning bool) *Trie {
   326  		dbm := database.NewMemoryDBManager()
   327  		if pruning {
   328  			dbm.WritePruningEnabled()
   329  		}
   330  		db := NewDatabase(dbm)
   331  		trie, _ := NewStorageTrie(common.ExtHash{}, db, nil)
   332  		updateString(trie, "doe", "reindeer")
   333  		return trie
   334  	}
   335  
   336  	// non-pruning storage trie returns Legacy ExtHash for root
   337  	trie := newStorageTrie(false)
   338  	root := trie.HashExt()
   339  	assert.True(t, root.IsZeroExtended())
   340  
   341  	trie = newStorageTrie(false)
   342  	root, _ = trie.CommitExt(nil)
   343  	assert.True(t, root.IsZeroExtended())
   344  
   345  	// pruning storage trie returns non-Legacy ExtHash for root
   346  	trie = newStorageTrie(true)
   347  	root = trie.HashExt()
   348  	assert.False(t, root.IsZeroExtended())
   349  
   350  	trie = newStorageTrie(true)
   351  	root, _ = trie.CommitExt(nil)
   352  	assert.False(t, root.IsZeroExtended())
   353  }
   354  
   355  func TestPruningByUpdate(t *testing.T) {
   356  	dbm := database.NewMemoryDBManager()
   357  	dbm.WritePruningEnabled()
   358  	db := NewDatabase(dbm)
   359  	hasnode := func(hash common.ExtHash) bool { ok, _ := dbm.HasTrieNode(hash); return ok }
   360  	common.ResetExtHashCounterForTest(0xccccddddeeee00)
   361  
   362  	trie, _ := NewTrie(common.Hash{}, db, &TrieOpts{PruningBlockNumber: 1})
   363  	nodehash1 := common.HexToExtHash("05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c400000000000000")
   364  	nodehash2 := common.HexToExtHash("f226ef598ed9195f2211546cf5b2860dc27b4da07ff7ab5108ee68107f0c9d00ccccddddeeee01")
   365  
   366  	// Test that extension and branch nodes are correctly pruned via Update.
   367  	// - extension <05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c400000000000045>
   368  	//   - branch  <f226ef598ed9195f2211546cf5b2860dc27b4da07ff7ab5108ee68107f0c9d00ccccddddeeee01>
   369  	//     - [5]value "reindeer"
   370  	//     - [7]value "puppy"
   371  	// By inserting "dogglesworth", both extension and branch nodes are affected, hence pruning the both.
   372  
   373  	// Update and commit to store the nodes
   374  	updateString(trie, "doe", "reindeer")
   375  	updateString(trie, "dog", "puppy")
   376  	trie.Commit(nil)
   377  	db.Cap(0)
   378  
   379  	// The nodes still exist
   380  	assert.True(t, hasnode(nodehash1))
   381  	assert.True(t, hasnode(nodehash2))
   382  
   383  	// Trigger pruning
   384  	updateString(trie, "dogglesworth", "cat")
   385  	trie.Commit(nil)
   386  	db.Cap(0)
   387  
   388  	// Those nodes and the only those nodes are scheduled to be deleted
   389  	expectedMarks := []database.PruningMark{
   390  		{Number: 1, Hash: nodehash1},
   391  		{Number: 1, Hash: nodehash2},
   392  	}
   393  	marks := dbm.ReadPruningMarks(0, 0)
   394  	assert.Equal(t, expectedMarks, marks)
   395  
   396  	// The nodes are deleted
   397  	dbm.PruneTrieNodes(marks)
   398  	assert.False(t, hasnode(nodehash1))
   399  	assert.False(t, hasnode(nodehash2))
   400  }
   401  
   402  func TestPruningByDelete(t *testing.T) {
   403  	dbm := database.NewMemoryDBManager()
   404  	dbm.WritePruningEnabled()
   405  	db := NewDatabase(dbm)
   406  	hasnode := func(hash common.ExtHash) bool { ok, _ := dbm.HasTrieNode(hash); return ok }
   407  	common.ResetExtHashCounterForTest(0xccccddddeeee00)
   408  
   409  	trie, _ := NewTrie(common.Hash{}, db, &TrieOpts{PruningBlockNumber: 1})
   410  	nodehash1 := common.HexToExtHash("05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c400000000000000")
   411  	nodehash2 := common.HexToExtHash("f226ef598ed9195f2211546cf5b2860dc27b4da07ff7ab5108ee68107f0c9d00ccccddddeeee01")
   412  
   413  	// Test that extension and branch nodes are correctly pruned via Delete.
   414  	// - extension <05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c400000000000045>
   415  	//   - branch  <f226ef598ed9195f2211546cf5b2860dc27b4da07ff7ab5108ee68107f0c9d00ccccddddeeee01>
   416  	//     - [5]value "reindeer"
   417  	//     - [7]value "puppy"
   418  	// By deleting "doe", both extension and branch nodes are affected, hence pruning the both.
   419  
   420  	// Update and commit to store the nodes
   421  	updateString(trie, "doe", "reindeer")
   422  	updateString(trie, "dog", "puppy")
   423  	trie.Commit(nil)
   424  	db.Cap(0)
   425  
   426  	// The nodes still exist
   427  	assert.True(t, hasnode(nodehash1))
   428  	assert.True(t, hasnode(nodehash2))
   429  
   430  	// Trigger pruning
   431  	deleteString(trie, "doe")
   432  	trie.Commit(nil)
   433  	db.Cap(0)
   434  
   435  	// Those nodes and the only those nodes are scheduled to be deleted
   436  	expectedMarks := []database.PruningMark{
   437  		{Number: 1, Hash: nodehash1},
   438  		{Number: 1, Hash: nodehash2},
   439  	}
   440  	marks := dbm.ReadPruningMarks(0, 0)
   441  	assert.Equal(t, expectedMarks, marks)
   442  
   443  	// The nodes are deleted
   444  	dbm.PruneTrieNodes(marks)
   445  	assert.False(t, hasnode(nodehash1))
   446  	assert.False(t, hasnode(nodehash2))
   447  }
   448  
   449  type countingDB struct {
   450  	database.DBManager
   451  	gets map[string]int
   452  }
   453  
   454  //func (db *countingDB) Get(key []byte) ([]byte, error) {
   455  //	db.gets[string(key)]++
   456  //	return db.Database.Get(key)
   457  //}
   458  
   459  // randTest performs random trie operations.
   460  // Instances of this test are created by Generate.
   461  type randTest []randTestStep
   462  
   463  type randTestStep struct {
   464  	op    int
   465  	key   []byte // for opUpdate, opDelete, opGet
   466  	value []byte // for opUpdate
   467  	err   error  // for debugging
   468  }
   469  
   470  const (
   471  	opUpdate = iota
   472  	opDelete
   473  	opGet
   474  	opCommit
   475  	opHash
   476  	opReset
   477  	opItercheckhash
   478  	opMax // boundary value, not an actual op
   479  )
   480  
   481  func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
   482  	var allKeys [][]byte
   483  	genKey := func() []byte {
   484  		if len(allKeys) < 2 || r.Intn(100) < 10 {
   485  			// new key
   486  			key := make([]byte, r.Intn(50))
   487  			r.Read(key)
   488  			allKeys = append(allKeys, key)
   489  			return key
   490  		}
   491  		// use existing key
   492  		return allKeys[r.Intn(len(allKeys))]
   493  	}
   494  
   495  	var steps randTest
   496  	for i := 0; i < size; i++ {
   497  		step := randTestStep{op: r.Intn(opMax)}
   498  		switch step.op {
   499  		case opUpdate:
   500  			step.key = genKey()
   501  			step.value = make([]byte, 8)
   502  			binary.BigEndian.PutUint64(step.value, uint64(i))
   503  		case opGet, opDelete:
   504  			step.key = genKey()
   505  		}
   506  		steps = append(steps, step)
   507  	}
   508  	return reflect.ValueOf(steps)
   509  }
   510  
   511  func runRandTest(rt randTest) bool {
   512  	triedb := NewDatabase(database.NewMemoryDBManager())
   513  
   514  	tr, _ := NewTrie(common.Hash{}, triedb, nil)
   515  	values := make(map[string]string) // tracks content of the trie
   516  
   517  	for i, step := range rt {
   518  		switch step.op {
   519  		case opUpdate:
   520  			tr.Update(step.key, step.value)
   521  			values[string(step.key)] = string(step.value)
   522  		case opDelete:
   523  			tr.Delete(step.key)
   524  			delete(values, string(step.key))
   525  		case opGet:
   526  			v := tr.Get(step.key)
   527  			want := values[string(step.key)]
   528  			if string(v) != want {
   529  				rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
   530  			}
   531  		case opCommit:
   532  			_, rt[i].err = tr.Commit(nil)
   533  		case opHash:
   534  			tr.Hash()
   535  		case opReset:
   536  			hash, err := tr.Commit(nil)
   537  			if err != nil {
   538  				rt[i].err = err
   539  				return false
   540  			}
   541  			newtr, err := NewTrie(hash, triedb, nil)
   542  			if err != nil {
   543  				rt[i].err = err
   544  				return false
   545  			}
   546  			tr = newtr
   547  		case opItercheckhash:
   548  			checktr, _ := NewTrie(common.Hash{}, triedb, nil)
   549  			it := NewIterator(tr.NodeIterator(nil))
   550  			for it.Next() {
   551  				checktr.Update(it.Key, it.Value)
   552  			}
   553  			if tr.Hash() != checktr.Hash() {
   554  				rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash")
   555  			}
   556  		}
   557  		// Abort the test on error.
   558  		if rt[i].err != nil {
   559  			return false
   560  		}
   561  	}
   562  	return true
   563  }
   564  
   565  func TestRandom(t *testing.T) {
   566  	if err := quick.Check(runRandTest, nil); err != nil {
   567  		if cerr, ok := err.(*quick.CheckError); ok {
   568  			t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
   569  		}
   570  		t.Fatal(err)
   571  	}
   572  }
   573  
   574  func BenchmarkGet(b *testing.B)      { benchGet(b, false) }
   575  func BenchmarkGetDB(b *testing.B)    { benchGet(b, true) }
   576  func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) }
   577  func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
   578  
   579  const benchElemCount = 20000
   580  
   581  func benchGet(b *testing.B, commit bool) {
   582  	trie := new(Trie)
   583  
   584  	if commit {
   585  		dbDir, tmpdb := tempDB()
   586  		trie, _ = NewTrie(common.Hash{}, tmpdb, nil)
   587  
   588  		defer os.RemoveAll(dbDir)
   589  		defer tmpdb.diskDB.Close()
   590  	}
   591  
   592  	k := make([]byte, 32)
   593  	for i := 0; i < benchElemCount; i++ {
   594  		binary.LittleEndian.PutUint64(k, uint64(i))
   595  		trie.Update(k, k)
   596  	}
   597  	binary.LittleEndian.PutUint64(k, benchElemCount/2)
   598  	if commit {
   599  		trie.Commit(nil)
   600  	}
   601  
   602  	b.ResetTimer()
   603  	for i := 0; i < b.N; i++ {
   604  		trie.Get(k)
   605  	}
   606  	b.StopTimer()
   607  }
   608  
   609  func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
   610  	trie := newEmptyTrie()
   611  	k := make([]byte, 32)
   612  	for i := 0; i < b.N; i++ {
   613  		e.PutUint64(k, uint64(i))
   614  		trie.Update(k, k)
   615  	}
   616  	return trie
   617  }
   618  
   619  // Benchmarks the trie hashing. Since the trie caches the result of any operation,
   620  // we cannot use b.N as the number of hashing rouns, since all rounds apart from
   621  // the first one will be NOOP. As such, we'll use b.N as the number of account to
   622  // insert into the trie before measuring the hashing.
   623  func BenchmarkHash(b *testing.B) {
   624  	// Make the random benchmark deterministic
   625  	random := rand.New(rand.NewSource(0))
   626  
   627  	// Create a realistic account trie to hash
   628  	addresses := make([][20]byte, b.N)
   629  	for i := 0; i < len(addresses); i++ {
   630  		for j := 0; j < len(addresses[i]); j++ {
   631  			addresses[i][j] = byte(random.Intn(256))
   632  		}
   633  	}
   634  	accounts := make([][]byte, len(addresses))
   635  	for i := 0; i < len(accounts); i++ {
   636  		var (
   637  			nonce   = uint64(random.Int63())
   638  			balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
   639  			root    = emptyRoot
   640  			code    = crypto.Keccak256(nil)
   641  		)
   642  		accounts[i], _ = rlp.EncodeToBytes([]interface{}{nonce, balance, root, code})
   643  	}
   644  	// Insert the accounts into the trie and hash it
   645  	trie := newEmptyTrie()
   646  	for i := 0; i < len(addresses); i++ {
   647  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   648  	}
   649  	b.ResetTimer()
   650  	b.ReportAllocs()
   651  	trie.Hash()
   652  }
   653  
   654  // Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation,
   655  // we cannot use b.N as the number of hashing rounds, since all rounds apart from
   656  // the first one will be NOOP. As such, we'll use b.N as the number of account to
   657  // insert into the trie before measuring the hashing.
   658  func BenchmarkCommitAfterHash(b *testing.B) {
   659  	b.Run("no-onleaf", func(b *testing.B) {
   660  		benchmarkCommitAfterHash(b)
   661  	})
   662  }
   663  
   664  func benchmarkCommitAfterHash(b *testing.B) {
   665  	// Make the random benchmark deterministic
   666  	addresses, accounts := makeAccounts(b.N)
   667  	trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager()), nil)
   668  	for i := 0; i < len(addresses); i++ {
   669  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   670  	}
   671  	// Insert the accounts into the trie and hash it
   672  	trie.Hash()
   673  	b.ResetTimer()
   674  	b.ReportAllocs()
   675  	trie.Commit(nil)
   676  }
   677  
   678  func tempDB() (string, *Database) {
   679  	dir, err := os.MkdirTemp("", "trie-bench")
   680  	if err != nil {
   681  		panic(fmt.Sprintf("can't create temporary directory: %v", err))
   682  	}
   683  	dbc := &database.DBConfig{Dir: dir, DBType: database.LevelDB, LevelDBCacheSize: 256, OpenFilesLimit: 0}
   684  	diskDB := database.NewDBManager(dbc)
   685  	return dir, NewDatabase(diskDB)
   686  }
   687  
   688  func genExternallyOwnedAccount(nonce uint64, balance *big.Int) (account.Account, error) {
   689  	return account.NewAccountWithMap(account.ExternallyOwnedAccountType, map[account.AccountValueKeyType]interface{}{
   690  		account.AccountValueKeyNonce:         nonce,
   691  		account.AccountValueKeyBalance:       balance,
   692  		account.AccountValueKeyHumanReadable: false,
   693  		account.AccountValueKeyAccountKey:    accountkey.NewAccountKeyLegacy(),
   694  	})
   695  }
   696  
   697  func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
   698  	// Make the random benchmark deterministic
   699  	random := rand.New(rand.NewSource(0))
   700  	// Create a realistic account trie to hash
   701  	addresses = make([][20]byte, size)
   702  	for i := 0; i < len(addresses); i++ {
   703  		data := make([]byte, 20)
   704  		random.Read(data)
   705  		copy(addresses[i][:], data)
   706  	}
   707  	accounts = make([][]byte, len(addresses))
   708  	for i := 0; i < len(accounts); i++ {
   709  		// The big.Rand function is not deterministic with regards to 64 vs 32 bit systems,
   710  		// and will consume different amount of data from the rand source.
   711  		// balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
   712  		// Therefore, we instead just read via byte buffer
   713  		numBytes := random.Uint32() % 33 // [0, 32] bytes
   714  		balanceBytes := make([]byte, numBytes)
   715  		random.Read(balanceBytes)
   716  		acc, _ := genExternallyOwnedAccount(uint64(i), big.NewInt(int64(i)))
   717  		serializer := account.NewAccountSerializerWithAccount(acc)
   718  		data, _ := rlp.EncodeToBytes(serializer)
   719  		accounts[i] = data
   720  	}
   721  	return addresses, accounts
   722  }
   723  
   724  // BenchmarkCommitAfterHashFixedSize benchmarks the Commit (after Hash) of a fixed number of updates to a trie.
   725  // This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically,
   726  // storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple
   727  // of thousand entries)
   728  func BenchmarkHashFixedSize(b *testing.B) {
   729  	b.Run("10", func(b *testing.B) {
   730  		b.StopTimer()
   731  		acc, add := makeAccounts(20)
   732  		for i := 0; i < b.N; i++ {
   733  			benchmarkHashFixedSize(b, acc, add)
   734  		}
   735  	})
   736  	b.Run("100", func(b *testing.B) {
   737  		b.StopTimer()
   738  		acc, add := makeAccounts(100)
   739  		for i := 0; i < b.N; i++ {
   740  			benchmarkHashFixedSize(b, acc, add)
   741  		}
   742  	})
   743  
   744  	b.Run("1K", func(b *testing.B) {
   745  		b.StopTimer()
   746  		acc, add := makeAccounts(1000)
   747  		for i := 0; i < b.N; i++ {
   748  			benchmarkHashFixedSize(b, acc, add)
   749  		}
   750  	})
   751  	b.Run("10K", func(b *testing.B) {
   752  		b.StopTimer()
   753  		acc, add := makeAccounts(10000)
   754  		for i := 0; i < b.N; i++ {
   755  			benchmarkHashFixedSize(b, acc, add)
   756  		}
   757  	})
   758  	b.Run("100K", func(b *testing.B) {
   759  		b.StopTimer()
   760  		acc, add := makeAccounts(100000)
   761  		for i := 0; i < b.N; i++ {
   762  			benchmarkHashFixedSize(b, acc, add)
   763  		}
   764  	})
   765  }
   766  
   767  func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
   768  	b.ReportAllocs()
   769  	trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager()), nil)
   770  	for i := 0; i < len(addresses); i++ {
   771  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   772  	}
   773  	// Insert the accounts into the trie and hash it
   774  	b.StartTimer()
   775  	trie.Hash()
   776  	b.StopTimer()
   777  }
   778  
   779  func BenchmarkCommitAfterHashFixedSize(b *testing.B) {
   780  	b.Run("10", func(b *testing.B) {
   781  		b.StopTimer()
   782  		acc, add := makeAccounts(20)
   783  		for i := 0; i < b.N; i++ {
   784  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   785  		}
   786  	})
   787  	b.Run("100", func(b *testing.B) {
   788  		b.StopTimer()
   789  		acc, add := makeAccounts(100)
   790  		for i := 0; i < b.N; i++ {
   791  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   792  		}
   793  	})
   794  
   795  	b.Run("1K", func(b *testing.B) {
   796  		b.StopTimer()
   797  		acc, add := makeAccounts(1000)
   798  		for i := 0; i < b.N; i++ {
   799  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   800  		}
   801  	})
   802  	b.Run("10K", func(b *testing.B) {
   803  		b.StopTimer()
   804  		acc, add := makeAccounts(10000)
   805  		for i := 0; i < b.N; i++ {
   806  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   807  		}
   808  	})
   809  	b.Run("100K", func(b *testing.B) {
   810  		b.StopTimer()
   811  		acc, add := makeAccounts(100000)
   812  		for i := 0; i < b.N; i++ {
   813  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   814  		}
   815  	})
   816  }
   817  
   818  func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
   819  	b.ReportAllocs()
   820  	trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager()), nil)
   821  	for i := 0; i < len(addresses); i++ {
   822  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   823  	}
   824  	// Insert the accounts into the trie and hash it
   825  	trie.Hash()
   826  	b.StartTimer()
   827  	trie.Commit(nil)
   828  	b.StopTimer()
   829  }
   830  
   831  func BenchmarkDerefRootFixedSize(b *testing.B) {
   832  	b.Run("10", func(b *testing.B) {
   833  		b.StopTimer()
   834  		acc, add := makeAccounts(20)
   835  		for i := 0; i < b.N; i++ {
   836  			benchmarkDerefRootFixedSize(b, acc, add)
   837  		}
   838  	})
   839  	b.Run("100", func(b *testing.B) {
   840  		b.StopTimer()
   841  		acc, add := makeAccounts(100)
   842  		for i := 0; i < b.N; i++ {
   843  			benchmarkDerefRootFixedSize(b, acc, add)
   844  		}
   845  	})
   846  
   847  	b.Run("1K", func(b *testing.B) {
   848  		b.StopTimer()
   849  		acc, add := makeAccounts(1000)
   850  		for i := 0; i < b.N; i++ {
   851  			benchmarkDerefRootFixedSize(b, acc, add)
   852  		}
   853  	})
   854  	b.Run("10K", func(b *testing.B) {
   855  		b.StopTimer()
   856  		acc, add := makeAccounts(10000)
   857  		for i := 0; i < b.N; i++ {
   858  			benchmarkDerefRootFixedSize(b, acc, add)
   859  		}
   860  	})
   861  	b.Run("100K", func(b *testing.B) {
   862  		b.StopTimer()
   863  		acc, add := makeAccounts(100000)
   864  		for i := 0; i < b.N; i++ {
   865  			benchmarkDerefRootFixedSize(b, acc, add)
   866  		}
   867  	})
   868  }
   869  
   870  func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
   871  	b.ReportAllocs()
   872  	triedb := NewDatabase(database.NewMemoryDBManager())
   873  	trie, _ := NewTrie(common.Hash{}, triedb, nil)
   874  	for i := 0; i < len(addresses); i++ {
   875  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   876  	}
   877  	h := trie.Hash()
   878  	trie.Commit(nil)
   879  	//_, nodes := trie.Commit(nil)
   880  	//triedb.Update(NewWithNodeSet(nodes))
   881  	b.StartTimer()
   882  	triedb.Dereference(h)
   883  	b.StopTimer()
   884  }
   885  
   886  func getString(trie *Trie, k string) []byte {
   887  	return trie.Get([]byte(k))
   888  }
   889  
   890  func updateString(trie *Trie, k, v string) {
   891  	trie.Update([]byte(k), []byte(v))
   892  }
   893  
   894  func deleteString(trie *Trie, k string) {
   895  	trie.Delete([]byte(k))
   896  }
   897  
   898  func TestDecodeNode(t *testing.T) {
   899  	t.Parallel()
   900  	var (
   901  		hash  = make([]byte, 20)
   902  		elems = make([]byte, 20)
   903  	)
   904  	for i := 0; i < 5000000; i++ {
   905  		rand.Read(hash)
   906  		rand.Read(elems)
   907  		decodeNode(hash, elems)
   908  	}
   909  }