diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 3a73f6ef20d9..4a1c68410126 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -147,7 +147,7 @@ func NewBaseApp( logger: logger, name: name, db: db, - cms: store.NewCommitMultiStore(db), + cms: store.NewCommitMultiStore(db, logger), storeLoader: DefaultStoreLoader, router: NewRouter(), queryRouter: NewQueryRouter(), diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index df891e136936..88d76634f3c9 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -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) @@ -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) diff --git a/go.mod b/go.mod index 493052507576..1609dcad0fda 100644 --- a/go.mod +++ b/go.mod @@ -48,8 +48,8 @@ require ( github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.14 github.com/tendermint/tm-db v0.6.4 - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 - google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 + google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 google.golang.org/grpc v1.42.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 @@ -68,3 +68,5 @@ replace github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210 replace github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 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 diff --git a/go.sum b/go.sum index c304167accc6..427558779db0 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,6 @@ github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/Tv github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= -github.com/cosmos/iavl v0.17.3 h1:s2N819a2olOmiauVa0WAhoIJq9EhSXE9HDBAoR9k+8Y= -github.com/cosmos/iavl v0.17.3/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8= github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4= @@ -497,6 +495,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -573,8 +572,6 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -618,6 +615,14 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/osmosis-labs/iavl v0.17.3-fast.1.0.20220207021926-5f889f6b44d5 h1:Yxj5CB5vnE2BSWbfWlDFzmyccDQmaFVGTms5RlD2Rgo= +github.com/osmosis-labs/iavl v0.17.3-fast.1.0.20220207021926-5f889f6b44d5/go.mod h1:lJEOIlsd3sVO0JDyXWIXa9/Ur5FBscP26zJx0KxHjto= +github.com/osmosis-labs/iavl v0.17.3-fast.4 h1:P6872Aq9Q+X2nCQFMpUb+VCP0rNYZPW5OKa4tTnzR+A= +github.com/osmosis-labs/iavl v0.17.3-fast.4/go.mod h1:lJEOIlsd3sVO0JDyXWIXa9/Ur5FBscP26zJx0KxHjto= +github.com/osmosis-labs/iavl v0.17.3-osmo-v1 h1:orHUut98Miu2+bsFiNZJ29B3ogrbiBbQpti94L2w3Z4= +github.com/osmosis-labs/iavl v0.17.3-osmo-v1/go.mod h1:lJEOIlsd3sVO0JDyXWIXa9/Ur5FBscP26zJx0KxHjto= +github.com/osmosis-labs/iavl v0.17.3-osmo-v3 h1:q2Qv3+DK52w5b68I96VApHI05jBu7HeQK/YDttKh/jY= +github.com/osmosis-labs/iavl v0.17.3-osmo-v3/go.mod h1:lJEOIlsd3sVO0JDyXWIXa9/Ur5FBscP26zJx0KxHjto= github.com/osmosis-labs/tm-db v0.6.5-0.20210911033928-ba9154613417 h1:otchJDd2SjFWfs7Tse3ULblGcVWqMJ50BE02XCaqXOo= github.com/osmosis-labs/tm-db v0.6.5-0.20210911033928-ba9154613417/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ= @@ -874,8 +879,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1215,7 +1220,6 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1226,8 +1230,8 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 h1:z+ErRPu0+KS02Td3fOAgdX+lnPDh/VyaABEJPD4JRQs= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 h1:ysnBoUyeL/H6RCvNRhWHjKoDEmguI+mPU+qHgK8qv/w= +google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1248,9 +1252,8 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/store/iavl/store.go b/store/iavl/store.go index 29a4d9871139..ed232af1ffa8 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -3,6 +3,7 @@ package iavl import ( "errors" "fmt" + "github.com/tendermint/tendermint/libs/log" "io" "time" @@ -41,20 +42,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 { @@ -65,6 +76,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 @@ -173,8 +188,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. @@ -197,31 +211,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 @@ -296,7 +298,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 } @@ -376,17 +378,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) - -// 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 -} diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index b9c9e25ad43d..87d2db239618 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -3,6 +3,7 @@ package iavl import ( crand "crypto/rand" "fmt" + "github.com/tendermint/tendermint/libs/log" "testing" "github.com/cosmos/cosmos-sdk/store/cachekv" @@ -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") } diff --git a/store/iavl/tree.go b/store/iavl/tree.go index 83d1ada301fd..7ea79105575e 100644 --- a/store/iavl/tree.go +++ b/store/iavl/tree.go @@ -3,6 +3,7 @@ package iavl import ( "fmt" + "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/iavl" ) @@ -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) @@ -27,10 +28,11 @@ 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) + Iterator(start, end []byte, ascending bool) types.Iterator } // immutableTree is a simple wrapper around a reference to an iavl.ImmutableTree @@ -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 { if it.Version() != version { - return -1, nil + return nil } return it.Get(key) diff --git a/store/iavl/tree_test.go b/store/iavl/tree_test.go index 24332b42e06a..c7c331fe0b7f 100644 --- a/store/iavl/tree_test.go +++ b/store/iavl/tree_test.go @@ -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) diff --git a/store/rootmulti/proof_test.go b/store/rootmulti/proof_test.go index 10f8397e7284..06152eceffb5 100644 --- a/store/rootmulti/proof_test.go +++ b/store/rootmulti/proof_test.go @@ -1,6 +1,7 @@ package rootmulti import ( + "github.com/tendermint/tendermint/libs/log" "testing" "github.com/stretchr/testify/require" @@ -14,7 +15,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")) @@ -57,7 +58,7 @@ func TestVerifyIAVLStoreQueryProof(t *testing.T) { func TestVerifyMultiStoreQueryProof(t *testing.T) { // Create main tree for testing. db := dbm.NewMemDB() - store := NewStore(db) + store := NewStore(db, nil) iavlStoreKey := types.NewKVStoreKey("iavlStoreKey") store.MountStoreWithDB(iavlStoreKey, types.StoreTypeIAVL, nil) @@ -112,7 +113,7 @@ func TestVerifyMultiStoreQueryProof(t *testing.T) { func TestVerifyMultiStoreQueryProofAbsence(t *testing.T) { // Create main tree for testing. db := dbm.NewMemDB() - store := NewStore(db) + store := NewStore(db, log.NewNopLogger()) iavlStoreKey := types.NewKVStoreKey("iavlStoreKey") store.MountStoreWithDB(iavlStoreKey, types.StoreTypeIAVL, nil) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 17b9fd592bd3..20204388fe74 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -5,6 +5,7 @@ import ( "compress/zlib" "encoding/binary" "fmt" + "github.com/tendermint/tendermint/libs/log" "io" "math" "sort" @@ -46,6 +47,7 @@ const ( // the CommitMultiStore interface. type Store struct { db dbm.DB + logger log.Logger lastCommitInfo *types.CommitInfo pruningOpts types.PruningOptions iavlCacheSize int @@ -73,16 +75,17 @@ var ( // store will be created with a PruneNothing pruning strategy by default. After // a store is created, KVStores must be mounted and finally LoadLatestVersion or // LoadVersion must be called. -func NewStore(db dbm.DB) *Store { +func NewStore(db dbm.DB, logger log.Logger) *Store { return &Store{ - db: db, - pruningOpts: types.PruneNothing, + db: db, + logger: logger, + pruningOpts: types.PruneNothing, iavlCacheSize: iavl.DefaultIAVLCacheSize, - storesParams: make(map[types.StoreKey]storeParams), - stores: make(map[types.StoreKey]types.CommitKVStore), - keysByName: make(map[string]types.StoreKey), - pruneHeights: make([]int64, 0), - listeners: make(map[types.StoreKey][]types.WriteListener), + storesParams: make(map[types.StoreKey]storeParams), + stores: make(map[types.StoreKey]types.CommitKVStore), + keysByName: make(map[string]types.StoreKey), + pruneHeights: make([]int64, 0), + listeners: make(map[types.StoreKey][]types.WriteListener), } } @@ -385,6 +388,14 @@ func (rs *Store) Commit() types.CommitID { rs.lastCommitInfo = commitStores(version, rs.stores) + var pruneErr error + defer func () { + flushMetadata(rs.db, version, rs.lastCommitInfo, rs.pruneHeights) + if pruneErr != nil { + panic(pruneErr) + } + }() + // Determine if pruneHeight height needs to be added to the list of heights to // be pruned, where pruneHeight = (commitHeight - 1) - KeepRecent. if int64(rs.pruningOpts.KeepRecent) < previousHeight { @@ -401,11 +412,9 @@ func (rs *Store) Commit() types.CommitID { // batch prune if the current height is a pruning interval height if rs.pruningOpts.Interval > 0 && version%int64(rs.pruningOpts.Interval) == 0 { - rs.pruneStores() + pruneErr = rs.pruneStores() } - flushMetadata(rs.db, version, rs.lastCommitInfo, rs.pruneHeights) - return types.CommitID{ Version: version, Hash: rs.lastCommitInfo.Hash(), @@ -414,9 +423,9 @@ func (rs *Store) Commit() types.CommitID { // pruneStores will batch delete a list of heights from each mounted sub-store. // Afterwards, pruneHeights is reset. -func (rs *Store) pruneStores() { +func (rs *Store) pruneStores() error { if len(rs.pruneHeights) == 0 { - return + return nil } for key, store := range rs.stores { @@ -427,13 +436,14 @@ func (rs *Store) pruneStores() { if err := store.(*iavl.Store).DeleteVersions(rs.pruneHeights...); err != nil { if errCause := errors.Cause(err); errCause != nil && errCause != iavltree.ErrVersionDoesNotExist { - panic(err) + return err } } } } rs.pruneHeights = make([]int64, 0) + return nil } // CacheWrap implements CacheWrapper/Store/CommitStore. @@ -882,9 +892,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 { diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index cf7653b076cb..254efdfa1614 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -7,6 +7,7 @@ import ( "encoding/hex" "errors" "fmt" + "github.com/tendermint/tendermint/libs/log" "io" "io/ioutil" "math/rand" @@ -30,7 +31,7 @@ import ( func TestStoreType(t *testing.T) { db := dbm.NewMemDB() - store := NewStore(db) + store := NewStore(db, log.NewNopLogger()) store.MountStoreWithDB(types.NewKVStoreKey("store1"), types.StoreTypeIAVL, db) } @@ -53,7 +54,7 @@ func TestGetCommitKVStore(t *testing.T) { func TestStoreMount(t *testing.T) { db := dbm.NewMemDB() - store := NewStore(db) + store := NewStore(db, log.NewNopLogger()) key1 := types.NewKVStoreKey("store1") key2 := types.NewKVStoreKey("store2") @@ -831,7 +832,7 @@ func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) { b.StartTimer() for i := 0; i < b.N; i++ { - target := NewStore(dbm.NewMemDB()) + target := NewStore(dbm.NewMemDB(), log.NewNopLogger()) for key := range source.stores { target.MountStoreWithDB(key, types.StoreTypeIAVL, nil) } @@ -861,7 +862,7 @@ func benchmarkMultistoreSnapshotRestore(b *testing.B, stores uint8, storeKeys ui b.StartTimer() for i := 0; i < b.N; i++ { - target := NewStore(dbm.NewMemDB()) + target := NewStore(dbm.NewMemDB(), log.NewNopLogger()) for key := range source.stores { target.MountStoreWithDB(key, types.StoreTypeIAVL, nil) } @@ -887,7 +888,7 @@ var ( ) func newMultiStoreWithMounts(db dbm.DB, pruningOpts types.PruningOptions) *Store { - store := NewStore(db) + store := NewStore(db, log.NewNopLogger()) store.pruningOpts = pruningOpts store.MountStoreWithDB(testStoreKey1, types.StoreTypeIAVL, nil) @@ -898,7 +899,7 @@ func newMultiStoreWithMounts(db dbm.DB, pruningOpts types.PruningOptions) *Store } func newMultiStoreWithMixedMounts(db dbm.DB) *Store { - store := NewStore(db) + store := NewStore(db, log.NewNopLogger()) store.MountStoreWithDB(types.NewKVStoreKey("iavl1"), types.StoreTypeIAVL, nil) store.MountStoreWithDB(types.NewKVStoreKey("iavl2"), types.StoreTypeIAVL, nil) store.MountStoreWithDB(types.NewKVStoreKey("iavl3"), types.StoreTypeIAVL, nil) @@ -935,7 +936,7 @@ func newMultiStoreWithMixedMountsAndBasicData(db dbm.DB) *Store { } func newMultiStoreWithGeneratedData(db dbm.DB, stores uint8, storeKeys uint64) *Store { - multiStore := NewStore(db) + multiStore := NewStore(db, log.NewNopLogger()) r := rand.New(rand.NewSource(49872768940)) // Fixed seed for deterministic tests keys := []*types.KVStoreKey{} @@ -967,7 +968,7 @@ func newMultiStoreWithGeneratedData(db dbm.DB, stores uint8, storeKeys uint64) * } func newMultiStoreWithModifiedMounts(db dbm.DB, pruningOpts types.PruningOptions) (*Store, *types.StoreUpgrades) { - store := NewStore(db) + store := NewStore(db, log.NewNopLogger()) store.pruningOpts = pruningOpts store.MountStoreWithDB(types.NewKVStoreKey("store1"), types.StoreTypeIAVL, nil) diff --git a/store/store.go b/store/store.go index 2c068c413f47..a367e4ee3dfc 100644 --- a/store/store.go +++ b/store/store.go @@ -1,6 +1,7 @@ package store import ( + "github.com/tendermint/tendermint/libs/log" dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/store/cache" @@ -8,8 +9,8 @@ import ( "github.com/cosmos/cosmos-sdk/store/types" ) -func NewCommitMultiStore(db dbm.DB) types.CommitMultiStore { - return rootmulti.NewStore(db) +func NewCommitMultiStore(db dbm.DB, logger log.Logger) types.CommitMultiStore { + return rootmulti.NewStore(db, logger) } func NewCommitKVStoreCacheManager() types.MultiStorePersistentCache { diff --git a/store/types/iterator_test.go b/store/types/iterator_test.go index 686aa1123708..607d9c1e3d41 100644 --- a/store/types/iterator_test.go +++ b/store/types/iterator_test.go @@ -1,6 +1,7 @@ package types_test import ( + "github.com/tendermint/tendermint/libs/log" "testing" "github.com/stretchr/testify/require" @@ -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 } diff --git a/store/types/utils_test.go b/store/types/utils_test.go index 32064d7e1821..391b42b33023 100644 --- a/store/types/utils_test.go +++ b/store/types/utils_test.go @@ -2,6 +2,7 @@ package types_test import ( "bytes" + "github.com/tendermint/tendermint/libs/log" "testing" "github.com/stretchr/testify/require" @@ -13,7 +14,7 @@ import ( func initTestStores(t *testing.T) (types.KVStore, types.KVStore) { db := dbm.NewMemDB() - ms := rootmulti.NewStore(db) + ms := rootmulti.NewStore(db, log.NewNopLogger()) key1 := types.NewKVStoreKey("store1") key2 := types.NewKVStoreKey("store2") diff --git a/testutil/context.go b/testutil/context.go index 2fb9865a2696..bf1ef78a5471 100644 --- a/testutil/context.go +++ b/testutil/context.go @@ -12,7 +12,7 @@ import ( // DefaultContext creates a sdk.Context with a fresh MemDB that can be used in tests. func DefaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context { db := dbm.NewMemDB() - cms := store.NewCommitMultiStore(db) + cms := store.NewCommitMultiStore(db, log.NewNopLogger()) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db) err := cms.LoadLatestVersion() diff --git a/types/query/pagination_test.go b/types/query/pagination_test.go index da07a5e1b093..529200515d70 100644 --- a/types/query/pagination_test.go +++ b/types/query/pagination_test.go @@ -3,6 +3,7 @@ package query_test import ( gocontext "context" "fmt" + "github.com/tendermint/tendermint/libs/log" "testing" "github.com/stretchr/testify/suite" @@ -340,7 +341,7 @@ func setupTest() (*simapp.SimApp, sdk.Context, codec.Codec) { appCodec := app.AppCodec() db := dbm.NewMemDB() - ms := store.NewCommitMultiStore(db) + ms := store.NewCommitMultiStore(db, log.NewNopLogger()) ms.LoadLatestVersion() diff --git a/types/store_test.go b/types/store_test.go index 9c3ef2f79dd6..645d4eb6917b 100644 --- a/types/store_test.go +++ b/types/store_test.go @@ -1,6 +1,7 @@ package types_test import ( + "github.com/tendermint/tendermint/libs/log" "testing" "github.com/stretchr/testify/suite" @@ -108,7 +109,7 @@ func (s *storeTestSuite) TestDiffKVStores() { func (s *storeTestSuite) initTestStores() (types.KVStore, types.KVStore) { db := dbm.NewMemDB() - ms := rootmulti.NewStore(db) + ms := rootmulti.NewStore(db, log.NewNopLogger()) key1 := types.NewKVStoreKey("store1") key2 := types.NewKVStoreKey("store2") diff --git a/x/params/types/subspace_test.go b/x/params/types/subspace_test.go index a347a5f5427e..4aa785bbb307 100644 --- a/x/params/types/subspace_test.go +++ b/x/params/types/subspace_test.go @@ -29,7 +29,7 @@ type SubspaceTestSuite struct { func (suite *SubspaceTestSuite) SetupTest() { db := dbm.NewMemDB() - ms := store.NewCommitMultiStore(db) + ms := store.NewCommitMultiStore(db, log.NewNopLogger()) ms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db) suite.NoError(ms.LoadLatestVersion()) diff --git a/x/upgrade/types/storeloader_test.go b/x/upgrade/types/storeloader_test.go index ec2bfa824d07..c339aa4045f9 100644 --- a/x/upgrade/types/storeloader_test.go +++ b/x/upgrade/types/storeloader_test.go @@ -30,7 +30,7 @@ func defaultLogger() log.Logger { } 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) @@ -47,7 +47,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.PruneNothing) key := sdk.NewKVStoreKey(storeKey) rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil)