github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/store/iavl/store_test.go (about)

     1  package iavl
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/gnolang/gno/tm2/pkg/amino"
    10  	abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
    11  	dbm "github.com/gnolang/gno/tm2/pkg/db"
    12  	"github.com/gnolang/gno/tm2/pkg/db/memdb"
    13  	"github.com/gnolang/gno/tm2/pkg/iavl"
    14  	"github.com/gnolang/gno/tm2/pkg/random"
    15  
    16  	// "github.com/gnolang/gno/tm2/pkg/store/errors"
    17  	"github.com/gnolang/gno/tm2/pkg/store/types"
    18  )
    19  
    20  var (
    21  	cacheSize        = 100
    22  	numRecent  int64 = 5
    23  	storeEvery int64 = 3
    24  )
    25  
    26  var (
    27  	treeData = map[string]string{
    28  		"hello": "goodbye",
    29  		"aloha": "shalom",
    30  	}
    31  	nMoreData = 0
    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  
    38  	tree := iavl.NewMutableTree(db, cacheSize)
    39  	for k, v := range treeData {
    40  		tree.Set([]byte(k), []byte(v))
    41  	}
    42  	for i := 0; i < nMoreData; i++ {
    43  		key := random.RandBytes(12)
    44  		value := random.RandBytes(50)
    45  		tree.Set(key, value)
    46  	}
    47  	hash, ver, err := tree.SaveVersion()
    48  	require.Nil(t, err)
    49  	return tree, types.CommitID{ver, hash}
    50  }
    51  
    52  func TestGetImmutable(t *testing.T) {
    53  	t.Parallel()
    54  
    55  	db := memdb.NewMemDB()
    56  	tree, cID := newAlohaTree(t, db)
    57  	store := UnsafeNewStore(tree, storeOptions(10, 10))
    58  
    59  	require.True(t, tree.Set([]byte("hello"), []byte("adios")))
    60  	hash, ver, err := tree.SaveVersion()
    61  	cID = types.CommitID{ver, hash}
    62  	require.Nil(t, err)
    63  
    64  	_, err = store.GetImmutable(cID.Version + 1)
    65  	require.Error(t, err)
    66  
    67  	newStore, err := store.GetImmutable(cID.Version - 1)
    68  	require.NoError(t, err)
    69  	require.Equal(t, newStore.Get([]byte("hello")), []byte("goodbye"))
    70  
    71  	newStore, err = store.GetImmutable(cID.Version)
    72  	require.NoError(t, err)
    73  	require.Equal(t, newStore.Get([]byte("hello")), []byte("adios"))
    74  
    75  	res := newStore.Query(abci.RequestQuery{Data: []byte("hello"), Height: cID.Version, Path: "/key", Prove: true})
    76  	require.Equal(t, res.Value, []byte("adios"))
    77  	require.NotNil(t, res.Proof)
    78  
    79  	require.Panics(t, func() { newStore.Set(nil, nil) })
    80  	require.Panics(t, func() { newStore.Delete(nil) })
    81  	require.Panics(t, func() { newStore.Commit() })
    82  }
    83  
    84  func TestTestGetImmutableIterator(t *testing.T) {
    85  	t.Parallel()
    86  
    87  	db := memdb.NewMemDB()
    88  	tree, cID := newAlohaTree(t, db)
    89  	store := UnsafeNewStore(tree, storeOptions(10, 10))
    90  
    91  	newStore, err := store.GetImmutable(cID.Version)
    92  	require.NoError(t, err)
    93  
    94  	iter := newStore.Iterator([]byte("aloha"), []byte("hellz"))
    95  	expected := []string{"aloha", "hello"}
    96  	var i int
    97  
    98  	for i = 0; iter.Valid(); iter.Next() {
    99  		expectedKey := expected[i]
   100  		key, value := iter.Key(), iter.Value()
   101  		require.EqualValues(t, key, expectedKey)
   102  		require.EqualValues(t, value, treeData[expectedKey])
   103  		i++
   104  	}
   105  
   106  	require.Equal(t, len(expected), i)
   107  }
   108  
   109  func TestIAVLStoreGetSetHasDelete(t *testing.T) {
   110  	t.Parallel()
   111  
   112  	db := memdb.NewMemDB()
   113  	tree, _ := newAlohaTree(t, db)
   114  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   115  
   116  	key := "hello"
   117  
   118  	exists := iavlStore.Has([]byte(key))
   119  	require.True(t, exists)
   120  
   121  	value := iavlStore.Get([]byte(key))
   122  	require.EqualValues(t, value, treeData[key])
   123  
   124  	value2 := "notgoodbye"
   125  	iavlStore.Set([]byte(key), []byte(value2))
   126  
   127  	value = iavlStore.Get([]byte(key))
   128  	require.EqualValues(t, value, value2)
   129  
   130  	iavlStore.Delete([]byte(key))
   131  
   132  	exists = iavlStore.Has([]byte(key))
   133  	require.False(t, exists)
   134  }
   135  
   136  func TestIAVLStoreNoNilSet(t *testing.T) {
   137  	t.Parallel()
   138  
   139  	db := memdb.NewMemDB()
   140  	tree, _ := newAlohaTree(t, db)
   141  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   142  	require.Panics(t, func() { iavlStore.Set([]byte("key"), nil) }, "setting a nil value should panic")
   143  }
   144  
   145  func TestIAVLIterator(t *testing.T) {
   146  	t.Parallel()
   147  
   148  	db := memdb.NewMemDB()
   149  	tree, _ := newAlohaTree(t, db)
   150  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   151  	iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz"))
   152  	expected := []string{"aloha", "hello"}
   153  	var i int
   154  
   155  	for i = 0; iter.Valid(); iter.Next() {
   156  		expectedKey := expected[i]
   157  		key, value := iter.Key(), iter.Value()
   158  		require.EqualValues(t, key, expectedKey)
   159  		require.EqualValues(t, value, treeData[expectedKey])
   160  		i++
   161  	}
   162  	require.Equal(t, len(expected), i)
   163  
   164  	iter = iavlStore.Iterator([]byte("golang"), []byte("rocks"))
   165  	expected = []string{"hello"}
   166  	for i = 0; iter.Valid(); iter.Next() {
   167  		expectedKey := expected[i]
   168  		key, value := iter.Key(), iter.Value()
   169  		require.EqualValues(t, key, expectedKey)
   170  		require.EqualValues(t, value, treeData[expectedKey])
   171  		i++
   172  	}
   173  	require.Equal(t, len(expected), i)
   174  
   175  	iter = iavlStore.Iterator(nil, []byte("golang"))
   176  	expected = []string{"aloha"}
   177  	for i = 0; iter.Valid(); iter.Next() {
   178  		expectedKey := expected[i]
   179  		key, value := iter.Key(), iter.Value()
   180  		require.EqualValues(t, key, expectedKey)
   181  		require.EqualValues(t, value, treeData[expectedKey])
   182  		i++
   183  	}
   184  	require.Equal(t, len(expected), i)
   185  
   186  	iter = iavlStore.Iterator(nil, []byte("shalom"))
   187  	expected = []string{"aloha", "hello"}
   188  	for i = 0; iter.Valid(); iter.Next() {
   189  		expectedKey := expected[i]
   190  		key, value := iter.Key(), iter.Value()
   191  		require.EqualValues(t, key, expectedKey)
   192  		require.EqualValues(t, value, treeData[expectedKey])
   193  		i++
   194  	}
   195  	require.Equal(t, len(expected), i)
   196  
   197  	iter = iavlStore.Iterator(nil, nil)
   198  	expected = []string{"aloha", "hello"}
   199  	for i = 0; iter.Valid(); iter.Next() {
   200  		expectedKey := expected[i]
   201  		key, value := iter.Key(), iter.Value()
   202  		require.EqualValues(t, key, expectedKey)
   203  		require.EqualValues(t, value, treeData[expectedKey])
   204  		i++
   205  	}
   206  	require.Equal(t, len(expected), i)
   207  
   208  	iter = iavlStore.Iterator([]byte("golang"), nil)
   209  	expected = []string{"hello"}
   210  	for i = 0; iter.Valid(); iter.Next() {
   211  		expectedKey := expected[i]
   212  		key, value := iter.Key(), iter.Value()
   213  		require.EqualValues(t, key, expectedKey)
   214  		require.EqualValues(t, value, treeData[expectedKey])
   215  		i++
   216  	}
   217  	require.Equal(t, len(expected), i)
   218  }
   219  
   220  func TestIAVLReverseIterator(t *testing.T) {
   221  	t.Parallel()
   222  
   223  	db := memdb.NewMemDB()
   224  	tree := iavl.NewMutableTree(db, cacheSize)
   225  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   226  
   227  	iavlStore.Set([]byte{0x00}, []byte("0"))
   228  	iavlStore.Set([]byte{0x00, 0x00}, []byte("0 0"))
   229  	iavlStore.Set([]byte{0x00, 0x01}, []byte("0 1"))
   230  	iavlStore.Set([]byte{0x00, 0x02}, []byte("0 2"))
   231  	iavlStore.Set([]byte{0x01}, []byte("1"))
   232  
   233  	testReverseIterator := func(t *testing.T, start []byte, end []byte, expected []string) {
   234  		t.Helper()
   235  
   236  		iter := iavlStore.ReverseIterator(start, end)
   237  		var i int
   238  		for i = 0; iter.Valid(); iter.Next() {
   239  			expectedValue := expected[i]
   240  			value := iter.Value()
   241  			require.EqualValues(t, string(value), expectedValue)
   242  			i++
   243  		}
   244  		require.Equal(t, len(expected), i)
   245  	}
   246  
   247  	testReverseIterator(t, nil, nil, []string{"1", "0 2", "0 1", "0 0", "0"})
   248  	testReverseIterator(t, []byte{0x00}, nil, []string{"1", "0 2", "0 1", "0 0", "0"})
   249  	testReverseIterator(t, []byte{0x00}, []byte{0x00, 0x01}, []string{"0 0", "0"})
   250  	testReverseIterator(t, []byte{0x00}, []byte{0x01}, []string{"0 2", "0 1", "0 0", "0"})
   251  	testReverseIterator(t, []byte{0x00, 0x01}, []byte{0x01}, []string{"0 2", "0 1"})
   252  	testReverseIterator(t, nil, []byte{0x01}, []string{"0 2", "0 1", "0 0", "0"})
   253  }
   254  
   255  func TestIAVLPrefixIterator(t *testing.T) {
   256  	t.Parallel()
   257  
   258  	db := memdb.NewMemDB()
   259  	tree := iavl.NewMutableTree(db, cacheSize)
   260  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   261  
   262  	iavlStore.Set([]byte("test1"), []byte("test1"))
   263  	iavlStore.Set([]byte("test2"), []byte("test2"))
   264  	iavlStore.Set([]byte("test3"), []byte("test3"))
   265  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4"))
   266  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4"))
   267  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4"))
   268  	iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4"))
   269  	iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4"))
   270  	iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4"))
   271  
   272  	var i int
   273  
   274  	iter := types.PrefixIterator(iavlStore, []byte("test"))
   275  	expected := []string{"test1", "test2", "test3"}
   276  	for i = 0; iter.Valid(); iter.Next() {
   277  		expectedKey := expected[i]
   278  		key, value := iter.Key(), iter.Value()
   279  		require.EqualValues(t, key, expectedKey)
   280  		require.EqualValues(t, value, expectedKey)
   281  		i++
   282  	}
   283  	iter.Close()
   284  	require.Equal(t, len(expected), i)
   285  
   286  	iter = types.PrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)})
   287  	expected2 := [][]byte{
   288  		{byte(55), byte(255), byte(255), byte(0)},
   289  		{byte(55), byte(255), byte(255), byte(1)},
   290  		{byte(55), byte(255), byte(255), byte(255)},
   291  	}
   292  	for i = 0; iter.Valid(); iter.Next() {
   293  		expectedKey := expected2[i]
   294  		key, value := iter.Key(), iter.Value()
   295  		require.EqualValues(t, key, expectedKey)
   296  		require.EqualValues(t, value, []byte("test4"))
   297  		i++
   298  	}
   299  	iter.Close()
   300  	require.Equal(t, len(expected), i)
   301  
   302  	iter = types.PrefixIterator(iavlStore, []byte{byte(255), byte(255)})
   303  	expected2 = [][]byte{
   304  		{byte(255), byte(255), byte(0)},
   305  		{byte(255), byte(255), byte(1)},
   306  		{byte(255), byte(255), byte(255)},
   307  	}
   308  	for i = 0; iter.Valid(); iter.Next() {
   309  		expectedKey := expected2[i]
   310  		key, value := iter.Key(), iter.Value()
   311  		require.EqualValues(t, key, expectedKey)
   312  		require.EqualValues(t, value, []byte("test4"))
   313  		i++
   314  	}
   315  	iter.Close()
   316  	require.Equal(t, len(expected), i)
   317  }
   318  
   319  func TestIAVLReversePrefixIterator(t *testing.T) {
   320  	t.Parallel()
   321  
   322  	db := memdb.NewMemDB()
   323  	tree := iavl.NewMutableTree(db, cacheSize)
   324  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   325  
   326  	iavlStore.Set([]byte("test1"), []byte("test1"))
   327  	iavlStore.Set([]byte("test2"), []byte("test2"))
   328  	iavlStore.Set([]byte("test3"), []byte("test3"))
   329  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4"))
   330  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4"))
   331  	iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4"))
   332  	iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4"))
   333  	iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4"))
   334  	iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4"))
   335  
   336  	var i int
   337  
   338  	iter := types.ReversePrefixIterator(iavlStore, []byte("test"))
   339  	expected := []string{"test3", "test2", "test1"}
   340  	for i = 0; iter.Valid(); iter.Next() {
   341  		expectedKey := expected[i]
   342  		key, value := iter.Key(), iter.Value()
   343  		require.EqualValues(t, key, expectedKey)
   344  		require.EqualValues(t, value, expectedKey)
   345  		i++
   346  	}
   347  	require.Equal(t, len(expected), i)
   348  
   349  	iter = types.ReversePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)})
   350  	expected2 := [][]byte{
   351  		{byte(55), byte(255), byte(255), byte(255)},
   352  		{byte(55), byte(255), byte(255), byte(1)},
   353  		{byte(55), byte(255), byte(255), byte(0)},
   354  	}
   355  	for i = 0; iter.Valid(); iter.Next() {
   356  		expectedKey := expected2[i]
   357  		key, value := iter.Key(), iter.Value()
   358  		require.EqualValues(t, key, expectedKey)
   359  		require.EqualValues(t, value, []byte("test4"))
   360  		i++
   361  	}
   362  	require.Equal(t, len(expected), i)
   363  
   364  	iter = types.ReversePrefixIterator(iavlStore, []byte{byte(255), byte(255)})
   365  	expected2 = [][]byte{
   366  		{byte(255), byte(255), byte(255)},
   367  		{byte(255), byte(255), byte(1)},
   368  		{byte(255), byte(255), byte(0)},
   369  	}
   370  	for i = 0; iter.Valid(); iter.Next() {
   371  		expectedKey := expected2[i]
   372  		key, value := iter.Key(), iter.Value()
   373  		require.EqualValues(t, key, expectedKey)
   374  		require.EqualValues(t, value, []byte("test4"))
   375  		i++
   376  	}
   377  	require.Equal(t, len(expected), i)
   378  }
   379  
   380  func nextVersion(iavl *Store) {
   381  	key := []byte(fmt.Sprintf("Key for tree: %d", iavl.LastCommitID().Version))
   382  	value := []byte(fmt.Sprintf("Value for tree: %d", iavl.LastCommitID().Version))
   383  	iavl.Set(key, value)
   384  	iavl.Commit()
   385  }
   386  
   387  func TestIAVLDefaultPruning(t *testing.T) {
   388  	t.Parallel()
   389  
   390  	// Expected stored / deleted version numbers for:
   391  	// numRecent = 5, storeEvery = 3
   392  	states := []pruneState{
   393  		{[]int64{}, []int64{}},
   394  		{[]int64{1}, []int64{}},
   395  		{[]int64{1, 2}, []int64{}},
   396  		{[]int64{1, 2, 3}, []int64{}},
   397  		{[]int64{1, 2, 3, 4}, []int64{}},
   398  		{[]int64{1, 2, 3, 4, 5}, []int64{}},
   399  		{[]int64{1, 2, 3, 4, 5, 6}, []int64{}},
   400  		{[]int64{2, 3, 4, 5, 6, 7}, []int64{1}},
   401  		{[]int64{3, 4, 5, 6, 7, 8}, []int64{1, 2}},
   402  		{[]int64{3, 4, 5, 6, 7, 8, 9}, []int64{1, 2}},
   403  		{[]int64{3, 5, 6, 7, 8, 9, 10}, []int64{1, 2, 4}},
   404  		{[]int64{3, 6, 7, 8, 9, 10, 11}, []int64{1, 2, 4, 5}},
   405  		{[]int64{3, 6, 7, 8, 9, 10, 11, 12}, []int64{1, 2, 4, 5}},
   406  		{[]int64{3, 6, 8, 9, 10, 11, 12, 13}, []int64{1, 2, 4, 5, 7}},
   407  		{[]int64{3, 6, 9, 10, 11, 12, 13, 14}, []int64{1, 2, 4, 5, 7, 8}},
   408  		{[]int64{3, 6, 9, 10, 11, 12, 13, 14, 15}, []int64{1, 2, 4, 5, 7, 8}},
   409  	}
   410  	testPruning(t, int64(5), int64(3), states)
   411  }
   412  
   413  func TestIAVLAlternativePruning(t *testing.T) {
   414  	t.Parallel()
   415  
   416  	// Expected stored / deleted version numbers for:
   417  	// numRecent = 3, storeEvery = 5
   418  	states := []pruneState{
   419  		{[]int64{}, []int64{}},
   420  		{[]int64{1}, []int64{}},
   421  		{[]int64{1, 2}, []int64{}},
   422  		{[]int64{1, 2, 3}, []int64{}},
   423  		{[]int64{1, 2, 3, 4}, []int64{}},
   424  		{[]int64{2, 3, 4, 5}, []int64{1}},
   425  		{[]int64{3, 4, 5, 6}, []int64{1, 2}},
   426  		{[]int64{4, 5, 6, 7}, []int64{1, 2, 3}},
   427  		{[]int64{5, 6, 7, 8}, []int64{1, 2, 3, 4}},
   428  		{[]int64{5, 6, 7, 8, 9}, []int64{1, 2, 3, 4}},
   429  		{[]int64{5, 7, 8, 9, 10}, []int64{1, 2, 3, 4, 6}},
   430  		{[]int64{5, 8, 9, 10, 11}, []int64{1, 2, 3, 4, 6, 7}},
   431  		{[]int64{5, 9, 10, 11, 12}, []int64{1, 2, 3, 4, 6, 7, 8}},
   432  		{[]int64{5, 10, 11, 12, 13}, []int64{1, 2, 3, 4, 6, 7, 8, 9}},
   433  		{[]int64{5, 10, 11, 12, 13, 14}, []int64{1, 2, 3, 4, 6, 7, 8, 9}},
   434  		{[]int64{5, 10, 12, 13, 14, 15}, []int64{1, 2, 3, 4, 6, 7, 8, 9, 11}},
   435  	}
   436  	testPruning(t, int64(3), int64(5), states)
   437  }
   438  
   439  type pruneState struct {
   440  	stored  []int64
   441  	deleted []int64
   442  }
   443  
   444  func testPruning(t *testing.T, numRecent int64, storeEvery int64, states []pruneState) {
   445  	t.Helper()
   446  
   447  	db := memdb.NewMemDB()
   448  	tree := iavl.NewMutableTree(db, cacheSize)
   449  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   450  	for step, state := range states {
   451  		for _, ver := range state.stored {
   452  			require.True(t, iavlStore.VersionExists(ver),
   453  				"Missing version %d with latest version %d. Should save last %d and every %d",
   454  				ver, step, numRecent, storeEvery)
   455  		}
   456  		for _, ver := range state.deleted {
   457  			require.False(t, iavlStore.VersionExists(ver),
   458  				"Unpruned version %d with latest version %d. Should prune all but last %d and every %d",
   459  				ver, step, numRecent, storeEvery)
   460  		}
   461  		nextVersion(iavlStore)
   462  	}
   463  }
   464  
   465  func TestIAVLNoPrune(t *testing.T) {
   466  	t.Parallel()
   467  
   468  	db := memdb.NewMemDB()
   469  	tree := iavl.NewMutableTree(db, cacheSize)
   470  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, int64(1)))
   471  	nextVersion(iavlStore)
   472  	for i := 1; i < 100; i++ {
   473  		for j := 1; j <= i; j++ {
   474  			require.True(t, iavlStore.VersionExists(int64(j)),
   475  				"Missing version %d with latest version %d. Should be storing all versions",
   476  				j, i)
   477  		}
   478  		nextVersion(iavlStore)
   479  	}
   480  }
   481  
   482  func TestIAVLPruneEverything(t *testing.T) {
   483  	t.Parallel()
   484  
   485  	db := memdb.NewMemDB()
   486  	tree := iavl.NewMutableTree(db, cacheSize)
   487  	iavlStore := UnsafeNewStore(tree, storeOptions(int64(0), int64(0)))
   488  	nextVersion(iavlStore)
   489  	for i := 1; i < 100; i++ {
   490  		for j := 1; j < i; j++ {
   491  			require.False(t, iavlStore.VersionExists(int64(j)),
   492  				"Unpruned version %d with latest version %d. Should prune all old versions",
   493  				j, i)
   494  		}
   495  		require.True(t, iavlStore.VersionExists(int64(i)),
   496  			"Missing current version on step %d, should not prune current state tree",
   497  			i)
   498  		nextVersion(iavlStore)
   499  	}
   500  }
   501  
   502  func TestIAVLStoreQuery(t *testing.T) {
   503  	t.Parallel()
   504  
   505  	db := memdb.NewMemDB()
   506  	tree := iavl.NewMutableTree(db, cacheSize)
   507  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   508  
   509  	k1, v1 := []byte("key1"), []byte("val1")
   510  	k2, v2 := []byte("key2"), []byte("val2")
   511  	v3 := []byte("val3")
   512  
   513  	ksub := []byte("key")
   514  	KVs0 := []types.KVPair{}
   515  	KVs1 := []types.KVPair{
   516  		{Key: k1, Value: v1},
   517  		{Key: k2, Value: v2},
   518  	}
   519  	KVs2 := []types.KVPair{
   520  		{Key: k1, Value: v3},
   521  		{Key: k2, Value: v2},
   522  	}
   523  	valExpSubEmpty := amino.MustMarshalSized(KVs0)
   524  	valExpSub1 := amino.MustMarshalSized(KVs1)
   525  	valExpSub2 := amino.MustMarshalSized(KVs2)
   526  
   527  	cid := iavlStore.Commit()
   528  	ver := cid.Version
   529  	query := abci.RequestQuery{Path: "/key", Data: k1, Height: ver}
   530  	querySub := abci.RequestQuery{Path: "/subspace", Data: ksub, Height: ver}
   531  
   532  	// query subspace before anything set
   533  	qres := iavlStore.Query(querySub)
   534  	require.Nil(t, qres.Error)
   535  	require.Equal(t, valExpSubEmpty, qres.Value)
   536  
   537  	// set data
   538  	iavlStore.Set(k1, v1)
   539  	iavlStore.Set(k2, v2)
   540  
   541  	// set data without commit, doesn't show up
   542  	qres = iavlStore.Query(query)
   543  	require.Nil(t, qres.Error)
   544  	require.Nil(t, qres.Value)
   545  
   546  	// commit it, but still don't see on old version
   547  	cid = iavlStore.Commit()
   548  	qres = iavlStore.Query(query)
   549  	require.Nil(t, qres.Error)
   550  	require.Nil(t, qres.Value)
   551  
   552  	// but yes on the new version
   553  	query.Height = cid.Version
   554  	qres = iavlStore.Query(query)
   555  	require.Nil(t, qres.Error)
   556  	require.Equal(t, v1, qres.Value)
   557  
   558  	// and for the subspace
   559  	qres = iavlStore.Query(querySub)
   560  	require.Nil(t, qres.Error)
   561  	require.Equal(t, valExpSub1, qres.Value)
   562  
   563  	// modify
   564  	iavlStore.Set(k1, v3)
   565  	cid = iavlStore.Commit()
   566  
   567  	// query will return old values, as height is fixed
   568  	qres = iavlStore.Query(query)
   569  	require.Nil(t, qres.Error)
   570  	require.Equal(t, v1, qres.Value)
   571  
   572  	// update to latest in the query and we are happy
   573  	query.Height = cid.Version
   574  	qres = iavlStore.Query(query)
   575  	require.Nil(t, qres.Error)
   576  	require.Equal(t, v3, qres.Value)
   577  	query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version}
   578  
   579  	qres = iavlStore.Query(query2)
   580  	require.Nil(t, qres.Error)
   581  	require.Equal(t, v2, qres.Value)
   582  	// and for the subspace
   583  	qres = iavlStore.Query(querySub)
   584  	require.Nil(t, qres.Error)
   585  	require.Equal(t, valExpSub2, qres.Value)
   586  
   587  	// default (height 0) will show latest -1
   588  	query0 := abci.RequestQuery{Path: "/key", Data: k1}
   589  	qres = iavlStore.Query(query0)
   590  	require.Nil(t, qres.Error)
   591  	require.Equal(t, v1, qres.Value)
   592  }
   593  
   594  func BenchmarkIAVLIteratorNext(b *testing.B) {
   595  	db := memdb.NewMemDB()
   596  	treeSize := 1000
   597  	tree := iavl.NewMutableTree(db, cacheSize)
   598  	for i := 0; i < treeSize; i++ {
   599  		key := random.RandBytes(4)
   600  		value := random.RandBytes(50)
   601  		tree.Set(key, value)
   602  	}
   603  	iavlStore := UnsafeNewStore(tree, storeOptions(numRecent, storeEvery))
   604  	iterators := make([]types.Iterator, b.N/treeSize)
   605  	for i := 0; i < len(iterators); i++ {
   606  		iterators[i] = iavlStore.Iterator([]byte{0}, []byte{255, 255, 255, 255, 255})
   607  	}
   608  	b.ResetTimer()
   609  	for i := 0; i < len(iterators); i++ {
   610  		iter := iterators[i]
   611  		for j := 0; j < treeSize; j++ {
   612  			iter.Next()
   613  		}
   614  	}
   615  }
   616  
   617  func storeOptions(recent, every int64) types.StoreOptions {
   618  	return types.StoreOptions{
   619  		PruningOptions: types.PruningOptions{
   620  			KeepRecent: recent,
   621  			KeepEvery:  every,
   622  		},
   623  	}
   624  }