github.com/iotexproject/iotex-core@v1.14.1-rc1/db/trie/mptrie/merklepatriciatrie_test.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package mptrie
     7  
     8  import (
     9  	"context"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/pkg/errors"
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"github.com/iotexproject/go-pkgs/hash"
    17  
    18  	"github.com/iotexproject/iotex-core/db"
    19  	"github.com/iotexproject/iotex-core/db/batch"
    20  	"github.com/iotexproject/iotex-core/db/trie"
    21  	"github.com/iotexproject/iotex-core/testutil"
    22  )
    23  
    24  var (
    25  	ham = []byte{1, 2, 3, 4, 2, 3, 4, 5}
    26  	car = []byte{1, 2, 3, 4, 5, 6, 7, 7}
    27  	cat = []byte{1, 2, 3, 4, 5, 6, 7, 8}
    28  	rat = []byte{1, 2, 3, 4, 5, 6, 7, 9}
    29  	egg = []byte{1, 2, 3, 4, 5, 8, 1, 0}
    30  	dog = []byte{1, 2, 3, 4, 6, 7, 1, 0}
    31  	fox = []byte{1, 2, 3, 5, 6, 7, 8, 9}
    32  	cow = []byte{1, 2, 5, 6, 7, 8, 9, 0}
    33  	ant = []byte{2, 3, 4, 5, 6, 7, 8, 9}
    34  
    35  	br1 = []byte{0, 3, 4, 5, 6, 7, 8, 9}
    36  	br2 = []byte{1, 3, 4, 5, 6, 7, 8, 9}
    37  	cl1 = []byte{0, 0, 4, 5, 6, 7, 8, 9}
    38  	cl2 = []byte{1, 0, 4, 5, 6, 7, 8, 9}
    39  
    40  	testV = [8][]byte{
    41  		[]byte("ham"), []byte("car"), []byte("cat"), []byte("dog"),
    42  		[]byte("egg"), []byte("fox"), []byte("cow"), []byte("ant"),
    43  	}
    44  
    45  	emptyTrieRootHash = []byte{0x61, 0x8e, 0x1c, 0xe1, 0xff, 0xfb, 0x18, 0x25, 0x15, 0x9f, 0x9a, 0xa2, 0xc2, 0xe9, 0x37, 0x24, 0x2, 0xfb, 0xd0, 0xab}
    46  )
    47  
    48  func TestEmptyTrie(t *testing.T) {
    49  	require := require.New(t)
    50  	tr, err := New()
    51  	require.NoError(err)
    52  	require.NoError(tr.Start(context.Background()))
    53  	defer require.NoError(tr.Stop(context.Background()))
    54  	require.True(tr.IsEmpty())
    55  	rootHash, err := tr.RootHash()
    56  	require.NoError(err)
    57  	require.Equal(emptyTrieRootHash, rootHash)
    58  }
    59  
    60  func Test2Roots(t *testing.T) {
    61  	require := require.New(t)
    62  
    63  	// first trie
    64  	trieDB := trie.NewMemKVStore()
    65  	tr, err := New(KVStoreOption(trieDB), KeyLengthOption(8), AsyncOption())
    66  	require.NoError(err)
    67  	require.NoError(tr.Start(context.Background()))
    68  	require.NoError(tr.Upsert(cat, testV[2]))
    69  	v, err := tr.Get(cat)
    70  	require.NoError(err)
    71  	require.Equal(testV[2], v)
    72  	require.NoError(tr.Upsert(car, testV[1]))
    73  	v, err = tr.Get(car)
    74  	require.NoError(err)
    75  	require.Equal(testV[1], v)
    76  	require.NoError(tr.Upsert(egg, testV[4]))
    77  	v, err = tr.Get(egg)
    78  	require.NoError(err)
    79  	require.Equal(testV[4], v)
    80  	root, err := tr.RootHash()
    81  	require.NoError(err)
    82  	require.NoError(tr.Stop(context.Background()))
    83  
    84  	// second trie
    85  	tr1, err := New(KVStoreOption(trieDB), KeyLengthOption(8))
    86  	require.NoError(err)
    87  	require.NoError(tr1.Start(context.Background()))
    88  	require.NoError(tr1.Upsert(dog, testV[3]))
    89  	v, err = tr1.Get(dog)
    90  	require.NoError(err)
    91  	require.Equal(testV[3], v)
    92  	require.NoError(tr1.Upsert(ham, testV[0]))
    93  	v, err = tr1.Get(ham)
    94  	require.NoError(err)
    95  	require.Equal(testV[0], v)
    96  	require.NoError(tr1.Upsert(fox, testV[5]))
    97  	v, err = tr1.Get(fox)
    98  	require.NoError(err)
    99  	require.Equal(testV[5], v)
   100  	root1, err := tr1.RootHash()
   101  	require.NoError(err)
   102  	require.NotEqual(root, root1)
   103  	require.NoError(tr1.Stop(context.Background()))
   104  
   105  	// start first trie again
   106  	require.NoError(tr.Start(context.Background()))
   107  	v, err = tr.Get(cat)
   108  	require.NoError(err)
   109  	require.Equal(testV[2], v)
   110  	v, err = tr.Get(car)
   111  	require.NoError(err)
   112  	require.Equal(testV[1], v)
   113  	v, err = tr.Get(egg)
   114  	require.NoError(err)
   115  	require.Equal(testV[4], v)
   116  	// does not contain dog
   117  	_, err = tr.Get(dog)
   118  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   119  
   120  	// create a new one and load second trie's root
   121  	tr2, err := New(KVStoreOption(trieDB), KeyLengthOption(8))
   122  	require.NoError(err)
   123  	require.NoError(tr2.Start(context.Background()))
   124  	require.NoError(tr2.SetRootHash(root1))
   125  	root2, err := tr2.RootHash()
   126  	require.NoError(err)
   127  	require.Equal(root1, root2)
   128  	v, err = tr2.Get(dog)
   129  	require.NoError(err)
   130  	require.Equal(testV[3], v)
   131  	v, err = tr2.Get(ham)
   132  	require.NoError(err)
   133  	require.Equal(testV[0], v)
   134  	v, err = tr2.Get(fox)
   135  	require.NoError(err)
   136  	require.Equal(testV[5], v)
   137  	// does not contain cat
   138  	_, err = tr2.Get(cat)
   139  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   140  	require.NoError(tr.Stop(context.Background()))
   141  	require.NoError(tr2.Stop(context.Background()))
   142  }
   143  
   144  func TestInsert(t *testing.T) {
   145  	require := require.New(t)
   146  
   147  	tr, err := New(KVStoreOption(trie.NewMemKVStore()), KeyLengthOption(8))
   148  	require.NotNil(tr)
   149  	require.NoError(err)
   150  	require.NoError(tr.Start(context.Background()))
   151  	// this adds one L to root R
   152  	t.Log("Put[cat]")
   153  	require.NoError(tr.Upsert(cat, testV[2]))
   154  	require.False(tr.IsEmpty())
   155  	root, err := tr.RootHash()
   156  	require.NoError(err)
   157  
   158  	// this splits L --> E + B + 2L (cat, rat)
   159  	/*
   160  	 *  Root --1--> E --234567--> B --> (cat, rat)
   161  	 */
   162  	t.Log("Put[rat]")
   163  	require.NoError(tr.Upsert(rat, []byte("rat")))
   164  	ratRoot, err := tr.RootHash()
   165  	require.NoError(err)
   166  	require.NotEqual(ratRoot, root)
   167  	b, err := tr.Get(cat)
   168  	require.NoError(err)
   169  	require.Equal(testV[2], b)
   170  	b, err = tr.Get(rat)
   171  	require.NoError(err)
   172  	require.Equal([]byte("rat"), b)
   173  
   174  	// it's OK to upsert a key with same value again
   175  	require.NoError(tr.Upsert(rat, []byte("rat")))
   176  	require.NoError(tr.Upsert(cat, testV[2]))
   177  	b, err = tr.Get(cat)
   178  	require.NoError(err)
   179  	require.Equal(testV[2], b)
   180  	b, err = tr.Get(rat)
   181  	require.NoError(err)
   182  	require.Equal([]byte("rat"), b)
   183  	root, err = tr.RootHash()
   184  	require.NoError(err)
   185  	// root should keep the same since the value is same
   186  	require.Equal(root, ratRoot)
   187  
   188  	// this adds another L to B (car)
   189  	/*
   190  	 *  Root --1--> E --234567--> B --> (cat, rat, car)
   191  	 */
   192  	t.Log("Put[car]")
   193  	require.NoError(tr.Upsert(car, testV[1]))
   194  	newRoot, err := tr.RootHash()
   195  	require.NoError(err)
   196  	require.NotEqual(newRoot, root)
   197  	root = newRoot
   198  	b, err = tr.Get(car)
   199  	require.NoError(err)
   200  	require.Equal(testV[1], b)
   201  	// delete car
   202  	t.Log("Del[car]")
   203  	require.NoError(tr.Delete(car))
   204  	newRoot, err = tr.RootHash()
   205  	require.NoError(err)
   206  	require.NotEqual(newRoot, root)
   207  	require.Equal(newRoot, ratRoot)
   208  	root = newRoot
   209  
   210  	// this splits E --> B1 + E1 + L (match = 3, div = 3)
   211  	/*
   212  	 *  Root --1--> E --234--> B1 --5--> E1 --67--> B --> (cat, rat)
   213  	 *                          | --6--> L --710--> dog
   214  	 */
   215  	t.Log("Put[dog]")
   216  	require.NoError(tr.Upsert(dog, testV[3]))
   217  	newRoot, err = tr.RootHash()
   218  	require.NoError(err)
   219  	require.NotEqual(newRoot, root)
   220  	root = newRoot
   221  	// Get returns "dog" now
   222  	b, err = tr.Get(dog)
   223  	require.NoError(err)
   224  	require.Equal(testV[3], b)
   225  	b, err = tr.Get(cat)
   226  	require.NoError(err)
   227  	require.Equal(testV[2], b)
   228  	b, err = tr.Get(rat)
   229  	require.NoError(err)
   230  	require.Equal([]byte("rat"), b)
   231  	_, err = tr.Get(car)
   232  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   233  
   234  	// this deletes 'dog' and turns B1 into another E2
   235  	/*
   236  	 *  Root --1--> E --234--> E2 --5--> E1 --67--> B --> (cat, rat)
   237  	 */
   238  	t.Log("Del[dog]")
   239  	require.NoError(tr.Delete(dog))
   240  	newRoot, err = tr.RootHash()
   241  	require.NoError(err)
   242  	require.NotEqual(newRoot, root)
   243  	root = newRoot
   244  
   245  	// this splits E1 --> B2 + E3 + L (match = 0, div = 2)
   246  	/*
   247  	 *  Root --1--> E --234--> E2 --5--> B2 --6--> E3 --7--> B --> (cat, rat)
   248  	 *                                    | --8--> L --10--> egg
   249  	 */
   250  	t.Log("Put[egg]")
   251  	require.NoError(tr.Upsert(egg, testV[4]))
   252  	newRoot, err = tr.RootHash()
   253  	require.NoError(err)
   254  	require.NotEqual(newRoot, root)
   255  	root = newRoot
   256  	b, err = tr.Get(egg)
   257  	require.NoError(err)
   258  	require.Equal(testV[4], b)
   259  	// delete egg
   260  	t.Log("Del[egg]")
   261  	require.NoError(tr.Delete(egg))
   262  	eggRoot, err := tr.RootHash()
   263  	require.NoError(err)
   264  	require.NotEqual(eggRoot, root)
   265  	root = eggRoot
   266  
   267  	// this splits E (with match = 4, div = 1)
   268  	t.Log("Put[egg]")
   269  	require.NoError(tr.Upsert(egg, testV[4]))
   270  	newRoot, err = tr.RootHash()
   271  	require.NoError(err)
   272  	require.NotEqual(newRoot, root)
   273  	root = newRoot
   274  	b, err = tr.Get(egg)
   275  	require.NoError(err)
   276  	require.Equal(testV[4], b)
   277  	// delete egg
   278  	t.Log("Del[egg]")
   279  	require.NoError(tr.Delete(egg))
   280  	newRoot, err = tr.RootHash()
   281  	require.NoError(err)
   282  	require.NotEqual(newRoot, root)
   283  	require.Equal(newRoot, eggRoot)
   284  	root = newRoot
   285  	_, err = tr.Get(dog)
   286  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   287  	_, err = tr.Get(egg)
   288  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   289  
   290  	// insert 'ham' 'fox' 'cow'
   291  	t.Log("Put[ham]")
   292  	require.NoError(tr.Upsert(ham, testV[0]))
   293  	newRoot, err = tr.RootHash()
   294  	require.NoError(err)
   295  	require.NotEqual(newRoot, root)
   296  	root = newRoot
   297  	b, err = tr.Get(ham)
   298  	require.NoError(err)
   299  	require.Equal(testV[0], b)
   300  	t.Log("Put[fox]")
   301  	require.NoError(tr.Upsert(fox, testV[5]))
   302  	newRoot, err = tr.RootHash()
   303  	require.NoError(err)
   304  	require.NotEqual(newRoot, root)
   305  	root = newRoot
   306  	b, err = tr.Get(fox)
   307  	require.NoError(err)
   308  	require.Equal(testV[5], b)
   309  	t.Log("Put[cow]")
   310  	require.NoError(tr.Upsert(cow, testV[6]))
   311  	newRoot, err = tr.RootHash()
   312  	require.NoError(err)
   313  	require.NotEqual(newRoot, root)
   314  	root = newRoot
   315  	b, err = tr.Get(cow)
   316  	require.NoError(err)
   317  	require.Equal(testV[6], b)
   318  
   319  	// delete fox rat cow
   320  	t.Log("Del[fox]")
   321  	require.NoError(tr.Delete(fox))
   322  	newRoot, err = tr.RootHash()
   323  	require.NoError(err)
   324  	require.NotEqual(newRoot, root)
   325  	root = newRoot
   326  	t.Log("Del[rat]")
   327  	require.NoError(tr.Delete(rat))
   328  	newRoot, err = tr.RootHash()
   329  	require.NoError(err)
   330  	require.NotEqual(newRoot, root)
   331  	root = newRoot
   332  	t.Log("Del[cow]")
   333  	require.NoError(tr.Delete(cow))
   334  	newRoot, err = tr.RootHash()
   335  	require.NoError(err)
   336  	require.NotEqual(newRoot, root)
   337  	root = newRoot
   338  	_, err = tr.Get(fox)
   339  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   340  	_, err = tr.Get(rat)
   341  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   342  	_, err = tr.Get(cow)
   343  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   344  	b, err = tr.Get(ham)
   345  	require.NoError(err)
   346  	require.Equal(testV[0], b)
   347  
   348  	// this adds another path to root B
   349  	t.Log("Put[ant]")
   350  	require.NoError(tr.Upsert(ant, testV[7]))
   351  	newRoot, err = tr.RootHash()
   352  	require.NoError(err)
   353  	require.NotEqual(newRoot, root)
   354  	root = newRoot
   355  	b, err = tr.Get(ant)
   356  	require.NoError(err)
   357  	require.Equal(testV[7], b)
   358  	t.Log("Del[ant]")
   359  	require.NoError(tr.Delete(ant))
   360  	newRoot, err = tr.RootHash()
   361  	require.NoError(err)
   362  	require.NotEqual(newRoot, root)
   363  	root = newRoot
   364  
   365  	// delete "ham"
   366  	t.Log("Del[ham]")
   367  	require.NoError(tr.Delete(ham))
   368  	newRoot, err = tr.RootHash()
   369  	require.NoError(err)
   370  	require.NotEqual(newRoot, root)
   371  	_, err = tr.Get(ham)
   372  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   373  	_, err = tr.Get(ant)
   374  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   375  	b, err = tr.Get(cat)
   376  	require.NoError(err)
   377  	require.Equal(testV[2], b)
   378  
   379  	// delete "cat"
   380  	t.Log("Del[cat]")
   381  	require.NoError(tr.Delete(cat))
   382  	require.True(tr.IsEmpty())
   383  	require.NoError(tr.Stop(context.Background()))
   384  }
   385  
   386  func TestBatchCommit(t *testing.T) {
   387  	require := require.New(t)
   388  
   389  	trieDB := trie.NewMemKVStore()
   390  	tr, err := New(KeyLengthOption(8), KVStoreOption(trieDB))
   391  	require.NoError(err)
   392  	require.NoError(tr.Start(context.Background()))
   393  	// insert 3 entries
   394  	require.NoError(tr.Upsert(cat, testV[2]))
   395  	require.NoError(tr.Upsert(car, testV[1]))
   396  	require.NoError(tr.Upsert(egg, testV[4]))
   397  	c, _ := tr.Get(cat)
   398  	require.Equal(testV[2], c)
   399  	// entries committed exist
   400  	v, _ := tr.Get(cat)
   401  	require.Equal(testV[2], v)
   402  	v, _ = tr.Get(car)
   403  	require.Equal(testV[1], v)
   404  	v, _ = tr.Get(egg)
   405  	require.Equal(testV[4], v)
   406  	// entries not committed won't exist
   407  	_, err = tr.Get(dog)
   408  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   409  	_, err = tr.Get(ham)
   410  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   411  	_, err = tr.Get(fox)
   412  	require.Equal(trie.ErrNotExist, errors.Cause(err))
   413  
   414  	// insert 3 entries again
   415  	require.NoError(tr.Upsert(dog, testV[3]))
   416  	require.NoError(tr.Upsert(ham, testV[0]))
   417  	require.NoError(tr.Upsert(fox, testV[6]))
   418  	v, _ = tr.Get(fox)
   419  	require.Equal(testV[6], v)
   420  	require.NoError(tr.Upsert(fox, testV[5]))
   421  	v, _ = tr.Get(fox)
   422  	require.Equal(testV[5], v)
   423  	root, err := tr.RootHash()
   424  	require.NoError(err)
   425  	// commit and reopen
   426  	require.NoError(tr.Stop(context.Background()))
   427  	tr, err = New(KVStoreOption(trieDB), RootHashOption(root), KeyLengthOption(8))
   428  	require.NoError(err)
   429  	require.NoError(tr.Start(context.Background()))
   430  	// all entries should exist now
   431  	v, _ = tr.Get(cat)
   432  	require.Equal(testV[2], v)
   433  	v, _ = tr.Get(car)
   434  	require.Equal(testV[1], v)
   435  	v, _ = tr.Get(egg)
   436  	require.Equal(testV[4], v)
   437  	v, _ = tr.Get(dog)
   438  	require.Equal(testV[3], v)
   439  	v, _ = tr.Get(ham)
   440  	require.Equal(testV[0], v)
   441  	v, _ = tr.Get(fox)
   442  	require.Equal(testV[5], v)
   443  	require.NoError(tr.Stop(context.Background()))
   444  }
   445  
   446  func TestHistoryTrie(t *testing.T) {
   447  	require := require.New(t)
   448  	cfg := db.DefaultConfig
   449  	AccountKVNamespace := "Account"
   450  	path := "test-history-trie.bolt"
   451  	testPath, err := testutil.PathOfTempFile(path)
   452  	require.NoError(err)
   453  	defer testutil.CleanupPath(testPath)
   454  
   455  	cfg.DbPath = testPath
   456  	opts := []db.KVStoreFlusherOption{
   457  		db.FlushTranslateOption(func(wi *batch.WriteInfo) *batch.WriteInfo {
   458  			if wi.WriteType() == batch.Delete {
   459  				return nil
   460  			}
   461  			return wi
   462  		}),
   463  	}
   464  	dao := db.NewBoltDB(cfg)
   465  	ctx := context.Background()
   466  	require.NoError(dao.Start(ctx))
   467  	flusher, err := db.NewKVStoreFlusher(dao, batch.NewCachedBatch(), opts...)
   468  	require.NoError(err)
   469  	addrKey := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
   470  	value1 := []byte{1}
   471  	value2 := []byte{2}
   472  
   473  	trieDB, err := trie.NewKVStore(AccountKVNamespace, flusher.KVStoreWithBuffer())
   474  	require.NoError(err)
   475  	tr, err := New(KVStoreOption(trieDB), RootHashOption(nil))
   476  	require.NoError(err)
   477  	require.NoError(tr.Start(ctx))
   478  
   479  	// insert 1 entry
   480  	require.NoError(tr.Upsert(addrKey, value1))
   481  	c, err := tr.Get(addrKey)
   482  	require.NoError(err)
   483  	require.Equal(value1, c)
   484  	oldRoot, err := tr.RootHash()
   485  	require.NoError(err)
   486  
   487  	// update entry
   488  	require.NoError(tr.Upsert(addrKey, value2))
   489  	require.NoError(flusher.Flush())
   490  
   491  	// get new value
   492  	c, err = tr.Get(addrKey)
   493  	require.NoError(err)
   494  	require.Equal(value2, c)
   495  
   496  	// get history value
   497  	require.NoError(tr.SetRootHash(oldRoot))
   498  	c, err = tr.Get(addrKey)
   499  	require.NoError(err)
   500  	require.Equal(value1, c)
   501  }
   502  
   503  func TestCollision(t *testing.T) {
   504  	require := require.New(t)
   505  
   506  	tr, err := New(KeyLengthOption(8))
   507  	require.NoError(err)
   508  	require.NoError(tr.Start(context.Background()))
   509  	defer func() {
   510  		require.NoError(tr.Stop(context.Background()))
   511  	}()
   512  
   513  	// this creates 2 leaf (with same value) on branch '0' and '1'
   514  	require.NoError(tr.Upsert(br1, testV[0]))
   515  	require.NoError(tr.Upsert(br2, testV[0]))
   516  	// this adds another 2 leaf (with same value), which splits the first 2 leaf
   517  	require.NoError(tr.Upsert(cl1, testV[0]))
   518  	require.NoError(tr.Upsert(cl2, testV[0]))
   519  	v, _ := tr.Get(br1)
   520  	require.Equal(testV[0], v)
   521  	v, _ = tr.Get(br2)
   522  	require.Equal(testV[0], v)
   523  	v, _ = tr.Get(cl1)
   524  	require.Equal(testV[0], v)
   525  	v, _ = tr.Get(cl2)
   526  	require.Equal(testV[0], v)
   527  }
   528  
   529  func Test4kEntries(t *testing.T) {
   530  	t.Run("test async mode", func(t *testing.T) {
   531  		test4kEntries(t, true)
   532  	})
   533  	t.Run("test sync mode", func(t *testing.T) {
   534  		test4kEntries(t, false)
   535  	})
   536  }
   537  
   538  func test4kEntries(t *testing.T, enableAsync bool) {
   539  	require := require.New(t)
   540  
   541  	var tr trie.Trie
   542  	var err error
   543  	if enableAsync {
   544  		tr, err = New(KeyLengthOption(4), AsyncOption())
   545  	} else {
   546  		tr, err = New(KeyLengthOption(4))
   547  	}
   548  	require.NoError(err)
   549  	require.NoError(tr.Start(context.Background()))
   550  	root, err := tr.RootHash()
   551  	require.NoError(err)
   552  	seed := time.Now().Nanosecond()
   553  	// insert 4k entries
   554  	var k [32]byte
   555  	k[0] = byte(seed)
   556  	c := 0
   557  	for c = 0; c < 1<<12; c++ {
   558  		k = hash.Hash256b(k[:])
   559  		v := testV[k[0]&7]
   560  		if _, err := tr.Get(k[:4]); err == nil {
   561  			t.Logf("Warning: collision on k %x", k[:4])
   562  			break
   563  		}
   564  		require.NoError(tr.Upsert(k[:4], v))
   565  		newRoot, err := tr.RootHash()
   566  		require.NoError(err)
   567  		require.False(tr.IsEmpty())
   568  		require.NotEqual(newRoot, root)
   569  		root = newRoot
   570  		b, err := tr.Get(k[:4])
   571  		require.NoError(err)
   572  		require.Equal(v, b)
   573  		// update <k, v>
   574  		v = testV[7-k[0]&7]
   575  		require.NoError(tr.Upsert(k[:4], v))
   576  		b, err = tr.Get(k[:4])
   577  		require.NoError(err)
   578  		require.Equal(v, b)
   579  		if c%64 == 0 {
   580  			t.Logf("Put -- key: %x", k[:4])
   581  		}
   582  	}
   583  	// delete 4k entries
   584  	var d [32]byte
   585  	d[0] = byte(seed)
   586  	// save the first 3, delete them last
   587  	d1 := hash.Hash256b(d[:])
   588  	d2 := hash.Hash256b(d1[:])
   589  	d3 := hash.Hash256b(d2[:])
   590  	d = d3
   591  	for i := 0; i < c-3; i++ {
   592  		d = hash.Hash256b(d[:])
   593  		require.NoError(tr.Delete(d[:4]))
   594  		newRoot, err := tr.RootHash()
   595  		require.NoError(err)
   596  		require.False(tr.IsEmpty())
   597  		require.NotEqual(newRoot, root)
   598  		root = newRoot
   599  		_, err = tr.Get(d[:4])
   600  		require.Equal(trie.ErrNotExist, errors.Cause(err))
   601  		if i%64 == 0 {
   602  			t.Logf("Del -- key: %x", d[:4])
   603  		}
   604  	}
   605  	require.NoError(tr.Delete(d1[:4]))
   606  	require.NoError(tr.Delete(d2[:4]))
   607  	require.NoError(tr.Delete(d3[:4]))
   608  	// trie should fallback to empty
   609  	require.True(tr.IsEmpty())
   610  	require.NoError(tr.Stop(context.Background()))
   611  }
   612  
   613  func TestPressure(t *testing.T) {
   614  	if testing.Short() {
   615  		t.Skip("Skipping TestPressure in short mode.")
   616  	}
   617  
   618  	require := require.New(t)
   619  
   620  	tr, err := New(KeyLengthOption(4))
   621  	require.NoError(err)
   622  	require.NoError(tr.Start(context.Background()))
   623  	root, err := tr.RootHash()
   624  	require.NoError(err)
   625  	seed := time.Now().Nanosecond()
   626  	// insert 128k entries
   627  	var k [32]byte
   628  	k[0] = byte(seed)
   629  	c := 0
   630  	for c = 0; c < 1<<17; c++ {
   631  		k = hash.Hash256b(k[:])
   632  		v := testV[k[0]&7]
   633  		if _, err := tr.Get(k[:4]); err == nil {
   634  			t.Logf("Warning: collision on k %x", k[:4])
   635  			break
   636  		}
   637  		require.NoError(tr.Upsert(k[:4], v))
   638  		newRoot, err := tr.RootHash()
   639  		require.NoError(err)
   640  		require.False(tr.IsEmpty())
   641  		require.NotEqual(newRoot, root)
   642  		root = newRoot
   643  		b, err := tr.Get(k[:4])
   644  		require.NoError(err)
   645  		require.Equal(v, b)
   646  		if c%(2<<10) == 0 {
   647  			t.Logf("Put -- key: %x", k[:4])
   648  		}
   649  	}
   650  	// delete 128k entries
   651  	var d [32]byte
   652  	d[0] = byte(seed)
   653  	// save the first 3, delete them last
   654  	d1 := hash.Hash256b(d[:])
   655  	d2 := hash.Hash256b(d1[:])
   656  	d3 := hash.Hash256b(d2[:])
   657  	d = d3
   658  	for i := 0; i < c-3; i++ {
   659  		d = hash.Hash256b(d[:])
   660  		require.NoError(tr.Delete(d[:4]))
   661  		newRoot, err := tr.RootHash()
   662  		require.NoError(err)
   663  		require.False(tr.IsEmpty())
   664  		require.NotEqual(newRoot, root)
   665  		root = newRoot
   666  		_, err = tr.Get(d[:4])
   667  		require.Equal(trie.ErrNotExist, errors.Cause(err))
   668  		if i%(2<<10) == 0 {
   669  			t.Logf("Del -- key: %x", d[:4])
   670  		}
   671  	}
   672  	require.NoError(tr.Delete(d1[:4]))
   673  	require.NoError(tr.Delete(d2[:4]))
   674  	require.NoError(tr.Delete(d3[:4]))
   675  	// trie should fallback to empty
   676  	require.True(tr.IsEmpty())
   677  	require.NoError(tr.Stop(context.Background()))
   678  	t.Logf("Warning: test %d entries", c)
   679  }
   680  
   681  func TestTrieGet(t *testing.T) {
   682  	var (
   683  		require = require.New(t)
   684  		tests   = []struct{ k, v []byte }{
   685  			{[]byte("iotex"), []byte("coin")},
   686  			{[]byte("block"), []byte("chain")},
   687  			{[]byte("puppy"), []byte("dog")},
   688  		}
   689  	)
   690  
   691  	trie, err := New(KeyLengthOption(5))
   692  	require.NoError(err)
   693  	require.NoError(trie.Start(context.Background()))
   694  	defer require.NoError(trie.Stop(context.Background()))
   695  
   696  	for _, test := range tests {
   697  		require.NoError(trie.Upsert(test.k, test.v))
   698  	}
   699  	for _, test := range tests {
   700  		val, err := trie.Get(test.k)
   701  		require.NoError(err)
   702  		require.Equal(test.v, val)
   703  	}
   704  }
   705  
   706  func TestTrieUpsert(t *testing.T) {
   707  	var (
   708  		require = require.New(t)
   709  		key     = []byte("puppy")
   710  		tests   = []struct{ k, v []byte }{
   711  			{key, []byte("dog")},
   712  			{key, []byte("teddy")},
   713  			{key, []byte("snoop")},
   714  			{key, []byte("snooooooop")},
   715  		}
   716  	)
   717  
   718  	trie, err := New(KeyLengthOption(5))
   719  	require.NoError(err)
   720  	require.NoError(trie.Start(context.Background()))
   721  	defer require.NoError(trie.Stop(context.Background()))
   722  
   723  	for _, test := range tests {
   724  		require.NoError(trie.Upsert(test.k, test.v))
   725  	}
   726  	val, err := trie.Get(key)
   727  	require.NoError(err)
   728  	require.Equal(tests[len(tests)-1].v, val)
   729  }
   730  
   731  func TestTrieDelete(t *testing.T) {
   732  	var (
   733  		require = require.New(t)
   734  		tests   = []struct{ k, v []byte }{
   735  			{[]byte("iotex"), []byte("coin")},
   736  			{[]byte("block"), []byte("chain")},
   737  			{[]byte("puppy"), []byte("dog")},
   738  		}
   739  	)
   740  	tr, err := New(KeyLengthOption(5))
   741  	require.NoError(err)
   742  	require.NoError(tr.Start(context.Background()))
   743  	defer require.NoError(tr.Stop(context.Background()))
   744  
   745  	for _, test := range tests {
   746  		_, err = tr.Get(test.k)
   747  		require.Equal(trie.ErrNotExist, errors.Cause(err))
   748  
   749  		require.NoError(tr.Upsert(test.k, test.v))
   750  	}
   751  	for _, test := range tests {
   752  		val, err := tr.Get(test.k)
   753  		require.NoError(err)
   754  		require.Equal(test.v, val)
   755  
   756  		require.NoError(tr.Delete(test.k))
   757  		_, err = tr.Get(test.k)
   758  		require.Equal(trie.ErrNotExist, errors.Cause(err))
   759  	}
   760  	require.True(tr.IsEmpty())
   761  }
   762  
   763  func TestTrieSetRootHash(t *testing.T) {
   764  	var (
   765  		require = require.New(t)
   766  		tests   = []struct{ k, v []byte }{
   767  			{[]byte("iotex"), []byte("coin")},
   768  			{[]byte("block"), []byte("chain")},
   769  			{[]byte("chain"), []byte("link")},
   770  			{[]byte("puppy"), []byte("dog")},
   771  			{[]byte("night"), []byte("knight")},
   772  		}
   773  		trieDB = trie.NewMemKVStore()
   774  	)
   775  
   776  	tr, err := New(KVStoreOption(trieDB), KeyLengthOption(5))
   777  	require.NoError(err)
   778  	require.NoError(tr.Start(context.Background()))
   779  	defer require.NoError(tr.Stop(context.Background()))
   780  	for _, test := range tests {
   781  		require.NoError(tr.Upsert(test.k, test.v))
   782  	}
   783  	rootHash, err := tr.RootHash()
   784  	require.NoError(err)
   785  	require.NotEqual(emptyTrieRootHash, rootHash)
   786  
   787  	// new empty trie and load tr's rootHash
   788  	tr1, err := New(KVStoreOption(trieDB), KeyLengthOption(5))
   789  	require.NoError(err)
   790  	require.NoError(tr1.Start(context.Background()))
   791  	defer require.NoError(tr1.Stop(context.Background()))
   792  	tr1Hash, err := tr1.RootHash()
   793  	require.NoError(err)
   794  	require.Equal(emptyTrieRootHash, tr1Hash)
   795  	require.NoError(tr1.SetRootHash(rootHash))
   796  	for _, test := range tests {
   797  		val, err := tr1.Get(test.k)
   798  		require.NoError(err)
   799  		require.Equal(test.v, val)
   800  	}
   801  }