github.com/klaytn/klaytn@v1.10.2/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  	"io/ioutil"
    28  	"math/big"
    29  	"math/rand"
    30  	"os"
    31  	"reflect"
    32  	"testing"
    33  	"testing/quick"
    34  
    35  	"github.com/davecgh/go-spew/spew"
    36  	"github.com/klaytn/klaytn/blockchain/types/account"
    37  	"github.com/klaytn/klaytn/blockchain/types/accountkey"
    38  	"github.com/klaytn/klaytn/common"
    39  	"github.com/klaytn/klaytn/crypto"
    40  	"github.com/klaytn/klaytn/rlp"
    41  	"github.com/klaytn/klaytn/storage/database"
    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()))
    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()))
    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  	memDBManager := database.NewMemoryDBManager()
    89  	diskdb := memDBManager.GetMemDB()
    90  	triedb := NewDatabase(memDBManager)
    91  
    92  	trie, _ := NewTrie(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, 0)
    98  	}
    99  
   100  	trie, _ = NewTrie(root, triedb)
   101  	_, err := trie.TryGet([]byte("120000"))
   102  	if err != nil {
   103  		t.Errorf("Unexpected error: %v", err)
   104  	}
   105  	trie, _ = NewTrie(root, triedb)
   106  	_, err = trie.TryGet([]byte("120099"))
   107  	if err != nil {
   108  		t.Errorf("Unexpected error: %v", err)
   109  	}
   110  	trie, _ = NewTrie(root, triedb)
   111  	_, err = trie.TryGet([]byte("123456"))
   112  	if err != nil {
   113  		t.Errorf("Unexpected error: %v", err)
   114  	}
   115  	trie, _ = NewTrie(root, triedb)
   116  	err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv"))
   117  	if err != nil {
   118  		t.Errorf("Unexpected error: %v", err)
   119  	}
   120  	trie, _ = NewTrie(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("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9")
   127  	if memonly {
   128  		delete(triedb.nodes, hash)
   129  	} else {
   130  		diskdb.Delete(hash[:])
   131  	}
   132  
   133  	trie, _ = NewTrie(root, triedb)
   134  	_, err = trie.TryGet([]byte("120000"))
   135  	if _, ok := err.(*MissingNodeError); !ok {
   136  		t.Errorf("Wrong error: %v", err)
   137  	}
   138  	trie, _ = NewTrie(root, triedb)
   139  	_, err = trie.TryGet([]byte("120099"))
   140  	if _, ok := err.(*MissingNodeError); !ok {
   141  		t.Errorf("Wrong error: %v", err)
   142  	}
   143  	trie, _ = NewTrie(root, triedb)
   144  	_, err = trie.TryGet([]byte("123456"))
   145  	if err != nil {
   146  		t.Errorf("Unexpected error: %v", err)
   147  	}
   148  	trie, _ = NewTrie(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, _ = NewTrie(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 := newEmptyTrie()
   162  
   163  	updateString(trie, "doe", "reindeer")
   164  	updateString(trie, "dog", "puppy")
   165  	updateString(trie, "dogglesworth", "cat")
   166  
   167  	exp := common.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3")
   168  	root := trie.Hash()
   169  	if root != exp {
   170  		t.Errorf("exp %x got %x", exp, root)
   171  	}
   172  
   173  	trie = newEmptyTrie()
   174  	updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
   175  
   176  	exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
   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("exp %x got %x", exp, root)
   183  	}
   184  }
   185  
   186  func TestGet(t *testing.T) {
   187  	trie := newEmptyTrie()
   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 := newEmptyTrie()
   212  	vals := []struct{ k, v string }{
   213  		{"do", "verb"},
   214  		{"klaytn", "wookiedoo"},
   215  		{"horse", "stallion"},
   216  		{"shaman", "horse"},
   217  		{"doge", "coin"},
   218  		{"klaytn", ""},
   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("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   232  	if hash != exp {
   233  		t.Errorf("expected %x got %x", exp, hash)
   234  	}
   235  }
   236  
   237  func TestEmptyValues(t *testing.T) {
   238  	trie := newEmptyTrie()
   239  
   240  	vals := []struct{ k, v string }{
   241  		{"do", "verb"},
   242  		{"klaytn", "wookiedoo"},
   243  		{"horse", "stallion"},
   244  		{"shaman", "horse"},
   245  		{"doge", "coin"},
   246  		{"klaytn", ""},
   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("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   256  	if hash != exp {
   257  		t.Errorf("expected %x got %x", exp, hash)
   258  	}
   259  }
   260  
   261  func TestReplication(t *testing.T) {
   262  	trie := newEmptyTrie()
   263  	vals := []struct{ k, v string }{
   264  		{"do", "verb"},
   265  		{"klaytn", "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 := NewTrie(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  		{"klaytn", "wookiedoo"},
   302  		{"horse", "stallion"},
   303  		// {"shaman", "horse"},
   304  		// {"doge", "coin"},
   305  		// {"klaytn", ""},
   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 := newEmptyTrie()
   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  type countingDB struct {
   326  	database.DBManager
   327  	gets map[string]int
   328  }
   329  
   330  //func (db *countingDB) Get(key []byte) ([]byte, error) {
   331  //	db.gets[string(key)]++
   332  //	return db.Database.Get(key)
   333  //}
   334  
   335  // randTest performs random trie operations.
   336  // Instances of this test are created by Generate.
   337  type randTest []randTestStep
   338  
   339  type randTestStep struct {
   340  	op    int
   341  	key   []byte // for opUpdate, opDelete, opGet
   342  	value []byte // for opUpdate
   343  	err   error  // for debugging
   344  }
   345  
   346  const (
   347  	opUpdate = iota
   348  	opDelete
   349  	opGet
   350  	opCommit
   351  	opHash
   352  	opReset
   353  	opItercheckhash
   354  	opMax // boundary value, not an actual op
   355  )
   356  
   357  func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
   358  	var allKeys [][]byte
   359  	genKey := func() []byte {
   360  		if len(allKeys) < 2 || r.Intn(100) < 10 {
   361  			// new key
   362  			key := make([]byte, r.Intn(50))
   363  			r.Read(key)
   364  			allKeys = append(allKeys, key)
   365  			return key
   366  		}
   367  		// use existing key
   368  		return allKeys[r.Intn(len(allKeys))]
   369  	}
   370  
   371  	var steps randTest
   372  	for i := 0; i < size; i++ {
   373  		step := randTestStep{op: r.Intn(opMax)}
   374  		switch step.op {
   375  		case opUpdate:
   376  			step.key = genKey()
   377  			step.value = make([]byte, 8)
   378  			binary.BigEndian.PutUint64(step.value, uint64(i))
   379  		case opGet, opDelete:
   380  			step.key = genKey()
   381  		}
   382  		steps = append(steps, step)
   383  	}
   384  	return reflect.ValueOf(steps)
   385  }
   386  
   387  func runRandTest(rt randTest) bool {
   388  	triedb := NewDatabase(database.NewMemoryDBManager())
   389  
   390  	tr, _ := NewTrie(common.Hash{}, triedb)
   391  	values := make(map[string]string) // tracks content of the trie
   392  
   393  	for i, step := range rt {
   394  		switch step.op {
   395  		case opUpdate:
   396  			tr.Update(step.key, step.value)
   397  			values[string(step.key)] = string(step.value)
   398  		case opDelete:
   399  			tr.Delete(step.key)
   400  			delete(values, string(step.key))
   401  		case opGet:
   402  			v := tr.Get(step.key)
   403  			want := values[string(step.key)]
   404  			if string(v) != want {
   405  				rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
   406  			}
   407  		case opCommit:
   408  			_, rt[i].err = tr.Commit(nil)
   409  		case opHash:
   410  			tr.Hash()
   411  		case opReset:
   412  			hash, err := tr.Commit(nil)
   413  			if err != nil {
   414  				rt[i].err = err
   415  				return false
   416  			}
   417  			newtr, err := NewTrie(hash, triedb)
   418  			if err != nil {
   419  				rt[i].err = err
   420  				return false
   421  			}
   422  			tr = newtr
   423  		case opItercheckhash:
   424  			checktr, _ := NewTrie(common.Hash{}, triedb)
   425  			it := NewIterator(tr.NodeIterator(nil))
   426  			for it.Next() {
   427  				checktr.Update(it.Key, it.Value)
   428  			}
   429  			if tr.Hash() != checktr.Hash() {
   430  				rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash")
   431  			}
   432  		}
   433  		// Abort the test on error.
   434  		if rt[i].err != nil {
   435  			return false
   436  		}
   437  	}
   438  	return true
   439  }
   440  
   441  func TestRandom(t *testing.T) {
   442  	if err := quick.Check(runRandTest, nil); err != nil {
   443  		if cerr, ok := err.(*quick.CheckError); ok {
   444  			t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
   445  		}
   446  		t.Fatal(err)
   447  	}
   448  }
   449  
   450  func BenchmarkGet(b *testing.B)      { benchGet(b, false) }
   451  func BenchmarkGetDB(b *testing.B)    { benchGet(b, true) }
   452  func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) }
   453  func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
   454  
   455  const benchElemCount = 20000
   456  
   457  func benchGet(b *testing.B, commit bool) {
   458  	trie := new(Trie)
   459  
   460  	if commit {
   461  		dbDir, tmpdb := tempDB()
   462  		trie, _ = NewTrie(common.Hash{}, tmpdb)
   463  
   464  		defer os.RemoveAll(dbDir)
   465  		defer tmpdb.diskDB.Close()
   466  	}
   467  
   468  	k := make([]byte, 32)
   469  	for i := 0; i < benchElemCount; i++ {
   470  		binary.LittleEndian.PutUint64(k, uint64(i))
   471  		trie.Update(k, k)
   472  	}
   473  	binary.LittleEndian.PutUint64(k, benchElemCount/2)
   474  	if commit {
   475  		trie.Commit(nil)
   476  	}
   477  
   478  	b.ResetTimer()
   479  	for i := 0; i < b.N; i++ {
   480  		trie.Get(k)
   481  	}
   482  	b.StopTimer()
   483  }
   484  
   485  func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
   486  	trie := newEmptyTrie()
   487  	k := make([]byte, 32)
   488  	for i := 0; i < b.N; i++ {
   489  		e.PutUint64(k, uint64(i))
   490  		trie.Update(k, k)
   491  	}
   492  	return trie
   493  }
   494  
   495  // Benchmarks the trie hashing. Since the trie caches the result of any operation,
   496  // we cannot use b.N as the number of hashing rouns, since all rounds apart from
   497  // the first one will be NOOP. As such, we'll use b.N as the number of account to
   498  // insert into the trie before measuring the hashing.
   499  func BenchmarkHash(b *testing.B) {
   500  	// Make the random benchmark deterministic
   501  	random := rand.New(rand.NewSource(0))
   502  
   503  	// Create a realistic account trie to hash
   504  	addresses := make([][20]byte, b.N)
   505  	for i := 0; i < len(addresses); i++ {
   506  		for j := 0; j < len(addresses[i]); j++ {
   507  			addresses[i][j] = byte(random.Intn(256))
   508  		}
   509  	}
   510  	accounts := make([][]byte, len(addresses))
   511  	for i := 0; i < len(accounts); i++ {
   512  		var (
   513  			nonce   = uint64(random.Int63())
   514  			balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
   515  			root    = emptyRoot
   516  			code    = crypto.Keccak256(nil)
   517  		)
   518  		accounts[i], _ = rlp.EncodeToBytes([]interface{}{nonce, balance, root, code})
   519  	}
   520  	// Insert the accounts into the trie and hash it
   521  	trie := newEmptyTrie()
   522  	for i := 0; i < len(addresses); i++ {
   523  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   524  	}
   525  	b.ResetTimer()
   526  	b.ReportAllocs()
   527  	trie.Hash()
   528  }
   529  
   530  // Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation,
   531  // we cannot use b.N as the number of hashing rounds, since all rounds apart from
   532  // the first one will be NOOP. As such, we'll use b.N as the number of account to
   533  // insert into the trie before measuring the hashing.
   534  func BenchmarkCommitAfterHash(b *testing.B) {
   535  	b.Run("no-onleaf", func(b *testing.B) {
   536  		benchmarkCommitAfterHash(b)
   537  	})
   538  }
   539  
   540  func benchmarkCommitAfterHash(b *testing.B) {
   541  	// Make the random benchmark deterministic
   542  	addresses, accounts := makeAccounts(b.N)
   543  	trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager()))
   544  	for i := 0; i < len(addresses); i++ {
   545  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   546  	}
   547  	// Insert the accounts into the trie and hash it
   548  	trie.Hash()
   549  	b.ResetTimer()
   550  	b.ReportAllocs()
   551  	trie.Commit(nil)
   552  }
   553  
   554  func tempDB() (string, *Database) {
   555  	dir, err := ioutil.TempDir("", "trie-bench")
   556  	if err != nil {
   557  		panic(fmt.Sprintf("can't create temporary directory: %v", err))
   558  	}
   559  	dbc := &database.DBConfig{Dir: dir, DBType: database.LevelDB, LevelDBCacheSize: 256, OpenFilesLimit: 0}
   560  	diskDB := database.NewDBManager(dbc)
   561  	return dir, NewDatabase(diskDB)
   562  }
   563  
   564  func genExternallyOwnedAccount(nonce uint64, balance *big.Int) (account.Account, error) {
   565  	return account.NewAccountWithMap(account.ExternallyOwnedAccountType, map[account.AccountValueKeyType]interface{}{
   566  		account.AccountValueKeyNonce:         nonce,
   567  		account.AccountValueKeyBalance:       balance,
   568  		account.AccountValueKeyHumanReadable: false,
   569  		account.AccountValueKeyAccountKey:    accountkey.NewAccountKeyLegacy(),
   570  	})
   571  }
   572  
   573  func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
   574  	// Make the random benchmark deterministic
   575  	random := rand.New(rand.NewSource(0))
   576  	// Create a realistic account trie to hash
   577  	addresses = make([][20]byte, size)
   578  	for i := 0; i < len(addresses); i++ {
   579  		data := make([]byte, 20)
   580  		random.Read(data)
   581  		copy(addresses[i][:], data)
   582  	}
   583  	accounts = make([][]byte, len(addresses))
   584  	for i := 0; i < len(accounts); i++ {
   585  		// The big.Rand function is not deterministic with regards to 64 vs 32 bit systems,
   586  		// and will consume different amount of data from the rand source.
   587  		// balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
   588  		// Therefore, we instead just read via byte buffer
   589  		numBytes := random.Uint32() % 33 // [0, 32] bytes
   590  		balanceBytes := make([]byte, numBytes)
   591  		random.Read(balanceBytes)
   592  		acc, _ := genExternallyOwnedAccount(uint64(i), big.NewInt(int64(i)))
   593  		serializer := account.NewAccountSerializerWithAccount(acc)
   594  		data, _ := rlp.EncodeToBytes(serializer)
   595  		accounts[i] = data
   596  	}
   597  	return addresses, accounts
   598  }
   599  
   600  // BenchmarkCommitAfterHashFixedSize benchmarks the Commit (after Hash) of a fixed number of updates to a trie.
   601  // This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically,
   602  // storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple
   603  // of thousand entries)
   604  func BenchmarkHashFixedSize(b *testing.B) {
   605  	b.Run("10", func(b *testing.B) {
   606  		b.StopTimer()
   607  		acc, add := makeAccounts(20)
   608  		for i := 0; i < b.N; i++ {
   609  			benchmarkHashFixedSize(b, acc, add)
   610  		}
   611  	})
   612  	b.Run("100", func(b *testing.B) {
   613  		b.StopTimer()
   614  		acc, add := makeAccounts(100)
   615  		for i := 0; i < b.N; i++ {
   616  			benchmarkHashFixedSize(b, acc, add)
   617  		}
   618  	})
   619  
   620  	b.Run("1K", func(b *testing.B) {
   621  		b.StopTimer()
   622  		acc, add := makeAccounts(1000)
   623  		for i := 0; i < b.N; i++ {
   624  			benchmarkHashFixedSize(b, acc, add)
   625  		}
   626  	})
   627  	b.Run("10K", func(b *testing.B) {
   628  		b.StopTimer()
   629  		acc, add := makeAccounts(10000)
   630  		for i := 0; i < b.N; i++ {
   631  			benchmarkHashFixedSize(b, acc, add)
   632  		}
   633  	})
   634  	b.Run("100K", func(b *testing.B) {
   635  		b.StopTimer()
   636  		acc, add := makeAccounts(100000)
   637  		for i := 0; i < b.N; i++ {
   638  			benchmarkHashFixedSize(b, acc, add)
   639  		}
   640  	})
   641  }
   642  
   643  func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
   644  	b.ReportAllocs()
   645  	trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager()))
   646  	for i := 0; i < len(addresses); i++ {
   647  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   648  	}
   649  	// Insert the accounts into the trie and hash it
   650  	b.StartTimer()
   651  	trie.Hash()
   652  	b.StopTimer()
   653  }
   654  
   655  func BenchmarkCommitAfterHashFixedSize(b *testing.B) {
   656  	b.Run("10", func(b *testing.B) {
   657  		b.StopTimer()
   658  		acc, add := makeAccounts(20)
   659  		for i := 0; i < b.N; i++ {
   660  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   661  		}
   662  	})
   663  	b.Run("100", func(b *testing.B) {
   664  		b.StopTimer()
   665  		acc, add := makeAccounts(100)
   666  		for i := 0; i < b.N; i++ {
   667  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   668  		}
   669  	})
   670  
   671  	b.Run("1K", func(b *testing.B) {
   672  		b.StopTimer()
   673  		acc, add := makeAccounts(1000)
   674  		for i := 0; i < b.N; i++ {
   675  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   676  		}
   677  	})
   678  	b.Run("10K", func(b *testing.B) {
   679  		b.StopTimer()
   680  		acc, add := makeAccounts(10000)
   681  		for i := 0; i < b.N; i++ {
   682  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   683  		}
   684  	})
   685  	b.Run("100K", func(b *testing.B) {
   686  		b.StopTimer()
   687  		acc, add := makeAccounts(100000)
   688  		for i := 0; i < b.N; i++ {
   689  			benchmarkCommitAfterHashFixedSize(b, acc, add)
   690  		}
   691  	})
   692  }
   693  
   694  func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
   695  	b.ReportAllocs()
   696  	trie, _ := NewTrie(common.Hash{}, NewDatabase(database.NewMemoryDBManager()))
   697  	for i := 0; i < len(addresses); i++ {
   698  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   699  	}
   700  	// Insert the accounts into the trie and hash it
   701  	trie.Hash()
   702  	b.StartTimer()
   703  	trie.Commit(nil)
   704  	b.StopTimer()
   705  }
   706  
   707  func BenchmarkDerefRootFixedSize(b *testing.B) {
   708  	b.Run("10", func(b *testing.B) {
   709  		b.StopTimer()
   710  		acc, add := makeAccounts(20)
   711  		for i := 0; i < b.N; i++ {
   712  			benchmarkDerefRootFixedSize(b, acc, add)
   713  		}
   714  	})
   715  	b.Run("100", func(b *testing.B) {
   716  		b.StopTimer()
   717  		acc, add := makeAccounts(100)
   718  		for i := 0; i < b.N; i++ {
   719  			benchmarkDerefRootFixedSize(b, acc, add)
   720  		}
   721  	})
   722  
   723  	b.Run("1K", func(b *testing.B) {
   724  		b.StopTimer()
   725  		acc, add := makeAccounts(1000)
   726  		for i := 0; i < b.N; i++ {
   727  			benchmarkDerefRootFixedSize(b, acc, add)
   728  		}
   729  	})
   730  	b.Run("10K", func(b *testing.B) {
   731  		b.StopTimer()
   732  		acc, add := makeAccounts(10000)
   733  		for i := 0; i < b.N; i++ {
   734  			benchmarkDerefRootFixedSize(b, acc, add)
   735  		}
   736  	})
   737  	b.Run("100K", func(b *testing.B) {
   738  		b.StopTimer()
   739  		acc, add := makeAccounts(100000)
   740  		for i := 0; i < b.N; i++ {
   741  			benchmarkDerefRootFixedSize(b, acc, add)
   742  		}
   743  	})
   744  }
   745  
   746  func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
   747  	b.ReportAllocs()
   748  	triedb := NewDatabase(database.NewMemoryDBManager())
   749  	trie, _ := NewTrie(common.Hash{}, triedb)
   750  	for i := 0; i < len(addresses); i++ {
   751  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   752  	}
   753  	h := trie.Hash()
   754  	trie.Commit(nil)
   755  	//_, nodes := trie.Commit(nil)
   756  	//triedb.Update(NewWithNodeSet(nodes))
   757  	b.StartTimer()
   758  	triedb.Dereference(h)
   759  	b.StopTimer()
   760  }
   761  
   762  func getString(trie *Trie, k string) []byte {
   763  	return trie.Get([]byte(k))
   764  }
   765  
   766  func updateString(trie *Trie, k, v string) {
   767  	trie.Update([]byte(k), []byte(v))
   768  }
   769  
   770  func deleteString(trie *Trie, k string) {
   771  	trie.Delete([]byte(k))
   772  }
   773  
   774  func TestDecodeNode(t *testing.T) {
   775  	t.Parallel()
   776  	var (
   777  		hash  = make([]byte, 20)
   778  		elems = make([]byte, 20)
   779  	)
   780  	for i := 0; i < 5000000; i++ {
   781  		rand.Read(hash)
   782  		rand.Read(elems)
   783  		decodeNode(hash, elems)
   784  	}
   785  }