Skip to content

Commit

Permalink
chore(store): upgrade iavl to v0.19.0 (backport #12626) (#12697)
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] committed Jul 23, 2022
1 parent 4eec00f commit 1fcc404
Show file tree
Hide file tree
Showing 19 changed files with 150 additions and 131 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements

* [#12668](https://github.com/cosmos/cosmos-sdk/pull/12668) Add `authz_msg_index` event attribute to message events emitted when executing via `MsgExec` through `x/authz`.
* [#12697](https://github.com/cosmos/cosmos-sdk/pull/12697) Upgrade IAVL to v0.19.0 with fast index and error propagation. NOTE: first start will take a while to propagate into new model.

### Bug Fixes

Expand Down
4 changes: 2 additions & 2 deletions baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ func useDefaultLoader(app *BaseApp) {
}

func initStore(t *testing.T, db dbm.DB, storeKey string, k, v []byte) {
rs := rootmulti.NewStore(db)
rs := rootmulti.NewStore(db, log.NewNopLogger())
rs.SetPruning(store.PruneNothing)
key := sdk.NewKVStoreKey(storeKey)
rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil)
Expand All @@ -275,7 +275,7 @@ func initStore(t *testing.T, db dbm.DB, storeKey string, k, v []byte) {
}

func checkStore(t *testing.T, db dbm.DB, ver int64, storeKey string, k, v []byte) {
rs := rootmulti.NewStore(db)
rs := rootmulti.NewStore(db, log.NewNopLogger())
rs.SetPruning(store.PruneDefault)
key := sdk.NewKVStoreKey(storeKey)
rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil)
Expand Down
18 changes: 9 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ require (
github.com/bgentry/speakeasy v0.1.0
github.com/btcsuite/btcd v0.22.0-beta
github.com/coinbase/rosetta-sdk-go v0.7.0
github.com/confio/ics23/go v0.6.6
github.com/confio/ics23/go v0.7.0
github.com/cosmos/btcutil v1.0.4
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/iavl v0.17.3
github.com/cosmos/iavl v0.19.0
github.com/cosmos/ledger-cosmos-go v0.11.1
github.com/gogo/gateway v1.1.0
github.com/gogo/protobuf v1.3.3
Expand All @@ -38,16 +38,16 @@ require (
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.10.1
github.com/stretchr/testify v1.7.1
github.com/stretchr/testify v1.8.0
github.com/tendermint/btcd v0.1.1
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15
github.com/tendermint/go-amino v0.16.0
github.com/tendermint/tendermint v0.34.19
github.com/tendermint/tm-db v0.6.6
golang.org/x/crypto v0.0.0-20210915214749-c084706c2272
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb
google.golang.org/grpc v1.45.0
google.golang.org/protobuf v1.27.1
google.golang.org/protobuf v1.28.0
gopkg.in/yaml.v2 v2.4.0
)

Expand Down Expand Up @@ -110,12 +110,12 @@ require (
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
github.com/zondax/hid v0.9.0 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/ini.v1 v1.66.2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
nhooyr.io/websocket v1.8.6 // indirect
)

Expand Down
71 changes: 21 additions & 50 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion server/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ application.
return fmt.Errorf("failed to rollback tendermint state: %w", err)
}
// rollback the multistore
cms := rootmulti.NewStore(db)
cms := rootmulti.NewStore(db, ctx.Logger)
cms.RollbackToVersion(height)

fmt.Printf("Rolled back state to height %d and hash %X", height, hash)
Expand Down
2 changes: 1 addition & 1 deletion store/cachekv/store_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func benchmarkRandomSet(b *testing.B, keysize int) {
kvstore.Set(k, value)
}

iter := kvstore.Iterator(keys[0], keys[b.N])
iter := kvstore.Iterator(nil, nil)
defer iter.Close()

for _ = iter.Key(); iter.Valid(); iter.Next() {
Expand Down
85 changes: 58 additions & 27 deletions store/iavl/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
ics23 "github.com/confio/ics23/go"
"github.com/cosmos/iavl"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
dbm "github.com/tendermint/tm-db"

Expand Down Expand Up @@ -41,20 +42,35 @@ type Store struct {
// LoadStore returns an IAVL Store as a CommitKVStore. Internally, it will load the
// store's version (id) from the provided DB. An error is returned if the version
// fails to load, or if called with a positive version on an empty tree.
func LoadStore(db dbm.DB, id types.CommitID, lazyLoading bool, cacheSize int) (types.CommitKVStore, error) {
return LoadStoreWithInitialVersion(db, id, lazyLoading, 0, cacheSize)
func LoadStore(db dbm.DB, logger log.Logger, key types.StoreKey, id types.CommitID, lazyLoading bool, cacheSize int) (types.CommitKVStore, error) {
return LoadStoreWithInitialVersion(db, logger, key, id, lazyLoading, 0, cacheSize)
}

// LoadStoreWithInitialVersion returns an IAVL Store as a CommitKVStore setting its initialVersion
// to the one given. Internally, it will load the store's version (id) from the
// provided DB. An error is returned if the version fails to load, or if called with a positive
// version on an empty tree.
func LoadStoreWithInitialVersion(db dbm.DB, id types.CommitID, lazyLoading bool, initialVersion uint64, cacheSize int) (types.CommitKVStore, error) {
func LoadStoreWithInitialVersion(db dbm.DB, logger log.Logger, key types.StoreKey, id types.CommitID, lazyLoading bool, initialVersion uint64, cacheSize int) (types.CommitKVStore, error) {
tree, err := iavl.NewMutableTreeWithOpts(db, cacheSize, &iavl.Options{InitialVersion: initialVersion})
if err != nil {
return nil, err
}

isUpgradeable, err := tree.IsUpgradeable()
if err != nil {
return nil, err
}

if isUpgradeable && logger != nil {
logger.Info(
"Upgrading IAVL storage for faster queries + execution on live state. This may take a while",
"store_key", key.String(),
"version", initialVersion,
"commit", fmt.Sprintf("%X", id),
"is_lazy", lazyLoading,
)
}

if lazyLoading {
_, err = tree.LazyLoadVersion(id.Version)
} else {
Expand All @@ -65,6 +81,10 @@ func LoadStoreWithInitialVersion(db dbm.DB, id types.CommitID, lazyLoading bool,
return nil, err
}

if logger != nil {
logger.Debug("Finished loading IAVL tree")
}

return &Store{
tree: tree,
}, nil
Expand Down Expand Up @@ -120,9 +140,14 @@ func (st *Store) Commit() types.CommitID {

// LastCommitID implements Committer.
func (st *Store) LastCommitID() types.CommitID {
hash, err := st.tree.Hash()
if err != nil {
panic(err)
}

return types.CommitID{
Version: st.tree.Version(),
Hash: st.tree.Hash(),
Hash: hash,
}
}

Expand Down Expand Up @@ -178,14 +203,21 @@ func (st *Store) Set(key, value []byte) {
// Implements types.KVStore.
func (st *Store) Get(key []byte) []byte {
defer telemetry.MeasureSince(time.Now(), "store", "iavl", "get")
_, value := st.tree.Get(key)
value, err := st.tree.Get(key)
if err != nil {
panic(err)
}
return value
}

// Implements types.KVStore.
func (st *Store) Has(key []byte) (exists bool) {
defer telemetry.MeasureSince(time.Now(), "store", "iavl", "has")
return st.tree.Has(key)
has, err := st.tree.Has(key)
if err != nil {
panic(err)
}
return has
}

// Implements types.KVStore.
Expand All @@ -203,30 +235,20 @@ func (st *Store) DeleteVersions(versions ...int64) error {

// Implements types.KVStore.
func (st *Store) Iterator(start, end []byte) types.Iterator {
var iTree *iavl.ImmutableTree

switch tree := st.tree.(type) {
case *immutableTree:
iTree = tree.ImmutableTree
case *iavl.MutableTree:
iTree = tree.ImmutableTree
iterator, err := st.tree.Iterator(start, end, true)
if err != nil {
panic(err)
}

return newIAVLIterator(iTree, start, end, true)
return iterator
}

// Implements types.KVStore.
func (st *Store) ReverseIterator(start, end []byte) types.Iterator {
var iTree *iavl.ImmutableTree

switch tree := st.tree.(type) {
case *immutableTree:
iTree = tree.ImmutableTree
case *iavl.MutableTree:
iTree = tree.ImmutableTree
iterator, err := st.tree.Iterator(start, end, false)
if err != nil {
panic(err)
}

return newIAVLIterator(iTree, start, end, false)
return iterator
}

// SetInitialVersion sets the initial version of the IAVL tree. It is used when
Expand Down Expand Up @@ -301,7 +323,12 @@ func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
break
}

_, res.Value = tree.GetVersioned(key, res.Height)
value, err := tree.GetVersioned(key, res.Height)
if err != nil {
panic(err)
}
res.Value = value

if !req.Prove {
break
}
Expand Down Expand Up @@ -381,7 +408,7 @@ func getProofFromTree(tree *iavl.MutableTree, key []byte, exists bool) *tmcrypto

// Implements types.Iterator.
type iavlIterator struct {
*iavl.Iterator
dbm.Iterator
}

var _ types.Iterator = (*iavlIterator)(nil)
Expand All @@ -390,8 +417,12 @@ var _ types.Iterator = (*iavlIterator)(nil)
// CONTRACT: Caller must release the iavlIterator, as each one creates a new
// goroutine.
func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator {
iterator, err := tree.Iterator(start, end, ascending)
if err != nil {
panic(err)
}
iter := &iavlIterator{
Iterator: tree.Iterator(start, end, ascending),
Iterator: iterator,
}
return iter
}
22 changes: 15 additions & 7 deletions store/iavl/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/cosmos/iavl"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"

"github.com/cosmos/cosmos-sdk/store/types"
Expand Down Expand Up @@ -58,21 +59,27 @@ func TestLoadStore(t *testing.T) {
store := UnsafeNewStore(tree)

// Create non-pruned height H
require.True(t, tree.Set([]byte("hello"), []byte("hallo")))
updated, err := tree.Set([]byte("hello"), []byte("hallo"))
require.NoError(t, err)
require.True(t, updated)
hash, verH, err := tree.SaveVersion()
cIDH := types.CommitID{Version: verH, Hash: hash}
require.Nil(t, err)

// Create pruned height Hp
require.True(t, tree.Set([]byte("hello"), []byte("hola")))
updated, err = tree.Set([]byte("hello"), []byte("hola"))
require.NoError(t, err)
require.True(t, updated)
hash, verHp, err := tree.SaveVersion()
cIDHp := types.CommitID{Version: verHp, Hash: hash}
require.Nil(t, err)

// TODO: Prune this height

// Create current height Hc
require.True(t, tree.Set([]byte("hello"), []byte("ciao")))
updated, err = tree.Set([]byte("hello"), []byte("ciao"))
require.NoError(t, err)
require.True(t, updated)
hash, verHc, err := tree.SaveVersion()
cIDHc := types.CommitID{Version: verHc, Hash: hash}
require.Nil(t, err)
Expand All @@ -93,17 +100,17 @@ func TestLoadStore(t *testing.T) {
require.Equal(t, string(hcStore.Get([]byte("hello"))), "ciao")

// Querying a new store at some previous non-pruned height H
newHStore, err := LoadStore(db, cIDH, false, DefaultIAVLCacheSize)
newHStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDH, false, DefaultIAVLCacheSize)
require.NoError(t, err)
require.Equal(t, string(newHStore.Get([]byte("hello"))), "hallo")

// Querying a new store at some previous pruned height Hp
newHpStore, err := LoadStore(db, cIDHp, false, DefaultIAVLCacheSize)
newHpStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDHp, false, DefaultIAVLCacheSize)
require.NoError(t, err)
require.Equal(t, string(newHpStore.Get([]byte("hello"))), "hola")

// Querying a new store at current height H
newHcStore, err := LoadStore(db, cIDHc, false, DefaultIAVLCacheSize)
newHcStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDHc, false, DefaultIAVLCacheSize)
require.NoError(t, err)
require.Equal(t, string(newHcStore.Get([]byte("hello"))), "ciao")
}
Expand All @@ -113,7 +120,8 @@ func TestGetImmutable(t *testing.T) {
tree, cID := newAlohaTree(t, db)
store := UnsafeNewStore(tree)

require.True(t, tree.Set([]byte("hello"), []byte("adios")))
updated, err := tree.Set([]byte("hello"), []byte("adios"))
require.True(t, updated)
hash, ver, err := tree.SaveVersion()
cID = types.CommitID{Version: ver, Hash: hash}
require.Nil(t, err)
Expand Down
22 changes: 12 additions & 10 deletions store/iavl/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package iavl
import (
"fmt"

"github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/iavl"
)

Expand All @@ -17,20 +18,21 @@ type (
// implemented by an iavl.MutableTree. For an immutable IAVL tree, a wrapper
// must be made.
Tree interface {
Has(key []byte) bool
Get(key []byte) (index int64, value []byte)
Set(key, value []byte) bool
Remove(key []byte) ([]byte, bool)
Has(key []byte) (bool, error)
Get(key []byte) ([]byte, error)
Set(key, value []byte) (bool, error)
Remove(key []byte) ([]byte, bool, error)
SaveVersion() ([]byte, int64, error)
DeleteVersion(version int64) error
DeleteVersions(versions ...int64) error
Version() int64
Hash() []byte
Hash() ([]byte, error)
VersionExists(version int64) bool
GetVersioned(key []byte, version int64) (int64, []byte)
GetVersioned(key []byte, version int64) ([]byte, error)
GetVersionedWithProof(key []byte, version int64) ([]byte, *iavl.RangeProof, error)
GetImmutable(version int64) (*iavl.ImmutableTree, error)
SetInitialVersion(version uint64)
Iterator(start, end []byte, ascending bool) (types.Iterator, error)
}

// immutableTree is a simple wrapper around a reference to an iavl.ImmutableTree
Expand All @@ -41,11 +43,11 @@ type (
}
)

func (it *immutableTree) Set(_, _ []byte) bool {
func (it *immutableTree) Set(_, _ []byte) (bool, error) {
panic("cannot call 'Set' on an immutable IAVL tree")
}

func (it *immutableTree) Remove(_ []byte) ([]byte, bool) {
func (it *immutableTree) Remove(_ []byte) ([]byte, bool, error) {
panic("cannot call 'Remove' on an immutable IAVL tree")
}

Expand All @@ -69,9 +71,9 @@ func (it *immutableTree) VersionExists(version int64) bool {
return it.Version() == version
}

func (it *immutableTree) GetVersioned(key []byte, version int64) (int64, []byte) {
func (it *immutableTree) GetVersioned(key []byte, version int64) ([]byte, error) {
if it.Version() != version {
return -1, nil
return nil, fmt.Errorf("version mismatch on immutable IAVL tree; got: %d, expected: %d", version, it.Version())
}

return it.Get(key)
Expand Down
Loading

0 comments on commit 1fcc404

Please sign in to comment.