Skip to content

Commit

Permalink
feat: upgrade to fast storage on v0.45.0x-osmo-v7-fast (cosmos#108)
Browse files Browse the repository at this point in the history
* upgrade fast iavl

* add store key log

* flush commit metadata when prunning fails and upgrade iavl
  • Loading branch information
p0mvn authored and roysc committed Jul 10, 2022
1 parent be77252 commit 462c448
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 66 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,6 @@ replace (

replace github.com/tendermint/tm-db => github.com/osmosis-labs/tm-db v0.6.5-0.20210911033928-ba9154613417

replace github.com/cosmos/iavl => github.com/osmosis-labs/iavl v0.17.3-osmo-v3

retract v0.43.0
54 changes: 42 additions & 12 deletions go.sum

Large diffs are not rendered by default.

66 changes: 29 additions & 37 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 @@ -42,20 +43,30 @@ 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
}

if tree.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 @@ -66,6 +77,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 @@ -179,8 +194,7 @@ 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)
return value
return st.tree.Get(key)
}

// Implements types.KVStore.
Expand All @@ -203,31 +217,19 @@ func (st *Store) DeleteVersions(versions ...int64) error {
}

// Implements types.KVStore.
// CONTRACT: Caller must release the iavlIterator, as each one creates a new
// goroutine.
// CONTRACT: There must be no writes to the store while an iterator is not closed.
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
}

return newIAVLIterator(iTree, start, end, true)
return st.tree.Iterator(start, end, true)
}

// Implements types.KVStore.
// CONTRACT: Caller must release the iavlIterator, as each one creates a new
// goroutine.
// CONTRACT: There must be no writes to the store while an iterator is not closed.
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
}

return newIAVLIterator(iTree, start, end, false)
return st.tree.Iterator(start, end, false)
}

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

_, res.Value = tree.GetVersioned(key, res.Height)
res.Value = tree.GetVersioned(key, res.Height)
if !req.Prove {
break
}
Expand Down Expand Up @@ -382,17 +384,7 @@ func getProofFromTree(tree *iavl.MutableTree, key []byte, exists bool) *tmcrypto

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

var _ types.Iterator = (*iavlIterator)(nil)

// newIAVLIterator will create a new iavlIterator.
// CONTRACT: Caller must release the iavlIterator, as each one creates a new
// goroutine.
func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator {
iter := &iavlIterator{
Iterator: tree.Iterator(start, end, ascending),
}
return iter
}
7 changes: 4 additions & 3 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 @@ -93,17 +94,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 Down
10 changes: 6 additions & 4 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 @@ -18,7 +19,7 @@ type (
// must be made.
Tree interface {
Has(key []byte) bool
Get(key []byte) (index int64, value []byte)
Get(key []byte) []byte
Set(key, value []byte) bool
Remove(key []byte) ([]byte, bool)
SaveVersion() ([]byte, int64, error)
Expand All @@ -27,11 +28,12 @@ type (
Version() int64
Hash() []byte
VersionExists(version int64) bool
GetVersioned(key []byte, version int64) (int64, []byte)
GetVersioned(key []byte, version int64) []byte
GetVersionedWithProof(key []byte, version int64) ([]byte, *iavl.RangeProof, error)
GetImmutable(version int64) (*iavl.ImmutableTree, error)
SetInitialVersion(version uint64)
AvailableVersions() []int
Iterator(start, end []byte, ascending bool) types.Iterator
}

// immutableTree is a simple wrapper around a reference to an iavl.ImmutableTree
Expand Down Expand Up @@ -70,9 +72,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 {
if it.Version() != version {
return -1, nil
return nil
}

return it.Get(key)
Expand Down
8 changes: 4 additions & 4 deletions store/iavl/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ func TestImmutableTreePanics(t *testing.T) {
require.Panics(t, func() { it.Remove([]byte{}) })
require.Panics(t, func() { it.SaveVersion() }) // nolint:errcheck
require.Panics(t, func() { it.DeleteVersion(int64(1)) }) // nolint:errcheck
v, _ := it.GetVersioned([]byte{0x01}, 1)
require.Equal(t, int64(-1), v)
v, _ = it.GetVersioned([]byte{0x01}, 0)
require.Equal(t, int64(0), v)
v := it.GetVersioned([]byte{0x01}, 1)
require.Nil(t, v)
v = it.GetVersioned([]byte{0x01}, 0)
require.Nil(t, v)

val, proof, err := it.GetVersionedWithProof(nil, 1)
require.Error(t, err)
Expand Down
3 changes: 2 additions & 1 deletion store/rootmulti/proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/stretchr/testify/require"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
Expand All @@ -15,7 +16,7 @@ import (
func TestVerifyIAVLStoreQueryProof(t *testing.T) {
// Create main tree for testing.
db := dbm.NewMemDB()
iStore, err := iavl.LoadStore(db, types.CommitID{}, false, iavl.DefaultIAVLCacheSize)
iStore, err := iavl.LoadStore(db, nil, types.NewKVStoreKey("test"), types.CommitID{}, false, iavl.DefaultIAVLCacheSize)
store := iStore.(*iavl.Store)
require.Nil(t, err)
store.Set([]byte("MYKEY"), []byte("MYVALUE"))
Expand Down
4 changes: 2 additions & 2 deletions store/rootmulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -865,9 +865,9 @@ func (rs *Store) loadCommitStoreFromParams(key types.StoreKey, id types.CommitID
var err error

if params.initialVersion == 0 {
store, err = iavl.LoadStore(db, id, rs.lazyLoading, rs.iavlCacheSize)
store, err = iavl.LoadStore(db, rs.logger, key, id, rs.lazyLoading, rs.iavlCacheSize)
} else {
store, err = iavl.LoadStoreWithInitialVersion(db, id, rs.lazyLoading, params.initialVersion, rs.iavlCacheSize)
store, err = iavl.LoadStoreWithInitialVersion(db, rs.logger, key, id, rs.lazyLoading, params.initialVersion, rs.iavlCacheSize)
}

if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion store/types/iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"

"github.com/cosmos/cosmos-sdk/store/iavl"
Expand All @@ -12,7 +13,7 @@ import (

func newMemTestKVStore(t *testing.T) types.KVStore {
db := dbm.NewMemDB()
store, err := iavl.LoadStore(db, types.CommitID{}, false, iavl.DefaultIAVLCacheSize)
store, err := iavl.LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), types.CommitID{}, false, iavl.DefaultIAVLCacheSize)
require.NoError(t, err)
return store
}
Expand Down
3 changes: 1 addition & 2 deletions types/module/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import (
"github.com/golang/mock/gomock"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
Expand Down

0 comments on commit 462c448

Please sign in to comment.