github.com/Finschia/finschia-sdk@v0.49.1/store/iavl/store_test.go (about)

     1  package iavl
     2  
     3  import (
     4  	crand "crypto/rand"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/Finschia/ostracon/libs/log"
     9  	"github.com/cosmos/iavl"
    10  	"github.com/stretchr/testify/require"
    11  	abci "github.com/tendermint/tendermint/abci/types"
    12  	dbm "github.com/tendermint/tm-db"
    13  
    14  	"github.com/Finschia/finschia-sdk/store/cachekv"
    15  	"github.com/Finschia/finschia-sdk/store/types"
    16  	"github.com/Finschia/finschia-sdk/types/kv"
    17  )
    18  
    19  var (
    20  	cacheSize = 100
    21  	treeData  = map[string]string{
    22  		"hello": "goodbye",
    23  		"aloha": "shalom",
    24  	}
    25  	nMoreData = 0
    26  )
    27  
    28  func randBytes(numBytes int) []byte {
    29  	b := make([]byte, numBytes)
    30  	_, _ = crand.Read(b)
    31  	return b
    32  }
    33  
    34  // make a tree with data from above and save it
    35  func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, types.CommitID) {
    36  	t.Helper()
    37  	tree, err := iavl.NewMutableTree(db, cacheSize, false)
    38  	require.NoError(t, err)
    39  
    40  	for k, v := range treeData {
    41  		_, err := tree.Set([]byte(k), []byte(v))
    42  		if err != nil {
    43  			panic(err)
    44  		}
    45  	}
    46  
    47  	for i := 0; i < nMoreData; i++ {
    48  		key := randBytes(12)
    49  		value := randBytes(50)
    50  		_, err := tree.Set(key, value)
    51  		if err != nil {
    52  			panic(err)
    53  		}
    54  	}
    55  
    56  	hash, ver, err := tree.SaveVersion()
    57  	require.Nil(t, err)
    58  
    59  	return tree, types.CommitID{Version: ver, Hash: hash}
    60  }
    61  
    62  func TestLoadStore(t *testing.T) {
    63  	db := dbm.NewMemDB()
    64  	tree, _ := newAlohaTree(t, db)
    65  	store := UnsafeNewStore(tree)
    66  
    67  	// Create non-pruned height H
    68  	updated, err := tree.Set([]byte("hello"), []byte("hallo"))
    69  	require.NoError(t, err)
    70  	require.True(t, updated)
    71  	hash, verH, err := tree.SaveVersion()
    72  	cIDH := types.CommitID{Version: verH, Hash: hash}
    73  	require.Nil(t, err)
    74  
    75  	// Create pruned height Hp
    76  	updated, err = tree.Set([]byte("hello"), []byte("hola"))
    77  	require.NoError(t, err)
    78  	require.True(t, updated)
    79  	hash, verHp, err := tree.SaveVersion()
    80  	cIDHp := types.CommitID{Version: verHp, Hash: hash}
    81  	require.Nil(t, err)
    82  
    83  	// TODO: Prune this height
    84  
    85  	// Create current height Hc
    86  	updated, err = tree.Set([]byte("hello"), []byte("ciao"))
    87  	require.NoError(t, err)
    88  	require.True(t, updated)
    89  	hash, verHc, err := tree.SaveVersion()
    90  	cIDHc := types.CommitID{Version: verHc, Hash: hash}
    91  	require.Nil(t, err)
    92  
    93  	// Querying an existing store at some previous non-pruned height H
    94  	hStore, err := store.GetImmutable(verH)
    95  	require.NoError(t, err)
    96  	require.Equal(t, string(hStore.Get([]byte("hello"))), "hallo")
    97  
    98  	// Querying an existing store at some previous pruned height Hp
    99  	hpStore, err := store.GetImmutable(verHp)
   100  	require.NoError(t, err)
   101  	require.Equal(t, string(hpStore.Get([]byte("hello"))), "hola")
   102  
   103  	// Querying an existing store at current height Hc
   104  	hcStore, err := store.GetImmutable(verHc)
   105  	require.NoError(t, err)
   106  	require.Equal(t, string(hcStore.Get([]byte("hello"))), "ciao")
   107  
   108  	// Querying a new store at some previous non-pruned height H
   109  	newHStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDH, false, DefaultIAVLCacheSize, false)
   110  	require.NoError(t, err)
   111  	require.Equal(t, string(newHStore.Get([]byte("hello"))), "hallo")
   112  
   113  	// Querying a new store at some previous pruned height Hp
   114  	newHpStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDHp, false, DefaultIAVLCacheSize, false)
   115  	require.NoError(t, err)
   116  	require.Equal(t, string(newHpStore.Get([]byte("hello"))), "hola")
   117  
   118  	// Querying a new store at current height H
   119  	newHcStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDHc, false, DefaultIAVLCacheSize, false)
   120  	require.NoError(t, err)
   121  	require.Equal(t, string(newHcStore.Get([]byte("hello"))), "ciao")
   122  }
   123  
   124  func TestGetImmutable(t *testing.T) {
   125  	db := dbm.NewMemDB()
   126  	tree, _ := newAlohaTree(t, db)
   127  	store := UnsafeNewStore(tree)
   128  
   129  	updated, err := tree.Set([]byte("hello"), []byte("adios"))
   130  	require.NoError(t, err)
   131  	require.True(t, updated)
   132  	hash, ver, err := tree.SaveVersion()
   133  	cID := types.CommitID{Version: ver, Hash: hash}
   134  	require.Nil(t, err)
   135  
   136  	_, err = store.GetImmutable(cID.Version + 1)
   137  	require.NoError(t, err)
   138  
   139  	newStore, err := store.GetImmutable(cID.Version - 1)
   140  	require.NoError(t, err)
   141  	require.Equal(t, newStore.Get([]byte("hello")), []byte("goodbye"))
   142  
   143  	newStore, err = store.GetImmutable(cID.Version)
   144  	require.NoError(t, err)
   145  	require.Equal(t, newStore.Get([]byte("hello")), []byte("adios"))
   146  
   147  	res := newStore.Query(abci.RequestQuery{Data: []byte("hello"), Height: cID.Version, Path: "/key", Prove: true})
   148  	require.Equal(t, res.Value, []byte("adios"))
   149  	require.NotNil(t, res.ProofOps)
   150  
   151  	require.Panics(t, func() { newStore.Set(nil, nil) })
   152  	require.Panics(t, func() { newStore.Delete(nil) })
   153  	require.Panics(t, func() { newStore.Commit() })
   154  }
   155  
   156  func TestTestGetImmutableIterator(t *testing.T) {
   157  	db := dbm.NewMemDB()
   158  	tree, cID := newAlohaTree(t, db)
   159  	store := UnsafeNewStore(tree)
   160  
   161  	newStore, err := store.GetImmutable(cID.Version)
   162  	require.NoError(t, err)
   163  
   164  	iter := newStore.Iterator([]byte("aloha"), []byte("hellz"))
   165  	expected := []string{"aloha", "hello"}
   166  	var i int
   167  
   168  	for i = 0; iter.Valid(); iter.Next() {
   169  		expectedKey := expected[i]
   170  		key, value := iter.Key(), iter.Value()
   171  		require.EqualValues(t, key, expectedKey)
   172  		require.EqualValues(t, value, treeData[expectedKey])
   173  		i++
   174  	}
   175  
   176  	require.Equal(t, len(expected), i)
   177  }
   178  
   179  func TestIAVLStoreGetSetHasDelete(t *testing.T) {
   180  	db := dbm.NewMemDB()
   181  	tree, _ := newAlohaTree(t, db)
   182  	iavlStore := UnsafeNewStore(tree)
   183  
   184  	key := "hello"
   185  
   186  	exists := iavlStore.Has([]byte(key))
   187  	require.True(t, exists)
   188  
   189  	value := iavlStore.Get([]byte(key))
   190  	require.EqualValues(t, value, treeData[key])
   191  
   192  	value2 := "notgoodbye"
   193  	iavlStore.Set([]byte(key), []byte(value2))
   194  
   195  	value = iavlStore.Get([]byte(key))
   196  	require.EqualValues(t, value, value2)
   197  
   198  	iavlStore.Delete([]byte(key))
   199  
   200  	exists = iavlStore.Has([]byte(key))
   201  	require.False(t, exists)
   202  }
   203  
   204  func TestIAVLStoreNoNilSet(t *testing.T) {
   205  	db := dbm.NewMemDB()
   206  	tree, _ := newAlohaTree(t, db)
   207  	iavlStore := UnsafeNewStore(tree)
   208  
   209  	require.Panics(t, func() { iavlStore.Set(nil, []byte("value")) }, "setting a nil key should panic")
   210  	require.Panics(t, func() { iavlStore.Set([]byte(""), []byte("value")) }, "setting an empty key should panic")
   211  
   212  	require.Panics(t, func() { iavlStore.Set([]byte("key"), nil) }, "setting a nil value should panic")
   213  }
   214  
   215  func TestIAVLIterator(t *testing.T) {
   216  	db := dbm.NewMemDB()
   217  	tree, _ := newAlohaTree(t, db)
   218  	iavlStore := UnsafeNewStore(tree)
   219  	iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz"))
   220  	expected := []string{"aloha", "hello"}
   221  	var i int
   222  
   223  	for i = 0; iter.Valid(); iter.Next() {
   224  		expectedKey := expected[i]
   225  		key, value := iter.Key(), iter.Value()
   226  		require.EqualValues(t, key, expectedKey)
   227  		require.EqualValues(t, value, treeData[expectedKey])
   228  		i++
   229  	}
   230  	require.Equal(t, len(expected), i)
   231  
   232  	iter = iavlStore.Iterator([]byte("golang"), []byte("rocks"))
   233  	expected = []string{"hello"}
   234  	for i = 0; iter.Valid(); iter.Next() {
   235  		expectedKey := expected[i]
   236  		key, value := iter.Key(), iter.Value()
   237  		require.EqualValues(t, key, expectedKey)
   238  		require.EqualValues(t, value, treeData[expectedKey])
   239  		i++
   240  	}
   241  	require.Equal(t, len(expected), i)
   242  
   243  	iter = iavlStore.Iterator(nil, []byte("golang"))
   244  	expected = []string{"aloha"}
   245  	for i = 0; iter.Valid(); iter.Next() {
   246  		expectedKey := expected[i]
   247  		key, value := iter.Key(), iter.Value()
   248  		require.EqualValues(t, key, expectedKey)
   249  		require.EqualValues(t, value, treeData[expectedKey])
   250  		i++
   251  	}
   252  	require.Equal(t, len(expected), i)
   253  
   254  	iter = iavlStore.Iterator(nil, []byte("shalom"))
   255  	expected = []string{"aloha", "hello"}
   256  	for i = 0; iter.Valid(); iter.Next() {
   257  		expectedKey := expected[i]
   258  		key, value := iter.Key(), iter.Value()
   259  		require.EqualValues(t, key, expectedKey)
   260  		require.EqualValues(t, value, treeData[expectedKey])
   261  		i++
   262  	}
   263  	require.Equal(t, len(expected), i)
   264  
   265  	iter = iavlStore.Iterator(nil, nil)
   266  	expected = []string{"aloha", "hello"}
   267  	for i = 0; iter.Valid(); iter.Next() {
   268  		expectedKey := expected[i]
   269  		key, value := iter.Key(), iter.Value()
   270  		require.EqualValues(t, key, expectedKey)
   271  		require.EqualValues(t, value, treeData[expectedKey])
   272  		i++
   273  	}
   274  	require.Equal(t, len(expected), i)
   275  
   276  	iter = iavlStore.Iterator([]byte("golang"), nil)
   277  	expected = []string{"hello"}
   278  	for i = 0; iter.Valid(); iter.Next() {
   279  		expectedKey := expected[i]
   280  		key, value := iter.Key(), iter.Value()
   281  		require.EqualValues(t, key, expectedKey)
   282  		require.EqualValues(t, value, treeData[expectedKey])
   283  		i++
   284  	}
   285  	require.Equal(t, len(expected), i)
   286  }
   287  
   288  func TestIAVLReverseIterator(t *testing.T) {
   289  	db := dbm.NewMemDB()
   290  
   291  	tree, err := iavl.NewMutableTree(db, cacheSize, false)
   292  	require.NoError(t, err)
   293  
   294  	iavlStore := UnsafeNewStore(tree)
   295  
   296  	iavlStore.Set([]byte{0x00}, []byte("0"))
   297  	iavlStore.Set([]byte{0x00, 0x00}, []byte("0 0"))
   298  	iavlStore.Set([]byte{0x00, 0x01}, []byte("0 1"))
   299  	iavlStore.Set([]byte{0x00, 0x02}, []byte("0 2"))
   300  	iavlStore.Set([]byte{0x01}, []byte("1"))
   301  
   302  	testReverseIterator := func(t *testing.T, start, end []byte, expected []string) {
   303  		t.Helper()
   304  		iter := iavlStore.ReverseIterator(start, end)
   305  		var i int
   306  		for i = 0; iter.Valid(); iter.Next() {
   307  			expectedValue := expected[i]
   308  			value := iter.Value()
   309  			require.EqualValues(t, string(value), expectedValue)
   310  			i++
   311  		}
   312  		require.Equal(t, len(expected), i)
   313  	}
   314  
   315  	testReverseIterator(t, nil, nil, []string{"1", "0 2", "0 1", "0 0", "0"})
   316  	testReverseIterator(t, []byte{0x00}, nil, []string{"1", "0 2", "0 1", "0 0", "0"})
   317  	testReverseIterator(t, []byte{0x00}, []byte{0x00, 0x01}, []string{"0 0", "0"})
   318  	testReverseIterator(t, []byte{0x00}, []byte{0x01}, []string{"0 2", "0 1", "0 0", "0"})
   319  	testReverseIterator(t, []byte{0x00, 0x01}, []byte{0x01}, []string{"0 2", "0 1"})
   320  	testReverseIterator(t, nil, []byte{0x01}, []string{"0 2", "0 1", "0 0", "0"})
   321  }
   322  
   323  func TestIAVLPrefixIterator(t *testing.T) {
   324  	db := dbm.NewMemDB()
   325  	tree, err := iavl.NewMutableTree(db, cacheSize, false)
   326  	require.NoError(t, err)
   327  
   328  	iavlStore := UnsafeNewStore(tree)
   329  
   330  	iavlStore.Set([]byte("test1"), []byte("test1"))
   331  	iavlStore.Set([]byte("test2"), []byte("test2"))
   332  	iavlStore.Set([]byte("test3"), []byte("test3"))
   333  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4"))
   334  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4"))
   335  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4"))
   336  	iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4"))
   337  	iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4"))
   338  	iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4"))
   339  
   340  	var i int
   341  
   342  	iter := types.KVStorePrefixIterator(iavlStore, []byte("test"))
   343  	expected := []string{"test1", "test2", "test3"}
   344  	for i = 0; iter.Valid(); iter.Next() {
   345  		expectedKey := expected[i]
   346  		key, value := iter.Key(), iter.Value()
   347  		require.EqualValues(t, key, expectedKey)
   348  		require.EqualValues(t, value, expectedKey)
   349  		i++
   350  	}
   351  	iter.Close()
   352  	require.Equal(t, len(expected), i)
   353  
   354  	iter = types.KVStorePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)})
   355  	expected2 := [][]byte{
   356  		{byte(55), byte(255), byte(255), byte(0)},
   357  		{byte(55), byte(255), byte(255), byte(1)},
   358  		{byte(55), byte(255), byte(255), byte(255)},
   359  	}
   360  	for i = 0; iter.Valid(); iter.Next() {
   361  		expectedKey := expected2[i]
   362  		key, value := iter.Key(), iter.Value()
   363  		require.EqualValues(t, key, expectedKey)
   364  		require.EqualValues(t, value, []byte("test4"))
   365  		i++
   366  	}
   367  	iter.Close()
   368  	require.Equal(t, len(expected), i)
   369  
   370  	iter = types.KVStorePrefixIterator(iavlStore, []byte{byte(255), byte(255)})
   371  	expected2 = [][]byte{
   372  		{byte(255), byte(255), byte(0)},
   373  		{byte(255), byte(255), byte(1)},
   374  		{byte(255), byte(255), byte(255)},
   375  	}
   376  	for i = 0; iter.Valid(); iter.Next() {
   377  		expectedKey := expected2[i]
   378  		key, value := iter.Key(), iter.Value()
   379  		require.EqualValues(t, key, expectedKey)
   380  		require.EqualValues(t, value, []byte("test4"))
   381  		i++
   382  	}
   383  	iter.Close()
   384  	require.Equal(t, len(expected), i)
   385  }
   386  
   387  func TestIAVLReversePrefixIterator(t *testing.T) {
   388  	db := dbm.NewMemDB()
   389  	tree, err := iavl.NewMutableTree(db, cacheSize, false)
   390  	require.NoError(t, err)
   391  
   392  	iavlStore := UnsafeNewStore(tree)
   393  
   394  	iavlStore.Set([]byte("test1"), []byte("test1"))
   395  	iavlStore.Set([]byte("test2"), []byte("test2"))
   396  	iavlStore.Set([]byte("test3"), []byte("test3"))
   397  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4"))
   398  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4"))
   399  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4"))
   400  	iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4"))
   401  	iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4"))
   402  	iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4"))
   403  
   404  	var i int
   405  
   406  	iter := types.KVStoreReversePrefixIterator(iavlStore, []byte("test"))
   407  	expected := []string{"test3", "test2", "test1"}
   408  	for i = 0; iter.Valid(); iter.Next() {
   409  		expectedKey := expected[i]
   410  		key, value := iter.Key(), iter.Value()
   411  		require.EqualValues(t, key, expectedKey)
   412  		require.EqualValues(t, value, expectedKey)
   413  		i++
   414  	}
   415  	require.Equal(t, len(expected), i)
   416  
   417  	iter = types.KVStoreReversePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)})
   418  	expected2 := [][]byte{
   419  		{byte(55), byte(255), byte(255), byte(255)},
   420  		{byte(55), byte(255), byte(255), byte(1)},
   421  		{byte(55), byte(255), byte(255), byte(0)},
   422  	}
   423  	for i = 0; iter.Valid(); iter.Next() {
   424  		expectedKey := expected2[i]
   425  		key, value := iter.Key(), iter.Value()
   426  		require.EqualValues(t, key, expectedKey)
   427  		require.EqualValues(t, value, []byte("test4"))
   428  		i++
   429  	}
   430  	require.Equal(t, len(expected), i)
   431  
   432  	iter = types.KVStoreReversePrefixIterator(iavlStore, []byte{byte(255), byte(255)})
   433  	expected2 = [][]byte{
   434  		{byte(255), byte(255), byte(255)},
   435  		{byte(255), byte(255), byte(1)},
   436  		{byte(255), byte(255), byte(0)},
   437  	}
   438  	for i = 0; iter.Valid(); iter.Next() {
   439  		expectedKey := expected2[i]
   440  		key, value := iter.Key(), iter.Value()
   441  		require.EqualValues(t, key, expectedKey)
   442  		require.EqualValues(t, value, []byte("test4"))
   443  		i++
   444  	}
   445  	require.Equal(t, len(expected), i)
   446  }
   447  
   448  func nextVersion(iavl *Store) {
   449  	key := []byte(fmt.Sprintf("Key for tree: %d", iavl.LastCommitID().Version))
   450  	value := []byte(fmt.Sprintf("Value for tree: %d", iavl.LastCommitID().Version))
   451  	iavl.Set(key, value)
   452  	iavl.Commit()
   453  }
   454  
   455  func TestIAVLNoPrune(t *testing.T) {
   456  	db := dbm.NewMemDB()
   457  	tree, err := iavl.NewMutableTree(db, cacheSize, false)
   458  	require.NoError(t, err)
   459  
   460  	iavlStore := UnsafeNewStore(tree)
   461  	nextVersion(iavlStore)
   462  
   463  	for i := 1; i < 100; i++ {
   464  		for j := 1; j <= i; j++ {
   465  			require.True(t, iavlStore.VersionExists(int64(j)),
   466  				"Missing version %d with latest version %d. Should be storing all versions",
   467  				j, i)
   468  		}
   469  
   470  		nextVersion(iavlStore)
   471  	}
   472  }
   473  
   474  func TestIAVLGetAllVersions(t *testing.T) {
   475  	db := dbm.NewMemDB()
   476  	tree, err := iavl.NewMutableTree(db, cacheSize, false)
   477  	require.NoError(t, err)
   478  
   479  	iavlStore := UnsafeNewStore(tree)
   480  	nextVersion(iavlStore)
   481  
   482  	for i := 1; i < 100; i++ {
   483  		for _, ver := range iavlStore.GetAllVersions() {
   484  			require.True(t, iavlStore.VersionExists(int64(ver)),
   485  				"Missing version %d with latest version %d. Should be storing all versions",
   486  				ver, i)
   487  		}
   488  
   489  		nextVersion(iavlStore)
   490  	}
   491  }
   492  
   493  func TestIAVLStoreQuery(t *testing.T) {
   494  	db := dbm.NewMemDB()
   495  	tree, err := iavl.NewMutableTree(db, cacheSize, false)
   496  	require.NoError(t, err)
   497  
   498  	iavlStore := UnsafeNewStore(tree)
   499  
   500  	k1, v1 := []byte("key1"), []byte("val1")
   501  	k2, v2 := []byte("key2"), []byte("val2")
   502  	v3 := []byte("val3")
   503  
   504  	ksub := []byte("key")
   505  	KVs0 := kv.Pairs{}
   506  	KVs1 := kv.Pairs{
   507  		Pairs: []kv.Pair{
   508  			{Key: k1, Value: v1},
   509  			{Key: k2, Value: v2},
   510  		},
   511  	}
   512  	KVs2 := kv.Pairs{
   513  		Pairs: []kv.Pair{
   514  			{Key: k1, Value: v3},
   515  			{Key: k2, Value: v2},
   516  		},
   517  	}
   518  
   519  	valExpSubEmpty, err := KVs0.Marshal()
   520  	require.NoError(t, err)
   521  
   522  	valExpSub1, err := KVs1.Marshal()
   523  	require.NoError(t, err)
   524  
   525  	valExpSub2, err := KVs2.Marshal()
   526  	require.NoError(t, err)
   527  
   528  	cid := iavlStore.Commit()
   529  	ver := cid.Version
   530  	query := abci.RequestQuery{Path: "/key", Data: k1, Height: ver}
   531  	querySub := abci.RequestQuery{Path: "/subspace", Data: ksub, Height: ver}
   532  
   533  	// query subspace before anything set
   534  	qres := iavlStore.Query(querySub)
   535  	require.Equal(t, uint32(0), qres.Code)
   536  	require.Equal(t, valExpSubEmpty, qres.Value)
   537  
   538  	// set data
   539  	iavlStore.Set(k1, v1)
   540  	iavlStore.Set(k2, v2)
   541  
   542  	// set data without commit, doesn't show up
   543  	qres = iavlStore.Query(query)
   544  	require.Equal(t, uint32(0), qres.Code)
   545  	require.Nil(t, qres.Value)
   546  
   547  	// commit it, but still don't see on old version
   548  	cid = iavlStore.Commit()
   549  	qres = iavlStore.Query(query)
   550  	require.Equal(t, uint32(0), qres.Code)
   551  	require.Nil(t, qres.Value)
   552  
   553  	// but yes on the new version
   554  	query.Height = cid.Version
   555  	qres = iavlStore.Query(query)
   556  	require.Equal(t, uint32(0), qres.Code)
   557  	require.Equal(t, v1, qres.Value)
   558  
   559  	// and for the subspace
   560  	qres = iavlStore.Query(querySub)
   561  	require.Equal(t, uint32(0), qres.Code)
   562  	require.Equal(t, valExpSub1, qres.Value)
   563  
   564  	// modify
   565  	iavlStore.Set(k1, v3)
   566  	cid = iavlStore.Commit()
   567  
   568  	// query will return old values, as height is fixed
   569  	qres = iavlStore.Query(query)
   570  	require.Equal(t, uint32(0), qres.Code)
   571  	require.Equal(t, v1, qres.Value)
   572  
   573  	// update to latest in the query and we are happy
   574  	query.Height = cid.Version
   575  	qres = iavlStore.Query(query)
   576  	require.Equal(t, uint32(0), qres.Code)
   577  	require.Equal(t, v3, qres.Value)
   578  	query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version}
   579  
   580  	qres = iavlStore.Query(query2)
   581  	require.Equal(t, uint32(0), qres.Code)
   582  	require.Equal(t, v2, qres.Value)
   583  	// and for the subspace
   584  	qres = iavlStore.Query(querySub)
   585  	require.Equal(t, uint32(0), qres.Code)
   586  	require.Equal(t, valExpSub2, qres.Value)
   587  
   588  	// default (height 0) will show latest -1
   589  	query0 := abci.RequestQuery{Path: "/key", Data: k1}
   590  	qres = iavlStore.Query(query0)
   591  	require.Equal(t, uint32(0), qres.Code)
   592  	require.Equal(t, v1, qres.Value)
   593  }
   594  
   595  func BenchmarkIAVLIteratorNext(b *testing.B) {
   596  	b.ReportAllocs()
   597  	db := dbm.NewMemDB()
   598  	treeSize := 1000
   599  	tree, err := iavl.NewMutableTree(db, cacheSize, false)
   600  	require.NoError(b, err)
   601  
   602  	for i := 0; i < treeSize; i++ {
   603  		key := randBytes(4)
   604  		value := randBytes(50)
   605  		_, err := tree.Set(key, value)
   606  		require.NoError(b, err)
   607  	}
   608  
   609  	iavlStore := UnsafeNewStore(tree)
   610  	iterators := make([]types.Iterator, b.N/treeSize)
   611  
   612  	for i := 0; i < len(iterators); i++ {
   613  		iterators[i] = iavlStore.Iterator([]byte{0}, []byte{255, 255, 255, 255, 255})
   614  	}
   615  
   616  	b.ResetTimer()
   617  	for i := 0; i < len(iterators); i++ {
   618  		iter := iterators[i]
   619  		for j := 0; j < treeSize; j++ {
   620  			iter.Next()
   621  		}
   622  	}
   623  }
   624  
   625  func TestSetInitialVersion(t *testing.T) {
   626  	testCases := []struct {
   627  		name     string
   628  		storeFn  func(db *dbm.MemDB) *Store
   629  		expPanic bool
   630  	}{
   631  		{
   632  			"works with a mutable tree",
   633  			func(db *dbm.MemDB) *Store {
   634  				tree, err := iavl.NewMutableTree(db, cacheSize, false)
   635  				require.NoError(t, err)
   636  				store := UnsafeNewStore(tree)
   637  
   638  				return store
   639  			}, false,
   640  		},
   641  		{
   642  			"throws error on immutable tree",
   643  			func(db *dbm.MemDB) *Store {
   644  				tree, err := iavl.NewMutableTree(db, cacheSize, false)
   645  				require.NoError(t, err)
   646  				store := UnsafeNewStore(tree)
   647  				_, version, err := store.tree.SaveVersion()
   648  				require.NoError(t, err)
   649  				require.Equal(t, int64(1), version)
   650  				store, err = store.GetImmutable(1)
   651  				require.NoError(t, err)
   652  
   653  				return store
   654  			}, true,
   655  		},
   656  	}
   657  
   658  	for _, tc := range testCases {
   659  		t.Run(tc.name, func(t *testing.T) {
   660  			db := dbm.NewMemDB()
   661  			store := tc.storeFn(db)
   662  
   663  			if tc.expPanic {
   664  				require.Panics(t, func() { store.SetInitialVersion(5) })
   665  			} else {
   666  				store.SetInitialVersion(5)
   667  				cid := store.Commit()
   668  				require.Equal(t, int64(5), cid.GetVersion())
   669  			}
   670  		})
   671  	}
   672  }
   673  
   674  func TestCacheWraps(t *testing.T) {
   675  	db := dbm.NewMemDB()
   676  	tree, _ := newAlohaTree(t, db)
   677  	store := UnsafeNewStore(tree)
   678  
   679  	cacheWrapper := store.CacheWrap()
   680  	require.IsType(t, &cachekv.Store{}, cacheWrapper)
   681  
   682  	cacheWrappedWithTrace := store.CacheWrapWithTrace(nil, nil)
   683  	require.IsType(t, &cachekv.Store{}, cacheWrappedWithTrace)
   684  
   685  	cacheWrappedWithListeners := store.CacheWrapWithListeners(nil, nil)
   686  	require.IsType(t, &cachekv.Store{}, cacheWrappedWithListeners)
   687  }