From a8556b66c0dcbd86887a367bf5ba683f3a021010 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 17 Feb 2023 17:57:32 +0000 Subject: [PATCH 01/47] fix: create snapshot dir for rocksdb backend (backport #15054) (#15065) Co-authored-by: yihuang --- server/util.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/util.go b/server/util.go index 1834da6c3384..2d9d02eb6834 100644 --- a/server/util.go +++ b/server/util.go @@ -431,6 +431,10 @@ func DefaultBaseappOptions(appOpts types.AppOptions) []func(*baseapp.BaseApp) { } snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots") + if err = os.MkdirAll(snapshotDir, os.ModePerm); err != nil { + panic(fmt.Errorf("failed to create snapshots directory: %w", err)) + } + snapshotDB, err := dbm.NewDB("metadata", GetAppDBBackend(appOpts), snapshotDir) if err != nil { panic(err) From 5848fd3295515f48a6024963f25849c7aebd3680 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 00:37:12 +0100 Subject: [PATCH 02/47] chore: Add check for uneven stores' height (backport #14410) (#15115) Co-authored-by: khanh-notional <50263489+catShaark@users.noreply.github.com> Co-authored-by: marbar3778 --- CHANGELOG.md | 1 + go.mod | 3 +-- store/rootmulti/store.go | 22 ++++++++++------ store/rootmulti/store_test.go | 39 +++++++++++++++++++++++++++++ x/upgrade/types/storeloader_test.go | 5 ---- 5 files changed, 55 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30bf59c12d83..ee70a2a12afb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (cli) [#14953](https://github.com/cosmos/cosmos-sdk/pull/14953) Enable profiling block replay during abci handshake with `--cpu-profile`. +* (store) [#14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height. ## [v0.46.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.9) - 2022-02-07 diff --git a/go.mod b/go.mod index 9330a7a22760..b0eb00e1a443 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/spf13/viper v1.13.0 github.com/stretchr/testify v1.8.1 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.26 + github.com/tendermint/tendermint v0.34.24 github.com/tendermint/tm-db v0.6.7 github.com/tidwall/btree v1.5.0 golang.org/x/crypto v0.5.0 @@ -167,7 +167,6 @@ replace ( // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - github.com/jhump/protoreflect => github.com/jhump/protoreflect v1.9.0 // use informal system fork of tendermint github.com/tendermint/tendermint => github.com/informalsystems/tendermint v0.34.26 diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 3b5fede4321d..dd81d771eec5 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -134,11 +134,7 @@ func (rs *Store) MountStoreWithDB(key types.StoreKey, typ types.StoreType, db db if _, ok := rs.keysByName[key.Name()]; ok { panic(fmt.Sprintf("store duplicate store key name %v", key)) } - rs.storesParams[key] = storeParams{ - key: key, - typ: typ, - db: db, - } + rs.storesParams[key] = newStoreParams(key, db, typ, 0) rs.keysByName[key.Name()] = key } @@ -231,8 +227,10 @@ func (rs *Store) loadVersion(ver int64, upgrades *types.StoreUpgrades) error { commitID := rs.getCommitID(infos, key.Name()) // If it has been added, set the initial version - if upgrades.IsAdded(key.Name()) { + if upgrades.IsAdded(key.Name()) || upgrades.RenamedFrom(key.Name()) != "" { storeParams.initialVersion = uint64(ver) + 1 + } else if commitID.Version != ver && storeParams.typ == types.StoreTypeIAVL { + return fmt.Errorf("version of store %s mismatch root store's version; expected %d got %d", key.Name(), ver, commitID.Version) } store, err := rs.loadCommitStoreFromParams(key, commitID, storeParams) @@ -252,8 +250,7 @@ func (rs *Store) loadVersion(ver int64, upgrades *types.StoreUpgrades) error { // handle renames specially // make an unregistered key to satisfy loadCommitStore params oldKey := types.NewKVStoreKey(oldName) - oldParams := storeParams - oldParams.key = oldKey + oldParams := newStoreParams(oldKey, storeParams.db, storeParams.typ, 0) // load from the old name oldStore, err := rs.loadCommitStoreFromParams(oldKey, rs.getCommitID(infos, oldName), oldParams) @@ -1009,6 +1006,15 @@ type storeParams struct { initialVersion uint64 } +func newStoreParams(key types.StoreKey, db dbm.DB, typ types.StoreType, initialVersion uint64) storeParams { // nolint + return storeParams{ + key: key, + db: db, + typ: typ, + initialVersion: initialVersion, + } +} + func GetLatestVersion(db dbm.DB) int64 { bz, err := db.Get([]byte(latestVersionKey)) if err != nil { diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index 26204bceb21b..0e78e0f95bed 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -273,6 +273,12 @@ func TestMultistoreLoadWithUpgrade(t *testing.T) { require.Equal(t, migratedID.Version, int64(2)) reload, _ := newMultiStoreWithModifiedMounts(db, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)) + // unmount store3 since store3 was deleted + unmountStore(reload, "store3") + + rs3, _ := reload.GetStoreByName("store3").(types.KVStore) + require.Nil(t, rs3) + err = reload.LoadLatestVersion() require.Nil(t, err) require.Equal(t, migratedID, reload.LastCommitID()) @@ -607,6 +613,32 @@ func TestMultiStore_PruningRestart(t *testing.T) { } } +// TestUnevenStoresHeightCheck tests if loading root store correctly errors when +// there's any module store with the wrong height +func TestUnevenStoresHeightCheck(t *testing.T) { + var db dbm.DB = dbm.NewMemDB() + store := newMultiStoreWithMounts(db, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)) + err := store.LoadLatestVersion() + require.Nil(t, err) + + // commit to increment store's height + store.Commit() + + // mount store4 to root store + store.MountStoreWithDB(types.NewKVStoreKey("store4"), types.StoreTypeIAVL, nil) + + // load the stores without upgrades + err = store.LoadLatestVersion() + require.Error(t, err) + + // now, let's load with upgrades... + upgrades := &types.StoreUpgrades{ + Added: []string{"store4"}, + } + err = store.LoadLatestVersionAndUpgrade(upgrades) + require.Nil(t, err) +} + func TestSetInitialVersion(t *testing.T) { db := dbm.NewMemDB() multi := newMultiStoreWithMounts(db, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)) @@ -868,6 +900,13 @@ func newMultiStoreWithModifiedMounts(db dbm.DB, pruningOpts pruningtypes.Pruning return store, upgrades } +func unmountStore(rootStore *Store, storeKeyName string) { + sk := rootStore.keysByName[storeKeyName] + delete(rootStore.stores, sk) + delete(rootStore.storesParams, sk) + delete(rootStore.keysByName, storeKeyName) +} + func checkStore(t *testing.T, store *Store, expect, got types.CommitID) { require.Equal(t, expect, got) require.Equal(t, expect, store.LastCommitID()) diff --git a/x/upgrade/types/storeloader_test.go b/x/upgrade/types/storeloader_test.go index 6aaefa69d198..783c15caa346 100644 --- a/x/upgrade/types/storeloader_test.go +++ b/x/upgrade/types/storeloader_test.go @@ -151,11 +151,6 @@ func TestSetLoader(t *testing.T) { res := app.Commit() require.NotNil(t, res.Data) - // checking the case of the store being renamed - if tc.setLoader != nil { - checkStore(t, db, upgradeHeight, tc.origStoreKey, k, nil) - } - // check db is properly updated checkStore(t, db, upgradeHeight, tc.loadStoreKey, k, v) }) From 8499d162abf9e85d8833ce9f2ede6ca7d4051420 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 24 Feb 2023 16:45:47 +0100 Subject: [PATCH 03/47] refactor!: remove store v2alpha1 (#15152) --- CHANGELOG.md | 6 +- go.mod | 1 - go.sum | 2 - store/transient/store_test.go | 2 +- store/v2alpha1/dbadapter/store.go | 92 --- store/v2alpha1/dbadapter/store_test.go | 105 --- store/v2alpha1/mem/store.go | 45 -- store/v2alpha1/mem/store_test.go | 39 - store/v2alpha1/multi/cache_store.go | 36 - store/v2alpha1/multi/doc.go | 19 - store/v2alpha1/multi/migration.go | 68 -- store/v2alpha1/multi/migration_test.go | 107 --- store/v2alpha1/multi/proof.go | 52 -- store/v2alpha1/multi/proof_test.go | 125 ---- store/v2alpha1/multi/snapshot.go | 172 ----- store/v2alpha1/multi/snapshot_test.go | 317 -------- store/v2alpha1/multi/store.go | 915 ----------------------- store/v2alpha1/multi/store_test.go | 986 ------------------------- store/v2alpha1/multi/sub_store.go | 117 --- store/v2alpha1/multi/test_util.go | 88 --- store/v2alpha1/multi/view_store.go | 178 ----- store/v2alpha1/smt/ics23.go | 124 ---- store/v2alpha1/smt/ics23_test.go | 108 --- store/v2alpha1/smt/proof.go | 93 --- store/v2alpha1/smt/proof_test.go | 69 -- store/v2alpha1/smt/store.go | 143 ---- store/v2alpha1/smt/store_test.go | 46 -- store/v2alpha1/transient/store.go | 47 -- store/v2alpha1/transient/store_test.go | 27 - store/v2alpha1/types.go | 111 --- 30 files changed, 6 insertions(+), 4234 deletions(-) delete mode 100644 store/v2alpha1/dbadapter/store.go delete mode 100644 store/v2alpha1/dbadapter/store_test.go delete mode 100644 store/v2alpha1/mem/store.go delete mode 100644 store/v2alpha1/mem/store_test.go delete mode 100644 store/v2alpha1/multi/cache_store.go delete mode 100644 store/v2alpha1/multi/doc.go delete mode 100644 store/v2alpha1/multi/migration.go delete mode 100644 store/v2alpha1/multi/migration_test.go delete mode 100644 store/v2alpha1/multi/proof.go delete mode 100644 store/v2alpha1/multi/proof_test.go delete mode 100644 store/v2alpha1/multi/snapshot.go delete mode 100644 store/v2alpha1/multi/snapshot_test.go delete mode 100644 store/v2alpha1/multi/store.go delete mode 100644 store/v2alpha1/multi/store_test.go delete mode 100644 store/v2alpha1/multi/sub_store.go delete mode 100644 store/v2alpha1/multi/test_util.go delete mode 100644 store/v2alpha1/multi/view_store.go delete mode 100644 store/v2alpha1/smt/ics23.go delete mode 100644 store/v2alpha1/smt/ics23_test.go delete mode 100644 store/v2alpha1/smt/proof.go delete mode 100644 store/v2alpha1/smt/proof_test.go delete mode 100644 store/v2alpha1/smt/store.go delete mode 100644 store/v2alpha1/smt/store_test.go delete mode 100644 store/v2alpha1/transient/store.go delete mode 100644 store/v2alpha1/transient/store_test.go delete mode 100644 store/v2alpha1/types.go diff --git a/CHANGELOG.md b/CHANGELOG.md index ee70a2a12afb..2d752bb18aa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,12 +37,16 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +## Improvements + +* (store) [#15152](https://github.com/cosmos/cosmos-sdk/pull/15152) Remove unmaintained and experimental `store/v2alpha1`. +* (store) [#14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height. + ## [v0.46.10](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.10) - 2022-02-16 ### Improvements * (cli) [#14953](https://github.com/cosmos/cosmos-sdk/pull/14953) Enable profiling block replay during abci handshake with `--cpu-profile`. -* (store) [#14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height. ## [v0.46.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.9) - 2022-02-07 diff --git a/go.mod b/go.mod index b0eb00e1a443..59dbcc12dc13 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/armon/go-metrics v0.4.1 github.com/bgentry/speakeasy v0.1.0 github.com/btcsuite/btcd/btcec/v2 v2.3.2 - github.com/celestiaorg/smt v0.3.0 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/cockroachdb/apd/v2 v2.0.2 github.com/coinbase/rosetta-sdk-go v0.7.9 diff --git a/go.sum b/go.sum index dd446840ea8c..18465df7d274 100644 --- a/go.sum +++ b/go.sum @@ -176,8 +176,6 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/celestiaorg/smt v0.3.0 h1:Hc6m8fIVRajrg/Saf8ivX4xw551LHzOs8kqeadd6h9s= -github.com/celestiaorg/smt v0.3.0/go.mod h1:/sdYDakowo/XaxS2Fl7CBqtuf/O2uTqF2zmAUFAtAiw= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= diff --git a/store/transient/store_test.go b/store/transient/store_test.go index 900e6cb7a918..48324aa9491d 100644 --- a/store/transient/store_test.go +++ b/store/transient/store_test.go @@ -8,7 +8,7 @@ import ( pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" "github.com/cosmos/cosmos-sdk/store/transient" - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" + "github.com/cosmos/cosmos-sdk/store/types" ) var k, v = []byte("hello"), []byte("world") diff --git a/store/v2alpha1/dbadapter/store.go b/store/v2alpha1/dbadapter/store.go deleted file mode 100644 index 1cbd6c83585b..000000000000 --- a/store/v2alpha1/dbadapter/store.go +++ /dev/null @@ -1,92 +0,0 @@ -package dbadapter - -import ( - "io" - - dbm "github.com/cosmos/cosmos-sdk/db" - dbutil "github.com/cosmos/cosmos-sdk/internal/db" - "github.com/cosmos/cosmos-sdk/store/cachekv" - "github.com/cosmos/cosmos-sdk/store/listenkv" - "github.com/cosmos/cosmos-sdk/store/tracekv" - "github.com/cosmos/cosmos-sdk/store/types" -) - -var _ types.KVStore = Store{} - -// Wrapper type for dbm.Db with implementation of KVStore -type Store struct { - DB dbm.DBReadWriter -} - -// Get wraps the underlying DB's Get method panicing on error. -func (dsa Store) Get(key []byte) []byte { - v, err := dsa.DB.Get(key) - if err != nil { - panic(err) - } - - return v -} - -// Has wraps the underlying DB's Has method panicing on error. -func (dsa Store) Has(key []byte) bool { - ok, err := dsa.DB.Has(key) - if err != nil { - panic(err) - } - - return ok -} - -// Set wraps the underlying DB's Set method panicing on error. -func (dsa Store) Set(key, value []byte) { - types.AssertValidKey(key) - if err := dsa.DB.Set(key, value); err != nil { - panic(err) - } -} - -// Delete wraps the underlying DB's Delete method panicing on error. -func (dsa Store) Delete(key []byte) { - if err := dsa.DB.Delete(key); err != nil { - panic(err) - } -} - -// Iterator wraps the underlying DB's Iterator method panicing on error. -func (dsa Store) Iterator(start, end []byte) types.Iterator { - iter, err := dsa.DB.Iterator(start, end) - if err != nil { - panic(err) - } - return dbutil.DBToStoreIterator(iter) -} - -// ReverseIterator wraps the underlying DB's ReverseIterator method panicing on error. -func (dsa Store) ReverseIterator(start, end []byte) types.Iterator { - iter, err := dsa.DB.ReverseIterator(start, end) - if err != nil { - panic(err) - } - return dbutil.DBToStoreIterator(iter) -} - -// GetStoreType returns the type of the store. -func (dsa Store) GetStoreType() types.StoreType { - return types.StoreTypeDB -} - -// CacheWrap branches the underlying store. -func (dsa Store) CacheWrap() types.CacheWrap { - return cachekv.NewStore(dsa) -} - -// CacheWrapWithTrace implements KVStore. -func (dsa Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return cachekv.NewStore(tracekv.NewStore(dsa, w, tc)) -} - -// CacheWrapWithListeners implements the CacheWrapper interface. -func (dsa Store) CacheWrapWithListeners(storeKey types.StoreKey, listeners []types.WriteListener) types.CacheWrap { - return cachekv.NewStore(listenkv.NewStore(dsa, storeKey, listeners)) -} diff --git a/store/v2alpha1/dbadapter/store_test.go b/store/v2alpha1/dbadapter/store_test.go deleted file mode 100644 index 9bfa68518ab0..000000000000 --- a/store/v2alpha1/dbadapter/store_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package dbadapter_test - -import ( - "bytes" - "errors" - "testing" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/store/cachekv" - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/dbadapter" - mocks "github.com/cosmos/cosmos-sdk/tests/mocks/db" -) - -var errFoo = errors.New("dummy") - -func TestAccessors(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - mockDB := mocks.NewMockDBReadWriter(mockCtrl) - store := dbadapter.Store{mockDB} - key := []byte("test") - value := []byte("testvalue") - - require.Panics(t, func() { store.Set(nil, []byte("value")) }, "setting a nil key should panic") - require.Panics(t, func() { store.Set([]byte(""), []byte("value")) }, "setting an empty key should panic") - - require.Equal(t, types.StoreTypeDB, store.GetStoreType()) - - retFoo := []byte("xxx") - mockDB.EXPECT().Get(gomock.Eq(key)).Times(1).Return(retFoo, nil) - require.True(t, bytes.Equal(retFoo, store.Get(key))) - require.Equal(t, []byte{1, 2, 3}, []byte{1, 2, 3}) - - mockDB.EXPECT().Get(gomock.Eq(key)).Times(1).Return(nil, errFoo) - require.Panics(t, func() { store.Get(key) }) - - mockDB.EXPECT().Has(gomock.Eq(key)).Times(1).Return(true, nil) - require.True(t, store.Has(key)) - - mockDB.EXPECT().Has(gomock.Eq(key)).Times(1).Return(false, nil) - require.False(t, store.Has(key)) - - mockDB.EXPECT().Has(gomock.Eq(key)).Times(1).Return(false, errFoo) - require.Panics(t, func() { store.Has(key) }) - - mockDB.EXPECT().Set(gomock.Eq(key), gomock.Eq(value)).Times(1).Return(nil) - require.NotPanics(t, func() { store.Set(key, value) }) - - mockDB.EXPECT().Set(gomock.Eq(key), gomock.Eq(value)).Times(1).Return(errFoo) - require.Panics(t, func() { store.Set(key, value) }) - - mockDB.EXPECT().Delete(gomock.Eq(key)).Times(1).Return(nil) - require.NotPanics(t, func() { store.Delete(key) }) - - mockDB.EXPECT().Delete(gomock.Eq(key)).Times(1).Return(errFoo) - require.Panics(t, func() { store.Delete(key) }) -} - -func TestIterators(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - mockDB := mocks.NewMockDBReadWriter(mockCtrl) - store := dbadapter.Store{mockDB} - key := []byte("test") - value := []byte("testvalue") - - start, end := key, []byte("test_end") - - mockDB.EXPECT().Iterator(gomock.Eq(start), gomock.Eq(end)).Times(1).Return(nil, errFoo) - require.Panics(t, func() { store.Iterator(start, end) }) - - mockDB.EXPECT().ReverseIterator(gomock.Eq(start), gomock.Eq(end)).Times(1).Return(nil, errFoo) - require.Panics(t, func() { store.ReverseIterator(start, end) }) - - mockIter := mocks.NewMockIterator(mockCtrl) - mockIter.EXPECT().Next().Times(1).Return(true) - mockIter.EXPECT().Key().Times(1).Return(key) - mockIter.EXPECT().Value().Times(1).Return(value) - - mockDB.EXPECT().Iterator(gomock.Eq(start), gomock.Eq(end)).Times(1).Return(mockIter, nil) - iter := store.Iterator(start, end) - - require.Equal(t, key, iter.Key()) - require.Equal(t, value, iter.Value()) -} - -func TestCacheWraps(t *testing.T) { - mockCtrl := gomock.NewController(t) - mockDB := mocks.NewMockDBReadWriter(mockCtrl) - store := dbadapter.Store{mockDB} - - cacheWrapper := store.CacheWrap() - require.IsType(t, &cachekv.Store{}, cacheWrapper) - - cacheWrappedWithTrace := store.CacheWrapWithTrace(nil, nil) - require.IsType(t, &cachekv.Store{}, cacheWrappedWithTrace) - - cacheWrappedWithListeners := store.CacheWrapWithListeners(nil, nil) - require.IsType(t, &cachekv.Store{}, cacheWrappedWithListeners) -} diff --git a/store/v2alpha1/mem/store.go b/store/v2alpha1/mem/store.go deleted file mode 100644 index 3c8fa82bbaba..000000000000 --- a/store/v2alpha1/mem/store.go +++ /dev/null @@ -1,45 +0,0 @@ -package mem - -import ( - dbm "github.com/cosmos/cosmos-sdk/db" - "github.com/cosmos/cosmos-sdk/db/memdb" - pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" - "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/dbadapter" -) - -var ( - _ types.KVStore = (*Store)(nil) - _ types.Committer = (*Store)(nil) -) - -// Store implements an in-memory only KVStore. Entries are persisted between -// commits and thus between blocks. State in Memory store is not committed as part of app state but maintained privately by each node -type Store struct { - dbadapter.Store - conn dbm.DBConnection -} - -// NewStore constructs a new in-memory store. -func NewStore() *Store { - db := memdb.NewDB() - return &Store{ - Store: dbadapter.Store{DB: db.ReadWriter()}, - conn: db, - } -} - -// GetStoreType returns the Store's type. -func (s Store) GetStoreType() types.StoreType { - return types.StoreTypeMemory -} - -// Commit commits to the underlying DB. -func (s *Store) Commit() (id types.CommitID) { - return -} - -func (s *Store) SetPruning(pruningtypes.PruningOptions) {} -func (s *Store) GetPruning() pruningtypes.PruningOptions { return pruningtypes.PruningOptions{} } - -func (s Store) LastCommitID() (id types.CommitID) { return } diff --git a/store/v2alpha1/mem/store_test.go b/store/v2alpha1/mem/store_test.go deleted file mode 100644 index 297e2a75df76..000000000000 --- a/store/v2alpha1/mem/store_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package mem_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/mem" -) - -func TestStore(t *testing.T) { - store := mem.NewStore() - key, value := []byte("key"), []byte("value") - - require.Equal(t, types.StoreTypeMemory, store.GetStoreType()) - - require.Nil(t, store.Get(key)) - store.Set(key, value) - require.Equal(t, value, store.Get(key)) - - newValue := []byte("newValue") - store.Set(key, newValue) - require.Equal(t, newValue, store.Get(key)) - - store.Delete(key) - require.Nil(t, store.Get(key)) -} - -func TestCommit(t *testing.T) { - store := mem.NewStore() - key, value := []byte("key"), []byte("value") - - store.Set(key, value) - id := store.Commit() - require.True(t, id.IsZero()) - require.True(t, store.LastCommitID().IsZero()) - require.Equal(t, value, store.Get(key)) -} diff --git a/store/v2alpha1/multi/cache_store.go b/store/v2alpha1/multi/cache_store.go deleted file mode 100644 index 5d7ee786da43..000000000000 --- a/store/v2alpha1/multi/cache_store.go +++ /dev/null @@ -1,36 +0,0 @@ -package multi - -import ( - "github.com/cosmos/cosmos-sdk/store/cachekv" - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" -) - -// GetKVStore implements BasicMultiStore. -func (cs *cacheStore) GetKVStore(skey types.StoreKey) types.KVStore { - key := skey.Name() - sub, has := cs.substores[key] - if !has { - sub = cachekv.NewStore(cs.source.GetKVStore(skey)) - cs.substores[key] = sub - } - // Wrap with trace/listen if needed. Note: we don't cache this, so users must get a new substore after - // modifying tracers/listeners. - return cs.wrapTraceListen(sub, skey) -} - -// Write implements CacheMultiStore. -func (cs *cacheStore) Write() { - for _, sub := range cs.substores { - sub.Write() - } -} - -// CacheMultiStore implements BasicMultiStore. -// This recursively wraps the CacheMultiStore in another cache store. -func (cs *cacheStore) CacheMultiStore() types.CacheMultiStore { - return &cacheStore{ - source: cs, - substores: map[string]types.CacheKVStore{}, - traceListenMixin: newTraceListenMixin(), - } -} diff --git a/store/v2alpha1/multi/doc.go b/store/v2alpha1/multi/doc.go deleted file mode 100644 index 87f5b88705c9..000000000000 --- a/store/v2alpha1/multi/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -// This package provides concrete implementations of the store/v2alpha1 "MultiStore" types, including -// CommitMultiStore, CacheMultiStore, and BasicMultiStore (as read-only stores at past versions). -// -// Substores are declared as part of a schema within StoreOptions. -// The schema cannot be changed once a CommitMultiStore is initialized, and changes to the schema must be done -// by migrating via StoreOptions.Upgrades. If a past version is accessed, it will be loaded with the past schema. -// Stores may be declared as StoreTypePersistent, StoreTypeMemory (not persisted after close), or -// StoreTypeTransient (not persisted across commits). Non-persistent substores cannot be migrated or accessed -// in past versions. -// -// A declared persistent substore is initially empty and stores nothing in the backing DB until a value is set. -// A non-empty store is stored within a prefixed subdomain of the backing DB (using db/prefix). -// If the MultiStore is configured to use a separate DBConnection for StateCommitmentDB, it will store the -// state commitment (SC) store (as an SMT) in subdomains there, and the "flat" state is stored in the main DB. -// Each substore's SC is allocated as an independent SMT, and query proofs contain two components: a proof -// of a key's (non)existence within the substore SMT, and a proof of the substore's existence within the -// MultiStore (using the Merkle map proof spec (TendermintSpec)). - -package multi diff --git a/store/v2alpha1/multi/migration.go b/store/v2alpha1/multi/migration.go deleted file mode 100644 index 7481b421ac3b..000000000000 --- a/store/v2alpha1/multi/migration.go +++ /dev/null @@ -1,68 +0,0 @@ -package multi - -import ( - dbm "github.com/cosmos/cosmos-sdk/db" - "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/store/mem" - v1Store "github.com/cosmos/cosmos-sdk/store/rootmulti" - "github.com/cosmos/cosmos-sdk/store/transient" - "github.com/cosmos/cosmos-sdk/store/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// MigrateFromV1 will migrate the state from iavl to smt -func MigrateFromV1(rootMultiStore *v1Store.Store, store2db dbm.DBConnection, storeConfig StoreConfig) (*Store, error) { - type namedStore struct { - *iavl.Store - name string - } - var stores []namedStore - for _, storeKey := range rootMultiStore.StoreKeysByName() { - keyName := storeKey.Name() - switch store := rootMultiStore.GetStoreByName(keyName).(type) { - case *iavl.Store: - err := storeConfig.RegisterSubstore(keyName, types.StoreTypePersistent) - if err != nil { - return nil, err - } - stores = append(stores, namedStore{name: keyName, Store: store}) - case *transient.Store, *mem.Store: - continue - default: - return nil, sdkerrors.Wrapf(sdkerrors.ErrLogic, "don't know how to migrate store %q of type %T", keyName, store) - } - } - - // creating the new store of smt tree - rootStore, err := NewStore(store2db, storeConfig) - if err != nil { - return nil, err - } - - // if version is 0 there is no state data to commit - if rootMultiStore.LastCommitID().Version == 0 { - return rootStore, nil - } - - // iterate through the rootmulti stores and save the key/values into smt tree - for _, store := range stores { - subStore, err := rootStore.getSubstore(store.name) - if err != nil { - return nil, err - } - // iterate all iavl tree node key/values - iterator := store.Iterator(nil, nil) - for ; iterator.Valid(); iterator.Next() { - // set the iavl key,values into smt node - subStore.Set(iterator.Key(), iterator.Value()) - } - } - - // commit the all key/values from iavl to smt tree (SMT Store) - _, err = rootStore.commit(uint64(rootMultiStore.LastCommitID().Version)) - if err != nil { - return nil, err - } - - return rootStore, nil -} diff --git a/store/v2alpha1/multi/migration_test.go b/store/v2alpha1/multi/migration_test.go deleted file mode 100644 index bf7b0f921cd0..000000000000 --- a/store/v2alpha1/multi/migration_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package multi - -import ( - "encoding/binary" - "fmt" - "math/rand" - "testing" - - "github.com/cosmos/cosmos-sdk/db/memdb" - "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/store/rootmulti" - "github.com/cosmos/cosmos-sdk/store/types" - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/libs/log" - dbm "github.com/tendermint/tm-db" -) - -func TestMigrationV2(t *testing.T) { - r := rand.New(rand.NewSource(49872768940)) - - // setup a rootmulti store - db := dbm.NewMemDB() - v1Store := rootmulti.NewStore(db, log.NewNopLogger()) - - // mount the kvStores - var keys []*types.KVStoreKey - for i := uint8(0); i < 10; i++ { - key := types.NewKVStoreKey(fmt.Sprintf("store%v", i)) - v1Store.MountStoreWithDB(key, types.StoreTypeIAVL, nil) - keys = append(keys, key) - } - - err := v1Store.LoadLatestVersion() - require.Nil(t, err) - - // setup a random test data - for _, key := range keys { - store := v1Store.GetStore(key).(*iavl.Store) - store.Set([]byte("temp_data"), []byte("one")) - - for i := 0; i < len(keys); i++ { - k := make([]byte, 8) - v := make([]byte, 1024) - binary.BigEndian.PutUint64(k, uint64(i)) - _, err := r.Read(v) - if err != nil { - panic(err) - } - store.Set(k, v) - } - } - - testCases := []struct { - testName string - emptyStore bool - }{ - { - "Migration With Empty Store", - true, - }, - { - "Migration From Root Multi Store (IAVL) to SMT ", - false, - }, - } - - for _, testCase := range testCases { - if !testCase.emptyStore { - v1Store.Commit() - } - - // setup a new root store of smt - db2 := memdb.NewDB() - storeConfig := DefaultStoreConfig() - // migrating the iavl store (v1) to smt store (v2) - v2Store, err := MigrateFromV1(v1Store, db2, storeConfig) - require.NoError(t, err) - - for _, key := range keys { - v2StoreKVStore := v2Store.GetKVStore(key) - if testCase.emptyStore { - // check the empty store - require.Nil(t, v2StoreKVStore.Get([]byte("temp_data"))) - } else { - require.Equal(t, v2StoreKVStore.Get([]byte("temp_data")), []byte("one")) - } - require.Equal(t, v2Store.LastCommitID().Version, v1Store.LastCommitID().Version) - } - err = v2Store.Close() - require.NoError(t, err) - } -} - -// TestMigrateV2ForEmptyStore checking empty store migration -func TestMigrateV2ForEmptyStore(t *testing.T) { - // setup a rootmulti store - db := dbm.NewMemDB() - v1Store := rootmulti.NewStore(db, log.NewNopLogger()) - err := v1Store.LoadLatestVersion() - require.Nil(t, err) - db2 := memdb.NewDB() - storeConfig := DefaultStoreConfig() - // migrating the iavl store (v1) to smt store (v2) - v2Store, err := MigrateFromV1(v1Store, db2, storeConfig) - require.NoError(t, err) - require.Equal(t, v2Store.LastCommitID(), v1Store.LastCommitID()) -} diff --git a/store/v2alpha1/multi/proof.go b/store/v2alpha1/multi/proof.go deleted file mode 100644 index 1e8b538c5373..000000000000 --- a/store/v2alpha1/multi/proof.go +++ /dev/null @@ -1,52 +0,0 @@ -package multi - -import ( - "crypto/sha256" - - "github.com/tendermint/tendermint/crypto/merkle" - tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" - - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/smt" -) - -// DefaultProofRuntime returns a ProofRuntime supporting SMT and simple merkle proofs. -func DefaultProofRuntime() (prt *merkle.ProofRuntime) { - prt = merkle.NewProofRuntime() - prt.RegisterOpDecoder(types.ProofOpSMTCommitment, types.CommitmentOpDecoder) - prt.RegisterOpDecoder(types.ProofOpSimpleMerkleCommitment, types.CommitmentOpDecoder) - return prt -} - -// Prove commitment of key within an smt store and return ProofOps -func proveKey(s *smt.Store, key []byte) (*tmcrypto.ProofOps, error) { - var ret tmcrypto.ProofOps - keyProof, err := s.GetProofICS23(key) - if err != nil { - return nil, err - } - hkey := sha256.Sum256(key) - ret.Ops = append(ret.Ops, types.NewSmtCommitmentOp(hkey[:], keyProof).ProofOp()) - return &ret, nil -} - -// GetProof returns ProofOps containing: a proof for the given key within this substore; -// and a proof of the substore's existence within the MultiStore. -func (s *viewSubstore) GetProof(key []byte) (*tmcrypto.ProofOps, error) { - ret, err := proveKey(s.stateCommitmentStore, key) - if err != nil { - return nil, err - } - - // Prove commitment of substore within root store - storeHashes, err := s.root.getMerkleRoots() - if err != nil { - return nil, err - } - storeProof, err := types.ProofOpFromMap(storeHashes, s.name) - if err != nil { - return nil, err - } - ret.Ops = append(ret.Ops, storeProof) - return ret, nil -} diff --git a/store/v2alpha1/multi/proof_test.go b/store/v2alpha1/multi/proof_test.go deleted file mode 100644 index 86e9fbfd2ed0..000000000000 --- a/store/v2alpha1/multi/proof_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package multi - -import ( - "crypto/sha256" - "testing" - - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/db/memdb" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/smt" -) - -// We hash keys produce SMT paths, so reflect that here -func keyPath(prefix, key string) string { - hashed := sha256.Sum256([]byte(key)) - return prefix + string(hashed[:]) -} - -func TestVerifySMTStoreProof(t *testing.T) { - // Create main tree for testing. - txn := memdb.NewDB().ReadWriter() - store := smt.NewStore(txn) - store.Set([]byte("MYKEY"), []byte("MYVALUE")) - root := store.Root() - - res, err := proveKey(store, []byte("MYKEY")) - require.NoError(t, err) - - // Verify good proof. - prt := DefaultProofRuntime() - err = prt.VerifyValue(res, root, keyPath("/", "MYKEY"), []byte("MYVALUE")) - require.NoError(t, err) - - // Fail to verify bad proofs. - err = prt.VerifyValue(res, root, keyPath("/", "MYKEY_NOT"), []byte("MYVALUE")) - require.Error(t, err) - - err = prt.VerifyValue(res, root, keyPath("/", "MYKEY/MYKEY"), []byte("MYVALUE")) - require.Error(t, err) - - err = prt.VerifyValue(res, root, keyPath("", "MYKEY"), []byte("MYVALUE")) - require.Error(t, err) - - err = prt.VerifyValue(res, root, keyPath("/", "MYKEY"), []byte("MYVALUE_NOT")) - require.Error(t, err) - - err = prt.VerifyValue(res, root, keyPath("/", "MYKEY"), []byte(nil)) - require.Error(t, err) -} - -func TestVerifyMultiStoreQueryProof(t *testing.T) { - db := memdb.NewDB() - store, err := NewStore(db, simpleStoreConfig(t)) - require.NoError(t, err) - - substore := store.GetKVStore(skey_1) - substore.Set([]byte("MYKEY"), []byte("MYVALUE")) - cid := store.Commit() - - res := store.Query(abci.RequestQuery{ - Path: "/store1/key", // required path to get key/value+proof - Data: []byte("MYKEY"), - Prove: true, - }) - require.NotNil(t, res.ProofOps) - - // Verify good proofs. - prt := DefaultProofRuntime() - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("/store1/", "MYKEY"), []byte("MYVALUE")) - require.NoError(t, err) - - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("/store1/", "MYKEY"), []byte("MYVALUE")) - require.NoError(t, err) - - // Fail to verify bad proofs. - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("/store1/", "MYKEY_NOT"), []byte("MYVALUE")) - require.Error(t, err) - - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("/store1/MYKEY/", "MYKEY"), []byte("MYVALUE")) - require.Error(t, err) - - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("store1/", "MYKEY"), []byte("MYVALUE")) - require.Error(t, err) - - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("/", "MYKEY"), []byte("MYVALUE")) - require.Error(t, err) - - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("/store1/", "MYKEY"), []byte("MYVALUE_NOT")) - require.Error(t, err) - - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("/store1/", "MYKEY"), []byte(nil)) - require.Error(t, err) -} - -func TestVerifyMultiStoreQueryProofAbsence(t *testing.T) { - db := memdb.NewDB() - store, err := NewStore(db, simpleStoreConfig(t)) - require.NoError(t, err) - - substore := store.GetKVStore(skey_1) - substore.Set([]byte("MYKEY"), []byte("MYVALUE")) - cid := store.Commit() - - res := store.Query(abci.RequestQuery{ - Path: "/store1/key", // required path to get key/value+proof - Data: []byte("MYABSENTKEY"), - Prove: true, - }) - require.NotNil(t, res.ProofOps) - - // Verify good proof. - prt := DefaultProofRuntime() - err = prt.VerifyAbsence(res.ProofOps, cid.Hash, keyPath("/store1/", "MYABSENTKEY")) - require.NoError(t, err) - - // Fail to verify bad proofs. - prt = DefaultProofRuntime() - err = prt.VerifyAbsence(res.ProofOps, cid.Hash, keyPath("/", "MYABSENTKEY")) - require.Error(t, err) - - prt = DefaultProofRuntime() - err = prt.VerifyValue(res.ProofOps, cid.Hash, keyPath("/store1/", "MYABSENTKEY"), []byte("")) - require.Error(t, err) -} diff --git a/store/v2alpha1/multi/snapshot.go b/store/v2alpha1/multi/snapshot.go deleted file mode 100644 index 434c5e1c6fc5..000000000000 --- a/store/v2alpha1/multi/snapshot.go +++ /dev/null @@ -1,172 +0,0 @@ -package multi - -import ( - "bytes" - "fmt" - "io" - "sort" - - protoio "github.com/gogo/protobuf/io" - - "github.com/cosmos/cosmos-sdk/snapshots" - snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// Snapshot implements snapshottypes.Snapshotter. -func (rs *Store) Snapshot(height uint64, protoWriter protoio.Writer) error { - if height == 0 { - return snapshottypes.ErrInvalidSnapshotVersion - } - if height > uint64(rs.LastCommitID().Version) { - return sdkerrors.Wrapf(sdkerrors.ErrLogic, "cannot snapshot future height %v", height) - } - - // get the saved snapshot at height - vs, err := rs.getView(int64(height)) - if err != nil { - return sdkerrors.Wrap(err, fmt.Sprintf("error while get the version at height %d", height)) - } - - // sending the snapshot store schema - var storeByteKeys [][]byte - for sKey := range vs.schema { - if vs.schema[sKey] == storetypes.StoreTypePersistent { - storeByteKeys = append(storeByteKeys, []byte(sKey)) - } - } - - sort.Slice(storeByteKeys, func(i, j int) bool { - return bytes.Compare(storeByteKeys[i], storeByteKeys[j]) == -1 - }) - - err = protoWriter.WriteMsg(&snapshottypes.SnapshotItem{ - Item: &snapshottypes.SnapshotItem_Schema{ - Schema: &snapshottypes.SnapshotSchema{ - Keys: storeByteKeys, - }, - }, - }) - if err != nil { - return err - } - - for _, sKey := range storeByteKeys { - subStore, err := vs.getSubstore(string(sKey)) - if err != nil { - return err - } - - err = protoWriter.WriteMsg(&snapshottypes.SnapshotItem{ - Item: &snapshottypes.SnapshotItem_Store{ - Store: &snapshottypes.SnapshotStoreItem{ - Name: string(sKey), - }, - }, - }) - if err != nil { - return err - } - - iter := subStore.Iterator(nil, nil) - for ; iter.Valid(); iter.Next() { - err = protoWriter.WriteMsg(&snapshottypes.SnapshotItem{ - Item: &snapshottypes.SnapshotItem_KV{ - KV: &snapshottypes.SnapshotKVItem{ - Key: iter.Key(), - Value: iter.Value(), - }, - }, - }) - if err != nil { - return err - } - } - - err = iter.Close() - if err != nil { - return err - } - } - - return nil -} - -// Restore implements snapshottypes.Snapshotter. -func (rs *Store) Restore( - height uint64, format uint32, protoReader protoio.Reader, -) (snapshottypes.SnapshotItem, error) { - if err := snapshots.ValidRestoreHeight(format, height); err != nil { - return snapshottypes.SnapshotItem{}, err - } - - if rs.LastCommitID().Version != 0 { - return snapshottypes.SnapshotItem{}, sdkerrors.Wrapf(sdkerrors.ErrLogic, "cannot restore snapshot for non empty store at height %v", height) - } - - var subStore *substore - storeSchemaReceived := false - - var snapshotItem snapshottypes.SnapshotItem - -loop: - for { - snapshotItem = snapshottypes.SnapshotItem{} - err := protoReader.ReadMsg(&snapshotItem) - if err == io.EOF { - break - } else if err != nil { - return snapshottypes.SnapshotItem{}, sdkerrors.Wrap(err, "invalid protobuf message") - } - - switch item := snapshotItem.Item.(type) { - case *snapshottypes.SnapshotItem_Schema: - receivedStoreSchema := make(StoreSchema, len(item.Schema.GetKeys())) - storeSchemaReceived = true - for _, sKey := range item.Schema.GetKeys() { - receivedStoreSchema[string(sKey)] = types.StoreTypePersistent - } - - if !rs.schema.equal(receivedStoreSchema) { - return snapshottypes.SnapshotItem{}, sdkerrors.Wrap(sdkerrors.ErrLogic, "received schema does not match app schema") - } - - case *snapshottypes.SnapshotItem_Store: - storeName := item.Store.GetName() - // checking the store schema is received or not - if !storeSchemaReceived { - return snapshottypes.SnapshotItem{}, sdkerrors.Wrapf(sdkerrors.ErrLogic, "received store name before store schema %s", storeName) - } - // checking the store schema exists or not - if _, has := rs.schema[storeName]; !has { - return snapshottypes.SnapshotItem{}, sdkerrors.Wrapf(sdkerrors.ErrLogic, "store is missing from schema %s", storeName) - } - - // get the substore - subStore, err = rs.getSubstore(storeName) - if err != nil { - return snapshottypes.SnapshotItem{}, sdkerrors.Wrap(err, fmt.Sprintf("error while getting the substore for key %s", storeName)) - } - - case *snapshottypes.SnapshotItem_KV: - if subStore == nil { - return snapshottypes.SnapshotItem{}, sdkerrors.Wrap(sdkerrors.ErrLogic, "received KV Item before store item") - } - // update the key/value SMT.Store - subStore.Set(item.KV.Key, item.KV.Value) - - default: - break loop - } - } - - // commit the all key/values to store - _, err := rs.commit(height) - if err != nil { - return snapshotItem, sdkerrors.Wrap(err, fmt.Sprintf("error during commit the store at height %d", height)) - } - - return snapshotItem, nil -} diff --git a/store/v2alpha1/multi/snapshot_test.go b/store/v2alpha1/multi/snapshot_test.go deleted file mode 100644 index 77637910e768..000000000000 --- a/store/v2alpha1/multi/snapshot_test.go +++ /dev/null @@ -1,317 +0,0 @@ -package multi - -import ( - "crypto/sha256" - "encoding/binary" - "encoding/hex" - "errors" - "fmt" - "io" - "math/rand" - "sort" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - dbm "github.com/cosmos/cosmos-sdk/db" - "github.com/cosmos/cosmos-sdk/db/memdb" - pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" - "github.com/cosmos/cosmos-sdk/snapshots" - snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" - "github.com/cosmos/cosmos-sdk/store/types" -) - -func multiStoreConfig(t *testing.T, stores int) StoreConfig { - opts := DefaultStoreConfig() - opts.Pruning = pruningtypes.NewPruningOptions(pruningtypes.PruningNothing) - - for i := 0; i < stores; i++ { - sKey := types.NewKVStoreKey(fmt.Sprintf("store%d", i)) - require.NoError(t, opts.RegisterSubstore(sKey.Name(), types.StoreTypePersistent)) - } - - return opts -} - -func newMultiStoreWithGeneratedData(t *testing.T, db dbm.DBConnection, stores int, storeKeys uint64) *Store { - cfg := multiStoreConfig(t, stores) - store, err := NewStore(db, cfg) - require.NoError(t, err) - r := rand.New(rand.NewSource(49872768940)) // Fixed seed for deterministic tests - - var sKeys []string - for sKey := range store.schema { - sKeys = append(sKeys, sKey) - } - - sort.Slice(sKeys, func(i, j int) bool { - return strings.Compare(sKeys[i], sKeys[j]) == -1 - }) - - for _, sKey := range sKeys { - sStore, err := store.getSubstore(sKey) - require.NoError(t, err) - for i := uint64(0); i < storeKeys; i++ { - k := make([]byte, 8) - v := make([]byte, 1024) - binary.BigEndian.PutUint64(k, i) - _, err := r.Read(v) - if err != nil { - panic(err) - } - sStore.Set(k, v) - } - } - store.Commit() - return store -} - -func newMultiStoreWithBasicData(t *testing.T, db dbm.DBConnection, stores int) *Store { - cfg := multiStoreConfig(t, stores) - store, err := NewStore(db, cfg) - require.NoError(t, err) - - for sKey := range store.schema { - sStore, err := store.getSubstore(sKey) - require.NoError(t, err) - for k, v := range alohaData { - sStore.Set([]byte(k), []byte(v)) - } - } - - store.Commit() - return store -} - -func newMultiStore(t *testing.T, db dbm.DBConnection, stores int) *Store { - cfg := multiStoreConfig(t, stores) - store, err := NewStore(db, cfg) - require.NoError(t, err) - return store -} - -func TestMultistoreSnapshot_Errors(t *testing.T) { - store := newMultiStoreWithBasicData(t, memdb.NewDB(), 4) - testcases := map[string]struct { - height uint64 - expectType error - }{ - "0 height": {0, snapshottypes.ErrInvalidSnapshotVersion}, - "1 height": {1, nil}, - } - for name, tc := range testcases { - tc := tc - t.Run(name, func(t *testing.T) { - chunks := make(chan io.ReadCloser) - streamWriter := snapshots.NewStreamWriter(chunks) - err := store.Snapshot(tc.height, streamWriter) - if tc.expectType != nil { - assert.True(t, errors.Is(err, tc.expectType)) - } - }) - } -} - -func TestMultistoreRestore_Errors(t *testing.T) { - store := newMultiStoreWithBasicData(t, memdb.NewDB(), 4) - testcases := map[string]struct { - height uint64 - format uint32 - expectErrorType error - }{ - "0 height": {0, snapshottypes.CurrentFormat, nil}, - "0 format": {1, 0, snapshottypes.ErrUnknownFormat}, - "unknown format": {1, 9, snapshottypes.ErrUnknownFormat}, - } - for name, tc := range testcases { - tc := tc - t.Run(name, func(t *testing.T) { - _, err := store.Restore(tc.height, tc.format, nil) - require.Error(t, err) - if tc.expectErrorType != nil { - assert.True(t, errors.Is(err, tc.expectErrorType)) - } - }) - } -} - -func TestMultistoreSnapshot_Checksum(t *testing.T) { - store := newMultiStoreWithGeneratedData(t, memdb.NewDB(), 5, 10000) - version := uint64(store.LastCommitID().Version) - - testcases := []struct { - format uint32 - chunkHashes []string - }{ - {1, []string{ - "b0635a30d94d56b6cd1073fbfa109fa90b194d0ff2397659b00934c844a1f6fb", - "8c32e05f312cf2dee6b7d2bdb41e1a2bb2372697f25504e676af1718245d8b63", - "05dfef0e32c34ef3900300f9de51f228d7fb204fa8f4e4d0d1529f083d122029", - "77d30aeeb427b0bdcedf3639adde1e822c15233d652782e171125280875aa492", - "c00c3801da889ea4370f0e647ffe1e291bd47f500e2a7269611eb4cc198b993f", - "6d565eb28776631f3e3e764decd53436c3be073a8a01fa5434afd539f9ae6eda", - }}, - } - for _, tc := range testcases { - tc := tc - t.Run(fmt.Sprintf("Format %v", tc.format), func(t *testing.T) { - chunks := make(chan io.ReadCloser, 100) - hashes := []string{} - go func() { - streamWriter := snapshots.NewStreamWriter(chunks) - defer streamWriter.Close() - require.NotNil(t, streamWriter) - err := store.Snapshot(version, streamWriter) - require.NoError(t, err) - }() - hasher := sha256.New() - for chunk := range chunks { - hasher.Reset() - _, err := io.Copy(hasher, chunk) - require.NoError(t, err) - hashes = append(hashes, hex.EncodeToString(hasher.Sum(nil))) - } - assert.Equal(t, tc.chunkHashes, hashes, "Snapshot output for format %v has changed", tc.format) - }) - } -} - -func TestMultistoreSnapshotRestore(t *testing.T) { - source := newMultiStoreWithGeneratedData(t, memdb.NewDB(), 3, 4) - target := newMultiStore(t, memdb.NewDB(), 3) - require.Equal(t, source.LastCommitID().Version, int64(1)) - version := uint64(source.LastCommitID().Version) - // check for target store restore - require.Equal(t, target.LastCommitID().Version, int64(0)) - - dummyExtensionItem := snapshottypes.SnapshotItem{ - Item: &snapshottypes.SnapshotItem_Extension{ - Extension: &snapshottypes.SnapshotExtensionMeta{ - Name: "test", - Format: 1, - }, - }, - } - - chunks := make(chan io.ReadCloser, 100) - go func() { - streamWriter := snapshots.NewStreamWriter(chunks) - require.NotNil(t, streamWriter) - defer streamWriter.Close() - err := source.Snapshot(version, streamWriter) - require.NoError(t, err) - // write an extension metadata - err = streamWriter.WriteMsg(&dummyExtensionItem) - require.NoError(t, err) - }() - - streamReader, err := snapshots.NewStreamReader(chunks) - require.NoError(t, err) - nextItem, err := target.Restore(version, snapshottypes.CurrentFormat, streamReader) - require.NoError(t, err) - require.Equal(t, *dummyExtensionItem.GetExtension(), *nextItem.GetExtension()) - - assert.Equal(t, source.LastCommitID(), target.LastCommitID()) - - for sKey := range source.schema { - sourceSubStore, err := source.getSubstore(sKey) - require.NoError(t, err) - targetSubStore, err := target.getSubstore(sKey) - require.NoError(t, err) - require.Equal(t, sourceSubStore, targetSubStore) - } - - // checking snapshot restoring for store with existed schema and without existing versions - target3 := newMultiStore(t, memdb.NewDB(), 4) - chunks3 := make(chan io.ReadCloser, 100) - go func() { - streamWriter3 := snapshots.NewStreamWriter(chunks3) - require.NotNil(t, streamWriter3) - defer streamWriter3.Close() - err := source.Snapshot(version, streamWriter3) - require.NoError(t, err) - }() - streamReader3, err := snapshots.NewStreamReader(chunks3) - require.NoError(t, err) - _, err = target3.Restore(version, snapshottypes.CurrentFormat, streamReader3) - require.Error(t, err) -} - -func BenchmarkMultistoreSnapshot100K(b *testing.B) { - benchmarkMultistoreSnapshot(b, 10, 10000) -} - -func BenchmarkMultistoreSnapshot1M(b *testing.B) { - benchmarkMultistoreSnapshot(b, 10, 100000) -} - -func BenchmarkMultistoreSnapshotRestore100K(b *testing.B) { - benchmarkMultistoreSnapshotRestore(b, 10, 10000) -} - -func BenchmarkMultistoreSnapshotRestore1M(b *testing.B) { - benchmarkMultistoreSnapshotRestore(b, 10, 100000) -} - -func benchmarkMultistoreSnapshot(b *testing.B, stores int, storeKeys uint64) { - b.Skip("Noisy with slow setup time, please see https://github.com/cosmos/cosmos-sdk/issues/8855.") - - b.ReportAllocs() - b.StopTimer() - source := newMultiStoreWithGeneratedData(nil, memdb.NewDB(), stores, storeKeys) - - version := source.LastCommitID().Version - require.EqualValues(b, 1, version) - b.StartTimer() - - for i := 0; i < b.N; i++ { - target := newMultiStore(nil, memdb.NewDB(), stores) - require.EqualValues(b, 0, target.LastCommitID().Version) - - chunks := make(chan io.ReadCloser) - go func() { - streamWriter := snapshots.NewStreamWriter(chunks) - require.NotNil(b, streamWriter) - err := source.Snapshot(uint64(version), streamWriter) - require.NoError(b, err) - }() - for reader := range chunks { - _, err := io.Copy(io.Discard, reader) - require.NoError(b, err) - err = reader.Close() - require.NoError(b, err) - } - } -} - -func benchmarkMultistoreSnapshotRestore(b *testing.B, stores int, storeKeys uint64) { - b.Skip("Noisy with slow setup time, please see https://github.com/cosmos/cosmos-sdk/issues/8855.") - - b.ReportAllocs() - b.StopTimer() - source := newMultiStoreWithGeneratedData(nil, memdb.NewDB(), stores, storeKeys) - version := uint64(source.LastCommitID().Version) - require.EqualValues(b, 1, version) - b.StartTimer() - - for i := 0; i < b.N; i++ { - target := newMultiStore(nil, memdb.NewDB(), stores) - require.EqualValues(b, 0, target.LastCommitID().Version) - - chunks := make(chan io.ReadCloser) - go func() { - writer := snapshots.NewStreamWriter(chunks) - require.NotNil(b, writer) - err := source.Snapshot(version, writer) - require.NoError(b, err) - }() - - reader, err := snapshots.NewStreamReader(chunks) - require.NoError(b, err) - _, err = target.Restore(version, snapshottypes.CurrentFormat, reader) - require.NoError(b, err) - require.Equal(b, source.LastCommitID(), target.LastCommitID()) - } -} diff --git a/store/v2alpha1/multi/store.go b/store/v2alpha1/multi/store.go deleted file mode 100644 index 4916adea6c81..000000000000 --- a/store/v2alpha1/multi/store.go +++ /dev/null @@ -1,915 +0,0 @@ -package multi - -import ( - "errors" - "fmt" - "io" - "math" - "strings" - "sync" - - abci "github.com/tendermint/tendermint/abci/types" - - dbm "github.com/cosmos/cosmos-sdk/db" - prefixdb "github.com/cosmos/cosmos-sdk/db/prefix" - util "github.com/cosmos/cosmos-sdk/internal" - pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" - sdkmaps "github.com/cosmos/cosmos-sdk/store/internal/maps" - "github.com/cosmos/cosmos-sdk/store/listenkv" - "github.com/cosmos/cosmos-sdk/store/prefix" - "github.com/cosmos/cosmos-sdk/store/tracekv" - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/mem" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/smt" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/transient" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/kv" -) - -var ( - _ types.Queryable = (*Store)(nil) - _ types.CommitMultiStore = (*Store)(nil) - _ types.CacheMultiStore = (*cacheStore)(nil) - _ types.BasicMultiStore = (*viewStore)(nil) - _ types.KVStore = (*substore)(nil) -) - -var ( - // Root prefixes - merkleRootKey = []byte{0} // Key for root hash of namespace tree - schemaPrefix = []byte{1} // Prefix for store keys (namespaces) - contentPrefix = []byte{2} // Prefix for store contents - - // Per-substore prefixes - substoreMerkleRootKey = []byte{0} // Key for root hashes of Merkle trees - dataPrefix = []byte{1} // Prefix for state mappings - indexPrefix = []byte{2} // Prefix for Store reverse index - smtPrefix = []byte{3} // Prefix for SMT data - - ErrVersionDoesNotExist = errors.New("version does not exist") - ErrMaximumHeight = errors.New("maximum block height reached") -) - -func ErrStoreNotFound(skey string) error { - return fmt.Errorf("store does not exist for key: %s", skey) -} - -// StoreConfig is used to define a schema and other options and pass them to the MultiStore constructor. -type StoreConfig struct { - // Version pruning options for backing DBs. - Pruning pruningtypes.PruningOptions - // The minimum allowed version number. - InitialVersion uint64 - // The backing DB to use for the state commitment Merkle tree data. - // If nil, Merkle data is stored in the state storage DB under a separate prefix. - StateCommitmentDB dbm.DBConnection - - prefixRegistry - PersistentCache types.MultiStorePersistentCache - Upgrades []types.StoreUpgrades - - *traceListenMixin -} - -// StoreSchema defineds a mapping of substore keys to store types -type StoreSchema map[string]types.StoreType - -// Store is the main persistent store type implementing CommitMultiStore. -// Substores consist of an SMT-based state commitment store and state storage. -// Substores must be reserved in the StoreConfig or defined as part of a StoreUpgrade in order to be valid. -// Note: -// The state commitment data and proof are structured in the same basic pattern as the MultiStore, but use an SMT rather than IAVL tree: -// * The state commitment store of each substore consists of a independent SMT. -// * The state commitment of the root store consists of a Merkle map of all registered persistent substore names to the root hash of their corresponding SMTs -type Store struct { - stateDB dbm.DBConnection - stateTxn dbm.DBReadWriter - StateCommitmentDB dbm.DBConnection - stateCommitmentTxn dbm.DBReadWriter - - schema StoreSchema - mem *mem.Store - tran *transient.Store - mtx sync.RWMutex - - // Copied from StoreConfig - Pruning pruningtypes.PruningOptions - InitialVersion uint64 // if - *traceListenMixin - - PersistentCache types.MultiStorePersistentCache - substoreCache map[string]*substore -} - -type substore struct { - root *Store - name string - dataBucket dbm.DBReadWriter - indexBucket dbm.DBReadWriter - stateCommitmentStore *smt.Store -} - -// Branched state -type cacheStore struct { - source types.BasicMultiStore - substores map[string]types.CacheKVStore - *traceListenMixin -} - -// Read-only store for querying past versions -type viewStore struct { - stateView dbm.DBReader - stateCommitmentView dbm.DBReader - substoreCache map[string]*viewSubstore - schema StoreSchema -} - -type viewSubstore struct { - root *viewStore - name string - dataBucket dbm.DBReader - indexBucket dbm.DBReader - stateCommitmentStore *smt.Store -} - -// Builder type used to create a valid schema with no prefix conflicts -type prefixRegistry struct { - StoreSchema - reserved []string -} - -// Mixin type that to compose trace & listen state into each root store variant type -type traceListenMixin struct { - listeners map[string][]types.WriteListener - TraceWriter io.Writer - TraceContext types.TraceContext -} - -func newTraceListenMixin() *traceListenMixin { - return &traceListenMixin{listeners: map[string][]types.WriteListener{}} -} - -// DefaultStoreConfig returns a MultiStore config with an empty schema, a single backing DB, -// pruning with PruneDefault, no listeners and no tracer. -func DefaultStoreConfig() StoreConfig { - return StoreConfig{ - Pruning: pruningtypes.NewPruningOptions(pruningtypes.PruningDefault), - prefixRegistry: prefixRegistry{ - StoreSchema: StoreSchema{}, - }, - traceListenMixin: newTraceListenMixin(), - } -} - -// Returns true for valid store types for a MultiStore schema -func validSubStoreType(sst types.StoreType) bool { - switch sst { - case types.StoreTypePersistent: - return true - case types.StoreTypeMemory: - return true - case types.StoreTypeTransient: - return true - default: - return false - } -} - -// Returns true iff both schema maps match exactly (including mem/tran stores) -func (ss StoreSchema) equal(that StoreSchema) bool { - if len(ss) != len(that) { - return false - } - for key, val := range that { - myval, has := ss[key] - if !has { - return false - } - if val != myval { - return false - } - } - return true -} - -// Parses a schema from the DB -func readSavedSchema(bucket dbm.DBReader) (*prefixRegistry, error) { - ret := prefixRegistry{StoreSchema: StoreSchema{}} - it, err := bucket.Iterator(nil, nil) - if err != nil { - return nil, err - } - for it.Next() { - value := it.Value() - if len(value) != 1 || !validSubStoreType(types.StoreType(value[0])) { - return nil, fmt.Errorf("invalid mapping for store key: %v => %v", it.Key(), value) - } - ret.StoreSchema[string(it.Key())] = types.StoreType(value[0]) - ret.reserved = append(ret.reserved, string(it.Key())) // assume iter yields keys sorted - } - if err = it.Close(); err != nil { - return nil, err - } - return &ret, nil -} - -// NewStore constructs a MultiStore directly from a database. -// Creates a new store if no data exists; otherwise loads existing data. -func NewStore(db dbm.DBConnection, opts StoreConfig) (ret *Store, err error) { - versions, err := db.Versions() - if err != nil { - return - } - // If the DB is not empty, attempt to load existing data - if saved := versions.Count(); saved != 0 { - if opts.InitialVersion != 0 && versions.Last() < opts.InitialVersion { - return nil, fmt.Errorf("latest saved version is less than initial version: %v < %v", - versions.Last(), opts.InitialVersion) - } - } - // To abide by atomicity constraints, revert the DB to the last saved version, in case it contains - // committed data in the "working" version. - // This should only happen if Store.Commit previously failed. - err = db.Revert() - if err != nil { - return - } - stateTxn := db.ReadWriter() - defer func() { - if err != nil { - err = util.CombineErrors(err, stateTxn.Discard(), "stateTxn.Discard also failed") - } - }() - stateCommitmentTxn := stateTxn - if opts.StateCommitmentDB != nil { - var scVersions dbm.VersionSet - scVersions, err = opts.StateCommitmentDB.Versions() - if err != nil { - return - } - // Version sets of each DB must match - if !versions.Equal(scVersions) { - err = fmt.Errorf("different version history between Storage and StateCommitment DB ") - return - } - err = opts.StateCommitmentDB.Revert() - if err != nil { - return - } - stateCommitmentTxn = opts.StateCommitmentDB.ReadWriter() - } - - ret = &Store{ - stateDB: db, - stateTxn: stateTxn, - StateCommitmentDB: opts.StateCommitmentDB, - stateCommitmentTxn: stateCommitmentTxn, - mem: mem.NewStore(), - tran: transient.NewStore(), - - substoreCache: map[string]*substore{}, - - traceListenMixin: opts.traceListenMixin, - PersistentCache: opts.PersistentCache, - - Pruning: opts.Pruning, - InitialVersion: opts.InitialVersion, - } - - // Now load the substore schema - schemaView := prefixdb.NewPrefixReader(ret.stateDB.Reader(), schemaPrefix) - defer func() { - if err != nil { - err = util.CombineErrors(err, schemaView.Discard(), "schemaView.Discard also failed") - err = util.CombineErrors(err, ret.Close(), "base.Close also failed") - } - }() - reg, err := readSavedSchema(schemaView) - if err != nil { - return - } - // If the loaded schema is empty (for new store), just copy the config schema; - // Otherwise, verify it is identical to the config schema - if len(reg.StoreSchema) == 0 { - for k, v := range opts.StoreSchema { - reg.StoreSchema[k] = v - } - reg.reserved = make([]string, len(opts.reserved)) - copy(reg.reserved, opts.reserved) - } else if !reg.equal(opts.StoreSchema) { - - err = errors.New("loaded schema does not match configured schema") - return - - } - // Apply migrations, then clear old schema and write the new one - for _, upgrades := range opts.Upgrades { - err = reg.migrate(ret, upgrades) - if err != nil { - return - } - } - schemaWriter := prefixdb.NewPrefixWriter(ret.stateTxn, schemaPrefix) - it, err := schemaView.Iterator(nil, nil) - if err != nil { - return - } - for it.Next() { - err = schemaWriter.Delete(it.Key()) - if err != nil { - return - } - } - err = it.Close() - if err != nil { - return - } - err = schemaView.Discard() - if err != nil { - return - } - // NB. the migrated contents and schema are not committed until the next store.Commit - for skey, typ := range reg.StoreSchema { - err = schemaWriter.Set([]byte(skey), []byte{byte(typ)}) - if err != nil { - return - } - } - ret.schema = reg.StoreSchema - return ret, nil -} - -func (s *Store) Close() error { - err := s.stateTxn.Discard() - if s.StateCommitmentDB != nil { - err = util.CombineErrors(err, s.stateCommitmentTxn.Discard(), "stateCommitmentTxn.Discard also failed") - } - return err -} - -// Applies store upgrades to the DB contents. -func (pr *prefixRegistry) migrate(store *Store, upgrades types.StoreUpgrades) error { - // Get a view of current state to allow mutation while iterating - reader := store.stateDB.Reader() - scReader := reader - if store.StateCommitmentDB != nil { - scReader = store.StateCommitmentDB.Reader() - } - - for _, key := range upgrades.Deleted { - sst, ix, err := pr.storeInfo(key) - if err != nil { - return err - } - if sst != types.StoreTypePersistent { - return fmt.Errorf("prefix is for non-persistent substore: %v (%v)", key, sst) - } - pr.reserved = append(pr.reserved[:ix], pr.reserved[ix+1:]...) - delete(pr.StoreSchema, key) - - pfx := substorePrefix(key) - subReader := prefixdb.NewPrefixReader(reader, pfx) - it, err := subReader.Iterator(nil, nil) - if err != nil { - return err - } - for it.Next() { - store.stateTxn.Delete(it.Key()) - } - it.Close() - if store.StateCommitmentDB != nil { - subReader = prefixdb.NewPrefixReader(scReader, pfx) - it, err = subReader.Iterator(nil, nil) - if err != nil { - return err - } - for it.Next() { - store.stateCommitmentTxn.Delete(it.Key()) - } - it.Close() - } - } - for _, rename := range upgrades.Renamed { - sst, ix, err := pr.storeInfo(rename.OldKey) - if err != nil { - return err - } - if sst != types.StoreTypePersistent { - return fmt.Errorf("prefix is for non-persistent substore: %v (%v)", rename.OldKey, sst) - } - pr.reserved = append(pr.reserved[:ix], pr.reserved[ix+1:]...) - delete(pr.StoreSchema, rename.OldKey) - err = pr.RegisterSubstore(rename.NewKey, types.StoreTypePersistent) - if err != nil { - return err - } - - oldPrefix := substorePrefix(rename.OldKey) - newPrefix := substorePrefix(rename.NewKey) - subReader := prefixdb.NewPrefixReader(reader, oldPrefix) - subWriter := prefixdb.NewPrefixWriter(store.stateTxn, newPrefix) - it, err := subReader.Iterator(nil, nil) - if err != nil { - return err - } - for it.Next() { - subWriter.Set(it.Key(), it.Value()) - } - it.Close() - if store.StateCommitmentDB != nil { - subReader = prefixdb.NewPrefixReader(scReader, oldPrefix) - subWriter = prefixdb.NewPrefixWriter(store.stateCommitmentTxn, newPrefix) - it, err = subReader.Iterator(nil, nil) - if err != nil { - return err - } - for it.Next() { - subWriter.Set(it.Key(), it.Value()) - } - it.Close() - } - } - - for _, key := range upgrades.Added { - err := pr.RegisterSubstore(key, types.StoreTypePersistent) - if err != nil { - return err - } - } - return nil -} - -func substorePrefix(key string) []byte { - return append(contentPrefix, key...) -} - -// GetKVStore implements BasicMultiStore. -func (rs *Store) GetKVStore(skey types.StoreKey) types.KVStore { - key := skey.Name() - var parent types.KVStore - typ, has := rs.schema[key] - if !has { - panic(ErrStoreNotFound(key)) - } - switch typ { - case types.StoreTypeMemory: - parent = rs.mem - case types.StoreTypeTransient: - parent = rs.tran - case types.StoreTypePersistent: - default: - panic(fmt.Errorf("StoreType not supported: %v", typ)) // should never happen - } - var ret types.KVStore - if parent != nil { // store is non-persistent - ret = prefix.NewStore(parent, []byte(key)) - } else { // store is persistent - sub, err := rs.getSubstore(key) - if err != nil { - panic(err) - } - rs.substoreCache[key] = sub - ret = sub - } - // Wrap with trace/listen if needed. Note: we don't cache this, so users must get a new substore after - // modifying tracers/listeners. - return rs.wrapTraceListen(ret, skey) -} - -// Gets a persistent substore. This reads, but does not update the substore cache. -// Use it in cases where we need to access a store internally (e.g. read/write Merkle keys, queries) -func (rs *Store) getSubstore(key string) (*substore, error) { - if cached, has := rs.substoreCache[key]; has { - return cached, nil - } - pfx := substorePrefix(key) - stateRW := prefixdb.NewPrefixReadWriter(rs.stateTxn, pfx) - stateCommitmentRW := prefixdb.NewPrefixReadWriter(rs.stateCommitmentTxn, pfx) - var stateCommitmentStore *smt.Store - - rootHash, err := stateRW.Get(substoreMerkleRootKey) - if err != nil { - return nil, err - } - if rootHash != nil { - stateCommitmentStore = loadSMT(stateCommitmentRW, rootHash) - } else { - smtdb := prefixdb.NewPrefixReadWriter(stateCommitmentRW, smtPrefix) - stateCommitmentStore = smt.NewStore(smtdb) - } - - return &substore{ - root: rs, - name: key, - dataBucket: prefixdb.NewPrefixReadWriter(stateRW, dataPrefix), - indexBucket: prefixdb.NewPrefixReadWriter(stateRW, indexPrefix), - stateCommitmentStore: stateCommitmentStore, - }, nil -} - -// Resets a substore's state after commit (because root stateTxn has been discarded) -func (s *substore) refresh(rootHash []byte) { - pfx := substorePrefix(s.name) - stateRW := prefixdb.NewPrefixReadWriter(s.root.stateTxn, pfx) - stateCommitmentRW := prefixdb.NewPrefixReadWriter(s.root.stateCommitmentTxn, pfx) - s.dataBucket = prefixdb.NewPrefixReadWriter(stateRW, dataPrefix) - s.indexBucket = prefixdb.NewPrefixReadWriter(stateRW, indexPrefix) - s.stateCommitmentStore = loadSMT(stateCommitmentRW, rootHash) -} - -// Commit implements Committer. -func (s *Store) Commit() types.CommitID { - // Substores read-lock this mutex; lock to prevent racey invalidation of underlying txns - s.mtx.Lock() - defer s.mtx.Unlock() - // Determine the target version - versions, err := s.stateDB.Versions() - if err != nil { - panic(err) - } - target := versions.Last() + 1 - if target > math.MaxInt64 { - panic(ErrMaximumHeight) - } - // Fast forward to initial version if needed - if s.InitialVersion != 0 && target < s.InitialVersion { - target = s.InitialVersion - } - cid, err := s.commit(target) - if err != nil { - panic(err) - } - - // Prune if necessary - previous := cid.Version - 1 - if s.Pruning.Interval != 0 && cid.Version%int64(s.Pruning.Interval) == 0 { - // The range of newly prunable versions - lastPrunable := previous - int64(s.Pruning.KeepRecent) - firstPrunable := lastPrunable - int64(s.Pruning.Interval) - - for version := firstPrunable; version <= lastPrunable; version++ { - s.stateDB.DeleteVersion(uint64(version)) - - if s.StateCommitmentDB != nil { - s.StateCommitmentDB.DeleteVersion(uint64(version)) - } - } - } - - s.tran.Commit() - return *cid -} - -func (s *Store) getMerkleRoots() (ret map[string][]byte, err error) { - ret = map[string][]byte{} - for key := range s.schema { - sub, has := s.substoreCache[key] - if !has { - sub, err = s.getSubstore(key) - if err != nil { - return - } - } - ret[key] = sub.stateCommitmentStore.Root() - } - return -} - -// Calculates root hashes and commits to DB. Does not verify target version or perform pruning. -func (s *Store) commit(target uint64) (id *types.CommitID, err error) { - storeHashes, err := s.getMerkleRoots() - if err != nil { - return - } - // Update substore Merkle roots - for key, storeHash := range storeHashes { - pfx := substorePrefix(key) - stateW := prefixdb.NewPrefixReadWriter(s.stateTxn, pfx) - if err = stateW.Set(substoreMerkleRootKey, storeHash); err != nil { - return - } - } - rootHash := sdkmaps.HashFromMap(storeHashes) - if err = s.stateTxn.Set(merkleRootKey, rootHash); err != nil { - return - } - if err = s.stateTxn.Commit(); err != nil { - return - } - defer func() { - if err != nil { - err = util.CombineErrors(err, s.stateDB.Revert(), "stateDB.Revert also failed") - } - }() - err = s.stateDB.SaveVersion(target) - if err != nil { - return - } - - stateTxn := s.stateDB.ReadWriter() - defer func() { - if err != nil { - err = util.CombineErrors(err, stateTxn.Discard(), "stateTxn.Discard also failed") - } - }() - stateCommitmentTxn := stateTxn - - // If DBs are not separate, StateCommitment state has been committed & snapshotted - if s.StateCommitmentDB != nil { - // if any error is encountered henceforth, we must revert the state and SC dbs - defer func() { - if err != nil { - if delerr := s.stateDB.DeleteVersion(target); delerr != nil { - err = fmt.Errorf("%w: commit rollback failed: %v", err, delerr) - } - } - }() - - err = s.stateCommitmentTxn.Commit() - if err != nil { - return - } - defer func() { - if err != nil { - err = util.CombineErrors(err, s.StateCommitmentDB.Revert(), "stateCommitmentDB.Revert also failed") - } - }() - - err = s.StateCommitmentDB.SaveVersion(target) - if err != nil { - return - } - stateCommitmentTxn = s.StateCommitmentDB.ReadWriter() - } - - s.stateTxn = stateTxn - s.stateCommitmentTxn = stateCommitmentTxn - // the state of all live substores must be refreshed - for key, sub := range s.substoreCache { - sub.refresh(storeHashes[key]) - } - - return &types.CommitID{Version: int64(target), Hash: rootHash}, nil -} - -// LastCommitID implements Committer. -func (s *Store) LastCommitID() types.CommitID { - versions, err := s.stateDB.Versions() - if err != nil { - panic(err) - } - last := versions.Last() - if last == 0 { - return types.CommitID{} - } - // Latest Merkle root is the one currently stored - hash, err := s.stateTxn.Get(merkleRootKey) - if err != nil { - panic(err) - } - return types.CommitID{Version: int64(last), Hash: hash} -} - -// SetInitialVersion implements CommitMultiStore. -func (rs *Store) SetInitialVersion(version uint64) error { - rs.InitialVersion = version - return nil -} - -// GetVersion implements CommitMultiStore. -func (rs *Store) GetVersion(version int64) (types.BasicMultiStore, error) { - return rs.getView(version) -} - -// CacheMultiStore implements BasicMultiStore. -func (rs *Store) CacheMultiStore() types.CacheMultiStore { - return &cacheStore{ - source: rs, - substores: map[string]types.CacheKVStore{}, - traceListenMixin: newTraceListenMixin(), - } -} - -// PruneSnapshotHeight prunes the given height according to the prune strategy. -// If PruneNothing, this is a no-op. -// If other strategy, this height is persisted until it is -// less than - KeepRecent and % Interval == 0 -func (rs *Store) PruneSnapshotHeight(height int64) { - panic("not implemented") -} - -// SetSnapshotInterval sets the interval at which the snapshots are taken. -// It is used by the store to determine which heights to retain until after the snapshot is complete. -func (rs *Store) SetSnapshotInterval(snapshotInterval uint64) { - panic("not implemented") -} - -// parsePath expects a format like /[/] -// Must start with /, subpath may be empty -// Returns error if it doesn't start with / -func parsePath(path string) (storeName string, subpath string, err error) { - if !strings.HasPrefix(path, "/") { - return storeName, subpath, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid path: %s", path) - } - - paths := strings.SplitN(path[1:], "/", 2) - storeName = paths[0] - - if len(paths) == 2 { - subpath = "/" + paths[1] - } - - return storeName, subpath, nil -} - -// Query implements ABCI interface, allows queries. -// -// by default we will return from (latest height -1), -// as we will have merkle proofs immediately (header height = data height + 1) -// If latest-1 is not present, use latest (which must be present) -// if you care to have the latest data to see a tx results, you must -// explicitly set the height you want to see -func (rs *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { - if len(req.Data) == 0 { - return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrTxDecode, "query cannot be zero length"), false) - } - - // if height is 0, use the latest height - height := req.Height - if height == 0 { - versions, err := rs.stateDB.Versions() - if err != nil { - return sdkerrors.QueryResult(errors.New("failed to get version info"), false) - } - latest := versions.Last() - if versions.Exists(latest - 1) { - height = int64(latest - 1) - } else { - height = int64(latest) - } - } - if height < 0 { - return sdkerrors.QueryResult(fmt.Errorf("height overflow: %v", height), false) - } - res.Height = height - - storeName, subpath, err := parsePath(req.Path) - if err != nil { - return sdkerrors.QueryResult(sdkerrors.Wrapf(err, "failed to parse path"), false) - } - view, err := rs.getView(height) - if err != nil { - if errors.Is(err, dbm.ErrVersionDoesNotExist) { - err = sdkerrors.ErrInvalidHeight - } - return sdkerrors.QueryResult(sdkerrors.Wrapf(err, "failed to access height"), false) - } - - if _, has := rs.schema[storeName]; !has { - return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "no such store: %s", storeName), false) - } - substore, err := view.getSubstore(storeName) - if err != nil { - return sdkerrors.QueryResult(sdkerrors.Wrapf(err, "failed to access store: %s", storeName), false) - } - - switch subpath { - case "/key": - var err error - res.Key = req.Data // data holds the key bytes - res.Value = substore.Get(res.Key) - if !req.Prove { - break - } - // TODO: actual IBC compatible proof. This is a placeholder so unit tests can pass - res.ProofOps, err = substore.GetProof(res.Key) - if err != nil { - return sdkerrors.QueryResult(fmt.Errorf("merkle proof creation failed for key: %v", res.Key), false) - } - - case "/subspace": - res.Key = req.Data // data holds the subspace prefix - - pairs := kv.Pairs{ - Pairs: make([]kv.Pair, 0), - } - - res.Key = req.Data // data holds the subspace prefix - - iterator := substore.Iterator(res.Key, types.PrefixEndBytes(res.Key)) - for ; iterator.Valid(); iterator.Next() { - pairs.Pairs = append(pairs.Pairs, kv.Pair{Key: iterator.Key(), Value: iterator.Value()}) - } - iterator.Close() - - bz, err := pairs.Marshal() - if err != nil { - panic(fmt.Errorf("failed to marshal KV pairs: %w", err)) - } - - res.Value = bz - - default: - return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unexpected query path: %v", req.Path), false) - } - - return res -} - -func loadSMT(stateCommitmentTxn dbm.DBReadWriter, root []byte) *smt.Store { - smtdb := prefixdb.NewPrefixReadWriter(stateCommitmentTxn, smtPrefix) - return smt.LoadStore(smtdb, root) -} - -// Returns closest index and whether it's a match -func binarySearch(hay []string, ndl string) (int, bool) { - var mid int - from, to := 0, len(hay)-1 - for from <= to { - mid = (from + to) / 2 - switch strings.Compare(hay[mid], ndl) { - case -1: - from = mid + 1 - case 1: - to = mid - 1 - default: - return mid, true - } - } - return from, false -} - -func (pr *prefixRegistry) storeInfo(key string) (sst types.StoreType, ix int, err error) { - ix, has := binarySearch(pr.reserved, key) - if !has { - err = fmt.Errorf("prefix does not exist: %v", key) - return - } - sst, has = pr.StoreSchema[key] - if !has { - err = fmt.Errorf("prefix is registered but not in schema: %v", key) - } - - return -} - -func (pr *prefixRegistry) RegisterSubstore(key string, typ types.StoreType) error { - if !validSubStoreType(typ) { - return fmt.Errorf("StoreType not supported: %v", typ) - } - - // Find the neighboring reserved prefix, and check for duplicates and conflicts - i, has := binarySearch(pr.reserved, key) - if has { - return fmt.Errorf("prefix already exists: %v", key) - } - if i > 0 && strings.HasPrefix(key, pr.reserved[i-1]) { - return fmt.Errorf("prefix conflict: '%v' exists, cannot add '%v'", pr.reserved[i-1], key) - } - if i < len(pr.reserved) && strings.HasPrefix(pr.reserved[i], key) { - return fmt.Errorf("prefix conflict: '%v' exists, cannot add '%v'", pr.reserved[i], key) - } - reserved := pr.reserved[:i] - reserved = append(reserved, key) - pr.reserved = append(reserved, pr.reserved[i:]...) - pr.StoreSchema[key] = typ - return nil -} - -func (tlm *traceListenMixin) AddListeners(skey types.StoreKey, listeners []types.WriteListener) { - key := skey.Name() - tlm.listeners[key] = append(tlm.listeners[key], listeners...) -} - -// ListeningEnabled returns if listening is enabled for a specific KVStore -func (tlm *traceListenMixin) ListeningEnabled(key types.StoreKey) bool { - if ls, has := tlm.listeners[key.Name()]; has { - return len(ls) != 0 - } - return false -} - -func (tlm *traceListenMixin) TracingEnabled() bool { - return tlm.TraceWriter != nil -} - -func (tlm *traceListenMixin) SetTracer(w io.Writer) { - tlm.TraceWriter = w -} - -func (tlm *traceListenMixin) SetTraceContext(tc types.TraceContext) { - tlm.TraceContext = tc -} - -func (tlm *traceListenMixin) wrapTraceListen(store types.KVStore, skey types.StoreKey) types.KVStore { - if tlm.TracingEnabled() { - store = tracekv.NewStore(store, tlm.TraceWriter, tlm.TraceContext) - } - if tlm.ListeningEnabled(skey) { - store = listenkv.NewStore(store, skey, tlm.listeners[skey.Name()]) - } - return store -} - -func (s *Store) GetPruning() pruningtypes.PruningOptions { return s.Pruning } -func (s *Store) SetPruning(po pruningtypes.PruningOptions) { s.Pruning = po } diff --git a/store/v2alpha1/multi/store_test.go b/store/v2alpha1/multi/store_test.go deleted file mode 100644 index de09003518d0..000000000000 --- a/store/v2alpha1/multi/store_test.go +++ /dev/null @@ -1,986 +0,0 @@ -package multi - -import ( - "bytes" - "math" - "testing" - - "github.com/stretchr/testify/require" - - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/codec" - codecTypes "github.com/cosmos/cosmos-sdk/codec/types" - dbm "github.com/cosmos/cosmos-sdk/db" - "github.com/cosmos/cosmos-sdk/db/memdb" - pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" - "github.com/cosmos/cosmos-sdk/types/kv" -) - -var ( - alohaData = map[string]string{ - "hello": "goodbye", - "aloha": "shalom", - } - skey_1 = types.NewKVStoreKey("store1") - skey_2 = types.NewKVStoreKey("store2") - skey_3 = types.NewKVStoreKey("store3") - skey_4 = types.NewKVStoreKey("store4") - skey_1b = types.NewKVStoreKey("store1b") - skey_2b = types.NewKVStoreKey("store2b") - skey_3b = types.NewKVStoreKey("store3b") -) - -func simpleStoreConfig(t *testing.T) StoreConfig { - opts := DefaultStoreConfig() - require.NoError(t, opts.RegisterSubstore(skey_1.Name(), types.StoreTypePersistent)) - return opts -} - -func storeConfig123(t *testing.T) StoreConfig { - opts := DefaultStoreConfig() - opts.Pruning = pruningtypes.NewPruningOptions(pruningtypes.PruningNothing) - require.NoError(t, opts.RegisterSubstore(skey_1.Name(), types.StoreTypePersistent)) - require.NoError(t, opts.RegisterSubstore(skey_2.Name(), types.StoreTypePersistent)) - require.NoError(t, opts.RegisterSubstore(skey_3.Name(), types.StoreTypePersistent)) - return opts -} - -func newSubStoreWithData(t *testing.T, db dbm.DBConnection, storeData map[string]string) (*Store, types.KVStore) { - root, err := NewStore(db, simpleStoreConfig(t)) - require.NoError(t, err) - - store := root.GetKVStore(skey_1) - for k, v := range storeData { - store.Set([]byte(k), []byte(v)) - } - return root, store -} - -func TestGetSetHasDelete(t *testing.T) { - _, store := newSubStoreWithData(t, memdb.NewDB(), alohaData) - key := "hello" - - exists := store.Has([]byte(key)) - require.True(t, exists) - - require.EqualValues(t, []byte(alohaData[key]), store.Get([]byte(key))) - - value2 := "notgoodbye" - store.Set([]byte(key), []byte(value2)) - - require.EqualValues(t, value2, store.Get([]byte(key))) - - store.Delete([]byte(key)) - - exists = store.Has([]byte(key)) - require.False(t, exists) - - require.Panics(t, func() { store.Get(nil) }, "Get(nil key) should panic") - require.Panics(t, func() { store.Get([]byte{}) }, "Get(empty key) should panic") - require.Panics(t, func() { store.Has(nil) }, "Has(nil key) should panic") - require.Panics(t, func() { store.Has([]byte{}) }, "Has(empty key) should panic") - require.Panics(t, func() { store.Set(nil, []byte("value")) }, "Set(nil key) should panic") - require.Panics(t, func() { store.Set([]byte{}, []byte("value")) }, "Set(empty key) should panic") - require.Panics(t, func() { store.Set([]byte("key"), nil) }, "Set(nil value) should panic") - sub := store.(*substore) - sub.indexBucket = rwCrudFails{sub.indexBucket, nil} - require.Panics(t, func() { - store.Set([]byte("key"), []byte("value")) - }, "Set() when index fails should panic") -} - -func TestConstructors(t *testing.T) { - db := memdb.NewDB() - - store, err := NewStore(db, simpleStoreConfig(t)) - require.NoError(t, err) - _ = store.GetKVStore(skey_1) - store.Commit() - require.NoError(t, store.Close()) - - t.Run("fail to load if InitialVersion > lowest existing version", func(t *testing.T) { - opts := StoreConfig{InitialVersion: 5, Pruning: pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)} - store, err = NewStore(db, opts) - require.Error(t, err) - db.Close() - }) - - t.Run("can't load store when db.Versions fails", func(t *testing.T) { - store, err = NewStore(dbVersionsFails{memdb.NewDB()}, DefaultStoreConfig()) - require.Error(t, err) - store, err = NewStore(db, StoreConfig{StateCommitmentDB: dbVersionsFails{memdb.NewDB()}}) - require.Error(t, err) - }) - - db = memdb.NewDB() - merkledb := memdb.NewDB() - w := db.Writer() - t.Run("can't use a DB with open writers", func(t *testing.T) { - store, err = NewStore(db, DefaultStoreConfig()) - require.Error(t, err) - w.Discard() - w = merkledb.Writer() - store, err = NewStore(db, StoreConfig{StateCommitmentDB: merkledb}) - require.Error(t, err) - w.Discard() - }) - - t.Run("can't use DBs with different version history", func(t *testing.T) { - merkledb.SaveNextVersion() - store, err = NewStore(db, StoreConfig{StateCommitmentDB: merkledb}) - require.Error(t, err) - }) - merkledb.Close() - - t.Run("can't load existing store if we can't access root hash", func(t *testing.T) { - store, err = NewStore(db, simpleStoreConfig(t)) - require.NoError(t, err) - store.Commit() - require.NoError(t, store.Close()) - // ...whether because root is misssing - w = db.Writer() - s1RootKey := append(contentPrefix, substorePrefix(skey_1.Name())...) - s1RootKey = append(s1RootKey, merkleRootKey...) - w.Delete(s1RootKey) - w.Commit() - db.SaveNextVersion() - store, err = NewStore(db, DefaultStoreConfig()) - require.Error(t, err) - // ...or, because of an error - store, err = NewStore(dbRWCrudFails{db}, DefaultStoreConfig()) - require.Error(t, err) - }) -} - -func TestIterators(t *testing.T) { - _, store := newSubStoreWithData(t, memdb.NewDB(), map[string]string{ - string([]byte{0x00}): "0", - string([]byte{0x00, 0x00}): "0 0", - string([]byte{0x00, 0x01}): "0 1", - string([]byte{0x00, 0x02}): "0 2", - string([]byte{0x01}): "1", - }) - - testCase := func(t *testing.T, iter types.Iterator, expected []string) { - var i int - for i = 0; iter.Valid(); iter.Next() { - expectedValue := expected[i] - value := iter.Value() - require.EqualValues(t, string(value), expectedValue) - i++ - } - require.Equal(t, len(expected), i) - } - - testCase(t, store.Iterator(nil, nil), - []string{"0", "0 0", "0 1", "0 2", "1"}) - testCase(t, store.Iterator([]byte{0}, nil), - []string{"0", "0 0", "0 1", "0 2", "1"}) - testCase(t, store.Iterator([]byte{0}, []byte{0, 1}), - []string{"0", "0 0"}) - testCase(t, store.Iterator([]byte{0}, []byte{1}), - []string{"0", "0 0", "0 1", "0 2"}) - testCase(t, store.Iterator([]byte{0, 1}, []byte{1}), - []string{"0 1", "0 2"}) - testCase(t, store.Iterator(nil, []byte{1}), - []string{"0", "0 0", "0 1", "0 2"}) - testCase(t, store.Iterator([]byte{0}, []byte{0}), []string{}) // start = end - testCase(t, store.Iterator([]byte{1}, []byte{0}), []string{}) // start > end - - testCase(t, store.ReverseIterator(nil, nil), - []string{"1", "0 2", "0 1", "0 0", "0"}) - testCase(t, store.ReverseIterator([]byte{0}, nil), - []string{"1", "0 2", "0 1", "0 0", "0"}) - testCase(t, store.ReverseIterator([]byte{0}, []byte{0, 1}), - []string{"0 0", "0"}) - testCase(t, store.ReverseIterator([]byte{0}, []byte{1}), - []string{"0 2", "0 1", "0 0", "0"}) - testCase(t, store.ReverseIterator([]byte{0, 1}, []byte{1}), - []string{"0 2", "0 1"}) - testCase(t, store.ReverseIterator(nil, []byte{1}), - []string{"0 2", "0 1", "0 0", "0"}) - testCase(t, store.ReverseIterator([]byte{0}, []byte{0}), []string{}) // start = end - testCase(t, store.ReverseIterator([]byte{1}, []byte{0}), []string{}) // start > end - - testCase(t, types.KVStorePrefixIterator(store, []byte{0}), - []string{"0", "0 0", "0 1", "0 2"}) - testCase(t, types.KVStoreReversePrefixIterator(store, []byte{0}), - []string{"0 2", "0 1", "0 0", "0"}) - - require.Panics(t, func() { store.Iterator([]byte{}, nil) }, "Iterator(empty key) should panic") - require.Panics(t, func() { store.Iterator(nil, []byte{}) }, "Iterator(empty key) should panic") - require.Panics(t, func() { store.ReverseIterator([]byte{}, nil) }, "Iterator(empty key) should panic") - require.Panics(t, func() { store.ReverseIterator(nil, []byte{}) }, "Iterator(empty key) should panic") -} - -func TestCommit(t *testing.T) { - testBasic := func(opts StoreConfig) { - db := memdb.NewDB() - store, err := NewStore(db, opts) - require.NoError(t, err) - require.Zero(t, store.LastCommitID()) - idNew := store.Commit() - - // Adding one record changes the hash - s1 := store.GetKVStore(skey_1) - s1.Set([]byte{0}, []byte{0}) - idOne := store.Commit() - require.Equal(t, idNew.Version+1, idOne.Version) - require.NotEqual(t, idNew.Hash, idOne.Hash) - - // Hash of emptied store is same as new store - s1.Delete([]byte{0}) - idEmptied := store.Commit() - require.Equal(t, idNew.Hash, idEmptied.Hash) - - previd := idOne - for i := byte(1); i < 5; i++ { - s1.Set([]byte{i}, []byte{i}) - id := store.Commit() - lastid := store.LastCommitID() - require.Equal(t, id.Hash, lastid.Hash) - require.Equal(t, id.Version, lastid.Version) - require.NotEqual(t, previd.Hash, id.Hash) - require.NotEqual(t, previd.Version, id.Version) - } - } - basicOpts := simpleStoreConfig(t) - basicOpts.Pruning = pruningtypes.NewPruningOptions(pruningtypes.PruningNothing) - t.Run("sanity tests for Merkle hashing", func(t *testing.T) { - testBasic(basicOpts) - }) - t.Run("sanity tests for Merkle hashing with separate DBs", func(t *testing.T) { - basicOpts.StateCommitmentDB = memdb.NewDB() - testBasic(basicOpts) - }) - - // test that we can recover from a failed commit - testFailedCommit := func(t *testing.T, - store *Store, - db dbm.DBConnection, - opts StoreConfig, - ) { - if db == nil { - db = store.stateDB - } - s1 := store.GetKVStore(skey_1) - s1.Set([]byte{0}, []byte{0}) - require.Panics(t, func() { store.Commit() }) - require.NoError(t, store.Close()) - - // No version should be saved in the backing DB(s) - versions, _ := db.Versions() - require.Equal(t, 0, versions.Count()) - if store.StateCommitmentDB != nil { - versions, _ = store.StateCommitmentDB.Versions() - require.Equal(t, 0, versions.Count()) - } - - // The store should now be reloaded successfully - store, err := NewStore(db, opts) - require.NoError(t, err) - s1 = store.GetKVStore(skey_1) - require.Nil(t, s1.Get([]byte{0})) - require.NoError(t, store.Close()) - } - - opts := simpleStoreConfig(t) - opts.Pruning = pruningtypes.NewPruningOptions(pruningtypes.PruningNothing) - - // Ensure Store's commit is rolled back in each failure case... - t.Run("recover after failed Commit", func(t *testing.T) { - store, err := NewStore(dbRWCommitFails{memdb.NewDB()}, opts) - require.NoError(t, err) - testFailedCommit(t, store, nil, opts) - }) - // If SaveVersion and Revert both fail during Store.Commit, the DB will contain - // committed data that belongs to no version: non-atomic behavior from the Store user's perspective. - // So, that data must be reverted when the store is reloaded. - t.Run("recover after failed SaveVersion and Revert", func(t *testing.T) { - var db dbm.DBConnection - db = dbSaveVersionFails{memdb.NewDB()} - // Revert should succeed in initial NewStore call, but fail during Commit - db = dbRevertFails{db, []bool{false, true}} - store, err := NewStore(db, opts) - require.NoError(t, err) - testFailedCommit(t, store, nil, opts) - }) - // Repeat the above for StateCommitmentDB - t.Run("recover after failed StateCommitmentDB Commit", func(t *testing.T) { - opts.StateCommitmentDB = dbRWCommitFails{memdb.NewDB()} - store, err := NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - testFailedCommit(t, store, nil, opts) - }) - t.Run("recover after failed StateCommitmentDB SaveVersion and Revert", func(t *testing.T) { - var db dbm.DBConnection - db = dbSaveVersionFails{memdb.NewDB()} - db = dbRevertFails{db, []bool{false, true}} - opts.StateCommitmentDB = db - store, err := NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - testFailedCommit(t, store, nil, opts) - }) - - opts = simpleStoreConfig(t) - t.Run("recover after stateDB.Versions error triggers failure", func(t *testing.T) { - db := memdb.NewDB() - store, err := NewStore(db, opts) - require.NoError(t, err) - store.stateDB = dbVersionsFails{store.stateDB} - testFailedCommit(t, store, db, opts) - }) - t.Run("recover after stateTxn.Set error triggers failure", func(t *testing.T) { - store, err := NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - store.stateTxn = rwCrudFails{store.stateTxn, merkleRootKey} - testFailedCommit(t, store, nil, opts) - }) - - t.Run("stateDB.DeleteVersion error triggers failure", func(t *testing.T) { - opts.StateCommitmentDB = memdb.NewDB() - store, err := NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - store.stateCommitmentTxn = rwCommitFails{store.stateCommitmentTxn} - store.stateDB = dbDeleteVersionFails{store.stateDB} - require.Panics(t, func() { store.Commit() }) - }) - t.Run("height overflow triggers failure", func(t *testing.T) { - opts.StateCommitmentDB = nil - opts.InitialVersion = math.MaxInt64 - opts.Pruning = pruningtypes.NewPruningOptions(pruningtypes.PruningNothing) - store, err := NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - require.Equal(t, int64(math.MaxInt64), store.Commit().Version) - require.Panics(t, func() { store.Commit() }) - require.Equal(t, int64(math.MaxInt64), store.LastCommitID().Version) // version history not modified - }) - - t.Run("first commit version matches InitialVersion", func(t *testing.T) { - opts = simpleStoreConfig(t) - opts.InitialVersion = 5 - opts.Pruning = pruningtypes.NewPruningOptions(pruningtypes.PruningNothing) - opts.StateCommitmentDB = memdb.NewDB() - store, err := NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - require.Equal(t, int64(5), store.Commit().Version) - }) - - // test improbable failures to fill out test coverage - opts = simpleStoreConfig(t) - store, err := NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - store.Commit() - store.stateDB = dbVersionsFails{store.stateDB} - require.Panics(t, func() { store.LastCommitID() }) - - opts = simpleStoreConfig(t) - opts.StateCommitmentDB = memdb.NewDB() - store, err = NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - store.Commit() - store.stateTxn = rwCrudFails{store.stateTxn, nil} - require.Panics(t, func() { store.LastCommitID() }) -} - -func sliceToSet(slice []uint64) map[uint64]struct{} { - res := make(map[uint64]struct{}) - for _, x := range slice { - res[x] = struct{}{} - } - return res -} - -func TestPruning(t *testing.T) { - // Save versions up to 10 and verify pruning at final commit - testCases := []struct { - pruningtypes.PruningOptions - kept []uint64 - }{ - {pruningtypes.NewCustomPruningOptions(2, 10), []uint64{8, 9, 10}}, - {pruningtypes.NewCustomPruningOptions(0, 10), []uint64{10}}, - {pruningtypes.NewPruningOptions(pruningtypes.PruningEverything), []uint64{8, 9, 10}}, - {pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, - } - - for tci, tc := range testCases { - dbs := []dbm.DBConnection{memdb.NewDB(), memdb.NewDB()} - opts := simpleStoreConfig(t) - opts.Pruning = tc.PruningOptions - opts.StateCommitmentDB = dbs[1] - store, err := NewStore(dbs[0], opts) - require.NoError(t, err) - - s1 := store.GetKVStore(skey_1) - for i := byte(1); i <= 10; i++ { - s1.Set([]byte{i}, []byte{i}) - cid := store.Commit() - latest := uint64(i) - require.Equal(t, latest, uint64(cid.Version)) - } - - for _, db := range dbs { - versions, err := db.Versions() - require.NoError(t, err) - - kept := sliceToSet(tc.kept) - for v := uint64(1); v <= 10; v++ { - _, has := kept[v] - require.Equal(t, has, versions.Exists(v), "Version = %v; tc #%d", v, tci) - } - } - } - - // Test pruning interval - // Save up to 20th version while checking history at specific version checkpoints - testCheckPoints := map[uint64][]uint64{ - 5: {1, 2, 3, 4, 5}, - 10: {10}, - 15: {10, 11, 12, 13, 14, 15}, - 20: {20}, - } - - db := memdb.NewDB() - opts := simpleStoreConfig(t) - opts.Pruning = pruningtypes.NewCustomPruningOptions(0, 10) - store, err := NewStore(db, opts) - require.NoError(t, err) - - for i := byte(1); i <= 20; i++ { - store.GetKVStore(skey_1).Set([]byte{i}, []byte{i}) - - cid := store.Commit() - latest := uint64(i) - require.Equal(t, latest, uint64(cid.Version)) - - kept, has := testCheckPoints[latest] - if !has { - continue - } - - versions, err := db.Versions() - require.NoError(t, err) - - keptMap := sliceToSet(kept) - for v := uint64(1); v <= latest; v++ { - _, has := keptMap[v] - require.Equal(t, has, versions.Exists(v), "Version = %v; tc #%d", v, i) - } - } -} - -func queryPath(skey types.StoreKey, endp string) string { return "/" + skey.Name() + endp } - -func TestQuery(t *testing.T) { - k1, v1 := []byte("k1"), []byte("v1") - k2, v2 := []byte("k2"), []byte("v2") - v3 := []byte("v3") - - ksub := []byte("k") - KVs0 := kv.Pairs{} - KVs1 := kv.Pairs{ - Pairs: []kv.Pair{ - {Key: k1, Value: v1}, - {Key: k2, Value: v2}, - }, - } - KVs2 := kv.Pairs{ - Pairs: []kv.Pair{ - {Key: k1, Value: v3}, - {Key: k2, Value: v2}, - }, - } - - valExpSubEmpty, err := KVs0.Marshal() - require.NoError(t, err) - - valExpSub1, err := KVs1.Marshal() - require.NoError(t, err) - - valExpSub2, err := KVs2.Marshal() - require.NoError(t, err) - - store, err := NewStore(memdb.NewDB(), simpleStoreConfig(t)) - require.NoError(t, err) - cid := store.Commit() - ver := cid.Version - query := abci.RequestQuery{Path: queryPath(skey_1, "/key"), Data: k1, Height: ver} - querySub := abci.RequestQuery{Path: queryPath(skey_1, "/subspace"), Data: ksub, Height: ver} - queryHeight0 := abci.RequestQuery{Path: queryPath(skey_1, "/key"), Data: k1} - - // query subspace before anything set - qres := store.Query(querySub) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, valExpSubEmpty, qres.Value) - - sub := store.GetKVStore(skey_1) - require.NotNil(t, sub) - // set data - sub.Set(k1, v1) - sub.Set(k2, v2) - - t.Run("basic queries", func(t *testing.T) { - // set data without commit, doesn't show up - qres = store.Query(query) - require.True(t, qres.IsOK(), qres.Log) - require.Nil(t, qres.Value) - - // commit it, but still don't see on old version - cid = store.Commit() - qres = store.Query(query) - require.True(t, qres.IsOK(), qres.Log) - require.Nil(t, qres.Value) - - // but yes on the new version - query.Height = cid.Version - qres = store.Query(query) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, v1, qres.Value) - // and for the subspace - querySub.Height = cid.Version - qres = store.Query(querySub) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, valExpSub1, qres.Value) - - // modify - sub.Set(k1, v3) - cid = store.Commit() - - // query will return old values, as height is fixed - qres = store.Query(query) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, v1, qres.Value) - - // update to latest height in the query and we are happy - query.Height = cid.Version - qres = store.Query(query) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, v3, qres.Value) - // try other key - query2 := abci.RequestQuery{Path: queryPath(skey_1, "/key"), Data: k2, Height: cid.Version} - qres = store.Query(query2) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, v2, qres.Value) - // and for the subspace - querySub.Height = cid.Version - qres = store.Query(querySub) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, valExpSub2, qres.Value) - - // default (height 0) will show latest-1 - qres = store.Query(queryHeight0) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, v1, qres.Value) - }) - - // querying an empty store will fail - store2, err := NewStore(memdb.NewDB(), simpleStoreConfig(t)) - require.NoError(t, err) - qres = store2.Query(queryHeight0) - require.True(t, qres.IsErr()) - - // default shows latest, if latest-1 does not exist - store2.GetKVStore(skey_1).Set(k1, v1) - store2.Commit() - qres = store2.Query(queryHeight0) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, v1, qres.Value) - store2.Close() - - t.Run("failed queries", func(t *testing.T) { - // artificial error cases for coverage (should never happen with prescribed usage) - // ensure that height overflow triggers an error - require.NoError(t, err) - store2.stateDB = dbVersionsIs{store2.stateDB, dbm.NewVersionManager([]uint64{uint64(math.MaxInt64) + 1})} - qres = store2.Query(queryHeight0) - require.True(t, qres.IsErr()) - // failure to access versions triggers an error - store2.stateDB = dbVersionsFails{store.stateDB} - qres = store2.Query(queryHeight0) - require.True(t, qres.IsErr()) - store2.Close() - - // query with a nil or empty key fails - badquery := abci.RequestQuery{Path: queryPath(skey_1, "/key"), Data: []byte{}} - qres = store.Query(badquery) - require.True(t, qres.IsErr()) - badquery.Data = nil - qres = store.Query(badquery) - require.True(t, qres.IsErr()) - // querying an invalid height will fail - badquery = abci.RequestQuery{Path: queryPath(skey_1, "/key"), Data: k1, Height: store.LastCommitID().Version + 1} - qres = store.Query(badquery) - require.True(t, qres.IsErr()) - // or an invalid path - badquery = abci.RequestQuery{Path: queryPath(skey_1, "/badpath"), Data: k1} - qres = store.Query(badquery) - require.True(t, qres.IsErr()) - }) - - t.Run("queries with proof", func(t *testing.T) { - // test that proofs are generated with single and separate DBs - testProve := func() { - queryProve0 := abci.RequestQuery{Path: queryPath(skey_1, "/key"), Data: k1, Prove: true} - qres = store.Query(queryProve0) - require.True(t, qres.IsOK(), qres.Log) - require.Equal(t, v1, qres.Value) - require.NotNil(t, qres.ProofOps) - } - testProve() - store.Close() - - opts := simpleStoreConfig(t) - opts.StateCommitmentDB = memdb.NewDB() - store, err = NewStore(memdb.NewDB(), opts) - require.NoError(t, err) - store.GetKVStore(skey_1).Set(k1, v1) - store.Commit() - testProve() - store.Close() - }) -} - -func TestStoreConfig(t *testing.T) { - opts := DefaultStoreConfig() - // Fail with invalid types - require.Error(t, opts.RegisterSubstore(skey_1.Name(), types.StoreTypeDB)) - require.Error(t, opts.RegisterSubstore(skey_1.Name(), types.StoreTypeSMT)) - // Ensure that no prefix conflicts are allowed - require.NoError(t, opts.RegisterSubstore(skey_1.Name(), types.StoreTypePersistent)) - require.NoError(t, opts.RegisterSubstore(skey_2.Name(), types.StoreTypeMemory)) - require.NoError(t, opts.RegisterSubstore(skey_3b.Name(), types.StoreTypeTransient)) - require.Error(t, opts.RegisterSubstore(skey_1b.Name(), types.StoreTypePersistent)) - require.Error(t, opts.RegisterSubstore(skey_2b.Name(), types.StoreTypePersistent)) - require.Error(t, opts.RegisterSubstore(skey_3.Name(), types.StoreTypePersistent)) -} - -func TestMultiStoreBasic(t *testing.T) { - opts := DefaultStoreConfig() - err := opts.RegisterSubstore(skey_1.Name(), types.StoreTypePersistent) - require.NoError(t, err) - db := memdb.NewDB() - store, err := NewStore(db, opts) - require.NoError(t, err) - - store_1 := store.GetKVStore(skey_1) - require.NotNil(t, store_1) - store_1.Set([]byte{0}, []byte{0}) - val := store_1.Get([]byte{0}) - require.Equal(t, []byte{0}, val) - store_1.Delete([]byte{0}) - val = store_1.Get([]byte{0}) - require.Equal(t, []byte(nil), val) -} - -func TestGetVersion(t *testing.T) { - db := memdb.NewDB() - opts := storeConfig123(t) - store, err := NewStore(db, opts) - require.NoError(t, err) - - cid := store.Commit() - view, err := store.GetVersion(cid.Version) - require.NoError(t, err) - subview := view.GetKVStore(skey_1) - require.NotNil(t, subview) - - // version view should be read-only - require.Panics(t, func() { subview.Set([]byte{1}, []byte{1}) }) - require.Panics(t, func() { subview.Delete([]byte{0}) }) - // nonexistent version shouldn't be accessible - _, err = store.GetVersion(cid.Version + 1) - require.Equal(t, ErrVersionDoesNotExist, err) - - substore := store.GetKVStore(skey_1) - require.NotNil(t, substore) - substore.Set([]byte{0}, []byte{0}) - // setting a value shouldn't affect old version - require.False(t, subview.Has([]byte{0})) - - cid = store.Commit() - view, err = store.GetVersion(cid.Version) - require.NoError(t, err) - subview = view.GetKVStore(skey_1) - require.NotNil(t, subview) - // deleting a value shouldn't affect old version - substore.Delete([]byte{0}) - require.Equal(t, []byte{0}, subview.Get([]byte{0})) -} - -func TestMultiStoreMigration(t *testing.T) { - db := memdb.NewDB() - opts := storeConfig123(t) - store, err := NewStore(db, opts) - require.NoError(t, err) - - // write some data in all stores - k1, v1 := []byte("first"), []byte("store") - s1 := store.GetKVStore(skey_1) - require.NotNil(t, s1) - s1.Set(k1, v1) - - k2, v2 := []byte("second"), []byte("restore") - s2 := store.GetKVStore(skey_2) - require.NotNil(t, s2) - s2.Set(k2, v2) - - k3, v3 := []byte("third"), []byte("dropped") - s3 := store.GetKVStore(skey_3) - require.NotNil(t, s3) - s3.Set(k3, v3) - - k4, v4 := []byte("fourth"), []byte("created") - require.Panics(t, func() { store.GetKVStore(skey_4) }) - - cid := store.Commit() - require.NoError(t, store.Close()) - var migratedID types.CommitID - - // Load without changes and make sure it is sensible - store, err = NewStore(db, opts) - require.NoError(t, err) - - // let's query data to see it was saved properly - s2 = store.GetKVStore(skey_2) - require.NotNil(t, s2) - require.Equal(t, v2, s2.Get(k2)) - require.NoError(t, store.Close()) - - t.Run("basic migration", func(t *testing.T) { - // now, let's load with upgrades... - opts.Upgrades = []types.StoreUpgrades{ - { - Added: []string{skey_4.Name()}, - Renamed: []types.StoreRename{{ - OldKey: skey_2.Name(), - NewKey: skey_2b.Name(), - }}, - Deleted: []string{skey_3.Name()}, - }, - } - store, err = NewStore(db, opts) - require.Nil(t, err) - - // s1 was not changed - s1 = store.GetKVStore(skey_1) - require.NotNil(t, s1) - require.Equal(t, v1, s1.Get(k1)) - - // store2 is no longer valid - require.Panics(t, func() { store.GetKVStore(skey_2) }) - // store2b has the old data - rs2 := store.GetKVStore(skey_2b) - require.NotNil(t, rs2) - require.Equal(t, v2, rs2.Get(k2)) - - // store3 is gone - require.Panics(t, func() { s3 = store.GetKVStore(skey_3) }) - - // store4 is valid - s4 := store.GetKVStore(skey_4) - require.NotNil(t, s4) - values := 0 - it := s4.Iterator(nil, nil) - for ; it.Valid(); it.Next() { - values += 1 - } - require.Zero(t, values) - require.NoError(t, it.Close()) - // write something inside store4 - s4.Set(k4, v4) - - // store this migrated data, and load it again without migrations - migratedID = store.Commit() - require.Equal(t, migratedID.Version, int64(2)) - require.NoError(t, store.Close()) - }) - - t.Run("reload after migrations", func(t *testing.T) { - // fail to load the migrated store with the old schema - store, err = NewStore(db, storeConfig123(t)) - require.Error(t, err) - - // pass in a schema reflecting the migrations - migratedOpts := DefaultStoreConfig() - err = migratedOpts.RegisterSubstore(skey_1.Name(), types.StoreTypePersistent) - require.NoError(t, err) - err = migratedOpts.RegisterSubstore(skey_2b.Name(), types.StoreTypePersistent) - require.NoError(t, err) - err = migratedOpts.RegisterSubstore(skey_4.Name(), types.StoreTypePersistent) - require.NoError(t, err) - store, err = NewStore(db, migratedOpts) - require.Nil(t, err) - require.Equal(t, migratedID, store.LastCommitID()) - - // query this new store - rl1 := store.GetKVStore(skey_1) - require.NotNil(t, rl1) - require.Equal(t, v1, rl1.Get(k1)) - - rl2 := store.GetKVStore(skey_2b) - require.NotNil(t, rl2) - require.Equal(t, v2, rl2.Get(k2)) - - rl4 := store.GetKVStore(skey_4) - require.NotNil(t, rl4) - require.Equal(t, v4, rl4.Get(k4)) - }) - - t.Run("load view from before migrations", func(t *testing.T) { - // load and check a view of the store at first commit - view, err := store.GetVersion(cid.Version) - require.NoError(t, err) - - s1 = view.GetKVStore(skey_1) - require.NotNil(t, s1) - require.Equal(t, v1, s1.Get(k1)) - - s2 = view.GetKVStore(skey_2) - require.NotNil(t, s2) - require.Equal(t, v2, s2.Get(k2)) - - s3 = view.GetKVStore(skey_3) - require.NotNil(t, s3) - require.Equal(t, v3, s3.Get(k3)) - - require.Panics(t, func() { - view.GetKVStore(skey_4) - }) - }) -} - -func TestTrace(t *testing.T) { - key, value := []byte("test-key"), []byte("test-value") - tctx := types.TraceContext(map[string]interface{}{"blockHeight": 64}) - - expected_Set := "{\"operation\":\"write\",\"key\":\"dGVzdC1rZXk=\",\"value\":\"dGVzdC12YWx1ZQ==\",\"metadata\":{\"blockHeight\":64}}\n" - expected_Get := "{\"operation\":\"read\",\"key\":\"dGVzdC1rZXk=\",\"value\":\"dGVzdC12YWx1ZQ==\",\"metadata\":{\"blockHeight\":64}}\n" - expected_Get_missing := "{\"operation\":\"read\",\"key\":\"dGVzdC1rZXk=\",\"value\":\"\",\"metadata\":{\"blockHeight\":64}}\n" - expected_Delete := "{\"operation\":\"delete\",\"key\":\"dGVzdC1rZXk=\",\"value\":\"\",\"metadata\":{\"blockHeight\":64}}\n" - expected_IterKey := "{\"operation\":\"iterKey\",\"key\":\"dGVzdC1rZXk=\",\"value\":\"\",\"metadata\":{\"blockHeight\":64}}\n" - expected_IterValue := "{\"operation\":\"iterValue\",\"key\":\"\",\"value\":\"dGVzdC12YWx1ZQ==\",\"metadata\":{\"blockHeight\":64}}\n" - - db := memdb.NewDB() - opts := simpleStoreConfig(t) - require.NoError(t, opts.RegisterSubstore(skey_2.Name(), types.StoreTypeMemory)) - require.NoError(t, opts.RegisterSubstore(skey_3.Name(), types.StoreTypeTransient)) - - store, err := NewStore(db, opts) - require.NoError(t, err) - store.SetTraceContext(tctx) - require.False(t, store.TracingEnabled()) - - var buf bytes.Buffer - store.SetTracer(&buf) - require.True(t, store.TracingEnabled()) - - for _, skey := range []types.StoreKey{skey_1, skey_2, skey_3} { - buf.Reset() - store.GetKVStore(skey).Get(key) - require.Equal(t, expected_Get_missing, buf.String()) - - buf.Reset() - store.GetKVStore(skey).Set(key, value) - require.Equal(t, expected_Set, buf.String()) - - buf.Reset() - require.Equal(t, value, store.GetKVStore(skey).Get(key)) - require.Equal(t, expected_Get, buf.String()) - - iter := store.GetKVStore(skey).Iterator(nil, nil) - buf.Reset() - require.Equal(t, key, iter.Key()) - require.Equal(t, expected_IterKey, buf.String()) - buf.Reset() - require.Equal(t, value, iter.Value()) - require.Equal(t, expected_IterValue, buf.String()) - require.NoError(t, iter.Close()) - - buf.Reset() - store.GetKVStore(skey).Delete(key) - require.Equal(t, expected_Delete, buf.String()) - - } - store.SetTracer(nil) - require.False(t, store.TracingEnabled()) - require.NoError(t, store.Close()) -} - -func TestListeners(t *testing.T) { - kvPairs := []types.KVPair{ - {Key: []byte{1}, Value: []byte("v1")}, - {Key: []byte{2}, Value: []byte("v2")}, - {Key: []byte{3}, Value: []byte("v3")}, - } - - testCases := []struct { - key []byte - value []byte - skey types.StoreKey - }{ - { - key: kvPairs[0].Key, - value: kvPairs[0].Value, - skey: skey_1, - }, - { - key: kvPairs[1].Key, - value: kvPairs[1].Value, - skey: skey_2, - }, - { - key: kvPairs[2].Key, - value: kvPairs[2].Value, - skey: skey_3, - }, - } - - interfaceRegistry := codecTypes.NewInterfaceRegistry() - marshaller := codec.NewProtoCodec(interfaceRegistry) - - db := memdb.NewDB() - opts := simpleStoreConfig(t) - require.NoError(t, opts.RegisterSubstore(skey_2.Name(), types.StoreTypeMemory)) - require.NoError(t, opts.RegisterSubstore(skey_3.Name(), types.StoreTypeTransient)) - - store, err := NewStore(db, opts) - require.NoError(t, err) - - for i, tc := range testCases { - var buf bytes.Buffer - listener := types.NewStoreKVPairWriteListener(&buf, marshaller) - store.AddListeners(tc.skey, []types.WriteListener{listener}) - require.True(t, store.ListeningEnabled(tc.skey)) - - // Set case - expected := types.StoreKVPair{ - Key: tc.key, - Value: tc.value, - StoreKey: tc.skey.Name(), - Delete: false, - } - var kvpair types.StoreKVPair - - buf.Reset() - store.GetKVStore(tc.skey).Set(tc.key, tc.value) - require.NoError(t, marshaller.UnmarshalLengthPrefixed(buf.Bytes(), &kvpair)) - require.Equal(t, expected, kvpair, i) - - // Delete case - expected = types.StoreKVPair{ - Key: tc.key, - Value: nil, - StoreKey: tc.skey.Name(), - Delete: true, - } - kvpair = types.StoreKVPair{} - - buf.Reset() - store.GetKVStore(tc.skey).Delete(tc.key) - require.NoError(t, marshaller.UnmarshalLengthPrefixed(buf.Bytes(), &kvpair)) - require.Equal(t, expected, kvpair, i) - } - require.NoError(t, store.Close()) -} diff --git a/store/v2alpha1/multi/sub_store.go b/store/v2alpha1/multi/sub_store.go deleted file mode 100644 index 613b7ac2c412..000000000000 --- a/store/v2alpha1/multi/sub_store.go +++ /dev/null @@ -1,117 +0,0 @@ -package multi - -import ( - "crypto/sha256" - "io" - "sync" - - dbm "github.com/cosmos/cosmos-sdk/db" - dbutil "github.com/cosmos/cosmos-sdk/internal/db" - "github.com/cosmos/cosmos-sdk/store/cachekv" - "github.com/cosmos/cosmos-sdk/store/listenkv" - "github.com/cosmos/cosmos-sdk/store/tracekv" - "github.com/cosmos/cosmos-sdk/store/types" -) - -// Get implements KVStore. -func (s *substore) Get(key []byte) []byte { - s.root.mtx.RLock() - defer s.root.mtx.RUnlock() - - val, err := s.dataBucket.Get(key) - if err != nil { - panic(err) - } - return val -} - -// Has implements KVStore. -func (s *substore) Has(key []byte) bool { - s.root.mtx.RLock() - defer s.root.mtx.RUnlock() - - has, err := s.dataBucket.Has(key) - if err != nil { - panic(err) - } - return has -} - -// Set implements KVStore. -func (s *substore) Set(key, value []byte) { - s.root.mtx.Lock() - defer s.root.mtx.Unlock() - - err := s.dataBucket.Set(key, value) - if err != nil { - panic(err) - } - s.stateCommitmentStore.Set(key, value) - khash := sha256.Sum256(key) - err = s.indexBucket.Set(khash[:], key) - if err != nil { - panic(err) - } -} - -// Delete implements KVStore. -func (s *substore) Delete(key []byte) { - khash := sha256.Sum256(key) - s.root.mtx.Lock() - defer s.root.mtx.Unlock() - - s.stateCommitmentStore.Delete(key) - _ = s.indexBucket.Delete(khash[:]) - _ = s.dataBucket.Delete(key) -} - -type contentsIterator struct { - types.Iterator - locker sync.Locker -} - -func (s *substore) newSubstoreIterator(source dbm.Iterator) *contentsIterator { - locker := s.root.mtx.RLocker() - locker.Lock() - return &contentsIterator{dbutil.DBToStoreIterator(source), locker} -} - -func (it *contentsIterator) Close() error { - defer it.locker.Unlock() - return it.Iterator.Close() -} - -// Iterator implements KVStore. -func (s *substore) Iterator(start, end []byte) types.Iterator { - iter, err := s.dataBucket.Iterator(start, end) - if err != nil { - panic(err) - } - return s.newSubstoreIterator(iter) -} - -// ReverseIterator implements KVStore. -func (s *substore) ReverseIterator(start, end []byte) types.Iterator { - iter, err := s.dataBucket.ReverseIterator(start, end) - if err != nil { - panic(err) - } - return s.newSubstoreIterator(iter) -} - -// GetStoreType implements Store. -func (s *substore) GetStoreType() types.StoreType { - return types.StoreTypePersistent -} - -func (s *substore) CacheWrap() types.CacheWrap { - return cachekv.NewStore(s) -} - -func (s *substore) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return cachekv.NewStore(tracekv.NewStore(s, w, tc)) -} - -func (s *substore) CacheWrapWithListeners(storeKey types.StoreKey, listeners []types.WriteListener) types.CacheWrap { - return cachekv.NewStore(listenkv.NewStore(s, storeKey, listeners)) -} diff --git a/store/v2alpha1/multi/test_util.go b/store/v2alpha1/multi/test_util.go deleted file mode 100644 index d7005cd86f0b..000000000000 --- a/store/v2alpha1/multi/test_util.go +++ /dev/null @@ -1,88 +0,0 @@ -//nolint:unused -package multi - -import ( - "bytes" - "errors" - - dbm "github.com/cosmos/cosmos-sdk/db" -) - -type ( - dbDeleteVersionFails struct{ dbm.DBConnection } - dbRWCommitFails struct{ dbm.DBConnection } - dbRWCrudFails struct{ dbm.DBConnection } - dbSaveVersionFails struct{ dbm.DBConnection } - dbRevertFails struct { - dbm.DBConnection - // order of calls to fail on (eg. [1, 0] => first call fails; second succeeds) - failOn []bool - } -) - -type dbVersionsIs struct { - dbm.DBConnection - vset dbm.VersionSet -} -type ( - dbVersionsFails struct{ dbm.DBConnection } - rwCommitFails struct{ dbm.DBReadWriter } - rwCrudFails struct { - dbm.DBReadWriter - onKey []byte - } -) - -func (dbVersionsFails) Versions() (dbm.VersionSet, error) { return nil, errors.New("dbVersionsFails") } -func (db dbVersionsIs) Versions() (dbm.VersionSet, error) { return db.vset, nil } -func (db dbRWCrudFails) ReadWriter() dbm.DBReadWriter { - return rwCrudFails{db.DBConnection.ReadWriter(), nil} -} -func (dbSaveVersionFails) SaveVersion(uint64) error { return errors.New("dbSaveVersionFails") } -func (db dbRevertFails) Revert() error { - fail := false - if len(db.failOn) > 0 { - fail, db.failOn = db.failOn[0], db.failOn[1:] //nolint:staticcheck - } - if fail { - return errors.New("dbRevertFails") - } - return db.DBConnection.Revert() -} -func (dbDeleteVersionFails) DeleteVersion(uint64) error { return errors.New("dbDeleteVersionFails") } -func (tx rwCommitFails) Commit() error { - tx.Discard() - return errors.New("rwCommitFails") -} - -func (db dbRWCommitFails) ReadWriter() dbm.DBReadWriter { - return rwCommitFails{db.DBConnection.ReadWriter()} -} - -func (rw rwCrudFails) Get(k []byte) ([]byte, error) { - if rw.onKey == nil || bytes.Equal(rw.onKey, k) { - return nil, errors.New("rwCrudFails.Get") - } - return rw.DBReadWriter.Get(k) -} - -func (rw rwCrudFails) Has(k []byte) (bool, error) { - if rw.onKey == nil || bytes.Equal(rw.onKey, k) { - return false, errors.New("rwCrudFails.Has") - } - return rw.DBReadWriter.Has(k) -} - -func (rw rwCrudFails) Set(k []byte, v []byte) error { - if rw.onKey == nil || bytes.Equal(rw.onKey, k) { - return errors.New("rwCrudFails.Set") - } - return rw.DBReadWriter.Set(k, v) -} - -func (rw rwCrudFails) Delete(k []byte) error { - if rw.onKey == nil || bytes.Equal(rw.onKey, k) { - return errors.New("rwCrudFails.Delete") - } - return rw.DBReadWriter.Delete(k) -} diff --git a/store/v2alpha1/multi/view_store.go b/store/v2alpha1/multi/view_store.go deleted file mode 100644 index b06596c3161b..000000000000 --- a/store/v2alpha1/multi/view_store.go +++ /dev/null @@ -1,178 +0,0 @@ -package multi - -import ( - "errors" - "io" - - dbm "github.com/cosmos/cosmos-sdk/db" - prefixdb "github.com/cosmos/cosmos-sdk/db/prefix" - util "github.com/cosmos/cosmos-sdk/internal" - dbutil "github.com/cosmos/cosmos-sdk/internal/db" - "github.com/cosmos/cosmos-sdk/store/cachekv" - "github.com/cosmos/cosmos-sdk/store/listenkv" - "github.com/cosmos/cosmos-sdk/store/tracekv" - types "github.com/cosmos/cosmos-sdk/store/v2alpha1" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/smt" -) - -var ErrReadOnly = errors.New("cannot modify read-only store") - -func (s *viewSubstore) GetStateCommitmentStore() *smt.Store { - return s.stateCommitmentStore -} - -// Get implements KVStore. -func (s *viewSubstore) Get(key []byte) []byte { - val, err := s.dataBucket.Get(key) - if err != nil { - panic(err) - } - return val -} - -// Has implements KVStore. -func (s *viewSubstore) Has(key []byte) bool { - has, err := s.dataBucket.Has(key) - if err != nil { - panic(err) - } - return has -} - -// Set implements KVStore. -func (s *viewSubstore) Set(key []byte, value []byte) { - panic(ErrReadOnly) -} - -// Delete implements KVStore. -func (s *viewSubstore) Delete(key []byte) { - panic(ErrReadOnly) -} - -// Iterator implements KVStore. -func (s *viewSubstore) Iterator(start, end []byte) types.Iterator { - iter, err := s.dataBucket.Iterator(start, end) - if err != nil { - panic(err) - } - return dbutil.DBToStoreIterator(iter) -} - -// ReverseIterator implements KVStore. -func (s *viewSubstore) ReverseIterator(start, end []byte) types.Iterator { - iter, err := s.dataBucket.ReverseIterator(start, end) - if err != nil { - panic(err) - } - return dbutil.DBToStoreIterator(iter) -} - -// GetStoreType implements Store. -func (s *viewSubstore) GetStoreType() types.StoreType { - return types.StoreTypePersistent -} - -func (st *viewSubstore) CacheWrap() types.CacheWrap { - return cachekv.NewStore(st) -} - -func (st *viewSubstore) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { - return cachekv.NewStore(tracekv.NewStore(st, w, tc)) -} - -func (st *viewSubstore) CacheWrapWithListeners(storeKey types.StoreKey, listeners []types.WriteListener) types.CacheWrap { - return cachekv.NewStore(listenkv.NewStore(st, storeKey, listeners)) -} - -func (s *viewStore) getMerkleRoots() (ret map[string][]byte, err error) { - ret = map[string][]byte{} - for key := range s.schema { - sub, has := s.substoreCache[key] - if !has { - sub, err = s.getSubstore(key) - if err != nil { - return - } - } - ret[key] = sub.stateCommitmentStore.Root() - } - return -} - -func (store *Store) getView(version int64) (ret *viewStore, err error) { - stateView, err := store.stateDB.ReaderAt(uint64(version)) - if err != nil { - return - } - defer func() { - if err != nil { - err = util.CombineErrors(err, stateView.Discard(), "stateView.Discard also failed") - } - }() - - stateCommitmentView := stateView - if store.StateCommitmentDB != nil { - stateCommitmentView, err = store.StateCommitmentDB.ReaderAt(uint64(version)) - if err != nil { - return - } - defer func() { - if err != nil { - err = util.CombineErrors(err, stateCommitmentView.Discard(), "stateCommitmentView.Discard also failed") - } - }() - } - // Now read this version's schema - schemaView := prefixdb.NewPrefixReader(stateView, schemaPrefix) - defer func() { - if err != nil { - err = util.CombineErrors(err, schemaView.Discard(), "schemaView.Discard also failed") - } - }() - pr, err := readSavedSchema(schemaView) - if err != nil { - return - } - // The migrated contents and schema are not committed until the next store.Commit - ret = &viewStore{ - stateView: stateView, - stateCommitmentView: stateCommitmentView, - substoreCache: map[string]*viewSubstore{}, - schema: pr.StoreSchema, - } - return ret, nil -} - -func (vs *viewStore) GetKVStore(skey types.StoreKey) types.KVStore { - key := skey.Name() - if _, has := vs.schema[key]; !has { - panic(ErrStoreNotFound(key)) - } - ret, err := vs.getSubstore(key) - if err != nil { - panic(err) - } - vs.substoreCache[key] = ret - return ret -} - -// Reads but does not update substore cache -func (vs *viewStore) getSubstore(key string) (*viewSubstore, error) { - if cached, has := vs.substoreCache[key]; has { - return cached, nil - } - pfx := substorePrefix(key) - stateR := prefixdb.NewPrefixReader(vs.stateView, pfx) - stateCommitmentR := prefixdb.NewPrefixReader(vs.stateCommitmentView, pfx) - rootHash, err := stateR.Get(merkleRootKey) - if err != nil { - return nil, err - } - return &viewSubstore{ - root: vs, - name: key, - dataBucket: prefixdb.NewPrefixReader(stateR, dataPrefix), - indexBucket: prefixdb.NewPrefixReader(stateR, indexPrefix), - stateCommitmentStore: loadSMT(dbm.ReaderAsReadWriter(stateCommitmentR), rootHash), - }, nil -} diff --git a/store/v2alpha1/smt/ics23.go b/store/v2alpha1/smt/ics23.go deleted file mode 100644 index 43b75a19788f..000000000000 --- a/store/v2alpha1/smt/ics23.go +++ /dev/null @@ -1,124 +0,0 @@ -// Here we implement proof generation according to the ICS-23 specification: -// https://github.com/cosmos/ibc/tree/master/spec/core/ics-023-vector-commitments - -package smt - -import ( - "crypto/sha256" - "fmt" - - dbm "github.com/cosmos/cosmos-sdk/db" - - ics23 "github.com/confio/ics23/go" -) - -func createIcs23Proof(store *Store, key []byte) (*ics23.CommitmentProof, error) { - ret := &ics23.CommitmentProof{} - path := sha256.Sum256(key) - has, err := store.tree.Has(key) - if err != nil { - return nil, err - } - if has { // Membership proof - value, err := store.values.Get(path[:]) - if err != nil { - return nil, err - } - if value == nil { - return nil, fmt.Errorf("value not found for: %v", key) - } - proof, err := store.tree.Prove(key) - if err != nil { - return nil, err - } - ret.Proof = &ics23.CommitmentProof_Exist{Exist: &ics23.ExistenceProof{ - Key: path[:], - Value: value, - Leaf: ics23.SmtSpec.LeafSpec, - Path: convertInnerOps(path[:], proof.SideNodes), - }} - } else { // Non-membership - nonexist, err := toNonExistenceProof(store, path) - if err != nil { - return nil, err - } - ret.Proof = &ics23.CommitmentProof_Nonexist{Nonexist: nonexist} - } - return ret, nil -} - -func toNonExistenceProof(store *Store, path [32]byte) (*ics23.NonExistenceProof, error) { - // Seek to our neighbors via the backing DB - getNext := func(it dbm.Iterator) (*ics23.ExistenceProof, error) { - defer it.Close() - if it.Next() { - value, err := store.values.Get(it.Key()) - if err != nil { - return nil, err - } - if value == nil { - return nil, fmt.Errorf("value not found for: %v", it.Value()) - } - proof, err := store.tree.Prove(it.Value()) // pass the preimage to Prove - if err != nil { - return nil, err - } - return &ics23.ExistenceProof{ - Key: it.Key(), - Value: value, - Leaf: ics23.SmtSpec.LeafSpec, - Path: convertInnerOps(it.Key(), proof.SideNodes), - }, nil - } - return nil, nil - } - var lproof, rproof *ics23.ExistenceProof - it, err := store.preimages.ReverseIterator(nil, path[:]) - if err != nil { - return nil, err - } - lproof, err = getNext(it) - if err != nil { - return nil, err - } - it, err = store.preimages.Iterator(path[:], nil) - if err != nil { - return nil, err - } - rproof, err = getNext(it) - if err != nil { - return nil, err - } - return &ics23.NonExistenceProof{ - Key: path[:], - Left: lproof, - Right: rproof, - }, nil -} - -func convertInnerOps(path []byte, sideNodes [][]byte) []*ics23.InnerOp { - depth := len(sideNodes) - inners := make([]*ics23.InnerOp, 0, depth) - for i := 0; i < len(sideNodes); i++ { - op := &ics23.InnerOp{ - Hash: ics23.HashOp_SHA256, - Prefix: []byte{1}, - } - if getBitAtFromMSB(path, depth-1-i) == 1 { - // right child is on path - op.Prefix = append(op.Prefix, sideNodes[i]...) - } else { - op.Suffix = sideNodes[i] - } - inners = append(inners, op) - } - return inners -} - -// getBitAtFromMSB gets the bit at an offset from the most significant bit -func getBitAtFromMSB(data []byte, position int) int { - if int(data[position/8])&(1<<(8-1-uint(position)%8)) > 0 { - return 1 - } - return 0 -} diff --git a/store/v2alpha1/smt/ics23_test.go b/store/v2alpha1/smt/ics23_test.go deleted file mode 100644 index a94cc6f0a477..000000000000 --- a/store/v2alpha1/smt/ics23_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package smt_test - -import ( - "crypto/sha256" - "testing" - - ics23 "github.com/confio/ics23/go" - "github.com/stretchr/testify/assert" - - "github.com/cosmos/cosmos-sdk/db/memdb" - store "github.com/cosmos/cosmos-sdk/store/v2alpha1/smt" -) - -func TestProofICS23(t *testing.T) { - txn := memdb.NewDB().ReadWriter() - s := store.NewStore(txn) - // pick keys whose hashes begin with different bits - key00 := []byte("foo") // 00101100 = sha256(foo)[0] - key01 := []byte("bill") // 01100010 - key10 := []byte("baz") // 10111010 - key11 := []byte("bar") // 11111100 - path00 := sha256.Sum256(key00) - path01 := sha256.Sum256(key01) - path10 := sha256.Sum256(key10) - val1 := []byte("0") - val2 := []byte("1") - - s.Set(key01, val1) - - // Membership - proof, err := s.GetProofICS23(key01) - assert.NoError(t, err) - nonexist := proof.GetNonexist() - assert.Nil(t, nonexist) - exist := proof.GetExist() - assert.NotNil(t, exist) - assert.Equal(t, 0, len(exist.Path)) - assert.NoError(t, exist.Verify(ics23.SmtSpec, s.Root(), path01[:], val1)) - - // Non-membership - proof, err = s.GetProofICS23(key00) // When leaf is leftmost node - assert.NoError(t, err) - nonexist = proof.GetNonexist() - assert.NotNil(t, nonexist) - assert.Nil(t, nonexist.Left) - assert.Equal(t, path00[:], nonexist.Key) - assert.NotNil(t, nonexist.Right) - assert.Equal(t, 0, len(nonexist.Right.Path)) - assert.NoError(t, nonexist.Verify(ics23.SmtSpec, s.Root(), path00[:])) - - proof, err = s.GetProofICS23(key10) // When rightmost - assert.NoError(t, err) - nonexist = proof.GetNonexist() - assert.NotNil(t, nonexist) - assert.NotNil(t, nonexist.Left) - assert.Equal(t, 0, len(nonexist.Left.Path)) - assert.Nil(t, nonexist.Right) - assert.NoError(t, nonexist.Verify(ics23.SmtSpec, s.Root(), path10[:])) - badNonexist := nonexist - - s.Set(key11, val2) - - proof, err = s.GetProofICS23(key10) // In between two keys - assert.NoError(t, err) - nonexist = proof.GetNonexist() - assert.NotNil(t, nonexist) - assert.Equal(t, path10[:], nonexist.Key) - assert.NotNil(t, nonexist.Left) - assert.Equal(t, 1, len(nonexist.Left.Path)) - assert.NotNil(t, nonexist.Right) - assert.Equal(t, 1, len(nonexist.Right.Path)) - assert.NoError(t, nonexist.Verify(ics23.SmtSpec, s.Root(), path10[:])) - - // Make sure proofs work with a loaded store - root := s.Root() - s = store.LoadStore(txn, root) - proof, err = s.GetProofICS23(key10) - assert.NoError(t, err) - nonexist = proof.GetNonexist() - assert.Equal(t, path10[:], nonexist.Key) - assert.NotNil(t, nonexist.Left) - assert.Equal(t, 1, len(nonexist.Left.Path)) - assert.NotNil(t, nonexist.Right) - assert.Equal(t, 1, len(nonexist.Right.Path)) - assert.NoError(t, nonexist.Verify(ics23.SmtSpec, s.Root(), path10[:])) - - // Invalid proofs should fail to verify - badExist := exist // expired proof - assert.Error(t, badExist.Verify(ics23.SmtSpec, s.Root(), path01[:], val1)) - - badExist = nonexist.Left - badExist.Key = key01 // .Key must contain key path - assert.Error(t, badExist.Verify(ics23.SmtSpec, s.Root(), path01[:], val1)) - - badExist = nonexist.Left - badExist.Path[0].Prefix = []byte{0} // wrong inner node prefix - assert.Error(t, badExist.Verify(ics23.SmtSpec, s.Root(), path01[:], val1)) - - badExist = nonexist.Left - badExist.Path = []*ics23.InnerOp{} // empty path - assert.Error(t, badExist.Verify(ics23.SmtSpec, s.Root(), path01[:], val1)) - - assert.Error(t, badNonexist.Verify(ics23.SmtSpec, s.Root(), path10[:])) - - badNonexist = nonexist - badNonexist.Key = key10 - assert.Error(t, badNonexist.Verify(ics23.SmtSpec, s.Root(), path10[:])) -} diff --git a/store/v2alpha1/smt/proof.go b/store/v2alpha1/smt/proof.go deleted file mode 100644 index d247f1bf6617..000000000000 --- a/store/v2alpha1/smt/proof.go +++ /dev/null @@ -1,93 +0,0 @@ -package smt - -import ( - "bytes" - "crypto/sha256" - "encoding/gob" - "hash" - - "github.com/celestiaorg/smt" - "github.com/cosmos/cosmos-sdk/store/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/tendermint/tendermint/crypto/merkle" - tmmerkle "github.com/tendermint/tendermint/proto/tendermint/crypto" -) - -type HasherType byte - -const ( - SHA256 HasherType = iota -) - -const ( - ProofType = "smt" -) - -type ProofOp struct { - Root []byte - Key []byte - Hasher HasherType - Proof smt.SparseMerkleProof -} - -var _ merkle.ProofOperator = (*ProofOp)(nil) - -// NewProofOp returns a ProofOp for a SparseMerkleProof. -func NewProofOp(root, key []byte, hasher HasherType, proof smt.SparseMerkleProof) *ProofOp { - return &ProofOp{ - Root: root, - Key: key, - Hasher: hasher, - Proof: proof, - } -} - -func (p *ProofOp) Run(args [][]byte) ([][]byte, error) { - switch len(args) { - case 0: // non-membership proof - if !smt.VerifyProof(p.Proof, p.Root, p.Key, []byte{}, getHasher(p.Hasher)) { - return nil, sdkerrors.Wrapf(types.ErrInvalidProof, "proof did not verify absence of key: %s", p.Key) - } - case 1: // membership proof - if !smt.VerifyProof(p.Proof, p.Root, p.Key, args[0], getHasher(p.Hasher)) { - return nil, sdkerrors.Wrapf(types.ErrInvalidProof, "proof did not verify existence of key %s with given value %x", p.Key, args[0]) - } - default: - return nil, sdkerrors.Wrapf(types.ErrInvalidProof, "args must be length 0 or 1, got: %d", len(args)) - } - return [][]byte{p.Root}, nil -} - -func (p *ProofOp) GetKey() []byte { - return p.Key -} - -func (p *ProofOp) ProofOp() tmmerkle.ProofOp { - var data bytes.Buffer - enc := gob.NewEncoder(&data) - enc.Encode(p) - return tmmerkle.ProofOp{ - Type: "smt", - Key: p.Key, - Data: data.Bytes(), - } -} - -func ProofDecoder(pop tmmerkle.ProofOp) (merkle.ProofOperator, error) { - dec := gob.NewDecoder(bytes.NewBuffer(pop.Data)) - var proof ProofOp - err := dec.Decode(&proof) - if err != nil { - return nil, err - } - return &proof, nil -} - -func getHasher(hasher HasherType) hash.Hash { - switch hasher { - case SHA256: - return sha256.New() - default: - return nil - } -} diff --git a/store/v2alpha1/smt/proof_test.go b/store/v2alpha1/smt/proof_test.go deleted file mode 100644 index a5b3bf4869ec..000000000000 --- a/store/v2alpha1/smt/proof_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package smt_test - -import ( - "crypto/sha256" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/celestiaorg/smt" - "github.com/cosmos/cosmos-sdk/db/memdb" - smtstore "github.com/cosmos/cosmos-sdk/store/v2alpha1/smt" -) - -func TestProofOpInterface(t *testing.T) { - hasher := sha256.New() - nodes, values := memdb.NewDB(), memdb.NewDB() - tree := smt.NewSparseMerkleTree(nodes.ReadWriter(), values.ReadWriter(), hasher) - key := []byte("foo") - value := []byte("bar") - root, err := tree.Update(key, value) - require.NoError(t, err) - require.NotEmpty(t, root) - - proof, err := tree.Prove(key) - require.True(t, smt.VerifyProof(proof, root, key, value, hasher)) - - storeProofOp := smtstore.NewProofOp(root, key, smtstore.SHA256, proof) - require.NotNil(t, storeProofOp) - // inclusion proof - r, err := storeProofOp.Run([][]byte{value}) - assert.NoError(t, err) - assert.NotEmpty(t, r) - assert.Equal(t, root, r[0]) - - // inclusion proof - wrong value - should fail - r, err = storeProofOp.Run([][]byte{key}) - assert.Error(t, err) - assert.Empty(t, r) - - // exclusion proof - should fail - r, err = storeProofOp.Run([][]byte{}) - assert.Error(t, err) - assert.Empty(t, r) - - // invalid request - should fail - r, err = storeProofOp.Run([][]byte{key, key}) - assert.Error(t, err) - assert.Empty(t, r) - - // encode - tmProofOp := storeProofOp.ProofOp() - assert.NotNil(t, tmProofOp) - assert.Equal(t, smtstore.ProofType, tmProofOp.Type) - assert.Equal(t, key, tmProofOp.Key, key) - assert.NotEmpty(t, tmProofOp.Data) - - // decode - decoded, err := smtstore.ProofDecoder(tmProofOp) - assert.NoError(t, err) - assert.NotNil(t, decoded) - assert.Equal(t, key, decoded.GetKey()) - - // run proof after decoding - r, err = decoded.Run([][]byte{value}) - assert.NoError(t, err) - assert.NotEmpty(t, r) - assert.Equal(t, root, r[0]) -} diff --git a/store/v2alpha1/smt/store.go b/store/v2alpha1/smt/store.go deleted file mode 100644 index 3965eae18dbe..000000000000 --- a/store/v2alpha1/smt/store.go +++ /dev/null @@ -1,143 +0,0 @@ -package smt - -import ( - "crypto/sha256" - "errors" - - dbm "github.com/cosmos/cosmos-sdk/db" - "github.com/cosmos/cosmos-sdk/db/prefix" - "github.com/cosmos/cosmos-sdk/store/types" - - "github.com/celestiaorg/smt" - ics23 "github.com/confio/ics23/go" - tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" -) - -var ( - _ types.BasicKVStore = (*Store)(nil) - _ smt.MapStore = (dbMapStore{}) -) - -var ( - nodesPrefix = []byte{0} - valuesPrefix = []byte{1} - preimagesPrefix = []byte{2} - - errKeyEmpty = errors.New("key is empty or nil") - errValueNil = errors.New("value is nil") -) - -// Store Implements types.KVStore and CommitKVStore. -type Store struct { - tree *smt.SparseMerkleTree - values dbm.DBReadWriter - // Map hashed keys back to preimage - preimages dbm.DBReadWriter -} - -// An smt.MapStore that wraps Get to raise smt.InvalidKeyError; -// smt.SparseMerkleTree expects this error to be returned when a key is not found -type dbMapStore struct{ dbm.DBReadWriter } - -func NewStore(db dbm.DBReadWriter) *Store { - nodes := prefix.NewPrefixReadWriter(db, nodesPrefix) - values := prefix.NewPrefixReadWriter(db, valuesPrefix) - preimages := prefix.NewPrefixReadWriter(db, preimagesPrefix) - return &Store{ - tree: smt.NewSparseMerkleTree(dbMapStore{nodes}, dbMapStore{values}, sha256.New()), - values: values, - preimages: preimages, - } -} - -func LoadStore(db dbm.DBReadWriter, root []byte) *Store { - nodes := prefix.NewPrefixReadWriter(db, nodesPrefix) - values := prefix.NewPrefixReadWriter(db, valuesPrefix) - preimages := prefix.NewPrefixReadWriter(db, preimagesPrefix) - return &Store{ - tree: smt.ImportSparseMerkleTree(dbMapStore{nodes}, dbMapStore{values}, sha256.New(), root), - values: values, - preimages: preimages, - } -} - -func (s *Store) GetProof(key []byte) (*tmcrypto.ProofOps, error) { - if len(key) == 0 { - return nil, errKeyEmpty - } - proof, err := s.tree.Prove(key) - if err != nil { - return nil, err - } - op := NewProofOp(s.tree.Root(), key, SHA256, proof) - return &tmcrypto.ProofOps{Ops: []tmcrypto.ProofOp{op.ProofOp()}}, nil -} - -func (s *Store) GetProofICS23(key []byte) (*ics23.CommitmentProof, error) { - return createIcs23Proof(s, key) -} - -func (s *Store) Root() []byte { return s.tree.Root() } - -// BasicKVStore interface below: - -// Get returns nil iff key doesn't exist. Panics on nil or empty key. -func (s *Store) Get(key []byte) []byte { - if len(key) == 0 { - panic(errKeyEmpty) - } - val, err := s.tree.Get(key) - if err != nil { - panic(err) - } - return val -} - -// Has checks if a key exists. Panics on nil or empty key. -func (s *Store) Has(key []byte) bool { - if len(key) == 0 { - panic(errKeyEmpty) - } - has, err := s.tree.Has(key) - if err != nil { - panic(err) - } - return has -} - -// Set sets the key. Panics on nil key or value. -func (s *Store) Set(key []byte, value []byte) { - if len(key) == 0 { - panic(errKeyEmpty) - } - if value == nil { - panic(errValueNil) - } - _, err := s.tree.Update(key, value) - if err != nil { - panic(err) - } - path := sha256.Sum256(key) - s.preimages.Set(path[:], key) -} - -// Delete deletes the key. Panics on nil key. -func (s *Store) Delete(key []byte) { - if len(key) == 0 { - panic(errKeyEmpty) - } - _, _ = s.tree.Delete(key) - path := sha256.Sum256(key) - s.preimages.Delete(path[:]) -} - -func (ms dbMapStore) Get(key []byte) ([]byte, error) { - val, err := ms.DBReadWriter.Get(key) - if err != nil { - return nil, err - } - if val == nil { - return nil, &smt.InvalidKeyError{Key: key} - } - return val, nil -} diff --git a/store/v2alpha1/smt/store_test.go b/store/v2alpha1/smt/store_test.go deleted file mode 100644 index 2ad50be53dda..000000000000 --- a/store/v2alpha1/smt/store_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package smt_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/cosmos/cosmos-sdk/db/memdb" - store "github.com/cosmos/cosmos-sdk/store/v2alpha1/smt" -) - -func TestGetSetHasDelete(t *testing.T) { - db := memdb.NewDB() - s := store.NewStore(db.ReadWriter()) - - s.Set([]byte("foo"), []byte("bar")) - assert.Equal(t, []byte("bar"), s.Get([]byte("foo"))) - assert.Equal(t, true, s.Has([]byte("foo"))) - s.Delete([]byte("foo")) - assert.Equal(t, false, s.Has([]byte("foo"))) - - assert.Panics(t, func() { s.Get(nil) }, "Get(nil key) should panic") - assert.Panics(t, func() { s.Get([]byte{}) }, "Get(empty key) should panic") - assert.Panics(t, func() { s.Has(nil) }, "Has(nil key) should panic") - assert.Panics(t, func() { s.Has([]byte{}) }, "Has(empty key) should panic") - assert.Panics(t, func() { s.Set(nil, []byte("value")) }, "Set(nil key) should panic") - assert.Panics(t, func() { s.Set([]byte{}, []byte("value")) }, "Set(empty key) should panic") - assert.Panics(t, func() { s.Set([]byte("key"), nil) }, "Set(nil value) should panic") -} - -func TestLoadStore(t *testing.T) { - db := memdb.NewDB() - txn := db.ReadWriter() - s := store.NewStore(txn) - - s.Set([]byte{0}, []byte{0}) - s.Set([]byte{1}, []byte{1}) - s.Delete([]byte{1}) - root := s.Root() - - s = store.LoadStore(txn, root) - assert.Equal(t, []byte{0}, s.Get([]byte{0})) - assert.False(t, s.Has([]byte{1})) - s.Set([]byte{2}, []byte{2}) - assert.NotEqual(t, root, s.Root()) -} diff --git a/store/v2alpha1/transient/store.go b/store/v2alpha1/transient/store.go deleted file mode 100644 index 586cc4e9d36e..000000000000 --- a/store/v2alpha1/transient/store.go +++ /dev/null @@ -1,47 +0,0 @@ -package transient - -import ( - dbm "github.com/cosmos/cosmos-sdk/db" - "github.com/cosmos/cosmos-sdk/db/memdb" - pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" - "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/dbadapter" -) - -var ( - _ types.KVStore = (*Store)(nil) - _ types.Committer = (*Store)(nil) -) - -// Store is a wrapper for a memory store which does not persist data. -type Store struct { - dbadapter.Store - conn dbm.DBConnection -} - -// NewStore constructs a new transient store. -func NewStore() *Store { - db := memdb.NewDB() - return &Store{ - Store: dbadapter.Store{DB: db.ReadWriter()}, - conn: db, - } -} - -// Implements Store. -func (ts *Store) GetStoreType() types.StoreType { - return types.StoreTypeTransient -} - -// Implements CommitStore -// Commit cleans up Store. -func (ts *Store) Commit() (id types.CommitID) { - ts.DB.Discard() - ts.Store = dbadapter.Store{DB: ts.conn.ReadWriter()} - return -} - -func (ts *Store) SetPruning(pruningtypes.PruningOptions) {} -func (ts *Store) GetPruning() pruningtypes.PruningOptions { return pruningtypes.PruningOptions{} } - -func (ts *Store) LastCommitID() (id types.CommitID) { return } diff --git a/store/v2alpha1/transient/store_test.go b/store/v2alpha1/transient/store_test.go deleted file mode 100644 index 272b7a34a8bc..000000000000 --- a/store/v2alpha1/transient/store_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package transient_test - -import ( - "bytes" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/store/v2alpha1/transient" -) - -var k, v = []byte("hello"), []byte("world") - -func TestTransientStore(t *testing.T) { - tstore := transient.NewStore() - require.Nil(t, tstore.Get(k)) - tstore.Set(k, v) - require.Equal(t, v, tstore.Get(k)) - tstore.Commit() - require.Nil(t, tstore.Get(k)) - - emptyCommitID := tstore.LastCommitID() - require.Equal(t, emptyCommitID.Version, int64(0)) - require.True(t, bytes.Equal(emptyCommitID.Hash, nil)) - require.Equal(t, types.StoreTypeTransient, tstore.GetStoreType()) -} diff --git a/store/v2alpha1/types.go b/store/v2alpha1/types.go deleted file mode 100644 index 44c97ff4f52d..000000000000 --- a/store/v2alpha1/types.go +++ /dev/null @@ -1,111 +0,0 @@ -package types - -import ( - "io" - - snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" - v1 "github.com/cosmos/cosmos-sdk/store/types" -) - -// Re-export relevant original store types -type ( - StoreKey = v1.StoreKey - StoreType = v1.StoreType - CommitID = v1.CommitID - StoreUpgrades = v1.StoreUpgrades - StoreRename = v1.StoreRename - Iterator = v1.Iterator - - TraceContext = v1.TraceContext - WriteListener = v1.WriteListener - - BasicKVStore = v1.BasicKVStore - KVStore = v1.KVStore - Committer = v1.Committer - CommitKVStore = v1.CommitKVStore - CacheKVStore = v1.CacheKVStore - Queryable = v1.Queryable - CacheWrap = v1.CacheWrap - - KVStoreKey = v1.KVStoreKey - MemoryStoreKey = v1.MemoryStoreKey - TransientStoreKey = v1.TransientStoreKey - - KVPair = v1.KVPair - StoreKVPair = v1.StoreKVPair -) - -// Re-export relevant constants, values and utility functions -const ( - StoreTypeMemory = v1.StoreTypeMemory - StoreTypeTransient = v1.StoreTypeTransient - StoreTypeDB = v1.StoreTypeDB - StoreTypeSMT = v1.StoreTypeSMT - StoreTypePersistent = v1.StoreTypePersistent -) - -var ( - NewKVStoreKey = v1.NewKVStoreKey - PrefixEndBytes = v1.PrefixEndBytes - KVStorePrefixIterator = v1.KVStorePrefixIterator - KVStoreReversePrefixIterator = v1.KVStoreReversePrefixIterator - - NewStoreKVPairWriteListener = v1.NewStoreKVPairWriteListener - - ProofOpSMTCommitment = v1.ProofOpSMTCommitment - ProofOpSimpleMerkleCommitment = v1.ProofOpSimpleMerkleCommitment - - CommitmentOpDecoder = v1.CommitmentOpDecoder - ProofOpFromMap = v1.ProofOpFromMap - NewSmtCommitmentOp = v1.NewSmtCommitmentOp -) - -// BasicMultiStore defines a minimal interface for accessing root state. -type BasicMultiStore interface { - // Returns a KVStore which has access only to the namespace of the StoreKey. - // Panics if the key is not found in the schema. - GetKVStore(StoreKey) KVStore -} - -// mixin interface for trace and listen methods -type rootStoreTraceListen interface { - TracingEnabled() bool - SetTracer(w io.Writer) - SetTraceContext(TraceContext) - ListeningEnabled(key StoreKey) bool - AddListeners(key StoreKey, listeners []WriteListener) -} - -// CommitMultiStore defines a complete interface for persistent root state, including -// (read-only) access to past versions, pruning, trace/listen, and state snapshots. -type CommitMultiStore interface { - BasicMultiStore - rootStoreTraceListen - Committer - snapshottypes.Snapshotter - - // Gets a read-only view of the store at a specific version. - // Returns an error if the version is not found. - GetVersion(int64) (BasicMultiStore, error) - // Closes the store and all backing transactions. - Close() error - // Returns a branched whose modifications are later merged back in. - CacheMultiStore() CacheMultiStore - // Defines the minimum version number that can be saved by this store. - SetInitialVersion(uint64) error -} - -// CacheMultiStore defines a branch of the root state which can be written back to the source store. -type CacheMultiStore interface { - BasicMultiStore - rootStoreTraceListen - - // Returns a branched whose modifications are later merged back in. - CacheMultiStore() CacheMultiStore - // Write all cached changes back to the source store. Note: this overwrites any intervening changes. - Write() -} - -// MultiStorePersistentCache provides inter-block (persistent) caching capabilities for a CommitMultiStore. -// TODO: placeholder. Implement and redefine this -type MultiStorePersistentCache = v1.MultiStorePersistentCache From 3aaaf2cc7df748ffd8ff4f57688ed1000cf6cbfe Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 24 Feb 2023 17:26:12 +0100 Subject: [PATCH 04/47] build: use cometbft in v0.46 (#15090) --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/cosmovisor-release.yml | 2 +- .github/workflows/release.yml | 4 +- .github/workflows/sims.yml | 10 +- .github/workflows/test-race.yml | 8 +- .github/workflows/test.yml | 14 +- CHANGELOG.md | 7 +- Dockerfile | 2 +- Makefile | 2 +- README.md | 2 +- RELEASE_NOTES.md | 18 +- baseapp/baseapp_test.go | 18 +- contrib/devtools/Dockerfile | 2 +- contrib/images/simd-dlv/Dockerfile | 2 +- contrib/images/simd-env/Dockerfile | 2 +- contrib/rosetta/rosetta-ci/Dockerfile | 2 +- contrib/rosetta/rosetta-cli/Dockerfile | 2 +- go.mod | 36 ++-- go.sum | 231 ++++------------------- proto/tendermint/abci/types.proto | 111 ++++++----- proto/tendermint/crypto/keys.proto | 2 +- proto/tendermint/types/evidence.proto | 2 +- proto/tendermint/types/params.proto | 3 +- proto/tendermint/types/types.proto | 42 +++-- scripts/protocgen.sh | 2 +- server/rollback.go | 2 +- server/start.go | 2 +- server/util.go | 2 +- snapshots/helpers_test.go | 1 - snapshots/manager_test.go | 2 +- snapshots/stream.go | 4 - snapshots/types/format.go | 2 +- store/rootmulti/snapshot_test.go | 2 +- store/rootmulti/store.go | 2 +- 34 files changed, 206 insertions(+), 341 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 968b24c94448..67de44c531e2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/.github/workflows/cosmovisor-release.yml b/.github/workflows/cosmovisor-release.yml index 1a7100d5a780..f28ca050bfe7 100644 --- a/.github/workflows/cosmovisor-release.yml +++ b/.github/workflows/cosmovisor-release.yml @@ -13,7 +13,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 # get 'v*.*.*' part from 'cosmovisor/v*.*.*' and save to $GITHUB_ENV - name: Set env run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/cosmovisor/}" >> $GITHUB_ENV diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 544fcb1b4b24..23f965327abc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Unshallow run: git fetch --prune --unshallow - name: Create release @@ -42,4 +42,4 @@ jobs: SLACK_MESSAGE: "@channel :point_right: https://github.com/cosmos/cosmos-sdk/releases/tag/${{ github.ref_name }}" SLACK_FOOTER: "" SLACK_LINK_NAMES: true - MSG_MINIMAL: true \ No newline at end of file + MSG_MINIMAL: true diff --git a/.github/workflows/sims.yml b/.github/workflows/sims.yml index d7e97454a7b5..6a6e3723f6da 100644 --- a/.github/workflows/sims.yml +++ b/.github/workflows/sims.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - run: make build @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - name: Install runsim @@ -51,7 +51,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - uses: actions/cache@v3 @@ -70,7 +70,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - uses: actions/cache@v3 @@ -89,7 +89,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - uses: actions/cache@v3 diff --git a/.github/workflows/test-race.yml b/.github/workflows/test-race.yml index 1b92805875d2..642ca23bbdcf 100644 --- a/.github/workflows/test-race.yml +++ b/.github/workflows/test-race.yml @@ -24,7 +24,7 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - name: install tparse @@ -40,7 +40,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 id: git_diff with: @@ -60,7 +60,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Create a file with all core Cosmos SDK pkgs run: go list ./... > pkgs.txt - name: Split pkgs into 4 files @@ -94,7 +94,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 with: PATTERNS: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b5234cc89eba..2b1a8bc6008e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 id: git_diff with: @@ -48,7 +48,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 id: git_diff with: @@ -71,7 +71,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Create a file with all core Cosmos SDK pkgs run: go list ./... > pkgs.txt - name: Split pkgs into 4 files @@ -105,7 +105,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 with: PATTERNS: | @@ -201,7 +201,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - uses: technote-space/get-diff-action@v6.0.1 id: git_diff with: @@ -224,7 +224,7 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - name: Install runsim @@ -241,7 +241,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 - name: Display go version run: go version - uses: technote-space/get-diff-action@v6.0.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d752bb18aa2..c4bec9497aa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,11 +37,16 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] -## Improvements +### Improvements +* (deps) Migrate to [CometBFT](https://github.com/cometbft/cometbft). Follow the instructions in the [release notes](./RELEASE_NOTES.md). * (store) [#15152](https://github.com/cosmos/cosmos-sdk/pull/15152) Remove unmaintained and experimental `store/v2alpha1`. * (store) [#14410](https://github.com/cosmos/cosmos-sdk/pull/14410) `rootmulti.Store.loadVersion` has validation to check if all the module stores' height is correct, it will error if any module store has incorrect height. +### Bug Fixes + +* (snapshot) [#13400](https://github.com/cosmos/cosmos-sdk/pull/13400) Fix snapshot checksum issue in Go 1.19. + ## [v0.46.10](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.10) - 2022-02-16 ### Improvements diff --git a/Dockerfile b/Dockerfile index 026f222c594a..69718406a317 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ # > docker run -it -p 26657:26657 -p 26656:26656 -v ~/.simappcli:/root/.simapp simapp simd keys add foo # > docker run -it -p 26657:26657 -p 26656:26656 -v ~/.simappcli:/root/.simapp simapp simd keys list # TODO: demo connecting rest-server (or is this in server now?) -FROM golang:1.18-alpine AS build-env +FROM golang:1.19-alpine AS build-env # Install minimum necessary dependencies ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 diff --git a/Makefile b/Makefile index 442598e374f7..1bf7dbef792c 100644 --- a/Makefile +++ b/Makefile @@ -430,7 +430,7 @@ proto-lint: proto-check-breaking: @$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main -TM_URL = https://raw.githubusercontent.com/tendermint/tendermint/v0.34.22/proto/tendermint +TM_URL = https://raw.githubusercontent.com/cometbft/cometbft/v0.34.27-alpha.2/proto/tendermint TM_CRYPTO_TYPES = proto/tendermint/crypto TM_ABCI_TYPES = proto/tendermint/abci diff --git a/README.md b/README.md index c00ce7ee656c..02f12fd6173d 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The Cosmos SDK is a framework for building blockchain applications. [Tendermint **WARNING**: The Cosmos SDK has mostly stabilized, but we are still making some breaking changes. -**Note**: Requires [Go 1.18+](https://go.dev/dl) +**Note**: Requires [Go 1.19+](https://go.dev/dl) ## Quick Start diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c5f8b0140af2..c7f064eea7cc 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,19 @@ -# Cosmos SDK v0.46.10 Release Notes +# Cosmos SDK v0.46.11 Release Notes -This release improves CPU profiling when using the `--cpu-profile` flag, and fixes a possible way to DoS a node. +This release includes the migration to CometBFT. This migration should be not breaking. +From `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your application: + +```go +// use cometbft +replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 +``` + +A more complete migration is happening in Cosmos SDK v0.47. + +Additionally, the SDK sets its minimum version to Go 1.19. +This is not because the SDK uses new Go 1.19 functionalities, but because we recommend chains as well to upgrade to Go 1.19 because Go 1.18 is not supported anymore. +We recommend applications to perform a **coordinated upgrade** when migrating from Go 1.18 to Go 1.19. Please see the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/CHANGELOG.md) for an exhaustive list of changes. -Full Commit History: https://github.com/cosmos/cosmos-sdk/compare/v0.46.9...v0.46.10 +**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.10...v0.46.11 diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index bf5d6b213e8d..99e4541b5ea3 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -1792,7 +1792,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 2, Chunks: 5}, + {Height: 20, Format: snapshottypes.CurrentFormat, Chunks: 5}, }, }, "prune everything with snapshot": { @@ -1804,7 +1804,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningEverything), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 2, Chunks: 5}, + {Height: 20, Format: snapshottypes.CurrentFormat, Chunks: 5}, }, }, "default pruning with snapshot": { @@ -1816,7 +1816,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningDefault), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 2, Chunks: 5}, + {Height: 20, Format: snapshottypes.CurrentFormat, Chunks: 5}, }, }, "custom": { @@ -1828,8 +1828,8 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewCustomPruningOptions(12, 12), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 25, Format: 2, Chunks: 6}, - {Height: 20, Format: 2, Chunks: 5}, + {Height: 25, Format: snapshottypes.CurrentFormat, Chunks: 6}, + {Height: 20, Format: snapshottypes.CurrentFormat, Chunks: 5}, }, }, "no snapshots": { @@ -1850,9 +1850,9 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 9, Format: 2, Chunks: 2}, - {Height: 6, Format: 2, Chunks: 2}, - {Height: 3, Format: 2, Chunks: 1}, + {Height: 9, Format: snapshottypes.CurrentFormat, Chunks: 2}, + {Height: 6, Format: snapshottypes.CurrentFormat, Chunks: 2}, + {Height: 3, Format: snapshottypes.CurrentFormat, Chunks: 1}, }, }, } @@ -1928,7 +1928,7 @@ func TestLoadSnapshotChunk(t *testing.T) { }{ "Existing snapshot": {2, snapshottypes.CurrentFormat, 1, false}, "Missing height": {100, snapshottypes.CurrentFormat, 1, true}, - "Missing format": {2, 3, 1, true}, + "Missing format": {2, snapshottypes.CurrentFormat + 1, 1, true}, "Missing chunk": {2, snapshottypes.CurrentFormat, 9, true}, "Zero height": {0, snapshottypes.CurrentFormat, 1, true}, "Zero format": {2, 0, 1, true}, diff --git a/contrib/devtools/Dockerfile b/contrib/devtools/Dockerfile index 05bed5ac81bf..213950ec9e07 100644 --- a/contrib/devtools/Dockerfile +++ b/contrib/devtools/Dockerfile @@ -4,7 +4,7 @@ FROM bufbuild/buf:1.1.0 as BUILDER -FROM golang:1.18-alpine +FROM golang:1.19-alpine RUN apk add --no-cache \ nodejs \ diff --git a/contrib/images/simd-dlv/Dockerfile b/contrib/images/simd-dlv/Dockerfile index e88fc4da0d9e..78807305e3a0 100644 --- a/contrib/images/simd-dlv/Dockerfile +++ b/contrib/images/simd-dlv/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine AS build +FROM golang:1.19-alpine AS build RUN apk add build-base git linux-headers libc-dev RUN go install github.com/go-delve/delve/cmd/dlv@latest diff --git a/contrib/images/simd-env/Dockerfile b/contrib/images/simd-env/Dockerfile index 0d3565375837..aaeab8c5e5b7 100644 --- a/contrib/images/simd-env/Dockerfile +++ b/contrib/images/simd-env/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine AS build +FROM golang:1.19-alpine AS build RUN apk add build-base git linux-headers diff --git a/contrib/rosetta/rosetta-ci/Dockerfile b/contrib/rosetta/rosetta-ci/Dockerfile index d4cfc58528e9..a333fdc01b73 100644 --- a/contrib/rosetta/rosetta-ci/Dockerfile +++ b/contrib/rosetta/rosetta-ci/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine as build +FROM golang:1.19-alpine as build RUN apk add --no-cache tar git diff --git a/contrib/rosetta/rosetta-cli/Dockerfile b/contrib/rosetta/rosetta-cli/Dockerfile index da6ef2879239..f4fc15d9bced 100644 --- a/contrib/rosetta/rosetta-cli/Dockerfile +++ b/contrib/rosetta/rosetta-cli/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine as build +FROM golang:1.19-alpine as build RUN apk add git gcc libc-dev --no-cache diff --git a/go.mod b/go.mod index 59dbcc12dc13..0d6a1b9558ac 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -go 1.18 +go 1.19 module github.com/cosmos/cosmos-sdk @@ -48,23 +48,24 @@ require ( github.com/spf13/viper v1.13.0 github.com/stretchr/testify v1.8.1 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.24 + github.com/tendermint/tendermint v0.34.27 github.com/tendermint/tm-db v0.6.7 github.com/tidwall/btree v1.5.0 golang.org/x/crypto v0.5.0 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e - google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a - google.golang.org/grpc v1.50.1 + google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 + google.golang.org/grpc v1.52.0 google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 pgregory.net/rapid v0.4.7 sigs.k8s.io/yaml v1.3.0 ) require ( - cloud.google.com/go v0.102.1 // indirect - cloud.google.com/go/compute v1.7.0 // indirect - cloud.google.com/go/iam v0.4.0 // indirect - cloud.google.com/go/storage v1.22.1 // indirect + cloud.google.com/go v0.105.0 // indirect + cloud.google.com/go/compute v1.12.1 // indirect + cloud.google.com/go/compute/metadata v0.2.1 // indirect + cloud.google.com/go/iam v0.7.0 // indirect + cloud.google.com/go/storage v1.27.0 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect @@ -75,6 +76,7 @@ require ( github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cometbft/cometbft-db v0.7.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect @@ -95,12 +97,11 @@ require ( github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/btree v1.0.1 // indirect + github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/orderedcode v0.0.1 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect - github.com/googleapis/gax-go/v2 v2.4.0 // indirect - github.com/googleapis/go-type-adapters v1.0.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect @@ -137,18 +138,19 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/ulikunitz/xz v0.5.8 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/net v0.5.0 // indirect - golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 // indirect + golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/sys v0.4.0 // indirect golang.org/x/term v0.4.0 // indirect golang.org/x/text v0.6.0 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect - google.golang.org/api v0.93.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/api v0.102.0 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -167,8 +169,8 @@ replace ( github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/jhump/protoreflect => github.com/jhump/protoreflect v1.9.0 - // use informal system fork of tendermint - github.com/tendermint/tendermint => github.com/informalsystems/tendermint v0.34.26 + // use cometbft + github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27-alpha.2 ) retract ( diff --git a/go.sum b/go.sum index 18465df7d274..94de6d3ab869 100644 --- a/go.sum +++ b/go.sum @@ -19,21 +19,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1 h1:vpK6iQWv/2uUeFJth4/cBHsQAGjn1iIE6AAlxipRaA0= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -41,18 +28,15 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0 h1:v/k9Eueb8aAJ0vZuxKMrgm6kPhCLZU9HxFU+AFDs9Uk= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.4.0 h1:YBYU00SCDzZJdHqVc4I5d6lsklcYIjQZa1YmEz4jlSE= -cloud.google.com/go/iam v0.4.0/go.mod h1:cbaZxyScUhxl7ZAkNWiALgihfP75wS/fUsVNaa1r3vA= +cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -63,8 +47,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1 h1:F6IlQJZrZM++apn9V5/VfS3gbTUYg98PS3EMQAzqtfg= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= @@ -203,12 +187,6 @@ github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3h github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -216,6 +194,10 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= github.com/coinbase/rosetta-sdk-go v0.7.9/go.mod h1:0/knutI7XGVqXmmH4OQD8OckFrbQ8yMsUZTG7FXCR2M= +github.com/cometbft/cometbft v0.34.27-alpha.2 h1:ERW9qPlaHjshc6BuCAc5yfXcIWuDKAjGLCzJvQQ3YlM= +github.com/cometbft/cometbft v0.34.27-alpha.2/go.mod h1:6tEDwldPfO1ynAd9kx8j808atUVY0jUAJ18l3glfpuM= +github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= +github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= @@ -306,10 +288,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= @@ -404,7 +382,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -423,7 +400,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -433,8 +409,8 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -448,8 +424,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -461,7 +435,6 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -474,11 +447,6 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -486,19 +454,12 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= @@ -597,8 +558,6 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/informalsystems/tendermint v0.34.26 h1:89XvVexAy62geGWxmDmdmmJvfindx+Su2oTuwfSWMeU= -github.com/informalsystems/tendermint v0.34.26/go.mod h1:q3uAZ/t5+MblQhFuHSd4flqaLDx7iUtWpwWbwvHAFhs= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -946,6 +905,8 @@ github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= @@ -1009,7 +970,6 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1073,7 +1033,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1133,9 +1092,7 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1143,11 +1100,6 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1159,19 +1111,10 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 h1:+jnHzr9VPj32ykQVai5DNahi9+NSp7yYuCsl5eAQtL0= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1183,7 +1126,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1245,47 +1187,26 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1372,19 +1293,14 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= @@ -1411,28 +1327,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.93.0 h1:T2xt9gi0gHdxdnRkVQhT8mIvPaXKNsDNWz+L696M66M= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1485,54 +1381,9 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a h1:GH6UPn3ixhWcKDhpnEC55S75cerLPdpp3hrhfKYjZgw= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1557,23 +1408,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= +google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1588,7 +1424,6 @@ google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX7 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk= google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/proto/tendermint/abci/types.proto b/proto/tendermint/abci/types.proto index bcc7b036e290..44f86112938e 100644 --- a/proto/tendermint/abci/types.proto +++ b/proto/tendermint/abci/types.proto @@ -58,12 +58,13 @@ message RequestSetOption { } message RequestInitChain { - google.protobuf.Timestamp time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; - string chain_id = 2; - ConsensusParams consensus_params = 3; - repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; - bytes app_state_bytes = 5; - int64 initial_height = 6; + google.protobuf.Timestamp time = 1 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 2; + ConsensusParams consensus_params = 3; + repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; + int64 initial_height = 6; } message RequestQuery { @@ -105,8 +106,8 @@ message RequestListSnapshots {} // offers a snapshot to the application message RequestOfferSnapshot { - Snapshot snapshot = 1; // snapshot offered by peers - bytes app_hash = 2; // light client-verified app hash for snapshot height + Snapshot snapshot = 1; // snapshot offered by peers + bytes app_hash = 2; // light client-verified app hash for snapshot height } // loads a snapshot chunk @@ -185,8 +186,8 @@ message ResponseInitChain { message ResponseQuery { uint32 code = 1; // bytes data = 2; // use "value" instead. - string log = 3; // nondeterministic - string info = 4; // nondeterministic + string log = 3; // nondeterministic + string info = 4; // nondeterministic int64 index = 5; bytes key = 6; bytes value = 7; @@ -196,22 +197,24 @@ message ResponseQuery { } message ResponseBeginBlock { - repeated Event events = 1 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + repeated Event events = 1 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; } message ResponseCheckTx { uint32 code = 1; bytes data = 2; - string log = 3; // nondeterministic - string info = 4; // nondeterministic + string log = 3; // nondeterministic + string info = 4; // nondeterministic int64 gas_wanted = 5 [json_name = "gas_wanted"]; int64 gas_used = 6 [json_name = "gas_used"]; - repeated Event events = 7 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; - string codespace = 8; - string sender = 9; - int64 priority = 10; + repeated Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + string codespace = 8; + string sender = 9; + int64 priority = 10; - // mempool_error is set by Tendermint. + // mempool_error is set by CometBFT. // ABCI applictions creating a ResponseCheckTX should not set mempool_error. string mempool_error = 11; } @@ -219,20 +222,22 @@ message ResponseCheckTx { message ResponseDeliverTx { uint32 code = 1; bytes data = 2; - string log = 3; // nondeterministic - string info = 4; // nondeterministic + string log = 3; // nondeterministic + string info = 4; // nondeterministic int64 gas_wanted = 5 [json_name = "gas_wanted"]; int64 gas_used = 6 [json_name = "gas_used"]; - repeated Event events = 7 - [(gogoproto.nullable) = false, - (gogoproto.jsontag) = "events,omitempty"]; // nondeterministic + repeated Event events = 7 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; // nondeterministic string codespace = 8; } message ResponseEndBlock { repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; ConsensusParams consensus_param_updates = 2; - repeated Event events = 3 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + repeated Event events = 3 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; } message ResponseCommit { @@ -249,12 +254,12 @@ message ResponseOfferSnapshot { Result result = 1; enum Result { - UNKNOWN = 0; // Unknown result, abort all snapshot restoration - ACCEPT = 1; // Snapshot accepted, apply chunks - ABORT = 2; // Abort all snapshot restoration - REJECT = 3; // Reject this specific snapshot, try others - REJECT_FORMAT = 4; // Reject all snapshots of this format, try others - REJECT_SENDER = 5; // Reject all snapshots from the sender(s), try others + UNKNOWN = 0; // Unknown result, abort all snapshot restoration + ACCEPT = 1; // Snapshot accepted, apply chunks + ABORT = 2; // Abort all snapshot restoration + REJECT = 3; // Reject this specific snapshot, try others + REJECT_FORMAT = 4; // Reject all snapshots of this format, try others + REJECT_SENDER = 5; // Reject all snapshots from the sender(s), try others } } @@ -264,16 +269,16 @@ message ResponseLoadSnapshotChunk { message ResponseApplySnapshotChunk { Result result = 1; - repeated uint32 refetch_chunks = 2; // Chunks to refetch and reapply - repeated string reject_senders = 3; // Chunk senders to reject and ban + repeated uint32 refetch_chunks = 2; // Chunks to refetch and reapply + repeated string reject_senders = 3; // Chunk senders to reject and ban enum Result { - UNKNOWN = 0; // Unknown result, abort all snapshot restoration - ACCEPT = 1; // Chunk successfully accepted - ABORT = 2; // Abort all snapshot restoration - RETRY = 3; // Retry chunk (combine with refetch and reject) - RETRY_SNAPSHOT = 4; // Retry snapshot (combine with refetch and reject) - REJECT_SNAPSHOT = 5; // Reject this snapshot, try others + UNKNOWN = 0; // Unknown result, abort all snapshot restoration + ACCEPT = 1; // Chunk successfully accepted + ABORT = 2; // Abort all snapshot restoration + RETRY = 3; // Retry chunk (combine with refetch and reject) + RETRY_SNAPSHOT = 4; // Retry snapshot (combine with refetch and reject) + REJECT_SNAPSHOT = 5; // Reject this snapshot, try others } } @@ -307,14 +312,17 @@ message LastCommitInfo { // Later, transactions may be queried using these events. message Event { string type = 1; - repeated EventAttribute attributes = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "attributes,omitempty"]; + repeated EventAttribute attributes = 2 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "attributes,omitempty" + ]; } // EventAttribute is a single key-value pair, associated with an event. message EventAttribute { bytes key = 1; bytes value = 2; - bool index = 3; // nondeterministic + bool index = 3; // nondeterministic } // TxResult contains results of executing the transaction. @@ -332,9 +340,9 @@ message TxResult { // Validator message Validator { - bytes address = 1; // The first 20 bytes of SHA256(public key) + bytes address = 1; // The first 20 bytes of SHA256(public key) // PubKey pub_key = 2 [(gogoproto.nullable)=false]; - int64 power = 3; // The voting power + int64 power = 3; // The voting power } // ValidatorUpdate @@ -362,7 +370,8 @@ message Evidence { // The height when the offense occurred int64 height = 3; // The corresponding time where the offense occurred - google.protobuf.Timestamp time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + google.protobuf.Timestamp time = 4 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; // Total voting power of the validator set in case the ABCI application does // not store historical validators. // https://github.com/tendermint/tendermint/issues/4581 @@ -373,11 +382,11 @@ message Evidence { // State Sync Types message Snapshot { - uint64 height = 1; // The height at which the snapshot was taken - uint32 format = 2; // The application-specific snapshot format - uint32 chunks = 3; // Number of chunks in the snapshot - bytes hash = 4; // Arbitrary snapshot hash, equal only if identical - bytes metadata = 5; // Arbitrary application metadata + uint64 height = 1; // The height at which the snapshot was taken + uint32 format = 2; // The application-specific snapshot format + uint32 chunks = 3; // Number of chunks in the snapshot + bytes hash = 4; // Arbitrary snapshot hash, equal only if identical + bytes metadata = 5; // Arbitrary application metadata } //---------------------------------------- @@ -397,6 +406,8 @@ service ABCIApplication { rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); rpc ListSnapshots(RequestListSnapshots) returns (ResponseListSnapshots); rpc OfferSnapshot(RequestOfferSnapshot) returns (ResponseOfferSnapshot); - rpc LoadSnapshotChunk(RequestLoadSnapshotChunk) returns (ResponseLoadSnapshotChunk); - rpc ApplySnapshotChunk(RequestApplySnapshotChunk) returns (ResponseApplySnapshotChunk); + rpc LoadSnapshotChunk(RequestLoadSnapshotChunk) + returns (ResponseLoadSnapshotChunk); + rpc ApplySnapshotChunk(RequestApplySnapshotChunk) + returns (ResponseApplySnapshotChunk); } diff --git a/proto/tendermint/crypto/keys.proto b/proto/tendermint/crypto/keys.proto index 16fd7adf3eef..5b94ddaec9ac 100644 --- a/proto/tendermint/crypto/keys.proto +++ b/proto/tendermint/crypto/keys.proto @@ -5,7 +5,7 @@ option go_package = "github.com/tendermint/tendermint/proto/tendermint/crypto"; import "gogoproto/gogo.proto"; -// PublicKey defines the keys available for use with Tendermint Validators +// PublicKey defines the keys available for use with Validators message PublicKey { option (gogoproto.compare) = true; option (gogoproto.equal) = true; diff --git a/proto/tendermint/types/evidence.proto b/proto/tendermint/types/evidence.proto index d9548a430296..451b8dca3c71 100644 --- a/proto/tendermint/types/evidence.proto +++ b/proto/tendermint/types/evidence.proto @@ -30,7 +30,7 @@ message LightClientAttackEvidence { int64 common_height = 2; repeated tendermint.types.Validator byzantine_validators = 3; int64 total_voting_power = 4; - google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; } message EvidenceList { diff --git a/proto/tendermint/types/params.proto b/proto/tendermint/types/params.proto index 70789222a5d3..0de7d846fbd3 100644 --- a/proto/tendermint/types/params.proto +++ b/proto/tendermint/types/params.proto @@ -45,7 +45,8 @@ message EvidenceParams { // It should correspond with an app's "unbonding period" or other similar // mechanism for handling [Nothing-At-Stake // attacks](https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed). - google.protobuf.Duration max_age_duration = 2 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + google.protobuf.Duration max_age_duration = 2 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; // This sets the maximum size of total evidence in bytes that can be committed in a single block. // and should fall comfortably under the max block bytes. diff --git a/proto/tendermint/types/types.proto b/proto/tendermint/types/types.proto index 57efc33c5b7e..3ce1694594ff 100644 --- a/proto/tendermint/types/types.proto +++ b/proto/tendermint/types/types.proto @@ -54,7 +54,7 @@ message BlockID { // -------------------------------- -// Header defines the structure of a Tendermint block header. +// Header defines the structure of a block header. message Header { // basic block info tendermint.version.Consensus version = 1 [(gogoproto.nullable) = false]; @@ -66,19 +66,19 @@ message Header { BlockID last_block_id = 5 [(gogoproto.nullable) = false]; // hashes of block data - bytes last_commit_hash = 6; // commit from validators from the last block - bytes data_hash = 7; // transactions + bytes last_commit_hash = 6; // commit from validators from the last block + bytes data_hash = 7; // transactions // hashes from the app output from the prev block - bytes validators_hash = 8; // validators for the current block - bytes next_validators_hash = 9; // validators for the next block - bytes consensus_hash = 10; // consensus params for current block - bytes app_hash = 11; // state after txs from the previous block - bytes last_results_hash = 12; // root hash of all results from the txs from the previous block + bytes validators_hash = 8; // validators for the current block + bytes next_validators_hash = 9; // validators for the next block + bytes consensus_hash = 10; // consensus params for current block + bytes app_hash = 11; // state after txs from the previous block + bytes last_results_hash = 12; // root hash of all results from the txs from the previous block // consensus info - bytes evidence_hash = 13; // evidence included in the block - bytes proposer_address = 14; // original proposer of the block + bytes evidence_hash = 13; // evidence included in the block + bytes proposer_address = 14; // original proposer of the block } // Data contains the set of transactions included in the block @@ -95,11 +95,13 @@ message Vote { SignedMsgType type = 1; int64 height = 2; int32 round = 3; - BlockID block_id = 4 [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; // zero if vote is nil. - google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; - bytes validator_address = 6; - int32 validator_index = 7; - bytes signature = 8; + BlockID block_id = 4 + [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; // zero if vote is nil. + google.protobuf.Timestamp timestamp = 5 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes validator_address = 6; + int32 validator_index = 7; + bytes signature = 8; } // Commit contains the evidence that a block was committed by a set of validators. @@ -114,8 +116,9 @@ message Commit { message CommitSig { BlockIDFlag block_id_flag = 1; bytes validator_address = 2; - google.protobuf.Timestamp timestamp = 3 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; - bytes signature = 4; + google.protobuf.Timestamp timestamp = 3 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes signature = 4; } message Proposal { @@ -124,8 +127,9 @@ message Proposal { int32 round = 3; int32 pol_round = 4; BlockID block_id = 5 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; - google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; - bytes signature = 7; + google.protobuf.Timestamp timestamp = 6 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes signature = 7; } message SignedHeader { diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index 7b61f31ea5f2..3e740c8b630a 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -39,4 +39,4 @@ cd .. cp -r github.com/cosmos/cosmos-sdk/* ./ rm -rf github.com -go mod tidy -compat=1.18 +go mod tidy -compat=1.19 diff --git a/server/rollback.go b/server/rollback.go index c3dba335466b..c5245589aacb 100644 --- a/server/rollback.go +++ b/server/rollback.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server/types" "github.com/spf13/cobra" - tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + tmcmd "github.com/tendermint/tendermint/cmd/cometbft/commands" ) // NewRollbackCmd creates a command to rollback tendermint and multistore state by one height. diff --git a/server/start.go b/server/start.go index 0f5bd05d3eb2..208bfb8db674 100644 --- a/server/start.go +++ b/server/start.go @@ -12,7 +12,7 @@ import ( "github.com/spf13/cobra" "github.com/tendermint/tendermint/abci/server" - tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + tcmd "github.com/tendermint/tendermint/cmd/cometbft/commands" tmos "github.com/tendermint/tendermint/libs/os" "github.com/tendermint/tendermint/node" "github.com/tendermint/tendermint/p2p" diff --git a/server/util.go b/server/util.go index 2d9d02eb6834..98e82be44b03 100644 --- a/server/util.go +++ b/server/util.go @@ -20,7 +20,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" - tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + tmcmd "github.com/tendermint/tendermint/cmd/cometbft/commands" tmcfg "github.com/tendermint/tendermint/config" tmlog "github.com/tendermint/tendermint/libs/log" dbm "github.com/tendermint/tm-db" diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 24051a17a927..412b7de6caac 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -77,7 +77,6 @@ func snapshotItems(items [][]byte) [][]byte { _ = snapshottypes.WriteExtensionItem(protoWriter, item) } _ = protoWriter.Close() - _ = zWriter.Close() _ = bufWriter.Flush() _ = chunkWriter.Close() }() diff --git a/snapshots/manager_test.go b/snapshots/manager_test.go index 7fbddd6c7d6d..8f8e8d3da8d7 100644 --- a/snapshots/manager_test.go +++ b/snapshots/manager_test.go @@ -91,7 +91,7 @@ func TestManager_Take(t *testing.T) { Height: 5, Format: snapshotter.SnapshotFormat(), Chunks: 1, - Hash: []uint8{0xcd, 0x17, 0x9e, 0x7f, 0x28, 0xb6, 0x82, 0x90, 0xc7, 0x25, 0xf3, 0x42, 0xac, 0x65, 0x73, 0x50, 0xaa, 0xa0, 0x10, 0x5c, 0x40, 0x8c, 0xd5, 0x1, 0xed, 0x82, 0xb5, 0xca, 0x8b, 0xe0, 0x83, 0xa2}, + Hash: []uint8{0xcf, 0xd8, 0x16, 0xd2, 0xf8, 0x11, 0xe8, 0x90, 0x92, 0xf1, 0xfe, 0x3b, 0xea, 0xd2, 0x94, 0xfc, 0xfa, 0x4f, 0x9e, 0x2a, 0x91, 0xbe, 0xb0, 0x50, 0x83, 0xe9, 0x28, 0x62, 0x48, 0x6a, 0x4b, 0x4}, Metadata: types.Metadata{ ChunkHashes: checksums(expectChunks), }, diff --git a/snapshots/stream.go b/snapshots/stream.go index 935028313bb5..ce000f3e9c3d 100644 --- a/snapshots/stream.go +++ b/snapshots/stream.go @@ -57,10 +57,6 @@ func (sw *StreamWriter) Close() error { sw.chunkWriter.CloseWithError(err) return err } - if err := sw.zWriter.Close(); err != nil { - sw.chunkWriter.CloseWithError(err) - return err - } if err := sw.bufWriter.Flush(); err != nil { sw.chunkWriter.CloseWithError(err) return err diff --git a/snapshots/types/format.go b/snapshots/types/format.go index d5e960660ac9..317b6a6e329e 100644 --- a/snapshots/types/format.go +++ b/snapshots/types/format.go @@ -3,4 +3,4 @@ package types // CurrentFormat is the currently used format for snapshots. Snapshots using the same format // must be identical across all nodes for a given height, so this must be bumped when the binary // snapshot output changes. -const CurrentFormat uint32 = 2 +const CurrentFormat uint32 = 3 diff --git a/store/rootmulti/snapshot_test.go b/store/rootmulti/snapshot_test.go index bad1603da7c9..de7880788eee 100644 --- a/store/rootmulti/snapshot_test.go +++ b/store/rootmulti/snapshot_test.go @@ -128,7 +128,7 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) { "aa048b4ee0f484965d7b3b06822cf0772cdcaad02f3b1b9055e69f2cb365ef3c", "7921eaa3ed4921341e504d9308a9877986a879fe216a099c86e8db66fcba4c63", "a4a864e6c02c9fca5837ec80dc84f650b25276ed7e4820cf7516ced9f9901b86", - "ca2879ac6e7205d257440131ba7e72bef784cd61642e32b847729e543c1928b9", + "980925390cc50f14998ecb1e87de719ca9dd7e72f5fefbe445397bf670f36c31", }}, } for _, tc := range testcases { diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index dd81d771eec5..74915695ab40 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -1006,7 +1006,7 @@ type storeParams struct { initialVersion uint64 } -func newStoreParams(key types.StoreKey, db dbm.DB, typ types.StoreType, initialVersion uint64) storeParams { // nolint +func newStoreParams(key types.StoreKey, db dbm.DB, typ types.StoreType, initialVersion uint64) storeParams { return storeParams{ key: key, db: db, From f1ec5fe98167fc29670d701b215ee141f94dd72d Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Mon, 27 Feb 2023 22:10:32 +0100 Subject: [PATCH 05/47] chore: bump cometbft to v0.34.27 final (#15206) --- Makefile | 2 +- RELEASE_NOTES.md | 4 ++-- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 1bf7dbef792c..dff5e166c762 100644 --- a/Makefile +++ b/Makefile @@ -430,7 +430,7 @@ proto-lint: proto-check-breaking: @$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main -TM_URL = https://raw.githubusercontent.com/cometbft/cometbft/v0.34.27-alpha.2/proto/tendermint +TM_URL = https://raw.githubusercontent.com/cometbft/cometbft/v0.34.27/proto/tendermint TM_CRYPTO_TYPES = proto/tendermint/crypto TM_ABCI_TYPES = proto/tendermint/abci diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c7f064eea7cc..91d8165e913f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # Cosmos SDK v0.46.11 Release Notes -This release includes the migration to CometBFT. This migration should be not breaking. +This release includes the migration to [CometBFT](https://github.com/cometbft/cometbft/blob/v0.34.27/CHANGELOG.md#v03427). This migration should be not breaking. From `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your application: ```go @@ -8,7 +8,7 @@ From `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your a replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 ``` -A more complete migration is happening in Cosmos SDK v0.47. +A more complete migration is happening in Cosmos SDK v0.47.0. Additionally, the SDK sets its minimum version to Go 1.19. This is not because the SDK uses new Go 1.19 functionalities, but because we recommend chains as well to upgrade to Go 1.19 because Go 1.18 is not supported anymore. diff --git a/go.mod b/go.mod index 0d6a1b9558ac..d45aad66ba4e 100644 --- a/go.mod +++ b/go.mod @@ -144,11 +144,11 @@ require ( github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.opencensus.io v0.23.0 // indirect - golang.org/x/net v0.5.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/term v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.102.0 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -170,7 +170,7 @@ replace ( github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/jhump/protoreflect => github.com/jhump/protoreflect v1.9.0 // use cometbft - github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27-alpha.2 + github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 ) retract ( diff --git a/go.sum b/go.sum index 94de6d3ab869..12ad00eae55b 100644 --- a/go.sum +++ b/go.sum @@ -194,8 +194,8 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= github.com/coinbase/rosetta-sdk-go v0.7.9/go.mod h1:0/knutI7XGVqXmmH4OQD8OckFrbQ8yMsUZTG7FXCR2M= -github.com/cometbft/cometbft v0.34.27-alpha.2 h1:ERW9qPlaHjshc6BuCAc5yfXcIWuDKAjGLCzJvQQ3YlM= -github.com/cometbft/cometbft v0.34.27-alpha.2/go.mod h1:6tEDwldPfO1ynAd9kx8j808atUVY0jUAJ18l3glfpuM= +github.com/cometbft/cometbft v0.34.27 h1:ri6BvmwjWR0gurYjywcBqRe4bbwc3QVs9KRcCzgh/J0= +github.com/cometbft/cometbft v0.34.27/go.mod h1:BcCbhKv7ieM0KEddnYXvQZR+pZykTKReJJYf7YC7qhw= github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= @@ -1100,8 +1100,8 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1208,13 +1208,13 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1224,8 +1224,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 1229bd17aa2a427459da71ab981a71d79968f236 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 2 Mar 2023 19:55:25 +0100 Subject: [PATCH 06/47] fix: Change proposer address cast for `sdk_block` conversion (backport #15243) (#15245) Co-authored-by: Maksym Hontar <99190705+max-hontar@users.noreply.github.com> Co-authored-by: Julien Robert --- CHANGELOG.md | 1 + client/grpc/tmservice/service_test.go | 6 +++--- client/grpc/tmservice/util.go | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4bec9497aa1..5dd14d02ea18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* [#15243](https://github.com/cosmos/cosmos-sdk/pull/15243) `LatestBlockResponse` & `BlockByHeightResponse` types' field `sdk_block` was incorrectly cast `proposer_address` bytes to validator operator address, now to consensus address. * (snapshot) [#13400](https://github.com/cosmos/cosmos-sdk/pull/13400) Fix snapshot checksum issue in Go 1.19. ## [v0.46.10](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.10) - 2022-02-16 diff --git a/client/grpc/tmservice/service_test.go b/client/grpc/tmservice/service_test.go index 030e62d4f0dd..226b2feb88c9 100644 --- a/client/grpc/tmservice/service_test.go +++ b/client/grpc/tmservice/service_test.go @@ -88,8 +88,8 @@ func (s *IntegrationTestSuite) TestQueryLatestBlock() { s.Require().NoError(err) var blockInfoRes tmservice.GetLatestBlockResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockInfoRes)) - s.Require().Equal(types.ValAddress(blockInfoRes.Block.Header.ProposerAddress).String(), blockInfoRes.SdkBlock.Header.ProposerAddress) - s.Require().Contains(blockInfoRes.SdkBlock.Header.ProposerAddress, "cosmosvaloper") + s.Require().Equal(types.ConsAddress(blockInfoRes.Block.Header.ProposerAddress).String(), blockInfoRes.SdkBlock.Header.ProposerAddress) + s.Require().Contains(blockInfoRes.SdkBlock.Header.ProposerAddress, "cosmosvalcons") } func (s *IntegrationTestSuite) TestQueryBlockByHeight() { @@ -101,7 +101,7 @@ func (s *IntegrationTestSuite) TestQueryBlockByHeight() { s.Require().NoError(err) var blockInfoRes tmservice.GetBlockByHeightResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockInfoRes)) - s.Require().Contains(blockInfoRes.SdkBlock.Header.ProposerAddress, "cosmosvaloper") + s.Require().Contains(blockInfoRes.SdkBlock.Header.ProposerAddress, "cosmosvalcons") } func (s *IntegrationTestSuite) TestQueryLatestValidatorSet() { diff --git a/client/grpc/tmservice/util.go b/client/grpc/tmservice/util.go index 9bbda0d2e26e..aeffaa84c3b7 100644 --- a/client/grpc/tmservice/util.go +++ b/client/grpc/tmservice/util.go @@ -21,7 +21,7 @@ func convertHeader(h tmprototypes.Header) Header { EvidenceHash: h.EvidenceHash, LastResultsHash: h.LastResultsHash, LastCommitHash: h.LastCommitHash, - ProposerAddress: sdk.ValAddress(h.ProposerAddress).String(), + ProposerAddress: sdk.ConsAddress(h.ProposerAddress).String(), } } From 578c160cdf49b7c885ef82198284f20cf09ad452 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 3 Mar 2023 12:43:19 +0100 Subject: [PATCH 07/47] fix: revert double close fix (#15255) --- snapshots/helpers_test.go | 1 + snapshots/manager_test.go | 2 +- snapshots/stream.go | 4 ++++ snapshots/types/format.go | 2 +- store/rootmulti/snapshot_test.go | 2 +- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 412b7de6caac..24051a17a927 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -77,6 +77,7 @@ func snapshotItems(items [][]byte) [][]byte { _ = snapshottypes.WriteExtensionItem(protoWriter, item) } _ = protoWriter.Close() + _ = zWriter.Close() _ = bufWriter.Flush() _ = chunkWriter.Close() }() diff --git a/snapshots/manager_test.go b/snapshots/manager_test.go index 8f8e8d3da8d7..b71043022827 100644 --- a/snapshots/manager_test.go +++ b/snapshots/manager_test.go @@ -91,7 +91,7 @@ func TestManager_Take(t *testing.T) { Height: 5, Format: snapshotter.SnapshotFormat(), Chunks: 1, - Hash: []uint8{0xcf, 0xd8, 0x16, 0xd2, 0xf8, 0x11, 0xe8, 0x90, 0x92, 0xf1, 0xfe, 0x3b, 0xea, 0xd2, 0x94, 0xfc, 0xfa, 0x4f, 0x9e, 0x2a, 0x91, 0xbe, 0xb0, 0x50, 0x83, 0xe9, 0x28, 0x62, 0x48, 0x6a, 0x4b, 0x4}, + Hash: []uint8{0x14, 0x38, 0x97, 0x96, 0xba, 0xe4, 0x81, 0xaf, 0x6c, 0xac, 0xff, 0xa5, 0xb8, 0x7e, 0x63, 0x4b, 0xac, 0x69, 0x3f, 0x38, 0x90, 0x5c, 0x7d, 0x57, 0xb3, 0xf, 0x69, 0x73, 0xb3, 0xa0, 0xe0, 0xad}, Metadata: types.Metadata{ ChunkHashes: checksums(expectChunks), }, diff --git a/snapshots/stream.go b/snapshots/stream.go index ce000f3e9c3d..935028313bb5 100644 --- a/snapshots/stream.go +++ b/snapshots/stream.go @@ -57,6 +57,10 @@ func (sw *StreamWriter) Close() error { sw.chunkWriter.CloseWithError(err) return err } + if err := sw.zWriter.Close(); err != nil { + sw.chunkWriter.CloseWithError(err) + return err + } if err := sw.bufWriter.Flush(); err != nil { sw.chunkWriter.CloseWithError(err) return err diff --git a/snapshots/types/format.go b/snapshots/types/format.go index 317b6a6e329e..d5e960660ac9 100644 --- a/snapshots/types/format.go +++ b/snapshots/types/format.go @@ -3,4 +3,4 @@ package types // CurrentFormat is the currently used format for snapshots. Snapshots using the same format // must be identical across all nodes for a given height, so this must be bumped when the binary // snapshot output changes. -const CurrentFormat uint32 = 3 +const CurrentFormat uint32 = 2 diff --git a/store/rootmulti/snapshot_test.go b/store/rootmulti/snapshot_test.go index de7880788eee..f8b058656d33 100644 --- a/store/rootmulti/snapshot_test.go +++ b/store/rootmulti/snapshot_test.go @@ -128,7 +128,7 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) { "aa048b4ee0f484965d7b3b06822cf0772cdcaad02f3b1b9055e69f2cb365ef3c", "7921eaa3ed4921341e504d9308a9877986a879fe216a099c86e8db66fcba4c63", "a4a864e6c02c9fca5837ec80dc84f650b25276ed7e4820cf7516ced9f9901b86", - "980925390cc50f14998ecb1e87de719ca9dd7e72f5fefbe445397bf670f36c31", + "8ca5b957e36fa13e704c31494649b2a74305148d70d70f0f26dee066b615c1d0", }}, } for _, tc := range testcases { From 5023392bd9718679668dd8e88a792a6defa63c00 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 3 Mar 2023 20:25:55 +0100 Subject: [PATCH 08/47] chore: prepare v0.46.11 release (#15259) --- CHANGELOG.md | 3 ++- RELEASE_NOTES.md | 11 +++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dd14d02ea18..90ecc29180d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +## [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11) - 2022-03-03 + ### Improvements * (deps) Migrate to [CometBFT](https://github.com/cometbft/cometbft). Follow the instructions in the [release notes](./RELEASE_NOTES.md). @@ -46,7 +48,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes * [#15243](https://github.com/cosmos/cosmos-sdk/pull/15243) `LatestBlockResponse` & `BlockByHeightResponse` types' field `sdk_block` was incorrectly cast `proposer_address` bytes to validator operator address, now to consensus address. -* (snapshot) [#13400](https://github.com/cosmos/cosmos-sdk/pull/13400) Fix snapshot checksum issue in Go 1.19. ## [v0.46.10](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.10) - 2022-02-16 diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 91d8165e913f..381bb7ca8b0f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,7 @@ # Cosmos SDK v0.46.11 Release Notes -This release includes the migration to [CometBFT](https://github.com/cometbft/cometbft/blob/v0.34.27/CHANGELOG.md#v03427). This migration should be not breaking. +This release includes the migration to [CometBFT v0.34.27](https://github.com/cometbft/cometbft/blob/v0.34.27/CHANGELOG.md#v03427). +This migration should be not be breaking for chains. From `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your application: ```go @@ -8,11 +9,9 @@ From `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your a replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 ``` -A more complete migration is happening in Cosmos SDK v0.47.0. - -Additionally, the SDK sets its minimum version to Go 1.19. -This is not because the SDK uses new Go 1.19 functionalities, but because we recommend chains as well to upgrade to Go 1.19 because Go 1.18 is not supported anymore. -We recommend applications to perform a **coordinated upgrade** when migrating from Go 1.18 to Go 1.19. +Additionally, the SDK sets its minimum version to Go 1.19. This is not because the SDK uses new Go 1.19 functionalities, but to signal that we recommend chains to upgrade to Go 1.19 — Go 1.18 is not supported by the Go Team anymore. +Note, that SDK recommends chains to use the same Go version across all of their network. +We recommend, as well, chains to perform a **coordinated upgrade** when migrating from Go 1.18 to Go 1.19. Please see the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/CHANGELOG.md) for an exhaustive list of changes. From 570392aee8d4b701c42d7677e3e6a0d880f633f3 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 9 Mar 2023 19:06:23 +0800 Subject: [PATCH 09/47] feat: add extend cb to avoid unmarshal state twice for sim test (backport: #15305) (#15321) --- CHANGELOG.md | 1 + simapp/state.go | 13 +++++++++++++ types/simulation/types.go | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90ecc29180d3..c0d3d0831022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ # Changelog ## [Unreleased] +* (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState. ## [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11) - 2022-03-03 diff --git a/simapp/state.go b/simapp/state.go index 135863c5bd7c..21e71470b24e 100644 --- a/simapp/state.go +++ b/simapp/state.go @@ -27,6 +27,14 @@ import ( // It panics if the user provides files for both of them. // If a file is not given for the genesis or the sim params, it creates a randomized one. func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn { + return AppStateFnWithExtendedCb(cdc, simManager, nil) +} + +// AppStateFnWithExtendedCb returns the initial application state using a genesis or the simulation parameters. +// It panics if the user provides files for both of them. +// If a file is not given for the genesis or the sim params, it creates a randomized one. +// cb is the callback function to extend rawState. +func AppStateFnWithExtendedCb(cdc codec.JSONCodec, simManager *module.SimulationManager, cb func(rawState map[string]json.RawMessage)) simtypes.AppStateFn { return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, ) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) { if FlagGenesisTimeValue == 0 { @@ -127,6 +135,11 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) + // extend state from callback function + if cb != nil { + cb(rawState) + } + // replace appstate appState, err = json.Marshal(rawState) if err != nil { diff --git a/types/simulation/types.go b/types/simulation/types.go index 199f47fa38e2..bdc0b59659d0 100644 --- a/types/simulation/types.go +++ b/types/simulation/types.go @@ -161,6 +161,11 @@ type AppStateFn func(r *rand.Rand, accs []Account, config Config) ( appState json.RawMessage, accounts []Account, chainId string, genesisTimestamp time.Time, ) +// AppStateFnWithExtendedCb returns the app state json bytes and the genesis accounts +type AppStateFnWithExtendedCb func(r *rand.Rand, accs []Account, config Config) ( + appState json.RawMessage, accounts []Account, chainId string, genesisTimestamp time.Time, +) + // RandomAccountFn returns a slice of n random simulation accounts type RandomAccountFn func(r *rand.Rand, n int) []Account From f939979e11c21cfa8896cab7fbd6d2bdfa380063 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 11 Mar 2023 00:56:30 +0800 Subject: [PATCH 10/47] feat: add extend cb with genesisState for sim test (backport: #15305) (#15349) --- CHANGELOG.md | 4 +++- simapp/state.go | 29 ++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d3d0831022..96f0e0c451bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ # Changelog ## [Unreleased] -* (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState. + +### Improvements +* (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState and `AppStateRandomizedFnWithState` with extra genesisState argument which is the genesis state of the app. ## [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11) - 2022-03-03 diff --git a/simapp/state.go b/simapp/state.go index 21e71470b24e..836891cda88d 100644 --- a/simapp/state.go +++ b/simapp/state.go @@ -27,14 +27,21 @@ import ( // It panics if the user provides files for both of them. // If a file is not given for the genesis or the sim params, it creates a randomized one. func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn { - return AppStateFnWithExtendedCb(cdc, simManager, nil) + genesisState := NewDefaultGenesisState(cdc) + return AppStateFnWithExtendedCb(cdc, simManager, genesisState, nil) } // AppStateFnWithExtendedCb returns the initial application state using a genesis or the simulation parameters. // It panics if the user provides files for both of them. // If a file is not given for the genesis or the sim params, it creates a randomized one. +// genesisState is the genesis state of the app. // cb is the callback function to extend rawState. -func AppStateFnWithExtendedCb(cdc codec.JSONCodec, simManager *module.SimulationManager, cb func(rawState map[string]json.RawMessage)) simtypes.AppStateFn { +func AppStateFnWithExtendedCb( + cdc codec.JSONCodec, + simManager *module.SimulationManager, + genesisState map[string]json.RawMessage, + cb func(rawState map[string]json.RawMessage), +) simtypes.AppStateFn { return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, ) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) { if FlagGenesisTimeValue == 0 { @@ -72,11 +79,11 @@ func AppStateFnWithExtendedCb(cdc codec.JSONCodec, simManager *module.Simulation if err != nil { panic(err) } - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) + appState, simAccs = AppStateRandomizedFnWithState(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) default: appParams := make(simtypes.AppParams) - appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) + appState, simAccs = AppStateRandomizedFnWithState(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) } rawState := make(map[string]json.RawMessage) @@ -155,8 +162,20 @@ func AppStateRandomizedFn( simManager *module.SimulationManager, r *rand.Rand, cdc codec.JSONCodec, accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams, ) (json.RawMessage, []simtypes.Account) { - numAccs := int64(len(accs)) genesisState := NewDefaultGenesisState(cdc) + return AppStateRandomizedFnWithState(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState) +} + +// AppStateRandomizedFnWithState creates calls each module's GenesisState generator function +// and creates the simulation params +// genesisState is the genesis state of the app. +// This function will not exist in v0.47, but be replaced by AppStateRandomizedFn with an extra genesisState argument. +func AppStateRandomizedFnWithState( + simManager *module.SimulationManager, r *rand.Rand, cdc codec.JSONCodec, + accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams, + genesisState map[string]json.RawMessage, +) (json.RawMessage, []simtypes.Account) { + numAccs := int64(len(accs)) // generate a random amount of initial stake coins and a random initial // number of bonded accounts From f382e4340673ea5382005c71f19a6408f1f0bbee Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:37:38 +0100 Subject: [PATCH 11/47] fix: add extra check in vesting (backport #15373) (#15383) Co-authored-by: Julien Robert --- CHANGELOG.md | 5 +++++ x/auth/vesting/msg_server.go | 14 +++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96f0e0c451bb..3d62f194f5d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,8 +38,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] ### Improvements + * (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState and `AppStateRandomizedFnWithState` with extra genesisState argument which is the genesis state of the app. +### Bug Fixes + +* (x/auth/vesting) [#15383](https://github.com/cosmos/cosmos-sdk/pull/15383) Add extra checks when creating a periodic vesting account. + ## [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11) - 2022-03-03 ### Improvements diff --git a/x/auth/vesting/msg_server.go b/x/auth/vesting/msg_server.go index afcd2681e1bb..c3dd5785163d 100644 --- a/x/auth/vesting/msg_server.go +++ b/x/auth/vesting/msg_server.go @@ -79,8 +79,7 @@ func (s msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCre } }() - err = bk.SendCoins(ctx, from, to, msg.Amount) - if err != nil { + if err = bk.SendCoins(ctx, from, to, msg.Amount); err != nil { return nil, err } @@ -140,8 +139,7 @@ func (s msgServer) CreatePermanentLockedAccount(goCtx context.Context, msg *type } }() - err = bk.SendCoins(ctx, from, to, msg.Amount) - if err != nil { + if err = bk.SendCoins(ctx, from, to, msg.Amount); err != nil { return nil, err } @@ -175,11 +173,14 @@ func (s msgServer) CreatePeriodicVestingAccount(goCtx context.Context, msg *type } var totalCoins sdk.Coins - for _, period := range msg.VestingPeriods { totalCoins = totalCoins.Add(period.Amount...) } + if err := bk.IsSendEnabledCoins(ctx, totalCoins...); err != nil { + return nil, err + } + baseAccount := authtypes.NewBaseAccountWithAddress(to) baseAccount = ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) vestingAccount := types.NewPeriodicVestingAccount(baseAccount, totalCoins.Sort(), msg.StartTime, msg.VestingPeriods) @@ -200,8 +201,7 @@ func (s msgServer) CreatePeriodicVestingAccount(goCtx context.Context, msg *type } }() - err = bk.SendCoins(ctx, from, to, totalCoins) - if err != nil { + if err = bk.SendCoins(ctx, from, to, totalCoins); err != nil { return nil, err } From e1da9c54e813f13041c90821ffad81d693c40ae2 Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 17 Mar 2023 12:02:10 +0100 Subject: [PATCH 12/47] docs: update cosmwasm link (#15441) --- docs/CosmWasm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CosmWasm/README.md b/docs/CosmWasm/README.md index 409f31ebda4c..b6a14810b38c 100644 --- a/docs/CosmWasm/README.md +++ b/docs/CosmWasm/README.md @@ -10,4 +10,4 @@ parent: >CosmWasm is written as a module that can plug into the Cosmos SDK. This means that anyone currently building a blockchain using the Cosmos SDK can quickly and easily add CosmWasm smart contracting support to their chain, without adjusting existing logic. -Read more about writing smart contracts with CosmWasm at their [documentation site](https://docs.cosmwasm.com/docs/1.0/), or visit [the repository](https://github.com/CosmWasm/cosmwasm). +Read more about writing smart contracts with CosmWasm at their [documentation site](https://book.cosmwasm.com/), or visit [the repository](https://github.com/CosmWasm/cosmwasm). From 431e42a730851b607ab6a10da3096f162fad28ee Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 17 Mar 2023 14:57:52 +0100 Subject: [PATCH 13/47] fix: remove extra `;` in service.proto (#15443) --- proto/cosmos/tx/v1beta1/service.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/cosmos/tx/v1beta1/service.proto b/proto/cosmos/tx/v1beta1/service.proto index 4dd9b5354067..f6c39d52baaa 100644 --- a/proto/cosmos/tx/v1beta1/service.proto +++ b/proto/cosmos/tx/v1beta1/service.proto @@ -50,7 +50,7 @@ message GetTxsEventRequest { // pagination defines a pagination for the request. // Deprecated post v0.46.x: use page and limit instead. cosmos.base.query.v1beta1.PageRequest pagination = 2 [deprecated = true]; - ; + OrderBy order_by = 3; // page is the page number to query, starts at 1. If not provided, will default to first page. uint64 page = 4; From 8726f4203c31c3b16e52d6c26aa697264fc5a070 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 12:11:21 +0100 Subject: [PATCH 14/47] fix: flaky group genesis sim (backport #15447) (#15461) Co-authored-by: Robert Zaremba --- x/group/simulation/genesis.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/x/group/simulation/genesis.go b/x/group/simulation/genesis.go index 7f30a4fc7303..66b471fa5e47 100644 --- a/x/group/simulation/genesis.go +++ b/x/group/simulation/genesis.go @@ -21,6 +21,16 @@ const ( GroupVote = "group-vote" ) +func checkAccExists(acc sdk.AccAddress, g []*group.GroupMember, lastIndex int) bool { + s := acc.String() + for i := 0; i < lastIndex; i++ { + if g[i].Member.Address == s { + return true + } + } + return false +} + func getGroups(r *rand.Rand, accounts []simtypes.Account) []*group.GroupInfo { groups := make([]*group.GroupInfo, 3) for i := 0; i < 3; i++ { @@ -40,6 +50,9 @@ func getGroupMembers(r *rand.Rand, accounts []simtypes.Account) []*group.GroupMe groupMembers := make([]*group.GroupMember, 3) for i := 0; i < 3; i++ { acc, _ := simtypes.RandomAcc(r, accounts) + for checkAccExists(acc.Address, groupMembers, i) { + acc, _ = simtypes.RandomAcc(r, accounts) + } groupMembers[i] = &group.GroupMember{ GroupId: uint64(i + 1), Member: &group.Member{ @@ -147,6 +160,11 @@ func getVoteOption(index int) group.VoteOption { // RandomizedGenState generates a random GenesisState for the group module. func RandomizedGenState(simState *module.SimulationState) { + // The test requires we have at least 3 accounts. + if len(simState.Accounts) < 3 { + return + } + // groups var groups []*group.GroupInfo simState.AppParams.GetOrGenerate( From 31adbba958f69148ad49a1deed92c98395930db3 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 17:28:43 +0000 Subject: [PATCH 15/47] feat: add delegator to withdraw address (backport #15462) (#15473) Co-authored-by: Marko --- CHANGELOG.md | 1 + x/distribution/keeper/delegation.go | 1 + x/distribution/types/events.go | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d62f194f5d8..1cb9cdd92521 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState and `AppStateRandomizedFnWithState` with extra genesisState argument which is the genesis state of the app. +* (x/distribution) [#15462](https://github.com/cosmos/cosmos-sdk/pull/15462) Add delegator address to the event for withdrawing delegation rewards ### Bug Fixes diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index a5531e33f775..f94e1a73b4be 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -205,6 +205,7 @@ func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val stakingtypes.Vali types.EventTypeWithdrawRewards, sdk.NewAttribute(sdk.AttributeKeyAmount, emittedRewards.String()), sdk.NewAttribute(types.AttributeKeyValidator, val.GetOperator().String()), + sdk.NewAttribute(types.AttributeKeyDelegator, del.GetDelegatorAddr().String()), ), ) diff --git a/x/distribution/types/events.go b/x/distribution/types/events.go index ce4c0ef62e3c..9ca631db0076 100644 --- a/x/distribution/types/events.go +++ b/x/distribution/types/events.go @@ -11,6 +11,6 @@ const ( AttributeKeyWithdrawAddress = "withdraw_address" AttributeKeyValidator = "validator" - - AttributeValueCategory = ModuleName + AttributeKeyDelegator = "delegator" + AttributeValueCategory = ModuleName ) From 8d053c2a9554fbf7b75433d8aa7c880cbcaec752 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 18:30:40 +0100 Subject: [PATCH 16/47] docs: improve proto vesting docs about time attributes (backport #15474) (#15481) Co-authored-by: Julien Robert --- Makefile | 2 +- proto/cosmos/vesting/v1beta1/tx.proto | 2 ++ proto/cosmos/vesting/v1beta1/vesting.proto | 3 +++ scripts/protocgen.sh | 2 -- x/auth/vesting/types/tx.pb.go | 10 ++++++---- x/auth/vesting/types/vesting.pb.go | 7 +++++-- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index dff5e166c762..8de4eb33af80 100644 --- a/Makefile +++ b/Makefile @@ -406,6 +406,7 @@ proto-gen: @echo "Generating Protobuf files" @if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \ sh ./scripts/protocgen.sh; fi + @go mod tidy # This generates the SDK's custom wrapper for google.protobuf.Any. It should only be run manually when needed proto-gen-any: @@ -423,7 +424,6 @@ proto-format: @if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoFmt}$$"; then docker start -a $(containerProtoFmt); else docker run --name $(containerProtoFmt) -v $(CURDIR):/workspace --workdir /workspace tendermintdev/docker-build-proto \ find ./ -not -path "./third_party/*" -name "*.proto" -exec clang-format -i {} \; ; fi - proto-lint: @$(DOCKER_BUF) lint --error-format=json diff --git a/proto/cosmos/vesting/v1beta1/tx.proto b/proto/cosmos/vesting/v1beta1/tx.proto index 27511ba80cbd..732fe12536b2 100644 --- a/proto/cosmos/vesting/v1beta1/tx.proto +++ b/proto/cosmos/vesting/v1beta1/tx.proto @@ -39,6 +39,7 @@ message MsgCreateVestingAccount { repeated cosmos.base.v1beta1.Coin amount = 3 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + // end of vesting as unix time (in seconds). int64 end_time = 4; bool delayed = 5; } @@ -75,6 +76,7 @@ message MsgCreatePeriodicVestingAccount { string from_address = 1; string to_address = 2; + // start of vesting as unix time (in seconds). int64 start_time = 3; repeated Period vesting_periods = 4 [(gogoproto.nullable) = false]; } diff --git a/proto/cosmos/vesting/v1beta1/vesting.proto b/proto/cosmos/vesting/v1beta1/vesting.proto index 824cc30d8bb1..d5c1c9e583d7 100644 --- a/proto/cosmos/vesting/v1beta1/vesting.proto +++ b/proto/cosmos/vesting/v1beta1/vesting.proto @@ -20,6 +20,7 @@ message BaseVestingAccount { [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; repeated cosmos.base.v1beta1.Coin delegated_vesting = 4 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + // Vesting end time, as unix timestamp (in seconds). int64 end_time = 5; } @@ -30,6 +31,7 @@ message ContinuousVestingAccount { option (gogoproto.goproto_stringer) = false; BaseVestingAccount base_vesting_account = 1 [(gogoproto.embed) = true]; + // Vesting start time, as unix timestamp (in seconds). int64 start_time = 2; } @@ -47,6 +49,7 @@ message DelayedVestingAccount { message Period { option (gogoproto.goproto_stringer) = false; + // Period duration in seconds. int64 length = 1; repeated cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index 3e740c8b630a..636479f79ac5 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -38,5 +38,3 @@ cd .. # move proto files to the right places cp -r github.com/cosmos/cosmos-sdk/* ./ rm -rf github.com - -go mod tidy -compat=1.19 diff --git a/x/auth/vesting/types/tx.pb.go b/x/auth/vesting/types/tx.pb.go index 96b06cdb922b..0165ea83312e 100644 --- a/x/auth/vesting/types/tx.pb.go +++ b/x/auth/vesting/types/tx.pb.go @@ -38,8 +38,9 @@ type MsgCreateVestingAccount struct { FromAddress string `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` ToAddress string `protobuf:"bytes,2,opt,name=to_address,json=toAddress,proto3" json:"to_address,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` - EndTime int64 `protobuf:"varint,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` - Delayed bool `protobuf:"varint,5,opt,name=delayed,proto3" json:"delayed,omitempty"` + // end of vesting as unix time (in seconds). + EndTime int64 `protobuf:"varint,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` + Delayed bool `protobuf:"varint,5,opt,name=delayed,proto3" json:"delayed,omitempty"` } func (m *MsgCreateVestingAccount) Reset() { *m = MsgCreateVestingAccount{} } @@ -257,8 +258,9 @@ var xxx_messageInfo_MsgCreatePermanentLockedAccountResponse proto.InternalMessag // // Since: cosmos-sdk 0.46 type MsgCreatePeriodicVestingAccount struct { - FromAddress string `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` - ToAddress string `protobuf:"bytes,2,opt,name=to_address,json=toAddress,proto3" json:"to_address,omitempty"` + FromAddress string `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` + ToAddress string `protobuf:"bytes,2,opt,name=to_address,json=toAddress,proto3" json:"to_address,omitempty"` + // start of vesting as unix time (in seconds). StartTime int64 `protobuf:"varint,3,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` VestingPeriods []Period `protobuf:"bytes,4,rep,name=vesting_periods,json=vestingPeriods,proto3" json:"vesting_periods"` } diff --git a/x/auth/vesting/types/vesting.pb.go b/x/auth/vesting/types/vesting.pb.go index 1404b5891cc6..9c05fa2dff68 100644 --- a/x/auth/vesting/types/vesting.pb.go +++ b/x/auth/vesting/types/vesting.pb.go @@ -33,7 +33,8 @@ type BaseVestingAccount struct { OriginalVesting github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=original_vesting,json=originalVesting,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"original_vesting"` DelegatedFree github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=delegated_free,json=delegatedFree,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"delegated_free"` DelegatedVesting github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,4,rep,name=delegated_vesting,json=delegatedVesting,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"delegated_vesting"` - EndTime int64 `protobuf:"varint,5,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` + // Vesting end time, as unix timestamp (in seconds). + EndTime int64 `protobuf:"varint,5,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` } func (m *BaseVestingAccount) Reset() { *m = BaseVestingAccount{} } @@ -72,7 +73,8 @@ var xxx_messageInfo_BaseVestingAccount proto.InternalMessageInfo // continuously vests by unlocking coins linearly with respect to time. type ContinuousVestingAccount struct { *BaseVestingAccount `protobuf:"bytes,1,opt,name=base_vesting_account,json=baseVestingAccount,proto3,embedded=base_vesting_account" json:"base_vesting_account,omitempty"` - StartTime int64 `protobuf:"varint,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` + // Vesting start time, as unix timestamp (in seconds). + StartTime int64 `protobuf:"varint,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` } func (m *ContinuousVestingAccount) Reset() { *m = ContinuousVestingAccount{} } @@ -148,6 +150,7 @@ var xxx_messageInfo_DelayedVestingAccount proto.InternalMessageInfo // Period defines a length of time and amount of coins that will vest. type Period struct { + // Period duration in seconds. Length int64 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` } From cc39456c98482ccc581260db4989fc59e4f2515b Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 22:03:02 +0100 Subject: [PATCH 17/47] feat: add query `groups` in `x/group` (backport #14879) (#15476) Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com> Co-authored-by: marbar3778 --- CHANGELOG.md | 4 + proto/cosmos/group/v1/query.proto | 27 ++ x/group/client/cli/query.go | 35 ++ x/group/client/testutil/query.go | 49 +++ x/group/keeper/grpc_query.go | 23 ++ x/group/query.pb.go | 633 ++++++++++++++++++++++++++---- x/group/query.pb.gw.go | 83 ++++ 7 files changed, 774 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cb9cdd92521..b0d64cb7198c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Features + +* (x/groups) [#14879](https://github.com/cosmos/cosmos-sdk/pull/14879) Add `Query/Groups` query to get all the groups. + ### Improvements * (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState and `AppStateRandomizedFnWithState` with extra genesisState argument which is the genesis state of the app. diff --git a/proto/cosmos/group/v1/query.proto b/proto/cosmos/group/v1/query.proto index 51a011a9db8f..2ce08855f7b0 100644 --- a/proto/cosmos/group/v1/query.proto +++ b/proto/cosmos/group/v1/query.proto @@ -82,6 +82,13 @@ service Query { rpc TallyResult(QueryTallyResultRequest) returns (QueryTallyResultResponse) { option (google.api.http).get = "/cosmos/group/v1/proposals/{proposal_id}/tally"; }; + + // Groups queries all groups in state. + // + // Since: cosmos-sdk 0.47.1 + rpc Groups(QueryGroupsRequest) returns (QueryGroupsResponse) { + option (google.api.http).get = "/cosmos/group/v1/groups"; + }; } // QueryGroupInfoRequest is the Query/GroupInfo request type. @@ -311,3 +318,23 @@ message QueryTallyResultResponse { // tally defines the requested tally. TallyResult tally = 1 [(gogoproto.nullable) = false]; } + +// QueryGroupsRequest is the Query/Groups request type. +// +// Since: cosmos-sdk 0.47.1 +message QueryGroupsRequest { + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryGroupsResponse is the Query/Groups response type. +// +// Since: cosmos-sdk 0.47.1 +message QueryGroupsResponse { + // `groups` is all the groups present in state. + repeated GroupInfo groups = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/x/group/client/cli/query.go b/x/group/client/cli/query.go index 1535566f525d..e7b866d92508 100644 --- a/x/group/client/cli/query.go +++ b/x/group/client/cli/query.go @@ -33,6 +33,7 @@ func QueryCmd(name string) *cobra.Command { QueryVotesByVoterCmd(), QueryGroupsByMemberCmd(), QueryTallyResultCmd(), + QueryGroupsCmd(), ) return queryCmd @@ -504,3 +505,37 @@ func QueryVotesByVoterCmd() *cobra.Command { return cmd } + +func QueryGroupsCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "groups", + Short: "Query for groups present in the state", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.Groups(cmd.Context(), &group.QueryGroupsRequest{ + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "groups") + + return cmd +} diff --git a/x/group/client/testutil/query.go b/x/group/client/testutil/query.go index 74c152b50978..28ec0746be81 100644 --- a/x/group/client/testutil/query.go +++ b/x/group/client/testutil/query.go @@ -149,6 +149,55 @@ func (s *IntegrationTestSuite) TestQueryGroupsByMembers() { } } +func (s *IntegrationTestSuite) TestQueryGroups() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + require := s.Require() + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + numItems int + expectGroups []*group.GroupInfo + }{ + { + name: "valid req", + args: []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + expectErr: false, + numItems: 5, + }, + { + name: "valid req with pagination", + args: []string{ + "--limit=2", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + expectErr: false, + numItems: 2, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := client.QueryGroupsCmd() + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + require.Contains(out.String(), tc.expectErrMsg) + } else { + require.NoError(err, out.String()) + + var resp group.QueryGroupsResponse + val.ClientCtx.Codec.MustUnmarshalJSON(out.Bytes(), &resp) + + require.Len(resp.Groups, tc.numItems) + } + }) + } +} + func (s *IntegrationTestSuite) TestQueryGroupMembers() { val := s.network.Validators[0] clientCtx := val.ClientCtx diff --git a/x/group/keeper/grpc_query.go b/x/group/keeper/grpc_query.go index ff26844dde56..616f21133847 100644 --- a/x/group/keeper/grpc_query.go +++ b/x/group/keeper/grpc_query.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "math" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -346,3 +347,25 @@ func (k Keeper) TallyResult(goCtx context.Context, request *group.QueryTallyResu Tally: tallyResult, }, nil } + +// Groups returns all the groups present in the state. +func (k Keeper) Groups(goCtx context.Context, request *group.QueryGroupsRequest) (*group.QueryGroupsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + it, err := k.groupTable.PrefixScan(ctx.KVStore(k.key), 1, math.MaxUint64) + if err != nil { + return nil, err + } + defer it.Close() + + var groups []*group.GroupInfo + pageRes, err := orm.Paginate(it, request.Pagination, &groups) + if err != nil { + return nil, err + } + + return &group.QueryGroupsResponse{ + Groups: groups, + Pagination: pageRes, + }, nil +} diff --git a/x/group/query.pb.go b/x/group/query.pb.go index 47cfd7fccd98..ec7e0f9a6da0 100644 --- a/x/group/query.pb.go +++ b/x/group/query.pb.go @@ -1380,6 +1380,111 @@ func (m *QueryTallyResultResponse) GetTally() TallyResult { return TallyResult{} } +// QueryGroupsRequest is the Query/Groups request type. +// +// Since: cosmos-sdk 0.47.1 +type QueryGroupsRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupsRequest) Reset() { *m = QueryGroupsRequest{} } +func (m *QueryGroupsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryGroupsRequest) ProtoMessage() {} +func (*QueryGroupsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_0fcf9f1d74302290, []int{26} +} +func (m *QueryGroupsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryGroupsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupsRequest.Merge(m, src) +} +func (m *QueryGroupsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupsRequest proto.InternalMessageInfo + +func (m *QueryGroupsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupsResponse is the Query/Groups response type. +// +// Since: cosmos-sdk 0.47.1 +type QueryGroupsResponse struct { + // `groups` is all the groups present in state. + Groups []*GroupInfo `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupsResponse) Reset() { *m = QueryGroupsResponse{} } +func (m *QueryGroupsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryGroupsResponse) ProtoMessage() {} +func (*QueryGroupsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_0fcf9f1d74302290, []int{27} +} +func (m *QueryGroupsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryGroupsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupsResponse.Merge(m, src) +} +func (m *QueryGroupsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupsResponse proto.InternalMessageInfo + +func (m *QueryGroupsResponse) GetGroups() []*GroupInfo { + if m != nil { + return m.Groups + } + return nil +} + +func (m *QueryGroupsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + func init() { proto.RegisterType((*QueryGroupInfoRequest)(nil), "cosmos.group.v1.QueryGroupInfoRequest") proto.RegisterType((*QueryGroupInfoResponse)(nil), "cosmos.group.v1.QueryGroupInfoResponse") @@ -1407,91 +1512,95 @@ func init() { proto.RegisterType((*QueryGroupsByMemberResponse)(nil), "cosmos.group.v1.QueryGroupsByMemberResponse") proto.RegisterType((*QueryTallyResultRequest)(nil), "cosmos.group.v1.QueryTallyResultRequest") proto.RegisterType((*QueryTallyResultResponse)(nil), "cosmos.group.v1.QueryTallyResultResponse") + proto.RegisterType((*QueryGroupsRequest)(nil), "cosmos.group.v1.QueryGroupsRequest") + proto.RegisterType((*QueryGroupsResponse)(nil), "cosmos.group.v1.QueryGroupsResponse") } func init() { proto.RegisterFile("cosmos/group/v1/query.proto", fileDescriptor_0fcf9f1d74302290) } var fileDescriptor_0fcf9f1d74302290 = []byte{ - // 1249 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x98, 0xcf, 0x6f, 0xdc, 0x44, - 0x14, 0xc7, 0x33, 0x25, 0x69, 0x92, 0x97, 0xb6, 0x11, 0x43, 0x5a, 0x12, 0x37, 0xda, 0x04, 0x03, - 0xf9, 0x1d, 0x3b, 0xbb, 0x49, 0xd3, 0x8a, 0x9f, 0xea, 0x4a, 0x10, 0x72, 0x28, 0x4a, 0x97, 0x88, - 0x03, 0x97, 0xc8, 0x9b, 0x75, 0x8c, 0xc5, 0xae, 0x67, 0xbb, 0x76, 0x22, 0x56, 0xd1, 0x5e, 0x90, - 0xca, 0x01, 0x71, 0x00, 0x8a, 0x50, 0x89, 0x38, 0xf4, 0x80, 0x04, 0x7f, 0x00, 0x08, 0x89, 0x5b, - 0x6f, 0x3d, 0x56, 0x70, 0xe1, 0x84, 0x50, 0xc2, 0x1f, 0x82, 0x3c, 0xf3, 0xbc, 0xeb, 0xdf, 0xeb, - 0x15, 0x2b, 0xc8, 0xa9, 0x5d, 0xfb, 0xbd, 0x79, 0x9f, 0xf9, 0xbe, 0xe7, 0xf1, 0xd7, 0x81, 0xeb, - 0xfb, 0xcc, 0xae, 0x31, 0x5b, 0x35, 0x1a, 0xec, 0xb0, 0xae, 0x1e, 0xe5, 0xd5, 0x7b, 0x87, 0x7a, - 0xa3, 0xa9, 0xd4, 0x1b, 0xcc, 0x61, 0x74, 0x5c, 0xdc, 0x54, 0xf8, 0x4d, 0xe5, 0x28, 0x2f, 0x4d, - 0x18, 0xcc, 0x60, 0xfc, 0x9e, 0xea, 0xfe, 0x4f, 0x84, 0x49, 0xd3, 0x06, 0x63, 0x46, 0x55, 0x57, - 0xb5, 0xba, 0xa9, 0x6a, 0x96, 0xc5, 0x1c, 0xcd, 0x31, 0x99, 0x65, 0xe3, 0xdd, 0x48, 0x05, 0xa7, - 0x59, 0xd7, 0xbd, 0x9b, 0x4b, 0x78, 0xb3, 0xac, 0xd9, 0xba, 0x28, 0xad, 0x1e, 0xe5, 0xcb, 0xba, - 0xa3, 0xe5, 0xd5, 0xba, 0x66, 0x98, 0x16, 0x5f, 0x09, 0x63, 0xa7, 0x44, 0xec, 0x9e, 0xa8, 0x8f, - 0x68, 0xfc, 0x87, 0x5c, 0x80, 0xab, 0x77, 0xdd, 0xe4, 0x2d, 0xb7, 0xc6, 0xb6, 0x75, 0xc0, 0x4a, - 0xfa, 0xbd, 0x43, 0xdd, 0x76, 0xe8, 0x14, 0x8c, 0xf0, 0xba, 0x7b, 0x66, 0x65, 0x92, 0xcc, 0x92, - 0x85, 0xc1, 0xd2, 0x30, 0xff, 0xbd, 0x5d, 0x91, 0xdf, 0x81, 0x6b, 0xe1, 0x1c, 0xbb, 0xce, 0x2c, - 0x5b, 0xa7, 0x0a, 0x0c, 0x9a, 0xd6, 0x01, 0xe3, 0x09, 0x63, 0x05, 0x49, 0x09, 0xa9, 0xa0, 0x74, - 0x32, 0x78, 0x9c, 0x7c, 0x17, 0xae, 0x77, 0x56, 0xda, 0x61, 0x55, 0x73, 0xbf, 0xe9, 0x67, 0x28, - 0xc0, 0xb0, 0x56, 0xa9, 0x34, 0x74, 0xdb, 0xe6, 0x2b, 0x8e, 0x16, 0x27, 0x7f, 0xfb, 0x69, 0x75, - 0x02, 0x17, 0xbd, 0x2d, 0xee, 0xbc, 0xe7, 0x34, 0x4c, 0xcb, 0x28, 0x79, 0x81, 0xf2, 0x2e, 0x4c, - 0xc7, 0x2f, 0x89, 0x88, 0x1b, 0x01, 0xc4, 0xd9, 0x78, 0x44, 0x5f, 0x9e, 0x00, 0x6d, 0xc1, 0x64, - 0x67, 0xd5, 0x3b, 0x7a, 0xad, 0xac, 0x37, 0xec, 0xee, 0x4a, 0xd1, 0xb7, 0x01, 0x3a, 0xcd, 0x98, - 0xbc, 0xc0, 0x4b, 0xce, 0x79, 0x25, 0xdd, 0xce, 0x29, 0x62, 0x68, 0xb0, 0x73, 0xca, 0x8e, 0x66, - 0xe8, 0xb8, 0x6c, 0xc9, 0x97, 0x29, 0x7f, 0x47, 0x60, 0x2a, 0xa6, 0x3e, 0x6e, 0x69, 0x13, 0x86, - 0x6b, 0xe2, 0xd2, 0x24, 0x99, 0x7d, 0x66, 0x61, 0xac, 0x30, 0x1d, 0xbf, 0x2b, 0x91, 0x57, 0xf2, - 0x82, 0xe9, 0x56, 0x0c, 0xdd, 0x7c, 0x57, 0x3a, 0x51, 0x34, 0x80, 0xf7, 0x20, 0x80, 0x67, 0x17, - 0x9b, 0xb7, 0x2b, 0x35, 0xd3, 0xf2, 0xf4, 0x51, 0x60, 0x48, 0x73, 0x7f, 0x77, 0xed, 0xa1, 0x08, - 0xeb, 0x9b, 0x68, 0xdf, 0x12, 0x90, 0xe2, 0xa8, 0x50, 0xb5, 0x02, 0x5c, 0xe4, 0xf2, 0x78, 0xa2, - 0xa5, 0x4d, 0x2b, 0x46, 0xf6, 0x4f, 0xb1, 0xfb, 0x04, 0x66, 0x43, 0x63, 0x6a, 0xea, 0x76, 0x51, - 0xfc, 0xfc, 0x0f, 0x07, 0xeb, 0x67, 0x02, 0x2f, 0xa4, 0x70, 0xa0, 0x54, 0x5b, 0x70, 0x45, 0x80, - 0xd4, 0x31, 0x00, 0x25, 0xeb, 0xfe, 0xf4, 0x5c, 0x36, 0xfc, 0xeb, 0xf6, 0x4f, 0xbf, 0x93, 0x04, - 0xfd, 0xce, 0xc5, 0xe0, 0x25, 0x89, 0x1a, 0x9c, 0xbf, 0xf3, 0x27, 0xea, 0x4d, 0x98, 0xe0, 0xd8, - 0x3b, 0x0d, 0x56, 0x67, 0xb6, 0x56, 0xf5, 0x74, 0x9c, 0x81, 0xb1, 0x3a, 0x5e, 0xea, 0x8c, 0x22, - 0x78, 0x97, 0xb6, 0x2b, 0xf2, 0xbb, 0xf8, 0x12, 0xe9, 0x24, 0xe2, 0x1e, 0x6f, 0xc0, 0x88, 0x17, - 0x86, 0x07, 0xee, 0x54, 0x64, 0x77, 0xed, 0xa4, 0x76, 0xa8, 0xfc, 0x88, 0x80, 0x1c, 0x58, 0xd0, - 0x9b, 0x48, 0x21, 0xc2, 0xbf, 0x78, 0x3d, 0xf4, 0xad, 0xc7, 0x3f, 0x10, 0x78, 0x31, 0x15, 0x11, - 0x15, 0xb8, 0x09, 0xa3, 0xde, 0xb6, 0xbc, 0x06, 0xa7, 0x48, 0xd0, 0x89, 0xed, 0x5f, 0x57, 0x1b, - 0x30, 0xc3, 0x41, 0xdf, 0x67, 0x8e, 0x5e, 0x6c, 0xe3, 0xba, 0xbf, 0x1a, 0x59, 0x1b, 0xec, 0x3e, - 0x49, 0x47, 0x6e, 0x02, 0xe7, 0x48, 0x7d, 0x92, 0x78, 0x98, 0x7c, 0x07, 0x9f, 0xce, 0xd8, 0x9a, - 0xa8, 0xcc, 0x22, 0x0c, 0xba, 0xc1, 0x38, 0x17, 0x57, 0x23, 0xa2, 0xb8, 0xd1, 0x25, 0x1e, 0x22, - 0x7f, 0x4a, 0xd0, 0x27, 0xb8, 0xd7, 0xec, 0x62, 0xcf, 0x03, 0xda, 0xb7, 0xae, 0x7f, 0x4d, 0xd0, - 0x5d, 0x44, 0x40, 0x70, 0x53, 0xcb, 0x42, 0x28, 0xaf, 0xd5, 0x09, 0xbb, 0x12, 0x31, 0xfd, 0x6b, - 0xf1, 0x57, 0x04, 0xed, 0x09, 0x62, 0x05, 0x9a, 0xdb, 0xee, 0x1d, 0xc9, 0xd4, 0xbb, 0xbe, 0x69, - 0xf5, 0xa5, 0x67, 0x0a, 0x82, 0x50, 0xff, 0xab, 0x50, 0x0f, 0xc3, 0x96, 0x00, 0x2d, 0xd1, 0x39, - 0x38, 0x50, 0x4e, 0x88, 0xdf, 0x0b, 0xfb, 0xd0, 0xce, 0x83, 0x5d, 0x79, 0x05, 0x9e, 0xe7, 0x6c, - 0xbb, 0x5a, 0xb5, 0xea, 0x9e, 0x6d, 0x87, 0x55, 0x27, 0xf3, 0xcb, 0x61, 0x17, 0x67, 0x33, 0x90, - 0x8b, 0x9b, 0xba, 0x05, 0x43, 0x8e, 0x7b, 0x19, 0x0f, 0x81, 0xa8, 0x6f, 0xf5, 0x25, 0x15, 0x07, - 0x9f, 0xfc, 0x39, 0x33, 0x50, 0x12, 0x09, 0x85, 0xfb, 0xcf, 0xc2, 0x10, 0x5f, 0x96, 0x7e, 0x4e, - 0x60, 0xb4, 0xbd, 0x75, 0x3a, 0x17, 0x59, 0x22, 0xf6, 0xf3, 0x46, 0x9a, 0xef, 0x1a, 0x27, 0x10, - 0x65, 0xe5, 0x93, 0xdf, 0xff, 0x7e, 0x70, 0x61, 0x81, 0xce, 0xa9, 0xe1, 0xaf, 0x31, 0xf4, 0x66, - 0xd6, 0x01, 0x53, 0x8f, 0x3d, 0x9f, 0xd6, 0xa2, 0xdf, 0x13, 0x18, 0x0f, 0xbd, 0xb0, 0xe9, 0x4a, - 0x4a, 0xb1, 0xc8, 0x57, 0x8f, 0xb4, 0x9a, 0x31, 0x1a, 0x01, 0x37, 0x38, 0xa0, 0x42, 0x57, 0x12, - 0x00, 0xb9, 0xbd, 0x68, 0x22, 0x27, 0x4e, 0x6d, 0x8b, 0x3e, 0x24, 0x70, 0xc9, 0xff, 0x31, 0x41, - 0x17, 0x53, 0xaa, 0x06, 0x3f, 0x78, 0xa4, 0xa5, 0x2c, 0xa1, 0x48, 0x97, 0xe7, 0x74, 0xcb, 0x74, - 0x31, 0x81, 0x0e, 0xbf, 0x45, 0xfc, 0x0a, 0x9e, 0x10, 0xb8, 0x1c, 0xb0, 0xec, 0x34, 0xad, 0x60, - 0xc8, 0xf4, 0x49, 0xcb, 0x99, 0x62, 0x91, 0x6e, 0x8d, 0xd3, 0x2d, 0xd1, 0x85, 0x78, 0x3a, 0x7b, - 0xaf, 0xdc, 0xdc, 0xe3, 0xde, 0xd0, 0x55, 0xae, 0x66, 0x5a, 0x2d, 0xfa, 0x2b, 0x81, 0x89, 0x38, - 0xaf, 0x4c, 0xf3, 0xdd, 0xba, 0x16, 0xf1, 0xf7, 0x52, 0xa1, 0x97, 0x14, 0x24, 0x7e, 0x95, 0x13, - 0xdf, 0xa0, 0xeb, 0x69, 0xdd, 0x36, 0x75, 0x4e, 0x2e, 0x6e, 0xf9, 0x94, 0xfd, 0x25, 0x0a, 0x2f, - 0x04, 0xce, 0x06, 0x1f, 0xd0, 0xb9, 0xd0, 0x4b, 0x0a, 0xc2, 0xdf, 0xe2, 0xf0, 0x05, 0xba, 0x96, - 0x01, 0x3e, 0x28, 0xfb, 0x67, 0x04, 0x46, 0xbc, 0x97, 0x2d, 0x7d, 0x39, 0xbe, 0x74, 0xc8, 0x15, - 0x48, 0x73, 0xdd, 0xc2, 0x90, 0x4a, 0xe5, 0x54, 0x8b, 0x74, 0x3e, 0x42, 0xe5, 0x9d, 0x62, 0xea, - 0xb1, 0xef, 0x88, 0x6b, 0xd1, 0xc7, 0x04, 0xae, 0xc5, 0xdb, 0x3e, 0xba, 0x9e, 0x5e, 0x33, 0xd6, - 0xc7, 0x4a, 0x1b, 0xbd, 0x25, 0x21, 0xf6, 0x6b, 0x1c, 0x7b, 0x93, 0x6e, 0x24, 0x62, 0x77, 0x86, - 0x00, 0x0f, 0x01, 0xdf, 0xf3, 0xff, 0x98, 0xc0, 0x73, 0x31, 0xee, 0x8c, 0xae, 0xc5, 0xb3, 0x24, - 0x9b, 0x47, 0x29, 0xdf, 0x43, 0x06, 0xa2, 0xbf, 0xc5, 0xd1, 0xdf, 0xa4, 0xaf, 0x47, 0xd0, 0xdd, - 0xf7, 0xbd, 0x4b, 0xdd, 0xd6, 0x9b, 0x7b, 0x92, 0xa0, 0xfe, 0xea, 0x31, 0xbf, 0xd8, 0xa2, 0x3f, - 0x12, 0x18, 0x0f, 0x19, 0xb1, 0xa4, 0xa3, 0x36, 0xde, 0x38, 0x26, 0x1d, 0xb5, 0x09, 0xee, 0x2e, - 0x65, 0x7e, 0xb9, 0x4f, 0xf1, 0x83, 0x87, 0x46, 0xe6, 0x1b, 0x02, 0x97, 0xfc, 0x3e, 0x28, 0xe9, - 0xb8, 0x8d, 0x31, 0x70, 0x49, 0xc7, 0x6d, 0x9c, 0xad, 0x4a, 0x99, 0xe5, 0x36, 0x21, 0x2a, 0x8a, - 0x1a, 0x3e, 0x22, 0x70, 0x25, 0xe8, 0x38, 0x68, 0x97, 0x13, 0x34, 0x60, 0x99, 0xa4, 0x95, 0x6c, - 0xc1, 0x88, 0xb7, 0xce, 0xf1, 0x56, 0xe9, 0x72, 0xca, 0x79, 0x2b, 0xde, 0x08, 0xbe, 0x51, 0x3d, - 0x21, 0x30, 0xe6, 0xf3, 0x01, 0x74, 0x21, 0xbe, 0x64, 0xd4, 0x9b, 0x48, 0x8b, 0x19, 0x22, 0x91, - 0x6c, 0x93, 0x93, 0xad, 0x51, 0x25, 0xf9, 0x69, 0x0a, 0x4d, 0x21, 0xf7, 0x21, 0xc5, 0x37, 0x9e, - 0x9c, 0xe6, 0xc8, 0xd3, 0xd3, 0x1c, 0xf9, 0xeb, 0x34, 0x47, 0xbe, 0x38, 0xcb, 0x0d, 0x3c, 0x3d, - 0xcb, 0x0d, 0xfc, 0x71, 0x96, 0x1b, 0xf8, 0xe0, 0x25, 0xc3, 0x74, 0x3e, 0x3c, 0x2c, 0x2b, 0xfb, - 0xac, 0xe6, 0xad, 0x29, 0xfe, 0x59, 0xb5, 0x2b, 0x1f, 0xa9, 0x1f, 0x8b, 0x02, 0xe5, 0x8b, 0xfc, - 0xcf, 0xb0, 0xeb, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x11, 0xfe, 0x04, 0xa9, 0x4e, 0x16, 0x00, - 0x00, + // 1292 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x98, 0x4b, 0x6f, 0x1b, 0x55, + 0x14, 0xc7, 0x73, 0x4b, 0x9e, 0x27, 0x6d, 0x23, 0x6e, 0xd3, 0x36, 0x99, 0x46, 0x4e, 0x98, 0x96, + 0xbc, 0x33, 0x13, 0x3b, 0x69, 0x5a, 0xf1, 0x54, 0x2d, 0x41, 0xc8, 0xa2, 0x28, 0x35, 0x11, 0x0b, + 0x84, 0x14, 0x8d, 0xe3, 0x89, 0x19, 0x61, 0xcf, 0xb8, 0x9e, 0x49, 0x84, 0x15, 0x79, 0x83, 0x04, + 0x0b, 0xc4, 0x02, 0x5a, 0x84, 0x4a, 0xc4, 0xa2, 0x0b, 0x24, 0xf8, 0x00, 0x20, 0x24, 0x76, 0xdd, + 0x75, 0x59, 0xc1, 0x86, 0x15, 0x42, 0x09, 0xdf, 0x82, 0x0d, 0x9a, 0x7b, 0xcf, 0xb5, 0xe7, 0xed, + 0x89, 0xb0, 0xc0, 0xab, 0x76, 0x66, 0xce, 0xb9, 0xe7, 0x37, 0xff, 0x73, 0xe6, 0xfa, 0x7f, 0x03, + 0xd7, 0xf6, 0x2c, 0xbb, 0x6a, 0xd9, 0x6a, 0xb9, 0x6e, 0x1d, 0xd4, 0xd4, 0xc3, 0xac, 0x7a, 0xff, + 0x40, 0xaf, 0x37, 0x94, 0x5a, 0xdd, 0x72, 0x2c, 0x3a, 0xc6, 0x1f, 0x2a, 0xec, 0xa1, 0x72, 0x98, + 0x95, 0xc6, 0xcb, 0x56, 0xd9, 0x62, 0xcf, 0x54, 0xf7, 0x7f, 0x3c, 0x4c, 0x9a, 0x2a, 0x5b, 0x56, + 0xb9, 0xa2, 0xab, 0x5a, 0xcd, 0x50, 0x35, 0xd3, 0xb4, 0x1c, 0xcd, 0x31, 0x2c, 0xd3, 0xc6, 0xa7, + 0xa1, 0x0a, 0x4e, 0xa3, 0xa6, 0x8b, 0x87, 0x8b, 0xf8, 0xb0, 0xa8, 0xd9, 0x3a, 0x2f, 0xad, 0x1e, + 0x66, 0x8b, 0xba, 0xa3, 0x65, 0xd5, 0x9a, 0x56, 0x36, 0x4c, 0xb6, 0x12, 0xc6, 0x4e, 0xf2, 0xd8, + 0x5d, 0x5e, 0x1f, 0xd1, 0xd8, 0x85, 0x9c, 0x83, 0xcb, 0xf7, 0xdc, 0xe4, 0x4d, 0xb7, 0xc6, 0x96, + 0xb9, 0x6f, 0x15, 0xf4, 0xfb, 0x07, 0xba, 0xed, 0xd0, 0x49, 0x18, 0x66, 0x75, 0x77, 0x8d, 0xd2, + 0x04, 0x99, 0x21, 0xf3, 0xfd, 0x85, 0x21, 0x76, 0xbd, 0x55, 0x92, 0xdf, 0x82, 0x2b, 0xc1, 0x1c, + 0xbb, 0x66, 0x99, 0xb6, 0x4e, 0x15, 0xe8, 0x37, 0xcc, 0x7d, 0x8b, 0x25, 0x8c, 0xe6, 0x24, 0x25, + 0xa0, 0x82, 0xd2, 0xce, 0x60, 0x71, 0xf2, 0x3d, 0xb8, 0xd6, 0x5e, 0x69, 0xdb, 0xaa, 0x18, 0x7b, + 0x0d, 0x2f, 0x43, 0x0e, 0x86, 0xb4, 0x52, 0xa9, 0xae, 0xdb, 0x36, 0x5b, 0x71, 0x24, 0x3f, 0xf1, + 0xeb, 0x8f, 0x2b, 0xe3, 0xb8, 0xe8, 0x1d, 0xfe, 0xe4, 0x1d, 0xa7, 0x6e, 0x98, 0xe5, 0x82, 0x08, + 0x94, 0x77, 0x60, 0x2a, 0x7a, 0x49, 0x44, 0x5c, 0xf7, 0x21, 0xce, 0x44, 0x23, 0x7a, 0xf2, 0x38, + 0x68, 0x13, 0x26, 0xda, 0xab, 0xde, 0xd5, 0xab, 0x45, 0xbd, 0x6e, 0x77, 0x56, 0x8a, 0xbe, 0x09, + 0xd0, 0x6e, 0xc6, 0xc4, 0x39, 0x56, 0x72, 0x56, 0x94, 0x74, 0x3b, 0xa7, 0xf0, 0xa1, 0xc1, 0xce, + 0x29, 0xdb, 0x5a, 0x59, 0xc7, 0x65, 0x0b, 0x9e, 0x4c, 0xf9, 0x5b, 0x02, 0x93, 0x11, 0xf5, 0xf1, + 0x95, 0x36, 0x60, 0xa8, 0xca, 0x6f, 0x4d, 0x90, 0x99, 0xe7, 0xe6, 0x47, 0x73, 0x53, 0xd1, 0x6f, + 0xc5, 0xf3, 0x0a, 0x22, 0x98, 0x6e, 0x46, 0xd0, 0xcd, 0x75, 0xa4, 0xe3, 0x45, 0x7d, 0x78, 0x0f, + 0x7d, 0x78, 0x76, 0xbe, 0x71, 0xa7, 0x54, 0x35, 0x4c, 0xa1, 0x8f, 0x02, 0x03, 0x9a, 0x7b, 0xdd, + 0xb1, 0x87, 0x3c, 0xac, 0x6b, 0xa2, 0x7d, 0x43, 0x40, 0x8a, 0xa2, 0x42, 0xd5, 0x72, 0x30, 0xc8, + 0xe4, 0x11, 0xa2, 0x25, 0x4d, 0x2b, 0x46, 0x76, 0x4f, 0xb1, 0x4f, 0x08, 0xcc, 0x04, 0xc6, 0xd4, + 0xd0, 0xed, 0x3c, 0xbf, 0xfc, 0x0f, 0x07, 0xeb, 0x27, 0x02, 0x2f, 0x24, 0x70, 0xa0, 0x54, 0x9b, + 0x70, 0x91, 0x83, 0xd4, 0x30, 0x00, 0x25, 0xeb, 0xfc, 0xf5, 0x5c, 0x28, 0x7b, 0xd7, 0xed, 0x9e, + 0x7e, 0xc7, 0x31, 0xfa, 0xf5, 0xc4, 0xe0, 0xc5, 0x89, 0xea, 0x9f, 0xbf, 0xde, 0x13, 0xf5, 0x16, + 0x8c, 0x33, 0xec, 0xed, 0xba, 0x55, 0xb3, 0x6c, 0xad, 0x22, 0x74, 0x9c, 0x86, 0xd1, 0x1a, 0xde, + 0x6a, 0x8f, 0x22, 0x88, 0x5b, 0x5b, 0x25, 0xf9, 0x6d, 0xfc, 0x11, 0x69, 0x27, 0xe2, 0x3b, 0xde, + 0x84, 0x61, 0x11, 0x86, 0x1b, 0xee, 0x64, 0xe8, 0xed, 0x5a, 0x49, 0xad, 0x50, 0xf9, 0x31, 0x01, + 0xd9, 0xb7, 0xa0, 0x98, 0x48, 0x2e, 0xc2, 0xbf, 0xf8, 0x79, 0xe8, 0x5a, 0x8f, 0xbf, 0x27, 0x70, + 0x3d, 0x11, 0x11, 0x15, 0xb8, 0x05, 0x23, 0xe2, 0xb5, 0x44, 0x83, 0x13, 0x24, 0x68, 0xc7, 0x76, + 0xaf, 0xab, 0x75, 0x98, 0x66, 0xa0, 0xef, 0x5a, 0x8e, 0x9e, 0x6f, 0xe1, 0xba, 0x57, 0xf5, 0xb4, + 0x0d, 0x76, 0xbf, 0xa4, 0x43, 0x37, 0x81, 0x71, 0x24, 0x7e, 0x49, 0x2c, 0x4c, 0xbe, 0x8b, 0x5f, + 0x67, 0x64, 0x4d, 0x54, 0x66, 0x01, 0xfa, 0xdd, 0x60, 0x9c, 0x8b, 0xcb, 0x21, 0x51, 0xdc, 0xe8, + 0x02, 0x0b, 0x91, 0x3f, 0x25, 0xe8, 0x13, 0xdc, 0x7b, 0x76, 0xfe, 0xcc, 0x03, 0xda, 0xb5, 0xae, + 0x7f, 0x45, 0xd0, 0x5d, 0x84, 0x40, 0xf0, 0xa5, 0x96, 0xb8, 0x50, 0xa2, 0xd5, 0x31, 0x6f, 0xc5, + 0x63, 0xba, 0xd7, 0xe2, 0x07, 0x04, 0xed, 0x09, 0x62, 0xf9, 0x9a, 0xdb, 0xea, 0x1d, 0x49, 0xd5, + 0xbb, 0xae, 0x69, 0xf5, 0xa5, 0x30, 0x05, 0x7e, 0xa8, 0xff, 0x55, 0xa8, 0x47, 0x41, 0x4b, 0x80, + 0x96, 0xa8, 0x07, 0x36, 0x94, 0x63, 0xe2, 0xf5, 0xc2, 0x1e, 0xb4, 0x5e, 0xb0, 0x2b, 0x2f, 0xc1, + 0x55, 0xc6, 0xb6, 0xa3, 0x55, 0x2a, 0xee, 0xde, 0x76, 0x50, 0x71, 0x52, 0xff, 0x38, 0xec, 0xe0, + 0x6c, 0xfa, 0x72, 0xf1, 0xa5, 0x6e, 0xc3, 0x80, 0xe3, 0xde, 0xc6, 0x4d, 0x20, 0xec, 0x5b, 0x3d, + 0x49, 0xf9, 0xfe, 0xa7, 0x7f, 0x4c, 0xf7, 0x15, 0x78, 0x82, 0xfc, 0x3e, 0x50, 0x8f, 0x5a, 0x02, + 0xa6, 0x5b, 0xcd, 0x78, 0x40, 0xe0, 0x92, 0x6f, 0xf9, 0x1e, 0x68, 0x42, 0xee, 0xef, 0xe7, 0x61, + 0x80, 0x41, 0xd1, 0xcf, 0x09, 0x8c, 0xb4, 0x0a, 0xd1, 0xd9, 0x10, 0x44, 0xe4, 0x89, 0x4e, 0x9a, + 0xeb, 0x18, 0xc7, 0x8b, 0xca, 0xca, 0xc7, 0xbf, 0xfd, 0xf5, 0xf0, 0xdc, 0x3c, 0x9d, 0x55, 0x83, + 0x07, 0x50, 0xb4, 0xa3, 0xe6, 0xbe, 0xa5, 0x1e, 0x09, 0x6b, 0xda, 0xa4, 0xdf, 0x11, 0x18, 0x0b, + 0x78, 0x14, 0xba, 0x9c, 0x50, 0x2c, 0x74, 0xd0, 0x93, 0x56, 0x52, 0x46, 0x23, 0xe0, 0x3a, 0x03, + 0x54, 0xe8, 0x72, 0x0c, 0x20, 0x73, 0x54, 0x0d, 0xe4, 0xc4, 0x0f, 0xb5, 0x49, 0x1f, 0x11, 0x38, + 0xef, 0x3d, 0x3f, 0xd1, 0x85, 0x84, 0xaa, 0xfe, 0x33, 0x9e, 0xb4, 0x98, 0x26, 0x14, 0xe9, 0xb2, + 0x8c, 0x6e, 0x89, 0x2e, 0xc4, 0xd0, 0xe1, 0xf1, 0xcb, 0xab, 0xe0, 0x31, 0x81, 0x0b, 0xbe, 0x53, + 0x0a, 0x4d, 0x2a, 0x18, 0xf0, 0xb9, 0xd2, 0x52, 0xaa, 0x58, 0xa4, 0x5b, 0x65, 0x74, 0x8b, 0x74, + 0x3e, 0x9a, 0xce, 0xde, 0x2d, 0x36, 0x76, 0x99, 0x1d, 0x76, 0x95, 0xab, 0x1a, 0x66, 0x93, 0xfe, + 0x42, 0x60, 0x3c, 0xea, 0x78, 0x40, 0xb3, 0x9d, 0xba, 0x16, 0x3a, 0xd2, 0x48, 0xb9, 0xb3, 0xa4, + 0x20, 0xf1, 0xcb, 0x8c, 0xf8, 0x26, 0x5d, 0x4b, 0xea, 0xb6, 0xa1, 0x33, 0x72, 0xfe, 0xc8, 0xa3, + 0xec, 0xcf, 0x61, 0x78, 0x2e, 0x70, 0x3a, 0x78, 0x9f, 0xce, 0xb9, 0xb3, 0xa4, 0x20, 0xfc, 0x6d, + 0x06, 0x9f, 0xa3, 0xab, 0x29, 0xe0, 0xfd, 0xb2, 0x7f, 0x46, 0x60, 0x58, 0xf8, 0x0b, 0xfa, 0x62, + 0x74, 0xe9, 0x80, 0x11, 0x92, 0x66, 0x3b, 0x85, 0x21, 0x95, 0xca, 0xa8, 0x16, 0xe8, 0x5c, 0x88, + 0x4a, 0x6c, 0xdc, 0xea, 0x91, 0x67, 0x57, 0x6f, 0xd2, 0x27, 0x04, 0xae, 0x44, 0x3b, 0x5d, 0xba, + 0x96, 0x5c, 0x33, 0xd2, 0xba, 0x4b, 0xeb, 0x67, 0x4b, 0x42, 0xec, 0x57, 0x18, 0xf6, 0x06, 0x5d, + 0x8f, 0xc5, 0x6e, 0x0f, 0x01, 0x6e, 0x02, 0x9e, 0xef, 0xff, 0x09, 0x81, 0x4b, 0x11, 0x86, 0x94, + 0xae, 0x46, 0xb3, 0xc4, 0xfb, 0x65, 0x29, 0x7b, 0x86, 0x0c, 0x44, 0x7f, 0x83, 0xa1, 0xbf, 0x4e, + 0x5f, 0x0d, 0xa1, 0xbb, 0x16, 0xc7, 0xa5, 0x6e, 0xe9, 0xcd, 0x6c, 0x98, 0x5f, 0x7f, 0xf5, 0x88, + 0xdd, 0x6c, 0xd2, 0x1f, 0x08, 0x8c, 0x05, 0xbc, 0x67, 0xdc, 0x56, 0x1b, 0xed, 0x95, 0xe3, 0xb6, + 0xda, 0x18, 0x43, 0x9b, 0x30, 0xbf, 0xcc, 0x9a, 0x79, 0xc1, 0x03, 0x23, 0xf3, 0x35, 0x81, 0xf3, + 0x5e, 0xeb, 0x17, 0xb7, 0xdd, 0x46, 0x78, 0xd6, 0xb8, 0xed, 0x36, 0xca, 0x49, 0x26, 0xcc, 0x72, + 0x8b, 0x10, 0x15, 0x45, 0x0d, 0x1f, 0x13, 0xb8, 0xe8, 0x37, 0x59, 0xb4, 0xc3, 0x0e, 0xea, 0x73, + 0x89, 0xd2, 0x72, 0xba, 0x60, 0xc4, 0x5b, 0x63, 0x78, 0x2b, 0x74, 0x29, 0x61, 0xbf, 0xe5, 0xbf, + 0x08, 0x9e, 0x51, 0x3d, 0x26, 0x30, 0xea, 0xb1, 0x3e, 0x74, 0x3e, 0xba, 0x64, 0xd8, 0x8e, 0x49, + 0x0b, 0x29, 0x22, 0x91, 0x6c, 0x83, 0x91, 0xad, 0x52, 0x25, 0xfe, 0x6b, 0x0a, 0x4c, 0x21, 0xb3, + 0x5e, 0xd4, 0x81, 0x41, 0xfe, 0xae, 0xf4, 0x7a, 0x92, 0x12, 0x82, 0xe8, 0x46, 0x72, 0x10, 0xc2, + 0x4c, 0x33, 0x98, 0x49, 0x7a, 0x35, 0x46, 0xa6, 0xfc, 0x6b, 0x4f, 0x4f, 0x32, 0xe4, 0xd9, 0x49, + 0x86, 0xfc, 0x79, 0x92, 0x21, 0x5f, 0x9c, 0x66, 0xfa, 0x9e, 0x9d, 0x66, 0xfa, 0x7e, 0x3f, 0xcd, + 0xf4, 0xbd, 0x77, 0xa3, 0x6c, 0x38, 0x1f, 0x1c, 0x14, 0x95, 0x3d, 0xab, 0x2a, 0x92, 0xf9, 0x3f, + 0x2b, 0x76, 0xe9, 0x43, 0xf5, 0x23, 0xbe, 0x40, 0x71, 0x90, 0xfd, 0xbd, 0x7b, 0xed, 0x9f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x1c, 0xce, 0x79, 0xa7, 0xb7, 0x17, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1536,6 +1645,10 @@ type QueryClient interface { // then it simply returns the `final_tally_result` state stored in the // proposal itself. TallyResult(ctx context.Context, in *QueryTallyResultRequest, opts ...grpc.CallOption) (*QueryTallyResultResponse, error) + // Groups queries all groups in state. + // + // Since: cosmos-sdk 0.47.1 + Groups(ctx context.Context, in *QueryGroupsRequest, opts ...grpc.CallOption) (*QueryGroupsResponse, error) } type queryClient struct { @@ -1663,6 +1776,15 @@ func (c *queryClient) TallyResult(ctx context.Context, in *QueryTallyResultReque return out, nil } +func (c *queryClient) Groups(ctx context.Context, in *QueryGroupsRequest, opts ...grpc.CallOption) (*QueryGroupsResponse, error) { + out := new(QueryGroupsResponse) + err := c.cc.Invoke(ctx, "/cosmos.group.v1.Query/Groups", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // GroupInfo queries group info based on group id. @@ -1695,6 +1817,10 @@ type QueryServer interface { // then it simply returns the `final_tally_result` state stored in the // proposal itself. TallyResult(context.Context, *QueryTallyResultRequest) (*QueryTallyResultResponse, error) + // Groups queries all groups in state. + // + // Since: cosmos-sdk 0.47.1 + Groups(context.Context, *QueryGroupsRequest) (*QueryGroupsResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1740,6 +1866,9 @@ func (*UnimplementedQueryServer) GroupsByMember(ctx context.Context, req *QueryG func (*UnimplementedQueryServer) TallyResult(ctx context.Context, req *QueryTallyResultRequest) (*QueryTallyResultResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method TallyResult not implemented") } +func (*UnimplementedQueryServer) Groups(ctx context.Context, req *QueryGroupsRequest) (*QueryGroupsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Groups not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1979,6 +2108,24 @@ func _Query_TallyResult_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Query_Groups_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGroupsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Groups(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.group.v1.Query/Groups", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Groups(ctx, req.(*QueryGroupsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.group.v1.Query", HandlerType: (*QueryServer)(nil), @@ -2035,6 +2182,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "TallyResult", Handler: _Query_TallyResult_Handler, }, + { + MethodName: "Groups", + Handler: _Query_Groups_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cosmos/group/v1/query.proto", @@ -3084,6 +3235,90 @@ func (m *QueryTallyResultResponse) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *QueryGroupsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryGroupsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryGroupsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Groups) > 0 { + for iNdEx := len(m.Groups) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Groups[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -3508,6 +3743,38 @@ func (m *QueryTallyResultResponse) Size() (n int) { return n } +func (m *QueryGroupsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Groups) > 0 { + for _, e := range m.Groups { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -6196,6 +6463,212 @@ func (m *QueryTallyResultResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryGroupsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryGroupsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryGroupsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Groups", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Groups = append(m.Groups, &GroupInfo{}) + if err := m.Groups[len(m.Groups)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/group/query.pb.gw.go b/x/group/query.pb.gw.go index d9f8b8c588b0..a0a30e91c3a6 100644 --- a/x/group/query.pb.gw.go +++ b/x/group/query.pb.gw.go @@ -901,6 +901,42 @@ func local_request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Ma } +var ( + filter_Query_Groups_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Groups_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Groups_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Groups(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Groups_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Groups_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Groups(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -1206,6 +1242,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_Groups_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Groups_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Groups_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1507,6 +1566,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_Groups_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Groups_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Groups_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1536,6 +1615,8 @@ var ( pattern_Query_GroupsByMember_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "group", "v1", "groups_by_member", "address"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_TallyResult_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "group", "v1", "proposals", "proposal_id", "tally"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Groups_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "group", "v1", "groups"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -1564,4 +1645,6 @@ var ( forward_Query_GroupsByMember_0 = runtime.ForwardResponseMessage forward_Query_TallyResult_0 = runtime.ForwardResponseMessage + + forward_Query_Groups_0 = runtime.ForwardResponseMessage ) From cb26943776e945a16667a7dcbb016d982958ba73 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 23 Mar 2023 12:07:48 +0100 Subject: [PATCH 18/47] fix: Makefile rocksdb (backport #15422) (#15525) Co-authored-by: Robert Zaremba --- Makefile | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 8de4eb33af80..88ad979ffad0 100644 --- a/Makefile +++ b/Makefile @@ -15,9 +15,6 @@ DOCKER := $(shell which docker) DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf:1.0.0-rc8 PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git) DOCS_DOMAIN=docs.cosmos.network -# RocksDB is a native dependency, so we don't assume the library is installed. -# Instead, it must be explicitly enabled and we warn when it is not. -ENABLE_ROCKSDB ?= false export GO111MODULE = on @@ -63,33 +60,23 @@ ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=sim \ -X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \ -X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \ -X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" \ - -X github.com/tendermint/tendermint/version.TMCoreSemVer=$(TMVERSION) - -ifeq ($(ENABLE_ROCKSDB),true) - BUILD_TAGS += rocksdb_build - test_tags += rocksdb_build -else - $(warning RocksDB support is disabled; to build and test with RocksDB support, set ENABLE_ROCKSDB=true) -endif + -X github.com/tendermint/tendermint/version.TMCoreSemVer=$(TMVERSION) # DB backend selection ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS))) build_tags += gcc endif ifeq (badgerdb,$(findstring badgerdb,$(COSMOS_BUILD_OPTIONS))) - BUILD_TAGS += badgerdb + build_tags += badgerdb endif # handle rocksdb ifeq (rocksdb,$(findstring rocksdb,$(COSMOS_BUILD_OPTIONS))) - ifneq ($(ENABLE_ROCKSDB),true) - $(error Cannot use RocksDB backend unless ENABLE_ROCKSDB=true) - endif CGO_ENABLED=1 - BUILD_TAGS += rocksdb + build_tags += rocksdb endif # handle boltdb ifeq (boltdb,$(findstring boltdb,$(COSMOS_BUILD_OPTIONS))) - BUILD_TAGS += boltdb + build_tags += boltdb endif ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS))) From f89d955e03e2143c6f985f692f87da0557e0654b Mon Sep 17 00:00:00 2001 From: yihuang Date: Mon, 3 Apr 2023 16:42:36 +0800 Subject: [PATCH 19/47] fix(x/gov): Return ErrInvalidProposalContent in SubmitProposal when legacy handler returns an error. (backport #13051) (#15667) Co-authored-by: Daniel Wedul Co-authored-by: Aleksandr Bezobchuk --- CHANGELOG.md | 1 + x/gov/keeper/proposal.go | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0d64cb7198c..3148998fb271 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes * (x/auth/vesting) [#15383](https://github.com/cosmos/cosmos-sdk/pull/15383) Add extra checks when creating a periodic vesting account. +* (x/gov) [#13051](https://github.com/cosmos/cosmos-sdk/pull/13051) In SubmitPropsal, when a legacy msg fails it's handler call, wrap the error as ErrInvalidProposalContent (instead of ErrNoProposalHandlerExists). ## [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11) - 2022-03-03 diff --git a/x/gov/keeper/proposal.go b/x/gov/keeper/proposal.go index 64088859c684..b49cd8335042 100644 --- a/x/gov/keeper/proposal.go +++ b/x/gov/keeper/proposal.go @@ -1,6 +1,7 @@ package keeper import ( + "errors" "fmt" "github.com/cosmos/cosmos-sdk/client" @@ -54,7 +55,10 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, messages []sdk.Msg, metadat if msg, ok := msg.(*v1.MsgExecLegacyContent); ok { cacheCtx, _ := ctx.CacheContext() if _, err := handler(cacheCtx, msg); err != nil { - return v1.Proposal{}, sdkerrors.Wrap(types.ErrNoProposalHandlerExists, err.Error()) + if errors.Is(types.ErrNoProposalHandlerExists, err) { + return v1.Proposal{}, err + } + return v1.Proposal{}, sdkerrors.Wrap(types.ErrInvalidProposalContent, err.Error()) } } From 152465bd0ca726e59a688fbb006c84760627c7e4 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 11:23:11 +0200 Subject: [PATCH 20/47] fix: remove unnecessary cms typecasting (backport #14054) (#15669) Co-authored-by: Javier Su Co-authored-by: Julien Robert --- CHANGELOG.md | 1 + baseapp/baseapp.go | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3148998fb271..00830c058496 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (simapp) [#15305](https://github.com/cosmos/cosmos-sdk/pull/15305) Add `AppStateFnWithExtendedCb` with callback function to extend rawState and `AppStateRandomizedFnWithState` with extra genesisState argument which is the genesis state of the app. * (x/distribution) [#15462](https://github.com/cosmos/cosmos-sdk/pull/15462) Add delegator address to the event for withdrawing delegation rewards +* [#14019](https://github.com/cosmos/cosmos-sdk/issues/14019) Remove the interface casting to allow other implementations of a `CommitMultiStore`. ### Bug Fixes diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 78d57763726e..98c2f226a059 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -1,6 +1,7 @@ package baseapp import ( + "errors" "fmt" "strings" @@ -14,7 +15,6 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/snapshots" "github.com/cosmos/cosmos-sdk/store" - "github.com/cosmos/cosmos-sdk/store/rootmulti" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -352,11 +352,11 @@ func (app *BaseApp) Init() error { app.setCheckState(tmproto.Header{}) app.Seal() - rms, ok := app.cms.(*rootmulti.Store) - if !ok { - return fmt.Errorf("invalid commit multi-store; expected %T, got: %T", &rootmulti.Store{}, app.cms) + if app.cms == nil { + return errors.New("commit multi-store must not be nil") } - return rms.GetPruning().Validate() + + return app.cms.GetPruning().Validate() } func (app *BaseApp) setMinGasPrices(gasPrices sdk.DecCoins) { From 5cd0b2316a7103468af38eab5d886f9f069c9cd7 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Tue, 4 Apr 2023 14:57:44 +0200 Subject: [PATCH 21/47] chore: prepare v0.46.12 release notes (#15685) --- CHANGELOG.md | 2 ++ RELEASE_NOTES.md | 14 +++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00830c058496..778a592cd08a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +## [v0.46.12](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.12) - 2022-04-04 + ### Features * (x/groups) [#14879](https://github.com/cosmos/cosmos-sdk/pull/14879) Add `Query/Groups` query to get all the groups. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 381bb7ca8b0f..524ad6e1f087 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,18 +1,14 @@ -# Cosmos SDK v0.46.11 Release Notes +# Cosmos SDK v0.46.12 Release Notes -This release includes the migration to [CometBFT v0.34.27](https://github.com/cometbft/cometbft/blob/v0.34.27/CHANGELOG.md#v03427). -This migration should be not be breaking for chains. -From `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your application: +This release introduces a number of improvements and bug fixes, notably a new query for the `x/group` module, for querying all groups on a chain. + +Note, from `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your application: ```go // use cometbft replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 ``` -Additionally, the SDK sets its minimum version to Go 1.19. This is not because the SDK uses new Go 1.19 functionalities, but to signal that we recommend chains to upgrade to Go 1.19 — Go 1.18 is not supported by the Go Team anymore. -Note, that SDK recommends chains to use the same Go version across all of their network. -We recommend, as well, chains to perform a **coordinated upgrade** when migrating from Go 1.18 to Go 1.19. - Please see the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/CHANGELOG.md) for an exhaustive list of changes. -**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.10...v0.46.11 +**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.11...v0.46.12 From 1a47cb26d24a44844524cd3c2d3a0c08db1ef6f3 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 09:55:02 +0200 Subject: [PATCH 22/47] fix: upstream error on empty version (backport #13355) (#15717) Co-authored-by: Marko Co-authored-by: Julien Robert --- CHANGELOG.md | 4 ++++ store/iavl/store.go | 2 +- store/iavl/store_test.go | 2 +- store/rootmulti/store_test.go | 12 ++++++------ 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 778a592cd08a..f3d21706382e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Bug Fixes + +* (store/iavl) [#15717](https://github.com/cosmos/cosmos-sdk/pull/15717) Upstream error on empty version (this change was present on all version but v0.46). + ## [v0.46.12](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.12) - 2022-04-04 ### Features diff --git a/store/iavl/store.go b/store/iavl/store.go index 3cf6c1dedbf2..7517f934f4de 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -111,7 +111,7 @@ func UnsafeNewStore(tree *iavl.MutableTree) *Store { // Any mutable operations executed will result in a panic. func (st *Store) GetImmutable(version int64) (*Store, error) { if !st.VersionExists(version) { - return &Store{tree: &immutableTree{&iavl.ImmutableTree{}}}, nil + return nil, fmt.Errorf("version mismatch on immutable IAVL tree; version does not exist. Version has either been pruned, or is for a future block height") } iTree, err := st.tree.GetImmutable(version) diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index dabe1e37f630..8379779c158b 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -127,7 +127,7 @@ func TestGetImmutable(t *testing.T) { require.Nil(t, err) _, err = store.GetImmutable(cID.Version + 1) - require.NoError(t, err) + require.Error(t, err) newStore, err := store.GetImmutable(cID.Version - 1) require.NoError(t, err) diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index 0e78e0f95bed..fe773b51d6e6 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -88,7 +88,7 @@ func TestCacheMultiStoreWithVersion(t *testing.T) { // require no failure when given an invalid or pruned version _, err = ms.CacheMultiStoreWithVersion(cID.Version + 1) - require.NoError(t, err) + require.Error(t, err) // require a valid version can be cache-loaded cms, err := ms.CacheMultiStoreWithVersion(cID.Version) @@ -482,9 +482,9 @@ func TestMultiStore_Pruning(t *testing.T) { saved []int64 }{ {"prune nothing", 10, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), nil, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, - {"prune everything", 10, pruningtypes.NewPruningOptions(pruningtypes.PruningEverything), []int64{1, 2, 3, 4, 5, 6, 7, 8, 9}, []int64{10}}, - {"prune some; no batch", 10, pruningtypes.NewCustomPruningOptions(2, 1), []int64{1, 2, 4, 5, 7}, []int64{3, 6, 8, 9, 10}}, - {"prune some; small batch", 10, pruningtypes.NewCustomPruningOptions(2, 3), []int64{1, 2, 4, 5}, []int64{3, 6, 7, 8, 9, 10}}, + {"prune everything", 12, pruningtypes.NewPruningOptions(pruningtypes.PruningEverything), []int64{1, 2, 3, 4, 5, 6, 7}, []int64{8, 9, 10, 11, 12}}, + {"prune some; no batch", 10, pruningtypes.NewCustomPruningOptions(2, 1), []int64{1, 2, 3, 4, 6, 5, 7}, []int64{8, 9, 10}}, + {"prune some; small batch", 10, pruningtypes.NewCustomPruningOptions(2, 3), []int64{1, 2, 3, 4, 5, 6}, []int64{7, 8, 9, 10}}, {"prune some; large batch", 10, pruningtypes.NewCustomPruningOptions(2, 11), nil, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, } @@ -502,12 +502,12 @@ func TestMultiStore_Pruning(t *testing.T) { for _, v := range tc.saved { _, err := ms.CacheMultiStoreWithVersion(v) - require.NoError(t, err, "expected error when loading height: %d", v) + require.NoError(t, err, "expected no error when loading height: %d", v) } for _, v := range tc.deleted { _, err := ms.CacheMultiStoreWithVersion(v) - require.NoError(t, err, "expected error when loading height: %d", v) + require.Error(t, err, "expected error when loading height: %d", v) } }) } From 95f529ee4380b4e91a4bcbf124fe0f110adeb984 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 11:31:13 +0200 Subject: [PATCH 23/47] feat: More flexibility for `CacheMultiStoreWithVersion` (backport #15683) (#15775) Co-authored-by: khanh-notional <50263489+catShaark@users.noreply.github.com> Co-authored-by: Julien Robert --- CHANGELOG.md | 4 ++++ store/rootmulti/store.go | 25 ++++++++++++++++++++++++- store/rootmulti/store_test.go | 11 +++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3d21706382e..f656130c3784 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Improvements + +* (store) [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has. + ### Bug Fixes * (store/iavl) [#15717](https://github.com/cosmos/cosmos-sdk/pull/15717) Upstream error on empty version (this change was present on all version but v0.46). diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 74915695ab40..7397abd0424e 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -481,6 +481,8 @@ func (rs *Store) CacheMultiStore() types.CacheMultiStore { // iterating at past heights. func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStore, error) { cachedStores := make(map[types.StoreKey]types.CacheWrapper) + var commitInfo *types.CommitInfo + storeInfos := map[string]bool{} for key, store := range rs.stores { var cacheStore types.KVStore switch store.GetStoreType() { @@ -493,9 +495,30 @@ func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStor // version does not exist or is pruned, an error should be returned. var err error cacheStore, err = store.(*iavl.Store).GetImmutable(version) + // if we got error from loading a module store + // we fetch commit info of this version + // we use commit info to check if the store existed at this version or not if err != nil { - return nil, err + if commitInfo == nil { + var errCommitInfo error + commitInfo, errCommitInfo = getCommitInfo(rs.db, version) + + if errCommitInfo != nil { + return nil, errCommitInfo + } + + for _, storeInfo := range commitInfo.StoreInfos { + storeInfos[storeInfo.Name] = true + } + } + + // If the store existed at this version, it means there's actually an error + // getting the root store at this version. + if storeInfos[key.Name()] { + return nil, err + } } + default: cacheStore = store } diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index fe773b51d6e6..69e773be1a80 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -99,6 +99,17 @@ func TestCacheMultiStoreWithVersion(t *testing.T) { require.NotNil(t, kvStore) require.Equal(t, kvStore.Get(k), v) + // add new module stores (store4 and store5) to multi stores and commit + ms.MountStoreWithDB(types.NewKVStoreKey("store4"), types.StoreTypeIAVL, nil) + ms.MountStoreWithDB(types.NewKVStoreKey("store5"), types.StoreTypeIAVL, nil) + err = ms.LoadLatestVersionAndUpgrade(&types.StoreUpgrades{Added: []string{"store4", "store5"}}) + require.NoError(t, err) + ms.Commit() + + // cache multistore of version before adding store4 should works + _, err = ms.CacheMultiStoreWithVersion(1) + require.NoError(t, err) + // require we cannot commit (write) to a cache-versioned multi-store require.Panics(t, func() { kvStore.Set(k, []byte("newValue")) From 742856fc1c3dee8e17ae73bfe294269000ef1da9 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 18:00:42 +0200 Subject: [PATCH 24/47] feat: add moduleStateCb to allow access moduleState in sim test (backport #15903) (#15925) Co-authored-by: mmsqe Co-authored-by: Julien Robert --- CHANGELOG.md | 1 + simapp/state.go | 37 +++++++++++++++++++++++++++++-------- types/simulation/types.go | 5 ++--- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f656130c3784..abf4bd83a231 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (store) [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has. +* (simapp) [#15903](https://github.com/cosmos/cosmos-sdk/pull/15903) Add `AppStateFnWithExtendedCbs` with moduleStateCb callback function to allow access moduleState. Note, this function is present in simtestutil from `v0.47.2+`. ### Bug Fixes diff --git a/simapp/state.go b/simapp/state.go index 836891cda88d..f491e098dd34 100644 --- a/simapp/state.go +++ b/simapp/state.go @@ -8,6 +8,7 @@ import ( "os" "time" + "github.com/gogo/protobuf/proto" tmjson "github.com/tendermint/tendermint/libs/json" tmtypes "github.com/tendermint/tendermint/types" @@ -32,15 +33,28 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty } // AppStateFnWithExtendedCb returns the initial application state using a genesis or the simulation parameters. +// It calls AppStateFnWithExtendedCbs with nil moduleStateCb. +func AppStateFnWithExtendedCb( + cdc codec.JSONCodec, + simManager *module.SimulationManager, + genesisState map[string]json.RawMessage, + rawStateCb func(rawState map[string]json.RawMessage), +) simtypes.AppStateFn { + return AppStateFnWithExtendedCbs(cdc, simManager, genesisState, nil, rawStateCb) +} + +// AppStateFnWithExtendedCbs returns the initial application state using a genesis or the simulation parameters. // It panics if the user provides files for both of them. // If a file is not given for the genesis or the sim params, it creates a randomized one. -// genesisState is the genesis state of the app. -// cb is the callback function to extend rawState. -func AppStateFnWithExtendedCb( +// genesisState is the default genesis state of the whole app. +// moduleStateCb is the callback function to access moduleState. +// rawStateCb is the callback function to extend rawState. +func AppStateFnWithExtendedCbs( cdc codec.JSONCodec, simManager *module.SimulationManager, genesisState map[string]json.RawMessage, - cb func(rawState map[string]json.RawMessage), + moduleStateCb func(moduleName string, genesisState interface{}), + rawStateCb func(rawState map[string]json.RawMessage), ) simtypes.AppStateFn { return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, ) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) { @@ -139,12 +153,19 @@ func AppStateFnWithExtendedCb( } // change appState back - rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) - rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) + for name, state := range map[string]proto.Message{ + stakingtypes.ModuleName: stakingState, + banktypes.ModuleName: bankState, + } { + if moduleStateCb != nil { + moduleStateCb(name, state) + } + rawState[name] = cdc.MustMarshalJSON(state) + } // extend state from callback function - if cb != nil { - cb(rawState) + if rawStateCb != nil { + rawStateCb(rawState) } // replace appstate diff --git a/types/simulation/types.go b/types/simulation/types.go index bdc0b59659d0..a152413f3c07 100644 --- a/types/simulation/types.go +++ b/types/simulation/types.go @@ -162,9 +162,8 @@ type AppStateFn func(r *rand.Rand, accs []Account, config Config) ( ) // AppStateFnWithExtendedCb returns the app state json bytes and the genesis accounts -type AppStateFnWithExtendedCb func(r *rand.Rand, accs []Account, config Config) ( - appState json.RawMessage, accounts []Account, chainId string, genesisTimestamp time.Time, -) +// Deprecated: Use AppStateFn instead. This will be removed in a future relase. +type AppStateFnWithExtendedCb AppStateFn // RandomAccountFn returns a slice of n random simulation accounts type RandomAccountFn func(r *rand.Rand, n int) []Account From 83eef6bcc79b95ee9c07b42e7174e66de39e7560 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 28 Apr 2023 11:11:47 +0200 Subject: [PATCH 25/47] build(deps): bump cometbft to v0.34.28 (#15973) --- CHANGELOG.md | 1 + Makefile | 2 +- RELEASE_NOTES.md | 8 ++++---- go.mod | 6 +++--- go.sum | 8 ++++---- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abf4bd83a231..54a5ecf770ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (deps) [#15973](https://github.com/cosmos/cosmos-sdk/pull/15973) Bump CometBFT to [v0.34.28](https://github.com/cometbft/cometbft/blob/v0.34.28/CHANGELOG.md#v03428). * (store) [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has. * (simapp) [#15903](https://github.com/cosmos/cosmos-sdk/pull/15903) Add `AppStateFnWithExtendedCbs` with moduleStateCb callback function to allow access moduleState. Note, this function is present in simtestutil from `v0.47.2+`. diff --git a/Makefile b/Makefile index 88ad979ffad0..464ed932482f 100644 --- a/Makefile +++ b/Makefile @@ -417,7 +417,7 @@ proto-lint: proto-check-breaking: @$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main -TM_URL = https://raw.githubusercontent.com/cometbft/cometbft/v0.34.27/proto/tendermint +TM_URL = https://raw.githubusercontent.com/cometbft/cometbft/v0.34.28/proto/tendermint TM_CRYPTO_TYPES = proto/tendermint/crypto TM_ABCI_TYPES = proto/tendermint/abci diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 524ad6e1f087..65aad49293f0 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,14 +1,14 @@ -# Cosmos SDK v0.46.12 Release Notes +# Cosmos SDK v0.46.13 Release Notes -This release introduces a number of improvements and bug fixes, notably a new query for the `x/group` module, for querying all groups on a chain. + Note, from `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your application: ```go // use cometbft -replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 +replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.28 ``` Please see the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/CHANGELOG.md) for an exhaustive list of changes. -**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.11...v0.46.12 +**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.12...v0.46.13 diff --git a/go.mod b/go.mod index d45aad66ba4e..e4b19279164c 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/spf13/viper v1.13.0 github.com/stretchr/testify v1.8.1 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.27 + github.com/tendermint/tendermint v0.34.28 github.com/tendermint/tm-db v0.6.7 github.com/tidwall/btree v1.5.0 golang.org/x/crypto v0.5.0 @@ -68,7 +68,7 @@ require ( cloud.google.com/go/storage v1.27.0 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/Workiva/go-datastructures v1.0.53 // indirect github.com/aws/aws-sdk-go v1.40.45 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -170,7 +170,7 @@ replace ( github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/jhump/protoreflect => github.com/jhump/protoreflect v1.9.0 // use cometbft - github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27 + github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.28 ) retract ( diff --git a/go.sum b/go.sum index 12ad00eae55b..1651603d0926 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,8 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -194,8 +194,8 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= github.com/coinbase/rosetta-sdk-go v0.7.9/go.mod h1:0/knutI7XGVqXmmH4OQD8OckFrbQ8yMsUZTG7FXCR2M= -github.com/cometbft/cometbft v0.34.27 h1:ri6BvmwjWR0gurYjywcBqRe4bbwc3QVs9KRcCzgh/J0= -github.com/cometbft/cometbft v0.34.27/go.mod h1:BcCbhKv7ieM0KEddnYXvQZR+pZykTKReJJYf7YC7qhw= +github.com/cometbft/cometbft v0.34.28 h1:gwryf55P1SWMUP4nOXpRVI2D0yPoYEzN+IBqmRBOsDc= +github.com/cometbft/cometbft v0.34.28/go.mod h1:L9shMfbkZ8B+7JlwANEr+NZbBcn+hBpwdbeYvA5rLCw= github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= From 5e199ca08d1393b3a734d180665d8d032eb821ea Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 28 Apr 2023 09:27:01 +0000 Subject: [PATCH 26/47] chore(gov): improve proposal conversion error message (backport #15979) (#15981) Co-authored-by: Julien Robert Co-authored-by: marbar3778 --- CHANGELOG.md | 1 + x/gov/migrations/v046/convert.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54a5ecf770ec..52bff96d01e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (deps) [#15973](https://github.com/cosmos/cosmos-sdk/pull/15973) Bump CometBFT to [v0.34.28](https://github.com/cometbft/cometbft/blob/v0.34.28/CHANGELOG.md#v03428). * (store) [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has. * (simapp) [#15903](https://github.com/cosmos/cosmos-sdk/pull/15903) Add `AppStateFnWithExtendedCbs` with moduleStateCb callback function to allow access moduleState. Note, this function is present in simtestutil from `v0.47.2+`. +* (gov) [#15979](https://github.com/cosmos/cosmos-sdk/pull/15979) Improve gov error message when failing to convert v1 proposal to v1beta1. ### Bug Fixes diff --git a/x/gov/migrations/v046/convert.go b/x/gov/migrations/v046/convert.go index e368a0b2b2b6..2c632a4124a6 100644 --- a/x/gov/migrations/v046/convert.go +++ b/x/gov/migrations/v046/convert.go @@ -49,7 +49,7 @@ func ConvertToLegacyProposal(proposal v1.Proposal) (v1beta1.Proposal, error) { return v1beta1.Proposal{}, err } if len(msgs) != 1 { - return v1beta1.Proposal{}, sdkerrors.ErrInvalidType.Wrap("can't convert a gov/v1 Proposal to gov/v1beta1 Proposal when amount of proposal messages is more than one") + return v1beta1.Proposal{}, sdkerrors.ErrInvalidType.Wrap("can't convert a gov/v1 Proposal to gov/v1beta1 Proposal when amount of proposal messages not exactly one") } if legacyMsg, ok := msgs[0].(*v1.MsgExecLegacyContent); ok { // check that the content struct can be unmarshalled From 738220aa18cd5248adcd41f1d8357bc92245c514 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 11:16:28 +0000 Subject: [PATCH 27/47] feat!: bootstrap comet cmd for local state sync (backport #16061) (#16080) Co-authored-by: Marko --- CHANGELOG.md | 1 + docs/run-node/run-node.md | 11 +++++ server/tm_cmds.go | 97 +++++++++++++++++++++++++++++++++++++++ server/util.go | 1 + 4 files changed, 110 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52bff96d01e4..bd533d44f0ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (store) [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has. * (simapp) [#15903](https://github.com/cosmos/cosmos-sdk/pull/15903) Add `AppStateFnWithExtendedCbs` with moduleStateCb callback function to allow access moduleState. Note, this function is present in simtestutil from `v0.47.2+`. * (gov) [#15979](https://github.com/cosmos/cosmos-sdk/pull/15979) Improve gov error message when failing to convert v1 proposal to v1beta1. +* (server) [#16061](https://github.com/cosmos/cosmos-sdk/pull/16061) add comet bootstrap command ### Bug Fixes diff --git a/docs/run-node/run-node.md b/docs/run-node/run-node.md index 2233f63aa128..502207761d9c 100644 --- a/docs/run-node/run-node.md +++ b/docs/run-node/run-node.md @@ -125,6 +125,17 @@ The previous command allow you to run a single node. This is enough for the next The naive way would be to run the same commands again in separate terminal windows. This is possible, however in the Cosmos SDK, we leverage the power of [Docker Compose](https://docs.docker.com/compose/) to run a localnet. If you need inspiration on how to set up your own localnet with Docker Compose, you can have a look at the Cosmos SDK's [`docker-compose.yml`](https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc1/docker-compose.yml). +## State Sync + +State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don't want to sync all the blocks in history. You can read more here: https://docs.cometbft.com/v0.37/core/state-sync + +### Local State Sync + +Local state sync work similar to normal state sync except that it works off a local snapshot of state instead of one provided via the p2p network. The steps to start local state sync are similar to normal state sync with a few different designs. + +1. As mentioned in https://docs.cometbft.com/v0.37/core/state-sync, one must set a height and hash in the config.toml along with a few rpc servers (the afromentioned link has instructions on how to do this). +2. Bootsrapping Comet state in order to start the node after the snapshot has been ingested. This can be done with the bootstrap command ` comet bootstrap-state` + ## Next {hide} Read about the [Interacting with your Node](./interact-node.md) {hide} diff --git a/server/tm_cmds.go b/server/tm_cmds.go index 2dc1ddc57336..3eae9fa43087 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -5,14 +5,23 @@ package server import ( "fmt" + "github.com/tendermint/tendermint/light" + "github.com/tendermint/tendermint/node" + cmtstore "github.com/tendermint/tendermint/proto/tendermint/store" + sm "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/statesync" + "github.com/spf13/cobra" "github.com/tendermint/tendermint/p2p" pvm "github.com/tendermint/tendermint/privval" + "github.com/tendermint/tendermint/store" tversion "github.com/tendermint/tendermint/version" "sigs.k8s.io/yaml" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -117,3 +126,91 @@ func VersionCmd() *cobra.Command { }, } } + +func BootstrapStateCmd(appCreator types.AppCreator) *cobra.Command { + cmd := &cobra.Command{ + Use: "bootstrap-state", + Short: "Bootstrap CometBFT state at an arbitrary block height using a light client", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + serverCtx := GetServerContextFromCmd(cmd) + cfg := serverCtx.Config + + height, err := cmd.Flags().GetInt64("height") + if err != nil { + return err + } + if height == 0 { + home := serverCtx.Viper.GetString(flags.FlagHome) + db, err := openDB(home, GetAppDBBackend(serverCtx.Viper)) + if err != nil { + return err + } + + app := appCreator(serverCtx.Logger, db, nil, serverCtx.Viper) + height = app.CommitMultiStore().LastCommitID().Version + } + + blockStoreDB, err := node.DefaultDBProvider(&node.DBContext{ID: "blockstore", Config: cfg}) + if err != nil { + return err + } + blockStore := store.NewBlockStore(blockStoreDB) + + stateDB, err := node.DefaultDBProvider(&node.DBContext{ID: "state", Config: cfg}) + if err != nil { + return err + } + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: cfg.Storage.DiscardABCIResponses, + }) + + genState, _, err := node.LoadStateFromDBOrGenesisDocProvider(stateDB, node.DefaultGenesisDocProviderFunc(cfg)) + if err != nil { + return err + } + + stateProvider, err := statesync.NewLightClientStateProvider( + cmd.Context(), + genState.ChainID, genState.Version, genState.InitialHeight, + cfg.StateSync.RPCServers, light.TrustOptions{ + Period: cfg.StateSync.TrustPeriod, + Height: cfg.StateSync.TrustHeight, + Hash: cfg.StateSync.TrustHashBytes(), + }, serverCtx.Logger.With("module", "light")) + if err != nil { + return fmt.Errorf("failed to set up light client state provider: %w", err) + } + + state, err := stateProvider.State(cmd.Context(), uint64(height)) + if err != nil { + return fmt.Errorf("failed to get state: %w", err) + } + + commit, err := stateProvider.Commit(cmd.Context(), uint64(height)) + if err != nil { + return fmt.Errorf("failed to get commit: %w", err) + } + + if err := stateStore.Bootstrap(state); err != nil { + return fmt.Errorf("failed to bootstrap state: %w", err) + } + + if err := blockStore.SaveSeenCommit(state.LastBlockHeight, commit); err != nil { + return fmt.Errorf("failed to save seen commit: %w", err) + } + + store.SaveBlockStoreState(&cmtstore.BlockStoreState{ + // it breaks the invariant that blocks in range [Base, Height] must exists, but it do works in practice. + Base: state.LastBlockHeight, + Height: state.LastBlockHeight, + }, blockStoreDB) + + return nil + }, + } + + cmd.Flags().Int64("height", 0, "Block height to bootstrap state at, if not provided will use the latest block height in app state") + + return cmd +} diff --git a/server/util.go b/server/util.go index 98e82be44b03..52caa5967794 100644 --- a/server/util.go +++ b/server/util.go @@ -284,6 +284,7 @@ func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator type VersionCmd(), tmcmd.ResetAllCmd, tmcmd.ResetStateCmd, + BootstrapStateCmd(appCreator), ) startCmd := StartCmd(appCreator, defaultNodeHome) From dcf04afc4a69c7c90d1614ec767ead15320f3779 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 14:51:26 +0000 Subject: [PATCH 28/47] chore(auth/vesting): fix typo in `create-period-vesting-account` cmd example (backport #16085) (#16087) Co-authored-by: Julien Robert --- x/auth/vesting/client/cli/tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/auth/vesting/client/cli/tx.go b/x/auth/vesting/client/cli/tx.go index 3c88d04500fa..f2ef3ba67fe7 100644 --- a/x/auth/vesting/client/cli/tx.go +++ b/x/auth/vesting/client/cli/tx.go @@ -142,7 +142,7 @@ func NewMsgCreatePeriodicVestingAccountCmd() *cobra.Command { An array of coin strings and unix epoch times for coins to vest { "start_time": 1625204910, -"period":[ +"periods":[ { "coins": "10test", "length_seconds":2592000 //30 days From 10cc30f36e1c293423c4e30d4f0d09a3015bdaea Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 12 May 2023 10:22:44 +0000 Subject: [PATCH 29/47] feat: add local snapshots management commands (backport #16067) (#16103) Co-authored-by: yihuang Co-authored-by: marbar3778 Co-authored-by: Julien Robert --- CHANGELOG.md | 1 + client/snapshot/cmd.go | 24 +++ client/snapshot/delete.go | 35 ++++ client/snapshot/dump.go | 120 +++++++++++++ client/snapshot/export.go | 53 ++++++ client/snapshot/list.go | 30 ++++ client/snapshot/load.go | 113 ++++++++++++ client/snapshot/restore.go | 50 ++++++ contrib/rosetta/rosetta-ci/data.tar.gz | Bin 44165 -> 47219 bytes go.mod | 82 ++++----- go.sum | 233 ++++++++++++++----------- server/types/app.go | 4 + server/util.go | 19 ++ simapp/simd/cmd/root.go | 2 + snapshots/manager.go | 19 ++ snapshots/store.go | 67 ++++--- 16 files changed, 685 insertions(+), 167 deletions(-) create mode 100644 client/snapshot/cmd.go create mode 100644 client/snapshot/delete.go create mode 100644 client/snapshot/dump.go create mode 100644 client/snapshot/export.go create mode 100644 client/snapshot/list.go create mode 100644 client/snapshot/load.go create mode 100644 client/snapshot/restore.go diff --git a/CHANGELOG.md b/CHANGELOG.md index bd533d44f0ae..3ca726fd72a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (simapp) [#15903](https://github.com/cosmos/cosmos-sdk/pull/15903) Add `AppStateFnWithExtendedCbs` with moduleStateCb callback function to allow access moduleState. Note, this function is present in simtestutil from `v0.47.2+`. * (gov) [#15979](https://github.com/cosmos/cosmos-sdk/pull/15979) Improve gov error message when failing to convert v1 proposal to v1beta1. * (server) [#16061](https://github.com/cosmos/cosmos-sdk/pull/16061) add comet bootstrap command +* (store) [#16067](https://github.com/cosmos/cosmos-sdk/pull/16067) Add local snapshots management commands. ### Bug Fixes diff --git a/client/snapshot/cmd.go b/client/snapshot/cmd.go new file mode 100644 index 000000000000..f49f2b51c2b4 --- /dev/null +++ b/client/snapshot/cmd.go @@ -0,0 +1,24 @@ +package snapshot + +import ( + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/spf13/cobra" +) + +// Cmd returns the snapshots group command +func Cmd(appCreator servertypes.AppCreator) *cobra.Command { + cmd := &cobra.Command{ + Use: "snapshots", + Short: "Manage local snapshots", + Long: "Manage local snapshots", + } + cmd.AddCommand( + ListSnapshotsCmd, + RestoreSnapshotCmd(appCreator), + ExportSnapshotCmd(appCreator), + DumpArchiveCmd(), + LoadArchiveCmd(), + DeleteSnapshotCmd(), + ) + return cmd +} diff --git a/client/snapshot/delete.go b/client/snapshot/delete.go new file mode 100644 index 000000000000..0259032e1134 --- /dev/null +++ b/client/snapshot/delete.go @@ -0,0 +1,35 @@ +package snapshot + +import ( + "strconv" + + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" +) + +func DeleteSnapshotCmd() *cobra.Command { + return &cobra.Command{ + Use: "delete ", + Short: "Delete a local snapshot", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + snapshotStore, err := server.GetSnapshotStore(ctx.Viper) + if err != nil { + return err + } + + return snapshotStore.Delete(height, uint32(format)) + }, + } +} diff --git a/client/snapshot/dump.go b/client/snapshot/dump.go new file mode 100644 index 000000000000..917dca071512 --- /dev/null +++ b/client/snapshot/dump.go @@ -0,0 +1,120 @@ +package snapshot + +import ( + "archive/tar" + "compress/gzip" + "fmt" + "io" + "os" + "strconv" + + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" +) + +// DumpArchiveCmd returns a command to dump the snapshot as portable archive format +func DumpArchiveCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "dump ", + Short: "Dump the snapshot as portable archive format", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + snapshotStore, err := server.GetSnapshotStore(ctx.Viper) + if err != nil { + return err + } + + output, err := cmd.Flags().GetString("output") + if err != nil { + return err + } + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + if output == "" { + output = fmt.Sprintf("%d-%d.tar.gz", height, format) + } + + snapshot, err := snapshotStore.Get(height, uint32(format)) + if err != nil { + return err + } + + bz, err := snapshot.Marshal() + if err != nil { + return err + } + + fp, err := os.Create(output) + if err != nil { + return err + } + defer fp.Close() + + // since the chunk files are already compressed, we just use fastest compression here + gzipWriter, err := gzip.NewWriterLevel(fp, gzip.BestSpeed) + if err != nil { + return err + } + tarWriter := tar.NewWriter(gzipWriter) + if err := tarWriter.WriteHeader(&tar.Header{ + Name: SnapshotFileName, + Mode: 0o644, + Size: int64(len(bz)), + }); err != nil { + return fmt.Errorf("failed to write snapshot header to tar: %w", err) + } + if _, err := tarWriter.Write(bz); err != nil { + return fmt.Errorf("failed to write snapshot to tar: %w", err) + } + + for i := uint32(0); i < snapshot.Chunks; i++ { + path := snapshotStore.PathChunk(height, uint32(format), i) + file, err := os.Open(path) + if err != nil { + return fmt.Errorf("failed to open chunk file %s: %w", path, err) + } + defer file.Close() + + st, err := file.Stat() + if err != nil { + return fmt.Errorf("failed to stat chunk file %s: %w", path, err) + } + + if err := tarWriter.WriteHeader(&tar.Header{ + Name: strconv.FormatUint(uint64(i), 10), + Mode: 0o644, + Size: st.Size(), + }); err != nil { + return fmt.Errorf("failed to write chunk header to tar: %w", err) + } + + if _, err := io.Copy(tarWriter, file); err != nil { + return fmt.Errorf("failed to write chunk to tar: %w", err) + } + } + + if err := tarWriter.Close(); err != nil { + return fmt.Errorf("failed to close tar writer: %w", err) + } + + if err := gzipWriter.Close(); err != nil { + return fmt.Errorf("failed to close gzip writer: %w", err) + } + + return fp.Close() + }, + } + + cmd.Flags().StringP("output", "o", "", "output file") + + return cmd +} diff --git a/client/snapshot/export.go b/client/snapshot/export.go new file mode 100644 index 000000000000..cc39209a08f8 --- /dev/null +++ b/client/snapshot/export.go @@ -0,0 +1,53 @@ +package snapshot + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/spf13/cobra" +) + +// ExportSnapshotCmd returns a command to take a snapshot of the application state +func ExportSnapshotCmd(appCreator servertypes.AppCreator) *cobra.Command { + cmd := &cobra.Command{ + Use: "export", + Short: "Export app state to snapshot store", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + + height, err := cmd.Flags().GetInt64("height") + if err != nil { + return err + } + + home := ctx.Config.RootDir + db, err := openDB(home, server.GetAppDBBackend(ctx.Viper)) + if err != nil { + return err + } + + app := appCreator(ctx.Logger, db, nil, ctx.Viper) + + if height == 0 { + height = app.CommitMultiStore().LastCommitID().Version + } + + fmt.Printf("Exporting snapshot for height %d\n", height) + + sm := app.SnapshotManager() + snapshot, err := sm.Create(uint64(height)) + if err != nil { + return err + } + + fmt.Printf("Snapshot created at height %d, format %d, chunks %d\n", snapshot.Height, snapshot.Format, snapshot.Chunks) + return nil + }, + } + + cmd.Flags().Int64("height", 0, "Height to export, default to latest state height") + + return cmd +} diff --git a/client/snapshot/list.go b/client/snapshot/list.go new file mode 100644 index 000000000000..6ff6391d4211 --- /dev/null +++ b/client/snapshot/list.go @@ -0,0 +1,30 @@ +package snapshot + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" +) + +// ListSnapshotsCmd returns the command to list local snapshots +var ListSnapshotsCmd = &cobra.Command{ + Use: "list", + Short: "List local snapshots", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + snapshotStore, err := server.GetSnapshotStore(ctx.Viper) + if err != nil { + return err + } + snapshots, err := snapshotStore.List() + if err != nil { + return fmt.Errorf("failed to list snapshots: %w", err) + } + for _, snapshot := range snapshots { + fmt.Println("height:", snapshot.Height, "format:", snapshot.Format, "chunks:", snapshot.Chunks) + } + + return nil + }, +} diff --git a/client/snapshot/load.go b/client/snapshot/load.go new file mode 100644 index 000000000000..6797d58bafec --- /dev/null +++ b/client/snapshot/load.go @@ -0,0 +1,113 @@ +package snapshot + +import ( + "archive/tar" + "bytes" + "compress/gzip" + "fmt" + "io" + "os" + "reflect" + "strconv" + + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" + + snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" +) + +const SnapshotFileName = "_snapshot" + +// LoadArchiveCmd load a portable archive format snapshot into snapshot store +func LoadArchiveCmd() *cobra.Command { + return &cobra.Command{ + Use: "load ", + Short: "Load a snapshot archive file into snapshot store", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + snapshotStore, err := server.GetSnapshotStore(ctx.Viper) + if err != nil { + return err + } + + path := args[0] + fp, err := os.Open(path) + if err != nil { + return fmt.Errorf("failed to open archive file: %w", err) + } + reader, err := gzip.NewReader(fp) + if err != nil { + return fmt.Errorf("failed to create gzip reader: %w", err) + } + + var snapshot snapshottypes.Snapshot + tr := tar.NewReader(reader) + if err != nil { + return fmt.Errorf("failed to create tar reader: %w", err) + } + + hdr, err := tr.Next() + if err != nil { + return fmt.Errorf("failed to read snapshot file header: %w", err) + } + if hdr.Name != SnapshotFileName { + return fmt.Errorf("invalid archive, expect file: snapshot, got: %s", hdr.Name) + } + bz, err := io.ReadAll(tr) + if err != nil { + return fmt.Errorf("failed to read snapshot file: %w", err) + } + if err := snapshot.Unmarshal(bz); err != nil { + return fmt.Errorf("failed to unmarshal snapshot: %w", err) + } + + // make sure the channel is unbuffered, because the tar reader can't do concurrency + chunks := make(chan io.ReadCloser) + quitChan := make(chan *snapshottypes.Snapshot) + go func() { + defer close(quitChan) + + savedSnapshot, err := snapshotStore.Save(snapshot.Height, snapshot.Format, chunks) + if err != nil { + fmt.Println("failed to save snapshot", err) + return + } + quitChan <- savedSnapshot + }() + + for i := uint32(0); i < snapshot.Chunks; i++ { + hdr, err = tr.Next() + if err != nil { + if err == io.EOF { + break + } + return err + } + + if hdr.Name != strconv.FormatInt(int64(i), 10) { + return fmt.Errorf("invalid archive, expect file: %d, got: %s", i, hdr.Name) + } + + bz, err := io.ReadAll(tr) + if err != nil { + return fmt.Errorf("failed to read chunk file: %w", err) + } + chunks <- io.NopCloser(bytes.NewReader(bz)) + } + close(chunks) + + savedSnapshot := <-quitChan + if savedSnapshot == nil { + return fmt.Errorf("failed to save snapshot") + } + + if !reflect.DeepEqual(&snapshot, savedSnapshot) { + _ = snapshotStore.Delete(snapshot.Height, snapshot.Format) + return fmt.Errorf("invalid archive, the saved snapshot is not equal to the original one") + } + + return nil + }, + } +} diff --git a/client/snapshot/restore.go b/client/snapshot/restore.go new file mode 100644 index 000000000000..7ab46dfe6b9e --- /dev/null +++ b/client/snapshot/restore.go @@ -0,0 +1,50 @@ +package snapshot + +import ( + "path/filepath" + "strconv" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + dbm "github.com/tendermint/tm-db" +) + +// RestoreSnapshotCmd returns a command to restore a snapshot +func RestoreSnapshotCmd(appCreator servertypes.AppCreator) *cobra.Command { + cmd := &cobra.Command{ + Use: "restore ", + Short: "Restore app state from local snapshot", + Long: "Restore app state from local snapshot", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := server.GetServerContextFromCmd(cmd) + + height, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + format, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return err + } + + home := ctx.Config.RootDir + db, err := openDB(home, server.GetAppDBBackend(ctx.Viper)) + if err != nil { + return err + } + app := appCreator(ctx.Logger, db, nil, ctx.Viper) + + sm := app.SnapshotManager() + return sm.RestoreLocalSnapshot(height, uint32(format)) + }, + } + return cmd +} + +func openDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) { + dataDir := filepath.Join(rootDir, "data") + return dbm.NewDB("application", backendType, dataDir) +} diff --git a/contrib/rosetta/rosetta-ci/data.tar.gz b/contrib/rosetta/rosetta-ci/data.tar.gz index 7ed3114345923c870cd7cc0b73a347088af7a4c6..ad152760a2e7a086ad8ec4404303001a738d710d 100644 GIT binary patch literal 47219 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

19z?H}%p=p6aQzxEHmedpotI-Tr4 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 diff --git a/go.mod b/go.mod index e4b19279164c..9b8fa6be2d93 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ module github.com/cosmos/cosmos-sdk require ( cosmossdk.io/errors v1.0.0-beta.7 - cosmossdk.io/math v1.0.0-beta.3 + cosmossdk.io/math v1.0.0-rc.0 github.com/99designs/keyring v1.2.1 github.com/armon/go-metrics v0.4.1 github.com/bgentry/speakeasy v0.1.0 @@ -22,7 +22,7 @@ require ( github.com/gogo/gateway v1.1.0 github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 - github.com/golang/protobuf v1.5.2 + github.com/golang/protobuf v1.5.3 github.com/google/uuid v1.3.0 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 @@ -32,40 +32,40 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 github.com/improbable-eng/grpc-web v0.15.0 - github.com/jhump/protoreflect v1.12.1-0.20220721211354-060cc04fc18b + github.com/jhump/protoreflect v1.15.1 github.com/magiconair/properties v1.8.6 github.com/manifoldco/promptui v0.9.0 - github.com/mattn/go-isatty v0.0.16 + github.com/mattn/go-isatty v0.0.18 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 - github.com/prometheus/common v0.37.0 + github.com/prometheus/common v0.42.0 github.com/rakyll/statik v0.1.7 github.com/regen-network/cosmos-proto v0.3.1 - github.com/rs/zerolog v1.27.0 + github.com/rs/zerolog v1.29.1 github.com/spf13/cast v1.5.0 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.13.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.2 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.28 github.com/tendermint/tm-db v0.6.7 github.com/tidwall/btree v1.5.0 - golang.org/x/crypto v0.5.0 - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e - google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 - google.golang.org/grpc v1.52.0 - google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 + golang.org/x/crypto v0.7.0 + golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 + google.golang.org/grpc v1.54.0 + google.golang.org/protobuf v1.30.0 pgregory.net/rapid v0.4.7 sigs.k8s.io/yaml v1.3.0 ) require ( - cloud.google.com/go v0.105.0 // indirect - cloud.google.com/go/compute v1.12.1 // indirect - cloud.google.com/go/compute/metadata v0.2.1 // indirect - cloud.google.com/go/iam v0.7.0 // indirect - cloud.google.com/go/storage v1.27.0 // indirect + cloud.google.com/go v0.110.0 // indirect + cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v0.12.0 // indirect + cloud.google.com/go/storage v1.28.1 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect @@ -75,13 +75,13 @@ require ( github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cometbft/cometbft-db v0.7.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect @@ -89,7 +89,7 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect @@ -100,8 +100,8 @@ require ( github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/orderedcode v0.0.1 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect @@ -114,43 +114,45 @@ require ( github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.15.11 // indirect - github.com/lib/pq v1.10.6 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.0.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/onsi/gomega v1.20.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.5 // indirect - github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pelletier/go-toml/v2 v2.0.7 // indirect + github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/rs/cors v1.8.2 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/ulikunitz/xz v0.5.8 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.opencensus.io v0.23.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + go.opencensus.io v0.24.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/oauth2 v0.5.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/term v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.102.0 // indirect + google.golang.org/api v0.110.0 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -164,11 +166,13 @@ replace ( // dgrijalva/jwt-go is deprecated and doesn't receive security updates. // TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 - // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. + // Fix upstream GHSA-h395-qcrw-5vmq and GHSA-3vp4-m3rf-835h vulnerabilities. // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 - github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 + github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/jhump/protoreflect => github.com/jhump/protoreflect v1.9.0 + // Downgraded to avoid bugs in following commits which caused simulations to fail. + github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // use cometbft github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.28 ) diff --git a/go.sum b/go.sum index 1651603d0926..e190a029afe7 100644 --- a/go.sum +++ b/go.sum @@ -19,8 +19,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -28,15 +28,15 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= -cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= +cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -47,13 +47,13 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= -cosmossdk.io/math v1.0.0-beta.3 h1:TbZxSopz2LqjJ7aXYfn7nJSb8vNaBklW6BLpcei1qwM= -cosmossdk.io/math v1.0.0-beta.3/go.mod h1:3LYasri3Zna4XpbrTNdKsWmD5fHHkaNAod/mNT9XdE4= +cosmossdk.io/math v1.0.0-rc.0 h1:ml46ukocrAAoBpYKMidF0R2tQJ1Uxfns0yH8wqgMAFc= +cosmossdk.io/math v1.0.0-rc.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= @@ -158,6 +158,9 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= +github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= @@ -170,9 +173,12 @@ github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= @@ -209,7 +215,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= @@ -246,8 +252,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= @@ -305,16 +312,16 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU= -github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= +github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= +github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= @@ -326,8 +333,6 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -338,13 +343,13 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= +github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -355,6 +360,8 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= +github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -400,8 +407,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -434,7 +441,7 @@ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPg github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -454,12 +461,12 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= @@ -580,7 +587,6 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -600,9 +606,12 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= -github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -611,7 +620,8 @@ 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.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 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= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -620,11 +630,11 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= -github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -653,8 +663,10 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -662,8 +674,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= @@ -674,8 +686,9 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -727,8 +740,9 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= @@ -752,17 +766,20 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= +github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= +github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -779,8 +796,6 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -799,20 +814,16 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= @@ -828,13 +839,16 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= -github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= +github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -899,8 +913,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -925,13 +940,13 @@ github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZF github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= +github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -952,6 +967,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= @@ -968,8 +984,8 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -979,6 +995,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1000,9 +1018,11 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1017,8 +1037,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 h1:LGJsf5LRplCck6jUCH3dBL2dmycNruWNF5xugkSlfXw= +golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1044,7 +1064,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1093,15 +1114,15 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1111,10 +1132,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1126,6 +1145,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1195,7 +1215,6 @@ golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1203,18 +1222,23 @@ golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1224,8 +1248,11 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1294,7 +1321,8 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1327,8 +1355,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1382,8 +1410,8 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1408,8 +1436,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1424,8 +1452,9 @@ google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX7 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk= -google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= diff --git a/server/types/app.go b/server/types/app.go index abc4c739e5bb..124dcf4c25ad 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" + "github.com/cosmos/cosmos-sdk/snapshots" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -55,6 +56,9 @@ type ( // Return the multistore instance CommitMultiStore() sdk.CommitMultiStore + + // Return the snapshot manager + SnapshotManager() *snapshots.Manager } // ApplicationQueryService defines an extension of the Application interface diff --git a/server/util.go b/server/util.go index 52caa5967794..019d0132085c 100644 --- a/server/util.go +++ b/server/util.go @@ -465,3 +465,22 @@ func DefaultBaseappOptions(appOpts types.AppOptions) []func(*baseapp.BaseApp) { baseapp.SetIAVLLazyLoading(cast.ToBool(appOpts.Get(FlagIAVLLazyLoading))), } } + +func GetSnapshotStore(appOpts types.AppOptions) (*snapshots.Store, error) { + homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) + snapshotDir := filepath.Join(homeDir, "data", "snapshots") + if err := os.MkdirAll(snapshotDir, os.ModePerm); err != nil { + return nil, fmt.Errorf("failed to create snapshots directory: %w", err) + } + + snapshotDB, err := dbm.NewDB("metadata", GetAppDBBackend(appOpts), snapshotDir) + if err != nil { + return nil, err + } + snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) + if err != nil { + return nil, err + } + + return snapshotStore, nil +} diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index d8b71c6df53a..03261d516ca1 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -20,6 +20,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/pruning" "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/client/snapshot" "github.com/cosmos/cosmos-sdk/server" serverconfig "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" @@ -169,6 +170,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { debug.Cmd(), config.Cmd(), pruning.PruningCmd(a.newApp), + snapshot.Cmd(a.newApp), ) server.AddCommands(rootCmd, simapp.DefaultNodeHome, a.newApp, a.appExport, addModuleInitFlags) diff --git a/snapshots/manager.go b/snapshots/manager.go index 05cbad3f5b30..4e46116a9199 100644 --- a/snapshots/manager.go +++ b/snapshots/manager.go @@ -391,6 +391,25 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) { return false, nil } +// RestoreLocalSnapshot restores app state from a local snapshot. +func (m *Manager) RestoreLocalSnapshot(height uint64, format uint32) error { + snapshot, ch, err := m.store.Load(height, format) + if err != nil { + return err + } + + m.mtx.Lock() + defer m.mtx.Unlock() + + err = m.beginLocked(opRestore) + if err != nil { + return err + } + defer m.endLocked() + + return m.restoreSnapshot(*snapshot, ch) +} + // sortedExtensionNames sort extension names for deterministic iteration. func (m *Manager) sortedExtensionNames() []string { names := make([]string, 0, len(m.extensions)) diff --git a/snapshots/store.go b/snapshots/store.go index 8105938b80f1..6a663e701641 100644 --- a/snapshots/store.go +++ b/snapshots/store.go @@ -3,6 +3,7 @@ package snapshots import ( "crypto/sha256" "encoding/binary" + "hash" "io" "math" "os" @@ -14,6 +15,7 @@ import ( db "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/snapshots/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -164,8 +166,8 @@ func (s *Store) Load(height uint64, format uint32) (*types.Snapshot, <-chan io.R // LoadChunk loads a chunk from disk, or returns nil if it does not exist. The caller must call // Close() on it when done. -func (s *Store) LoadChunk(height uint64, format uint32, chunk uint32) (io.ReadCloser, error) { - path := s.pathChunk(height, format, chunk) +func (s *Store) LoadChunk(height uint64, format, chunk uint32) (io.ReadCloser, error) { + path := s.PathChunk(height, format, chunk) file, err := os.Open(path) if os.IsNotExist(err) { return nil, nil @@ -174,8 +176,8 @@ func (s *Store) LoadChunk(height uint64, format uint32, chunk uint32) (io.ReadCl } // loadChunkFile loads a chunk from disk, and errors if it does not exist. -func (s *Store) loadChunkFile(height uint64, format uint32, chunk uint32) (io.ReadCloser, error) { - path := s.pathChunk(height, format, chunk) +func (s *Store) loadChunkFile(height uint64, format, chunk uint32) (io.ReadCloser, error) { + path := s.PathChunk(height, format, chunk) return os.Open(path) } @@ -259,33 +261,16 @@ func (s *Store) Save( snapshotHasher := sha256.New() chunkHasher := sha256.New() for chunkBody := range chunks { - defer chunkBody.Close() // nolint: staticcheck + defer chunkBody.Close() //nolint:staticcheck dir := s.pathSnapshot(height, format) err = os.MkdirAll(dir, 0o755) if err != nil { return nil, sdkerrors.Wrapf(err, "failed to create snapshot directory %q", dir) } - path := s.pathChunk(height, format, index) - file, err := os.Create(path) - if err != nil { - return nil, sdkerrors.Wrapf(err, "failed to create snapshot chunk file %q", path) - } - defer file.Close() // nolint: staticcheck - chunkHasher.Reset() - _, err = io.Copy(io.MultiWriter(file, chunkHasher, snapshotHasher), chunkBody) - if err != nil { - return nil, sdkerrors.Wrapf(err, "failed to generate snapshot chunk %v", index) - } - err = file.Close() - if err != nil { - return nil, sdkerrors.Wrapf(err, "failed to close snapshot chunk %v", index) - } - err = chunkBody.Close() - if err != nil { - return nil, sdkerrors.Wrapf(err, "failed to close snapshot chunk %v", index) + if err := s.saveChunk(chunkBody, index, snapshot, chunkHasher, snapshotHasher); err != nil { + return nil, err } - snapshot.Metadata.ChunkHashes = append(snapshot.Metadata.ChunkHashes, chunkHasher.Sum(nil)) index++ } snapshot.Chunks = index @@ -293,6 +278,36 @@ func (s *Store) Save( return snapshot, s.saveSnapshot(snapshot) } +// saveChunk saves the given chunkBody with the given index to its appropriate path on disk. +// The hash of the chunk is appended to the snapshot's metadata, +// and the overall snapshot hash is updated with the chunk content too. +func (s *Store) saveChunk(chunkBody io.ReadCloser, index uint32, snapshot *types.Snapshot, chunkHasher, snapshotHasher hash.Hash) error { + defer chunkBody.Close() + + path := s.PathChunk(snapshot.Height, snapshot.Format, index) + chunkFile, err := os.Create(path) + if err != nil { + return sdkerrors.Wrapf(err, "failed to create snapshot chunk file %q", path) + } + defer chunkFile.Close() + + chunkHasher.Reset() + if _, err := io.Copy(io.MultiWriter(chunkFile, chunkHasher, snapshotHasher), chunkBody); err != nil { + return sdkerrors.Wrapf(err, "failed to generate snapshot chunk %d", index) + } + + if err := chunkFile.Close(); err != nil { + return sdkerrors.Wrapf(err, "failed to close snapshot chunk file %d", index) + } + + if err := chunkBody.Close(); err != nil { + return sdkerrors.Wrapf(err, "failed to close snapshot chunk body %d", index) + } + + snapshot.Metadata.ChunkHashes = append(snapshot.Metadata.ChunkHashes, chunkHasher.Sum(nil)) + return nil +} + // saveSnapshot saves snapshot metadata to the database. func (s *Store) saveSnapshot(snapshot *types.Snapshot) error { value, err := proto.Marshal(snapshot) @@ -313,8 +328,8 @@ func (s *Store) pathSnapshot(height uint64, format uint32) string { return filepath.Join(s.pathHeight(height), strconv.FormatUint(uint64(format), 10)) } -// pathChunk generates a snapshot chunk path. -func (s *Store) pathChunk(height uint64, format uint32, chunk uint32) string { +// PathChunk generates a snapshot chunk path. +func (s *Store) PathChunk(height uint64, format, chunk uint32) string { return filepath.Join(s.pathSnapshot(height, format), strconv.FormatUint(uint64(chunk), 10)) } From 5472fb5995a0464207f60df5cfab5c6323acbc78 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 13 May 2023 09:10:01 +0000 Subject: [PATCH 30/47] fix: snapshot commands panic if snapshot don't exists (backport #16138) (#16140) Co-authored-by: yihuang Co-authored-by: marbar3778 Co-authored-by: Julien Robert --- .gitignore | 1 + client/snapshot/dump.go | 5 +++++ snapshots/manager.go | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/.gitignore b/.gitignore index 1ce4f5cfa123..1adf64472c42 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ dist tools-stamp buf-stamp artifacts +tools/ # Data - ideally these don't exist baseapp/data/* diff --git a/client/snapshot/dump.go b/client/snapshot/dump.go index 917dca071512..72dadbc57254 100644 --- a/client/snapshot/dump.go +++ b/client/snapshot/dump.go @@ -3,6 +3,7 @@ package snapshot import ( "archive/tar" "compress/gzip" + "errors" "fmt" "io" "os" @@ -48,6 +49,10 @@ func DumpArchiveCmd() *cobra.Command { return err } + if snapshot == nil { + return errors.New("snapshot doesn't exist") + } + bz, err := snapshot.Marshal() if err != nil { return err diff --git a/snapshots/manager.go b/snapshots/manager.go index 4e46116a9199..7bb5cd8abf5f 100644 --- a/snapshots/manager.go +++ b/snapshots/manager.go @@ -398,6 +398,10 @@ func (m *Manager) RestoreLocalSnapshot(height uint64, format uint32) error { return err } + if snapshot == nil { + return fmt.Errorf("snapshot doesn't exist, height: %d, format: %d", height, format) + } + m.mtx.Lock() defer m.mtx.Unlock() From 557da6ebd121c2117d9d15f6925888ca202923f4 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 19 May 2023 10:03:44 +0000 Subject: [PATCH 31/47] feat: add Close method for resource cleanup in graceful shutdown (backport #16193) (#16205) Co-authored-by: yihuang Co-authored-by: Julien Robert --- CHANGELOG.md | 1 + baseapp/baseapp.go | 5 +++++ server/start.go | 5 +++++ server/types/app.go | 3 +++ 4 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ca726fd72a6..27d224d77100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (gov) [#15979](https://github.com/cosmos/cosmos-sdk/pull/15979) Improve gov error message when failing to convert v1 proposal to v1beta1. * (server) [#16061](https://github.com/cosmos/cosmos-sdk/pull/16061) add comet bootstrap command * (store) [#16067](https://github.com/cosmos/cosmos-sdk/pull/16067) Add local snapshots management commands. +* (baseapp) [#16193](https://github.com/cosmos/cosmos-sdk/pull/16193) Add `Close` method to `BaseApp` for custom app to cleanup resource in graceful shutdown. ### Bug Fixes diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 98c2f226a059..ca2fe852af6e 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -844,3 +844,8 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*s func makeABCIData(msgResponses []*codectypes.Any) ([]byte, error) { return proto.Marshal(&sdk.TxMsgData{MsgResponses: msgResponses}) } + +// Close is called in start cmd to gracefully cleanup resources. +func (app *BaseApp) Close() error { + return nil +} diff --git a/server/start.go b/server/start.go index 208bfb8db674..2ea63c5fe1a9 100644 --- a/server/start.go +++ b/server/start.go @@ -244,6 +244,10 @@ func startStandAlone(ctx *Context, appCreator types.AppCreator) error { if err = svr.Stop(); err != nil { tmos.Exit(err.Error()) } + + if err = app.Close(); err != nil { + tmos.Exit(err.Error()) + } }() // Wait for SIGINT or SIGTERM signal @@ -485,6 +489,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App defer func() { if tmNode != nil && tmNode.IsRunning() { _ = tmNode.Stop() + _ = app.Close() } if apiSrv != nil { diff --git a/server/types/app.go b/server/types/app.go index 124dcf4c25ad..d886936f75c5 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -59,6 +59,9 @@ type ( // Return the snapshot manager SnapshotManager() *snapshots.Manager + + // Close is called in start cmd to gracefully cleanup resources. + Close() error } // ApplicationQueryService defines an extension of the Application interface From 5b02d46853ba3d930208a8794c8485384d5ede9a Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 16:50:04 +0200 Subject: [PATCH 32/47] feat: save restored snapshot locally (backport #16060) (#16262) Co-authored-by: yihuang Co-authored-by: marbar3778 --- CHANGELOG.md | 4 ++ snapshots/manager.go | 82 ++++++++++++++++++++++++++++++--------- snapshots/manager_test.go | 7 ++++ snapshots/store.go | 6 +++ 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27d224d77100..0e1f20107ec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +## Features + +* [#16060](https://github.com/cosmos/cosmos-sdk/pull/16060) Support saving restoring snapshot locally. + ### Improvements * (deps) [#15973](https://github.com/cosmos/cosmos-sdk/pull/15973) Bump CometBFT to [v0.34.28](https://github.com/cometbft/cometbft/blob/v0.34.28/CHANGELOG.md#v03428). diff --git a/snapshots/manager.go b/snapshots/manager.go index 7bb5cd8abf5f..b92a2b5b82d0 100644 --- a/snapshots/manager.go +++ b/snapshots/manager.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "math" + "os" "sort" "sync" @@ -38,12 +39,12 @@ type Manager struct { multistore types.Snapshotter logger log.Logger - mtx sync.Mutex - operation operation - chRestore chan<- io.ReadCloser - chRestoreDone <-chan restoreDone - restoreChunkHashes [][]byte - restoreChunkIndex uint32 + mtx sync.Mutex + operation operation + chRestore chan<- uint32 + chRestoreDone <-chan restoreDone + restoreSnapshot *types.Snapshot + restoreChunkIndex uint32 } // operation represents a Manager operation. Only one operation can be in progress at a time. @@ -61,7 +62,8 @@ const ( opPrune operation = "prune" opRestore operation = "restore" - chunkBufferSize = 4 + chunkBufferSize = 4 + chunkIDBufferSize = 1024 snapshotMaxItemSize = int(64e6) // SDK has no key/value size limit, so we set an arbitrary limit ) @@ -131,7 +133,7 @@ func (m *Manager) endLocked() { m.chRestore = nil } m.chRestoreDone = nil - m.restoreChunkHashes = nil + m.restoreSnapshot = nil m.restoreChunkIndex = 0 } @@ -284,11 +286,18 @@ func (m *Manager) Restore(snapshot types.Snapshot) error { } // Start an asynchronous snapshot restoration, passing chunks and completion status via channels. - chChunks := make(chan io.ReadCloser, chunkBufferSize) + chChunkIDs := make(chan uint32, chunkIDBufferSize) chDone := make(chan restoreDone, 1) + dir := m.store.pathSnapshot(snapshot.Height, snapshot.Format) + if err := os.MkdirAll(dir, 0o750); err != nil { + return sdkerrors.Wrapf(err, "failed to create snapshot directory %q", dir) + } + + chChunks := m.loadChunkStream(snapshot.Height, snapshot.Format, chChunkIDs) + go func() { - err := m.restoreSnapshot(snapshot, chChunks) + err := m.doRestoreSnapshot(snapshot, chChunks) chDone <- restoreDone{ complete: err == nil, err: err, @@ -296,15 +305,38 @@ func (m *Manager) Restore(snapshot types.Snapshot) error { close(chDone) }() - m.chRestore = chChunks + m.chRestore = chChunkIDs m.chRestoreDone = chDone - m.restoreChunkHashes = snapshot.Metadata.ChunkHashes + m.restoreSnapshot = &snapshot m.restoreChunkIndex = 0 return nil } -// restoreSnapshot do the heavy work of snapshot restoration after preliminary checks on request have passed. -func (m *Manager) restoreSnapshot(snapshot types.Snapshot, chChunks <-chan io.ReadCloser) error { +func (m *Manager) loadChunkStream(height uint64, format uint32, chunkIDs <-chan uint32) <-chan io.ReadCloser { + chunks := make(chan io.ReadCloser, chunkBufferSize) + go func() { + defer close(chunks) + + for chunkID := range chunkIDs { + chunk, err := m.store.loadChunkFile(height, format, chunkID) + if err != nil { + m.logger.Error("load chunk file failed", "height", height, "format", format, "chunk", chunkID, "err", err) + break + } + chunks <- chunk + } + }() + + return chunks +} + +// doRestoreSnapshot do the heavy work of snapshot restoration after preliminary checks on request have passed. +func (m *Manager) doRestoreSnapshot(snapshot types.Snapshot, chChunks <-chan io.ReadCloser) error { + dir := m.store.pathSnapshot(snapshot.Height, snapshot.Format) + if err := os.MkdirAll(dir, 0o750); err != nil { + return sdkerrors.Wrapf(err, "failed to create snapshot directory %q", dir) + } + streamReader, err := NewStreamReader(chChunks) if err != nil { return err @@ -348,7 +380,7 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) { return false, sdkerrors.Wrap(sdkerrors.ErrLogic, "no restore operation in progress") } - if int(m.restoreChunkIndex) >= len(m.restoreChunkHashes) { + if int(m.restoreChunkIndex) >= len(m.restoreSnapshot.Metadata.ChunkHashes) { return false, sdkerrors.Wrap(sdkerrors.ErrLogic, "received unexpected chunk") } @@ -365,19 +397,30 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) { // Verify the chunk hash. hash := sha256.Sum256(chunk) - expected := m.restoreChunkHashes[m.restoreChunkIndex] + expected := m.restoreSnapshot.Metadata.ChunkHashes[m.restoreChunkIndex] if !bytes.Equal(hash[:], expected) { return false, sdkerrors.Wrapf(types.ErrChunkHashMismatch, "expected %x, got %x", hash, expected) } + if err := m.store.saveChunkContent(chunk, m.restoreChunkIndex, m.restoreSnapshot); err != nil { + return false, sdkerrors.Wrapf(err, "save chunk content %d", m.restoreChunkIndex) + } + // Pass the chunk to the restore, and wait for completion if it was the final one. - m.chRestore <- io.NopCloser(bytes.NewReader(chunk)) + m.chRestore <- m.restoreChunkIndex m.restoreChunkIndex++ - if int(m.restoreChunkIndex) >= len(m.restoreChunkHashes) { + if int(m.restoreChunkIndex) >= len(m.restoreSnapshot.Metadata.ChunkHashes) { close(m.chRestore) m.chRestore = nil + + // the chunks are all written into files, we can save the snapshot to the db, + // even if the restoration may not completed yet. + if err := m.store.saveSnapshot(m.restoreSnapshot); err != nil { + return false, sdkerrors.Wrap(err, "save restoring snapshot") + } + done := <-m.chRestoreDone m.endLocked() if done.err != nil { @@ -386,6 +429,7 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) { if !done.complete { return false, sdkerrors.Wrap(sdkerrors.ErrLogic, "restore ended prematurely") } + return true, nil } return false, nil @@ -411,7 +455,7 @@ func (m *Manager) RestoreLocalSnapshot(height uint64, format uint32) error { } defer m.endLocked() - return m.restoreSnapshot(*snapshot, ch) + return m.doRestoreSnapshot(*snapshot, ch) } // sortedExtensionNames sort extension names for deterministic iteration. diff --git a/snapshots/manager_test.go b/snapshots/manager_test.go index b71043022827..d379f09cb9f1 100644 --- a/snapshots/manager_test.go +++ b/snapshots/manager_test.go @@ -205,6 +205,13 @@ func TestManager_Restore(t *testing.T) { assert.Equal(t, expectItems, target.items) + // The snapshot is saved in local snapshot store + snapshots, err := store.List() + require.NoError(t, err) + snapshot := snapshots[0] + require.Equal(t, uint64(3), snapshot.Height) + require.Equal(t, types.CurrentFormat, snapshot.Format) + // Starting a new restore should fail now, because the target already has contents. err = manager.Restore(types.Snapshot{ Height: 3, diff --git a/snapshots/store.go b/snapshots/store.go index 6a663e701641..254686e631b4 100644 --- a/snapshots/store.go +++ b/snapshots/store.go @@ -308,6 +308,12 @@ func (s *Store) saveChunk(chunkBody io.ReadCloser, index uint32, snapshot *types return nil } +// saveChunkContent save the chunk to disk +func (s *Store) saveChunkContent(chunk []byte, index uint32, snapshot *types.Snapshot) error { + path := s.PathChunk(snapshot.Height, snapshot.Format, index) + return os.WriteFile(path, chunk, 0o600) +} + // saveSnapshot saves snapshot metadata to the database. func (s *Store) saveSnapshot(snapshot *types.Snapshot) error { value, err := proto.Marshal(snapshot) From a9abe1c733a5e9e1fc9118573fedbb26fa84c82a Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 26 May 2023 11:27:17 +0200 Subject: [PATCH 33/47] chore: update sidebar v0.46 (#16304) --- docs/.vuepress/config.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 57edfc9cc14c..5456c1eb95f8 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -30,10 +30,6 @@ module.exports = { index: "cosmos_network_vue" }, versions: [ - { - "label": "v0.44", - "key": "v0.44" - }, { "label": "v0.45", "key": "v0.45" @@ -42,6 +38,10 @@ module.exports = { "label": "v0.46", "key": "v0.46" }, + { + "label": "v0.47", + "key": "v0.47" + }, { "label": "main", "key": "main" From 59f67147f374afd13a4f1e65ab66402755c7b9d7 Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 26 May 2023 15:02:52 +0200 Subject: [PATCH 34/47] chore: add baseapp circuit breaker setter (#16289) Co-authored-by: Julien Robert --- CHANGELOG.md | 1 + baseapp/baseapp.go | 9 +++++++++ baseapp/circuit.go | 10 ++++++++++ baseapp/msg_service_router.go | 12 ++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 baseapp/circuit.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e1f20107ec2..838540ea883b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Features +* (baseapp) [#16290](https://github.com/cosmos/cosmos-sdk/pull/16290) Add circuit breaker setter in baseapp. * [#16060](https://github.com/cosmos/cosmos-sdk/pull/16060) Support saving restoring snapshot locally. ### Improvements diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index ca2fe852af6e..b42a56efca68 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -229,6 +229,15 @@ func (app *BaseApp) SetMsgServiceRouter(msgServiceRouter *MsgServiceRouter) { app.msgServiceRouter = msgServiceRouter } +// SetCircuitBreaker sets the circuit breaker for the BaseApp. +// The circuit breaker is checked on every message execution to verify if a transaction should be executed or not. +func (app *BaseApp) SetCircuitBreaker(cb CircuitBreaker) { + if app.msgServiceRouter == nil { + panic("cannot set circuit breaker with no msg service router set") + } + app.msgServiceRouter.SetCircuit(cb) +} + // MountStores mounts all IAVL or DB stores to the provided keys in the BaseApp // multistore. func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) { diff --git a/baseapp/circuit.go b/baseapp/circuit.go new file mode 100644 index 000000000000..022ee6632c2e --- /dev/null +++ b/baseapp/circuit.go @@ -0,0 +1,10 @@ +package baseapp + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// CircuitBreaker is an interface that defines the methods for a circuit breaker. +type CircuitBreaker interface { + IsAllowed(ctx sdk.Context, typeURL string) bool +} diff --git a/baseapp/msg_service_router.go b/baseapp/msg_service_router.go index b42fc282ec31..a6494eebc6d1 100644 --- a/baseapp/msg_service_router.go +++ b/baseapp/msg_service_router.go @@ -17,6 +17,7 @@ import ( type MsgServiceRouter struct { interfaceRegistry codectypes.InterfaceRegistry routes map[string]MsgServiceHandler + circuitBreaker CircuitBreaker } var _ gogogrpc.Server = &MsgServiceRouter{} @@ -31,6 +32,10 @@ func NewMsgServiceRouter() *MsgServiceRouter { // MsgServiceHandler defines a function type which handles Msg service message. type MsgServiceHandler = func(ctx sdk.Context, req sdk.Msg) (*sdk.Result, error) +func (msr *MsgServiceRouter) SetCircuit(cb CircuitBreaker) { + msr.circuitBreaker = cb +} + // Handler returns the MsgServiceHandler for a given msg or nil if not found. func (msr *MsgServiceRouter) Handler(msg sdk.Msg) MsgServiceHandler { return msr.routes[sdk.MsgTypeURL(msg)] @@ -120,6 +125,13 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter } else { return nil, err } + + if msr.circuitBreaker != nil { + msgURL := sdk.MsgTypeURL(req) + if !msr.circuitBreaker.IsAllowed(ctx, msgURL) { + return nil, fmt.Errorf("circuit breaker disables execution of this message: %s", msgURL) + } + } } // Call the method handler from the service description with the handler object. // We don't do any decoding here because the decoding was already done. From 265b8a691716a16ddff0abef05df415f653ce1a5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 13:54:26 +0000 Subject: [PATCH 35/47] fix: allow any address in `ValidatePromptAddress` (backport #16312) (#16314) Co-authored-by: Julien Robert --- CHANGELOG.md | 17 ++++----- client/{prompts.go => prompt_validation.go} | 17 +++++++-- client/prompt_validation_test.go | 38 +++++++++++++++++++++ 3 files changed, 61 insertions(+), 11 deletions(-) rename client/{prompts.go => prompt_validation.go} (81%) create mode 100644 client/prompt_validation_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 838540ea883b..1f206fcfbe70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (cli) [#16312](https://github.com/cosmos/cosmos-sdk/pull/16312) Allow any addresses in `client.ValidatePromptAddress`. * (store/iavl) [#15717](https://github.com/cosmos/cosmos-sdk/pull/15717) Upstream error on empty version (this change was present on all version but v0.46). ## [v0.46.12](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.12) - 2022-04-04 @@ -268,7 +269,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 ### API Breaking Changes -* (cli) [#13089](https://github.com/cosmos/cosmos-sdk/pull/13089) Fix rollback command don't actually delete multistore versions, added method `RollbackToVersion` to interface `CommitMultiStore` and added method `CommitMultiStore` to `Application` interface. +* (cli) [#13089](https://github.com/cosmos/cosmos-sdk/pull/13089) Fix rollback command don't actually delete multistore versions, added method `RollbackToVersion` to interface `CommitMultiStore` and added method `CommitMultiStore` to `Application` interface. * (cli) [#13089](https://github.com/cosmos/cosmos-sdk/pull/13089) `NewRollbackCmd` now takes an `appCreator types.AppCreator`. ### Features @@ -287,7 +288,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/group) [#13214](https://github.com/cosmos/cosmos-sdk/pull/13214) Add `withdraw-proposal` command to group module's CLI transaction commands. * (x/auth) [#13048](https://github.com/cosmos/cosmos-sdk/pull/13048) Add handling of AccountNumberStoreKeyPrefix to the simulation decoder. * (simapp) [#13108](https://github.com/cosmos/cosmos-sdk/pull/13108) Call `SetIAVLCacheSize` with the configured value in simapp. -* [#13318](https://github.com/cosmos/cosmos-sdk/pull/13318) Keep the balance query endpoint compatible with legacy blocks. +* [#13318](https://github.com/cosmos/cosmos-sdk/pull/13318) Keep the balance query endpoint compatible with legacy blocks. * [#13321](https://github.com/cosmos/cosmos-sdk/pull/13321) Add flag to disable fast node migration and usage. ### Bug Fixes @@ -296,15 +297,15 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/auth) [#13200](https://github.com/cosmos/cosmos-sdk/pull/13200) Fix wrong sequences in `sign-batch`. * (export) [#13029](https://github.com/cosmos/cosmos-sdk/pull/13029) Fix exporting the blockParams regression. * [#13046](https://github.com/cosmos/cosmos-sdk/pull/13046) Fix missing return statement in BaseApp.Query. -* (store) [#13336](https://github.com/cosmos/cosmos-sdk/pull/13336) Call streaming listeners for deliver tx event, it was removed accidentally, backport #13334. -* (grpc) [#13417](https://github.com/cosmos/cosmos-sdk/pull/13417) fix grpc query panic that could crash the node (backport #13352). +* (store) [#13336](https://github.com/cosmos/cosmos-sdk/pull/13336) Call streaming listeners for deliver tx event, it was removed accidentally, backport #13334. +* (grpc) [#13417](https://github.com/cosmos/cosmos-sdk/pull/13417) fix grpc query panic that could crash the node (backport #13352). * (grpc) [#13418](https://github.com/cosmos/cosmos-sdk/pull/13418) Add close for grpc only mode. ## [v0.46.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.1) - 2022-08-24 ### Improvements -* [#12953](https://github.com/cosmos/cosmos-sdk/pull/12953) Change the default priority mechanism to be based on gas price. +* [#12953](https://github.com/cosmos/cosmos-sdk/pull/12953) Change the default priority mechanism to be based on gas price. * [#12981](https://github.com/cosmos/cosmos-sdk/pull/12981) Return proper error when parsing telemetry configuration. * [#12969](https://github.com/cosmos/cosmos-sdk/pull/12969) Bump Tendermint to `v0.34.21` and IAVL to `v0.19.1`. * [#12885](https://github.com/cosmos/cosmos-sdk/pull/12885) Amortize cost of processing cache KV store. @@ -317,7 +318,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 ### Bug Fixes * (x/group) [#12888](https://github.com/cosmos/cosmos-sdk/pull/12888) Fix event propagation to the current context of `x/group` message execution `[]sdk.Result`. -* (x/upgrade) [#12906](https://github.com/cosmos/cosmos-sdk/pull/12906) Fix upgrade failure by moving downgrade verification logic after store migration. +* (x/upgrade) [#12906](https://github.com/cosmos/cosmos-sdk/pull/12906) Fix upgrade failure by moving downgrade verification logic after store migration. * (store) [#12945](https://github.com/cosmos/cosmos-sdk/pull/12945) Fix nil end semantics in store/cachekv/iterator when iterating a dirty cache. ## [v0.46.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.0) - 2022-07-26 @@ -509,7 +510,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/auth) [\#11482](https://github.com/cosmos/cosmos-sdk/pull/11482) Improve panic message when attempting to register a method handler for a message that does not implement sdk.Msg * (x/staking) [\#11596](https://github.com/cosmos/cosmos-sdk/pull/11596) Add (re)delegation getters * (errors) [\#11960](https://github.com/cosmos/cosmos-sdk/pull/11960) Removed 'redacted' error message from defaultErrEncoder -* (ante) [#12013](https://github.com/cosmos/cosmos-sdk/pull/12013) Index ante events for failed tx. +* (ante) [#12013](https://github.com/cosmos/cosmos-sdk/pull/12013) Index ante events for failed tx. * [#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`. * [#12626](https://github.com/cosmos/cosmos-sdk/pull/12626) Upgrade IAVL to v0.19.0 with fast index and error propagation. NOTE: first start will take a while to propagate into new model. * [#12649](https://github.com/cosmos/cosmos-sdk/pull/12649) Bump tendermint to v0.34.20. @@ -612,7 +613,7 @@ replace github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8 * (x/upgrade) [\#10189](https://github.com/cosmos/cosmos-sdk/issues/10189) Removed potential sources of non-determinism in upgrades * [\#10422](https://github.com/cosmos/cosmos-sdk/pull/10422) and [\#10529](https://github.com/cosmos/cosmos-sdk/pull/10529) Add `MinCommissionRate` param to `x/staking` module. * (x/gov) [#10763](https://github.com/cosmos/cosmos-sdk/pull/10763) modify the fields in `TallyParams` to use `string` instead of `bytes` -* [#10770](https://github.com/cosmos/cosmos-sdk/pull/10770) revert tx when block gas limit exceeded +* [#10770](https://github.com/cosmos/cosmos-sdk/pull/10770) revert tx when block gas limit exceeded * (x/gov) [\#10868](https://github.com/cosmos/cosmos-sdk/pull/10868) Bump gov to v1beta2. Both v1beta1 and v1beta2 queries and Msgs are accepted. * [\#11011](https://github.com/cosmos/cosmos-sdk/pull/11011) Remove burning of deposits when qourum is not reached on a governance proposal and when the deposit is not fully met. * [\#11019](https://github.com/cosmos/cosmos-sdk/pull/11019) Add `MsgCreatePermanentLockedAccount` and CLI method for creating permanent locked account diff --git a/client/prompts.go b/client/prompt_validation.go similarity index 81% rename from client/prompts.go rename to client/prompt_validation.go index 050d806c49a8..d3e3e2321726 100644 --- a/client/prompts.go +++ b/client/prompt_validation.go @@ -29,11 +29,22 @@ func ValidatePromptURL(input string) error { // ValidatePromptAddress validates that the input is a valid Bech32 address. func ValidatePromptAddress(input string) error { - if _, err := sdk.AccAddressFromBech32(input); err != nil { - return fmt.Errorf("invalid address: %w", err) + _, err := sdk.AccAddressFromBech32(input) + if err == nil { + return nil } - return nil + _, err = sdk.ValAddressFromBech32(input) + if err == nil { + return nil + } + + _, err = sdk.ConsAddressFromBech32(input) + if err == nil { + return nil + } + + return fmt.Errorf("invalid address: %w", err) } // ValidatePromptYesNo validates that the input is valid sdk.COins diff --git a/client/prompt_validation_test.go b/client/prompt_validation_test.go new file mode 100644 index 000000000000..eba30c21c441 --- /dev/null +++ b/client/prompt_validation_test.go @@ -0,0 +1,38 @@ +package client_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/stretchr/testify/require" +) + +func TestValidatePromptNotEmpty(t *testing.T) { + require := require.New(t) + + require.NoError(client.ValidatePromptNotEmpty("foo")) + require.ErrorContains(client.ValidatePromptNotEmpty(""), "input cannot be empty") +} + +func TestValidatePromptURL(t *testing.T) { + require := require.New(t) + + require.NoError(client.ValidatePromptURL("https://example.com")) + require.ErrorContains(client.ValidatePromptURL("foo"), "invalid URL") +} + +func TestValidatePromptAddress(t *testing.T) { + require := require.New(t) + + require.NoError(client.ValidatePromptAddress("cosmos1huydeevpz37sd9snkgul6070mstupukw00xkw9")) + require.NoError(client.ValidatePromptAddress("cosmosvaloper1sjllsnramtg3ewxqwwrwjxfgc4n4ef9u2lcnj0")) + require.NoError(client.ValidatePromptAddress("cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h")) + require.ErrorContains(client.ValidatePromptAddress("foo"), "invalid address") +} + +func TestValidatePromptCoins(t *testing.T) { + require := require.New(t) + + require.NoError(client.ValidatePromptCoins("100stake")) + require.ErrorContains(client.ValidatePromptCoins("foo"), "invalid coins") +} From 863ad92d2e67f156ccddf02ac8e1a6884657d3f6 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 20:19:31 +0200 Subject: [PATCH 36/47] feat(group): add group event tally result (backport #16191) (#16306) Co-authored-by: Jeancarlo Barrios Co-authored-by: marbar3778 Co-authored-by: Julien Robert --- CHANGELOG.md | 1 + proto/cosmos/group/v1/events.proto | 13 ++ proto/cosmos/group/v1/query.proto | 6 +- proto/cosmos/group/v1/types.proto | 5 - x/group/events.pb.go | 307 ++++++++++++++++++++++++++--- x/group/keeper/genesis.go | 3 +- x/group/keeper/keeper.go | 17 ++ x/group/keeper/keeper_test.go | 67 ++++++- x/group/keeper/msg_server.go | 11 ++ x/group/spec/04_events.md | 9 + 10 files changed, 404 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f206fcfbe70..4da2920f42c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (baseapp) [#16290](https://github.com/cosmos/cosmos-sdk/pull/16290) Add circuit breaker setter in baseapp. * [#16060](https://github.com/cosmos/cosmos-sdk/pull/16060) Support saving restoring snapshot locally. +* (x/group) [#16191](https://github.com/cosmos/cosmos-sdk/pull/16191) Add EventProposalPruned event to group module whenever a proposal is pruned. ### Improvements diff --git a/proto/cosmos/group/v1/events.proto b/proto/cosmos/group/v1/events.proto index c2cfe8728f72..2b98ec9abc32 100644 --- a/proto/cosmos/group/v1/events.proto +++ b/proto/cosmos/group/v1/events.proto @@ -79,3 +79,16 @@ message EventLeaveGroup { // address is the account address of the group member. string address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; } + +// EventProposalPruned is an event emitted when a proposal is pruned. +message EventProposalPruned { + + // proposal_id is the unique ID of the proposal. + uint64 proposal_id = 1; + + // status is the proposal status (UNSPECIFIED, SUBMITTED, ACCEPTED, REJECTED, ABORTED, WITHDRAWN). + ProposalStatus status = 2; + + // tally_result is the proposal tally result (when applicable). + TallyResult tally_result = 3; +} diff --git a/proto/cosmos/group/v1/query.proto b/proto/cosmos/group/v1/query.proto index 2ce08855f7b0..20516d327702 100644 --- a/proto/cosmos/group/v1/query.proto +++ b/proto/cosmos/group/v1/query.proto @@ -84,7 +84,7 @@ service Query { }; // Groups queries all groups in state. - // + // // Since: cosmos-sdk 0.47.1 rpc Groups(QueryGroupsRequest) returns (QueryGroupsResponse) { option (google.api.http).get = "/cosmos/group/v1/groups"; @@ -320,7 +320,7 @@ message QueryTallyResultResponse { } // QueryGroupsRequest is the Query/Groups request type. -// +// // Since: cosmos-sdk 0.47.1 message QueryGroupsRequest { @@ -329,7 +329,7 @@ message QueryGroupsRequest { } // QueryGroupsResponse is the Query/Groups response type. -// +// // Since: cosmos-sdk 0.47.1 message QueryGroupsResponse { // `groups` is all the groups present in state. diff --git a/proto/cosmos/group/v1/types.proto b/proto/cosmos/group/v1/types.proto index 837271542c63..d975d6b62da6 100644 --- a/proto/cosmos/group/v1/types.proto +++ b/proto/cosmos/group/v1/types.proto @@ -14,7 +14,6 @@ import "google/protobuf/any.proto"; // Member represents a group member with an account address, // non-zero weight, metadata and added_at timestamp. message Member { - // address is the member's account address. string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; @@ -32,7 +31,6 @@ message Member { // Contrary to `Member`, it doesn't have any `added_at` field // since this field cannot be set as part of requests. message MemberRequest { - // address is the member's account address. string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; @@ -120,7 +118,6 @@ enum VoteOption { // GroupInfo represents the high-level on-chain information for a group. message GroupInfo { - // id is the unique ID of the group. uint64 id = 1; @@ -145,7 +142,6 @@ message GroupInfo { // GroupMember represents the relationship between a group and a member. message GroupMember { - // group_id is the unique ID of the group. uint64 group_id = 1; @@ -299,7 +295,6 @@ message TallyResult { // Vote represents a vote for a proposal. message Vote { - // proposal is the unique ID of the proposal. uint64 proposal_id = 1; diff --git a/x/group/events.pb.go b/x/group/events.pb.go index 3cbcb2d491d6..c724b905da7c 100644 --- a/x/group/events.pb.go +++ b/x/group/events.pb.go @@ -464,6 +464,70 @@ func (m *EventLeaveGroup) GetAddress() string { return "" } +// EventProposalPruned is an event emitted when a proposal is pruned. +type EventProposalPruned struct { + // proposal_id is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // status is the proposal status (UNSPECIFIED, SUBMITTED, ACCEPTED, REJECTED, ABORTED, WITHDRAWN). + Status ProposalStatus `protobuf:"varint,2,opt,name=status,proto3,enum=cosmos.group.v1.ProposalStatus" json:"status,omitempty"` + // tally_result is the proposal tally result (when applicable). + TallyResult *TallyResult `protobuf:"bytes,3,opt,name=tally_result,json=tallyResult,proto3" json:"tally_result,omitempty"` +} + +func (m *EventProposalPruned) Reset() { *m = EventProposalPruned{} } +func (m *EventProposalPruned) String() string { return proto.CompactTextString(m) } +func (*EventProposalPruned) ProtoMessage() {} +func (*EventProposalPruned) Descriptor() ([]byte, []int) { + return fileDescriptor_e8d753981546f032, []int{9} +} +func (m *EventProposalPruned) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventProposalPruned) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventProposalPruned.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventProposalPruned) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventProposalPruned.Merge(m, src) +} +func (m *EventProposalPruned) XXX_Size() int { + return m.Size() +} +func (m *EventProposalPruned) XXX_DiscardUnknown() { + xxx_messageInfo_EventProposalPruned.DiscardUnknown(m) +} + +var xxx_messageInfo_EventProposalPruned proto.InternalMessageInfo + +func (m *EventProposalPruned) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *EventProposalPruned) GetStatus() ProposalStatus { + if m != nil { + return m.Status + } + return PROPOSAL_STATUS_UNSPECIFIED +} + +func (m *EventProposalPruned) GetTallyResult() *TallyResult { + if m != nil { + return m.TallyResult + } + return nil +} + func init() { proto.RegisterType((*EventCreateGroup)(nil), "cosmos.group.v1.EventCreateGroup") proto.RegisterType((*EventUpdateGroup)(nil), "cosmos.group.v1.EventUpdateGroup") @@ -474,36 +538,41 @@ func init() { proto.RegisterType((*EventVote)(nil), "cosmos.group.v1.EventVote") proto.RegisterType((*EventExec)(nil), "cosmos.group.v1.EventExec") proto.RegisterType((*EventLeaveGroup)(nil), "cosmos.group.v1.EventLeaveGroup") + proto.RegisterType((*EventProposalPruned)(nil), "cosmos.group.v1.EventProposalPruned") } func init() { proto.RegisterFile("cosmos/group/v1/events.proto", fileDescriptor_e8d753981546f032) } var fileDescriptor_e8d753981546f032 = []byte{ - // 382 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0xce, 0x2f, 0xce, - 0xcd, 0x2f, 0xd6, 0x4f, 0x2f, 0xca, 0x2f, 0x2d, 0xd0, 0x2f, 0x33, 0xd4, 0x4f, 0x2d, 0x4b, 0xcd, - 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x87, 0xc8, 0xea, 0x81, 0x65, 0xf5, - 0xca, 0x0c, 0xa5, 0x24, 0x21, 0x02, 0xf1, 0x60, 0x69, 0x7d, 0xa8, 0x2c, 0x98, 0x23, 0x25, 0x8d, - 0x6e, 0x52, 0x49, 0x65, 0x41, 0x2a, 0x54, 0x52, 0x49, 0x97, 0x4b, 0xc0, 0x15, 0x64, 0xb0, 0x73, - 0x51, 0x6a, 0x62, 0x49, 0xaa, 0x3b, 0x48, 0x89, 0x90, 0x24, 0x17, 0x07, 0x58, 0x6d, 0x7c, 0x66, - 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x3b, 0x98, 0xef, 0x99, 0x02, 0x57, 0x1e, 0x5a, - 0x90, 0x42, 0x8c, 0x72, 0x1f, 0x2e, 0x31, 0x74, 0xd3, 0x03, 0xf2, 0x73, 0x32, 0x93, 0x2b, 0x85, - 0x8c, 0xb8, 0xd8, 0x13, 0x53, 0x52, 0x8a, 0x52, 0x8b, 0x8b, 0xc1, 0x7a, 0x38, 0x9d, 0x24, 0x2e, - 0x6d, 0xd1, 0x15, 0x81, 0xba, 0xdb, 0x11, 0x22, 0x13, 0x5c, 0x52, 0x94, 0x99, 0x97, 0x1e, 0x04, - 0x53, 0x08, 0x37, 0x0d, 0xc9, 0x72, 0x0a, 0x4c, 0x33, 0xe3, 0x12, 0x06, 0x9b, 0x16, 0x5c, 0x9a, - 0x94, 0x9b, 0x59, 0x12, 0x50, 0x94, 0x5f, 0x90, 0x5f, 0x9c, 0x98, 0x23, 0x24, 0xcf, 0xc5, 0x5d, - 0x00, 0x65, 0x23, 0x3c, 0xc4, 0x05, 0x13, 0xf2, 0x4c, 0x51, 0xb2, 0xe0, 0x12, 0x05, 0xeb, 0x0b, - 0xcf, 0x2c, 0xc9, 0x48, 0x29, 0x4a, 0x2c, 0x27, 0x5e, 0xa7, 0x0e, 0x17, 0x27, 0x58, 0x67, 0x58, - 0x7e, 0x49, 0x2a, 0x61, 0xd5, 0x8d, 0x8c, 0x50, 0xe5, 0xae, 0x15, 0xa9, 0xc9, 0x04, 0x95, 0x0b, - 0xd9, 0x73, 0xb1, 0x15, 0xa5, 0x16, 0x97, 0xe6, 0x94, 0x48, 0x30, 0x29, 0x30, 0x6a, 0xf0, 0x19, - 0xa9, 0xeb, 0xa1, 0x25, 0x11, 0x3d, 0x98, 0x43, 0x41, 0xe6, 0x95, 0x96, 0xe4, 0x17, 0x05, 0x81, - 0x95, 0x07, 0x41, 0xb5, 0x09, 0x09, 0x71, 0xb1, 0xe4, 0xe4, 0xa7, 0x17, 0x4b, 0x30, 0x83, 0x02, - 0x30, 0x08, 0xcc, 0x56, 0x4a, 0xe0, 0xe2, 0x07, 0x3b, 0xc1, 0x27, 0x35, 0xb1, 0x8c, 0x60, 0x6c, - 0x23, 0xc7, 0x02, 0x13, 0x91, 0xb1, 0xe0, 0x64, 0x77, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, - 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, - 0x72, 0x0c, 0x51, 0x2a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xd0, 0xf4, - 0x0c, 0xa5, 0x74, 0x8b, 0x53, 0xb2, 0xf5, 0x2b, 0x20, 0xc9, 0x39, 0x89, 0x0d, 0x9c, 0x8c, 0x8d, - 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xc0, 0x98, 0xf8, 0x2f, 0x03, 0x00, 0x00, + // 442 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0x4f, 0xef, 0xd2, 0x30, + 0x18, 0xc7, 0xe9, 0x4f, 0x02, 0x52, 0x8c, 0x98, 0xfa, 0x27, 0x03, 0xc9, 0x20, 0xc4, 0x44, 0x0e, + 0xb2, 0x05, 0x4c, 0xd4, 0x93, 0x44, 0x0c, 0x31, 0x24, 0x1c, 0xc8, 0xf0, 0x4f, 0xe2, 0x05, 0xc7, + 0xda, 0x8c, 0xc5, 0x41, 0x97, 0xb6, 0x9b, 0x70, 0xf4, 0x1d, 0xf8, 0x52, 0x3c, 0xf8, 0x22, 0x3c, + 0x12, 0x4f, 0x1e, 0x0d, 0xbc, 0x11, 0xb3, 0xae, 0x03, 0x82, 0x31, 0x23, 0xf9, 0x9d, 0x68, 0xfb, + 0xfd, 0x7c, 0xbf, 0x3c, 0x4f, 0x9f, 0x15, 0xd6, 0x1d, 0xca, 0x97, 0x94, 0x9b, 0x2e, 0xa3, 0x61, + 0x60, 0x46, 0x5d, 0x93, 0x44, 0x64, 0x25, 0xb8, 0x11, 0x30, 0x2a, 0x28, 0xaa, 0x24, 0xaa, 0x21, + 0x55, 0x23, 0xea, 0xd6, 0xaa, 0xc9, 0xc1, 0x4c, 0xca, 0xa6, 0x52, 0xe5, 0xa6, 0xf6, 0xf0, 0x3c, + 0x49, 0x6c, 0x02, 0xa2, 0xc4, 0x56, 0x07, 0xde, 0x19, 0xc6, 0xc1, 0xaf, 0x19, 0xb1, 0x05, 0x79, + 0x13, 0x23, 0xa8, 0x0a, 0x6f, 0x4a, 0x76, 0xe6, 0x61, 0x0d, 0x34, 0x41, 0x3b, 0x6f, 0x15, 0xe5, + 0x7e, 0x84, 0x0f, 0xf8, 0xbb, 0x00, 0x5f, 0x82, 0x8f, 0xe1, 0x83, 0xf3, 0xf4, 0x09, 0xf5, 0x3d, + 0x67, 0x83, 0x7a, 0xb0, 0x68, 0x63, 0xcc, 0x08, 0xe7, 0xd2, 0x53, 0x1a, 0x68, 0xbf, 0x7e, 0x74, + 0xee, 0xa9, 0xba, 0x5f, 0x25, 0xca, 0x54, 0x30, 0x6f, 0xe5, 0x5a, 0x29, 0x78, 0x48, 0x3b, 0xf9, + 0xf3, 0x6b, 0xa4, 0x3d, 0x83, 0x77, 0x65, 0xda, 0x34, 0x9c, 0x2f, 0x3d, 0x31, 0x61, 0x34, 0xa0, + 0xdc, 0xf6, 0x51, 0x03, 0x96, 0x03, 0xb5, 0x3e, 0x36, 0x04, 0xd3, 0xa3, 0x11, 0x6e, 0xbd, 0x80, + 0xf7, 0xa5, 0xef, 0x83, 0x27, 0x16, 0x98, 0xd9, 0x5f, 0x2e, 0x77, 0x3e, 0x81, 0x25, 0xe9, 0x7c, + 0x4f, 0x05, 0xc9, 0xa6, 0xbf, 0x02, 0x85, 0x0f, 0xd7, 0xc4, 0xc9, 0xc4, 0x51, 0x1f, 0x16, 0x18, + 0xe1, 0xa1, 0x2f, 0xb4, 0xab, 0x26, 0x68, 0xdf, 0xee, 0x3d, 0x36, 0xce, 0x3e, 0x11, 0x23, 0x2d, + 0x34, 0xce, 0x0b, 0x05, 0x65, 0x96, 0xc4, 0x2d, 0x65, 0x43, 0x08, 0xe6, 0x7d, 0xea, 0x72, 0xed, + 0x46, 0x7c, 0x81, 0x96, 0x5c, 0xb7, 0x3e, 0xc1, 0x8a, 0x2c, 0x61, 0x4c, 0xec, 0x28, 0x73, 0xda, + 0xa7, 0x53, 0xb8, 0xba, 0x74, 0x0a, 0xdf, 0x81, 0x1a, 0x43, 0x5a, 0xdd, 0x84, 0x85, 0x2b, 0x82, + 0xb3, 0xfb, 0x7d, 0x0e, 0x0b, 0x5c, 0xd8, 0x22, 0xe4, 0xaa, 0xdf, 0xc6, 0x7f, 0xfb, 0x9d, 0x4a, + 0xcc, 0x52, 0x38, 0xea, 0xc3, 0x5b, 0xc2, 0xf6, 0xfd, 0xcd, 0x4c, 0x5d, 0x57, 0xdc, 0x6f, 0xb9, + 0x57, 0xff, 0xc7, 0xfe, 0x36, 0x86, 0xd4, 0x1d, 0x95, 0xc5, 0x71, 0x33, 0x78, 0xf9, 0x73, 0xa7, + 0x83, 0xed, 0x4e, 0x07, 0x7f, 0x76, 0x3a, 0xf8, 0xb6, 0xd7, 0x73, 0xdb, 0xbd, 0x9e, 0xfb, 0xbd, + 0xd7, 0x73, 0x1f, 0x1f, 0xb9, 0x9e, 0x58, 0x84, 0x73, 0xc3, 0xa1, 0x4b, 0xf5, 0x04, 0xd5, 0x4f, + 0x87, 0xe3, 0xcf, 0xe6, 0x3a, 0x79, 0x81, 0xf3, 0x82, 0x7c, 0x79, 0x4f, 0xff, 0x06, 0x00, 0x00, + 0xff, 0xff, 0xa5, 0x1a, 0x1c, 0xb9, 0xe2, 0x03, 0x00, 0x00, } func (m *EventCreateGroup) Marshal() (dAtA []byte, err error) { @@ -781,6 +850,51 @@ func (m *EventLeaveGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *EventProposalPruned) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventProposalPruned) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventProposalPruned) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TallyResult != nil { + { + size, err := m.TallyResult.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Status != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x10 + } + if m.ProposalId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintEvents(dAtA []byte, offset int, v uint64) int { offset -= sovEvents(v) base := offset @@ -913,6 +1027,25 @@ func (m *EventLeaveGroup) Size() (n int) { return n } +func (m *EventProposalPruned) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovEvents(uint64(m.ProposalId)) + } + if m.Status != 0 { + n += 1 + sovEvents(uint64(m.Status)) + } + if m.TallyResult != nil { + l = m.TallyResult.Size() + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + func sovEvents(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1649,6 +1782,130 @@ func (m *EventLeaveGroup) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventProposalPruned) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventProposalPruned: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventProposalPruned: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= ProposalStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TallyResult", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TallyResult == nil { + m.TallyResult = &TallyResult{} + } + if err := m.TallyResult.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipEvents(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/group/keeper/genesis.go b/x/group/keeper/genesis.go index 2e0766ed716e..8043b52acce0 100644 --- a/x/group/keeper/genesis.go +++ b/x/group/keeper/genesis.go @@ -42,7 +42,8 @@ func (k Keeper) InitGenesis(ctx types.Context, cdc codec.JSONCodec, data json.Ra return []abci.ValidatorUpdate{} } -func (k Keeper) ExportGenesis(ctx types.Context, cdc codec.JSONCodec) *group.GenesisState { +// ExportGenesis returns the group module's exported genesis. +func (k Keeper) ExportGenesis(ctx types.Context, _ codec.JSONCodec) *group.GenesisState { genesisState := group.NewGenesisState() var groups []*group.GroupInfo diff --git a/x/group/keeper/keeper.go b/x/group/keeper/keeper.go index 210ce6014c58..02bd70d1206e 100644 --- a/x/group/keeper/keeper.go +++ b/x/group/keeper/keeper.go @@ -367,6 +367,15 @@ func (k Keeper) PruneProposals(ctx sdk.Context) error { if err != nil { return err } + // Emit event for proposal finalized with its result + if err := ctx.EventManager().EmitTypedEvent( + &group.EventProposalPruned{ + ProposalId: proposal.Id, + Status: proposal.Status, + TallyResult: &proposal.FinalTallyResult, + }); err != nil { + return err + } } return nil @@ -401,6 +410,14 @@ func (k Keeper) TallyProposalsAtVPEnd(ctx sdk.Context) error { if err := k.pruneVotes(ctx, proposalID); err != nil { return err } + // Emit event for proposal finalized with its result + if err := ctx.EventManager().EmitTypedEvent( + &group.EventProposalPruned{ + ProposalId: proposal.Id, + Status: proposal.Status, + }); err != nil { + return err + } } else if proposal.Status == group.PROPOSAL_STATUS_SUBMITTED { if err := k.doTallyAndUpdate(ctx, &proposal, electorate, policyInfo); err != nil { return sdkerrors.Wrap(err, "doTallyAndUpdate") diff --git a/x/group/keeper/keeper_test.go b/x/group/keeper/keeper_test.go index 56a748018965..e9c9aa9539cc 100644 --- a/x/group/keeper/keeper_test.go +++ b/x/group/keeper/keeper_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtime "github.com/tendermint/tendermint/types/time" @@ -23,6 +24,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/group/module" ) +var EventProposalPruned = "cosmos.group.v1.EventProposalPruned" + const minExecutionPeriod = 5 * time.Second type TestSuite struct { @@ -1663,6 +1666,8 @@ func (s *TestSuite) TestSubmitProposal() { s.Require().Contains(fromBalances, sdk.NewInt64Coin("test", 9900)) toBalances := s.app.BankKeeper.GetAllBalances(sdkCtx, addr2) s.Require().Contains(toBalances, sdk.NewInt64Coin("test", 100)) + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) }, }, "with try exec, not enough yes votes for proposal to pass": { @@ -1751,6 +1756,7 @@ func (s *TestSuite) TestWithdrawProposal() { proposalId uint64 admin string expErrMsg string + postRun func(sdkCtx sdk.Context) }{ "wrong admin": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1758,6 +1764,7 @@ func (s *TestSuite) TestWithdrawProposal() { }, admin: addr5.String(), expErrMsg: "unauthorized", + postRun: func(sdkCtx sdk.Context) {}, }, "wrong proposalId": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1765,6 +1772,7 @@ func (s *TestSuite) TestWithdrawProposal() { }, admin: proposers[0], expErrMsg: "not found", + postRun: func(sdkCtx sdk.Context) {}, }, "happy case with proposer": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1772,6 +1780,7 @@ func (s *TestSuite) TestWithdrawProposal() { }, proposalId: proposalID, admin: proposers[0], + postRun: func(sdkCtx sdk.Context) {}, }, "already closed proposal": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1786,6 +1795,7 @@ func (s *TestSuite) TestWithdrawProposal() { proposalId: proposalID, admin: proposers[0], expErrMsg: "cannot withdraw a proposal with the status of PROPOSAL_STATUS_WITHDRAWN", + postRun: func(sdkCtx sdk.Context) {}, }, "happy case with group admin address": { preRun: func(sdkCtx sdk.Context) uint64 { @@ -1793,6 +1803,17 @@ func (s *TestSuite) TestWithdrawProposal() { }, proposalId: proposalID, admin: proposers[0], + postRun: func(sdkCtx sdk.Context) { + resp, err := s.keeper.Proposal(s.ctx, &group.QueryProposalRequest{ProposalId: proposalID}) + s.Require().NoError(err) + vpe := resp.Proposal.VotingPeriodEnd + timeDiff := vpe.Sub(s.sdkCtx.BlockTime()) + ctxVPE := sdkCtx.WithBlockTime(s.sdkCtx.BlockTime().Add(timeDiff).Add(time.Second * 1)) + s.Require().NoError(s.keeper.TallyProposalsAtVPEnd(ctxVPE)) + events := ctxVPE.EventManager().ABCIEvents() + + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, } for msg, spec := range specs { @@ -1815,6 +1836,7 @@ func (s *TestSuite) TestWithdrawProposal() { resp, err := s.keeper.Proposal(s.ctx, &group.QueryProposalRequest{ProposalId: pId}) s.Require().NoError(err) s.Require().Equal(resp.GetProposal().Status, group.PROPOSAL_STATUS_WITHDRAWN) + spec.postRun(s.sdkCtx) }) } } @@ -2316,6 +2338,7 @@ func (s *TestSuite) TestExecProposal() { expBalance bool expFromBalances sdk.Coin expToBalances sdk.Coin + postRun func(sdkCtx sdk.Context) }{ "proposal executed when accepted": { setupProposal: func(ctx context.Context) uint64 { @@ -2328,6 +2351,10 @@ func (s *TestSuite) TestExecProposal() { expBalance: true, expFromBalances: sdk.NewInt64Coin("test", 9900), expToBalances: sdk.NewInt64Coin("test", 100), + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, "proposal with multiple messages executed when accepted": { setupProposal: func(ctx context.Context) uint64 { @@ -2340,6 +2367,10 @@ func (s *TestSuite) TestExecProposal() { expBalance: true, expFromBalances: sdk.NewInt64Coin("test", 9800), expToBalances: sdk.NewInt64Coin("test", 200), + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, "proposal not executed when rejected": { setupProposal: func(ctx context.Context) uint64 { @@ -2349,6 +2380,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end expProposalStatus: group.PROPOSAL_STATUS_REJECTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, + postRun: func(sdkCtx sdk.Context) {}, }, "open proposal must not fail": { setupProposal: func(ctx context.Context) uint64 { @@ -2356,12 +2388,14 @@ func (s *TestSuite) TestExecProposal() { }, expProposalStatus: group.PROPOSAL_STATUS_SUBMITTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, + postRun: func(sdkCtx sdk.Context) {}, }, "existing proposal required": { setupProposal: func(ctx context.Context) uint64 { return 9999 }, - expErr: true, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, }, "Decision policy also applied on exactly voting period end": { setupProposal: func(ctx context.Context) uint64 { @@ -2371,6 +2405,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(time.Second), // Voting period is 1s expProposalStatus: group.PROPOSAL_STATUS_REJECTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, + postRun: func(sdkCtx sdk.Context) {}, }, "Decision policy also applied after voting period end": { setupProposal: func(ctx context.Context) uint64 { @@ -2380,6 +2415,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(time.Second).Add(time.Millisecond), // Voting period is 1s expProposalStatus: group.PROPOSAL_STATUS_REJECTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN, + postRun: func(sdkCtx sdk.Context) {}, }, "exec proposal before MinExecutionPeriod should fail": { setupProposal: func(ctx context.Context) uint64 { @@ -2389,6 +2425,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(4 * time.Second), // min execution date is 5s later after s.blockTime expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_FAILURE, // Because MinExecutionPeriod has not passed + postRun: func(sdkCtx sdk.Context) {}, }, "exec proposal at exactly MinExecutionPeriod should pass": { setupProposal: func(ctx context.Context) uint64 { @@ -2398,6 +2435,10 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(5 * time.Second), // min execution date is 5s later after s.blockTime expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS, + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, "prevent double execution when successful": { setupProposal: func(ctx context.Context) uint64 { @@ -2419,6 +2460,10 @@ func (s *TestSuite) TestExecProposal() { expBalance: true, expFromBalances: sdk.NewInt64Coin("test", 9900), expToBalances: sdk.NewInt64Coin("test", 100), + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, "rollback all msg updates on failure": { setupProposal: func(ctx context.Context) uint64 { @@ -2428,6 +2473,7 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_FAILURE, + postRun: func(sdkCtx sdk.Context) {}, }, "executable when failed before": { setupProposal: func(ctx context.Context) uint64 { @@ -2444,6 +2490,10 @@ func (s *TestSuite) TestExecProposal() { srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED, expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS, + postRun: func(sdkCtx sdk.Context) { + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) + }, }, } for msg, spec := range specs { @@ -2487,6 +2537,8 @@ func (s *TestSuite) TestExecProposal() { toBalances := s.app.BankKeeper.GetAllBalances(sdkCtx, addr2) s.Require().Contains(toBalances, spec.expToBalances) } + + spec.postRun(sdkCtx) }) } } @@ -2629,6 +2681,8 @@ func (s *TestSuite) TestExecPrunedProposalsAndVotes() { res, err := s.keeper.VotesByProposal(ctx, &group.QueryVotesByProposalRequest{ProposalId: proposalID}) s.Require().NoError(err) s.Require().Empty(res.GetVotes()) + events := sdkCtx.EventManager().ABCIEvents() + s.Require().True(eventTypeFound(events, EventProposalPruned)) } else { // Check that proposal and votes exists @@ -3191,3 +3245,14 @@ func (s *TestSuite) TestTallyProposalsAtVPEnd_GroupMemberLeaving() { s.Require().NoError(s.app.GroupKeeper.TallyProposalsAtVPEnd(ctx)) s.NotPanics(func() { module.EndBlocker(ctx, s.app.GroupKeeper) }) } + +func eventTypeFound(events []abci.Event, eventType string) bool { + eventTypeFound := false + for _, e := range events { + if e.Type == eventType { + eventTypeFound = true + break + } + } + return eventTypeFound +} diff --git a/x/group/keeper/msg_server.go b/x/group/keeper/msg_server.go index 3947f0adad50..d4ffcdbbcffc 100644 --- a/x/group/keeper/msg_server.go +++ b/x/group/keeper/msg_server.go @@ -702,6 +702,7 @@ func (k Keeper) doTallyAndUpdate(ctx sdk.Context, p *group.Proposal, electorate } else { p.Status = group.PROPOSAL_STATUS_REJECTED } + } return nil @@ -773,6 +774,16 @@ func (k Keeper) Exec(goCtx context.Context, req *group.MsgExec) (*group.MsgExecR if err := k.pruneProposal(ctx, proposal.Id); err != nil { return nil, err } + + // Emit event for proposal finalized with its result + if err := ctx.EventManager().EmitTypedEvent( + &group.EventProposalPruned{ + ProposalId: proposal.Id, + Status: proposal.Status, + TallyResult: &proposal.FinalTallyResult, + }); err != nil { + return nil, err + } } else { store := ctx.KVStore(k.key) if err := k.proposalTable.Update(store, id, &proposal); err != nil { diff --git a/x/group/spec/04_events.md b/x/group/spec/04_events.md index ca4e2fdf20bb..1f064009d7bc 100644 --- a/x/group/spec/04_events.md +++ b/x/group/spec/04_events.md @@ -70,3 +70,12 @@ The group module emits the following events: | message | action | /cosmos.group.v1.Msg/LeaveGroup | | cosmos.group.v1.EventLeaveGroup | proposal_id | {proposalId} | | cosmos.group.v1.EventLeaveGroup | address | {address} | + +### EventProposalPruned + +| Type | Attribute Key | Attribute Value | +|-------------------------------------|---------------|---------------------------------| +| message | action | /cosmos.group.v1.Msg/LeaveGroup | +| cosmos.group.v1.EventProposalPruned | proposal_id | {proposalId} | +| cosmos.group.v1.EventProposalPruned | status | {ProposalStatus} | +| cosmos.group.v1.EventProposalPruned | tally_result | {TallyResult} | \ No newline at end of file From 5b4c59385bc6be42dbe4fbc17753f63a2af49d9b Mon Sep 17 00:00:00 2001 From: yihuang Date: Tue, 30 May 2023 18:28:18 +0800 Subject: [PATCH 37/47] fix: Revert "fix(x/gov): Return ErrInvalidProposalContent in SubmitProposal when legacy handler returns an error. (backport #13051) (#15667)" (#16331) --- CHANGELOG.md | 1 + x/gov/keeper/proposal.go | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4da2920f42c9..2a9c8316bd27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (cli) [#16312](https://github.com/cosmos/cosmos-sdk/pull/16312) Allow any addresses in `client.ValidatePromptAddress`. * (store/iavl) [#15717](https://github.com/cosmos/cosmos-sdk/pull/15717) Upstream error on empty version (this change was present on all version but v0.46). +* (x/gov) [#16331](https://github.com/cosmos/cosmos-sdk/pull/16331) Revert a change that breaks result hash. ## [v0.46.12](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.12) - 2022-04-04 diff --git a/x/gov/keeper/proposal.go b/x/gov/keeper/proposal.go index b49cd8335042..64088859c684 100644 --- a/x/gov/keeper/proposal.go +++ b/x/gov/keeper/proposal.go @@ -1,7 +1,6 @@ package keeper import ( - "errors" "fmt" "github.com/cosmos/cosmos-sdk/client" @@ -55,10 +54,7 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, messages []sdk.Msg, metadat if msg, ok := msg.(*v1.MsgExecLegacyContent); ok { cacheCtx, _ := ctx.CacheContext() if _, err := handler(cacheCtx, msg); err != nil { - if errors.Is(types.ErrNoProposalHandlerExists, err) { - return v1.Proposal{}, err - } - return v1.Proposal{}, sdkerrors.Wrap(types.ErrInvalidProposalContent, err.Error()) + return v1.Proposal{}, sdkerrors.Wrap(types.ErrNoProposalHandlerExists, err.Error()) } } From 26405d9b81f8653cb5bf3a8569359a910ccdbf81 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Fri, 2 Jun 2023 14:03:01 +0200 Subject: [PATCH 38/47] chore: prepare v0.46.13 (#16249) --- CHANGELOG.md | 8 +++++--- RELEASE_NOTES.md | 13 ++++++++++--- go.mod | 6 ++++-- go.sum | 4 ++-- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a9c8316bd27..64b9862ff596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,19 +37,21 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +## [v0.46.13](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.13) - 2022-06-05 + ## Features +* (snapshots) [#16060](https://github.com/cosmos/cosmos-sdk/pull/16060) Support saving and restoring snapshot locally. * (baseapp) [#16290](https://github.com/cosmos/cosmos-sdk/pull/16290) Add circuit breaker setter in baseapp. -* [#16060](https://github.com/cosmos/cosmos-sdk/pull/16060) Support saving restoring snapshot locally. * (x/group) [#16191](https://github.com/cosmos/cosmos-sdk/pull/16191) Add EventProposalPruned event to group module whenever a proposal is pruned. ### Improvements * (deps) [#15973](https://github.com/cosmos/cosmos-sdk/pull/15973) Bump CometBFT to [v0.34.28](https://github.com/cometbft/cometbft/blob/v0.34.28/CHANGELOG.md#v03428). * (store) [#15683](https://github.com/cosmos/cosmos-sdk/pull/15683) `rootmulti.Store.CacheMultiStoreWithVersion` now can handle loading archival states that don't persist any of the module stores the current state has. -* (simapp) [#15903](https://github.com/cosmos/cosmos-sdk/pull/15903) Add `AppStateFnWithExtendedCbs` with moduleStateCb callback function to allow access moduleState. Note, this function is present in simtestutil from `v0.47.2+`. +* (simapp) [#15903](https://github.com/cosmos/cosmos-sdk/pull/15903) Add `AppStateFnWithExtendedCbs` with moduleStateCb callback function to allow access moduleState. Note, this function is present in `simtestutil` from `v0.47.2+`. * (gov) [#15979](https://github.com/cosmos/cosmos-sdk/pull/15979) Improve gov error message when failing to convert v1 proposal to v1beta1. -* (server) [#16061](https://github.com/cosmos/cosmos-sdk/pull/16061) add comet bootstrap command +* (server) [#16061](https://github.com/cosmos/cosmos-sdk/pull/16061) Add Comet bootstrap command. * (store) [#16067](https://github.com/cosmos/cosmos-sdk/pull/16067) Add local snapshots management commands. * (baseapp) [#16193](https://github.com/cosmos/cosmos-sdk/pull/16193) Add `Close` method to `BaseApp` for custom app to cleanup resource in graceful shutdown. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 65aad49293f0..c258c002d686 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,14 +1,21 @@ # Cosmos SDK v0.46.13 Release Notes - +This release includes a few improvements and bug fixes. +Notably, a bump to [CometBFT v0.34.28](https://github.com/cometbft/cometbft/blob/v0.34.28/CHANGELOG.md#v03428). +Additionally, it includes new commands for snapshots management and bootstrapping from a local snapshot. +Add `snapshot.Cmd(appCreator)` to your chain root command for using it. -Note, from `v0.46.11`+, the following replace is *mandatory* in the `go.mod` of your application: +Did you know Cosmos SDK Twilight (a.k.a v0.47) has been released? Upgrade easily by reading the [upgrading guide](https://github.com/cosmos/cosmos-sdk/blob/release/v0.47.x/UPGRADING.md#v047x). + +Ensure you have the following replaces in the `go.mod` of your application: ```go // use cometbft replace github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.28 +// replace broken goleveldb +replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ``` Please see the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/CHANGELOG.md) for an exhaustive list of changes. -**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.12...v0.46.13 +**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.12...v0.46.13 \ No newline at end of file diff --git a/go.mod b/go.mod index 9b8fa6be2d93..3aaf3c199e8a 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/cosmos/cosmos-proto v1.0.0-alpha7 github.com/cosmos/cosmos-sdk/db v1.0.0-beta.1 github.com/cosmos/go-bip39 v1.0.0 - github.com/cosmos/iavl v0.19.5 + github.com/cosmos/iavl v0.19.6 github.com/cosmos/ledger-cosmos-go v0.12.2 github.com/gogo/gateway v1.1.0 github.com/gogo/protobuf v1.3.2 @@ -171,13 +171,15 @@ replace ( github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/jhump/protoreflect => github.com/jhump/protoreflect v1.9.0 - // Downgraded to avoid bugs in following commits which caused simulations to fail. + // replace broken goleveldb. github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // use cometbft github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.28 ) retract ( + // revert fix https://github.com/cosmos/cosmos-sdk/pull/16331 + v0.46.12 // subject to a bug in the group module and gov module migration [v0.46.5, v0.46.6] // subject to the dragonberry vulnerability diff --git a/go.sum b/go.sum index e190a029afe7..1035a8293d2f 100644 --- a/go.sum +++ b/go.sum @@ -228,8 +228,8 @@ 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/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= -github.com/cosmos/iavl v0.19.5 h1:rGA3hOrgNxgRM5wYcSCxgQBap7fW82WZgY78V9po/iY= -github.com/cosmos/iavl v0.19.5/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= +github.com/cosmos/iavl v0.19.6 h1:XY78yEeNPrEYyNCKlqr9chrwoeSDJ0bV2VjocTk//OU= +github.com/cosmos/iavl v0.19.6/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= From 67f33bd370f37da68ecce4c200bc3b7ce4ab5f19 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 2 Jun 2023 12:20:47 +0000 Subject: [PATCH 39/47] chore: small snapshot commands & docs improvement (backport #16404) (#16409) Co-authored-by: Julien Robert --- client/snapshot/cmd.go | 1 - client/snapshot/export.go | 6 ++---- client/snapshot/list.go | 2 +- client/snapshot/load.go | 4 ++-- docs/run-node/run-node.md | 38 ++++++++++++++++++++++++++++++++------ server/tm_cmds.go | 2 +- server/util.go | 5 +++-- snapshots/README.md | 23 +++++++++++------------ 8 files changed, 52 insertions(+), 29 deletions(-) diff --git a/client/snapshot/cmd.go b/client/snapshot/cmd.go index f49f2b51c2b4..14388bc8d05e 100644 --- a/client/snapshot/cmd.go +++ b/client/snapshot/cmd.go @@ -10,7 +10,6 @@ func Cmd(appCreator servertypes.AppCreator) *cobra.Command { cmd := &cobra.Command{ Use: "snapshots", Short: "Manage local snapshots", - Long: "Manage local snapshots", } cmd.AddCommand( ListSnapshotsCmd, diff --git a/client/snapshot/export.go b/client/snapshot/export.go index cc39209a08f8..cb6ebc1417a4 100644 --- a/client/snapshot/export.go +++ b/client/snapshot/export.go @@ -1,8 +1,6 @@ package snapshot import ( - "fmt" - "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/spf13/cobra" @@ -34,7 +32,7 @@ func ExportSnapshotCmd(appCreator servertypes.AppCreator) *cobra.Command { height = app.CommitMultiStore().LastCommitID().Version } - fmt.Printf("Exporting snapshot for height %d\n", height) + cmd.Printf("Exporting snapshot for height %d\n", height) sm := app.SnapshotManager() snapshot, err := sm.Create(uint64(height)) @@ -42,7 +40,7 @@ func ExportSnapshotCmd(appCreator servertypes.AppCreator) *cobra.Command { return err } - fmt.Printf("Snapshot created at height %d, format %d, chunks %d\n", snapshot.Height, snapshot.Format, snapshot.Chunks) + cmd.Printf("Snapshot created at height %d, format %d, chunks %d\n", snapshot.Height, snapshot.Format, snapshot.Chunks) return nil }, } diff --git a/client/snapshot/list.go b/client/snapshot/list.go index 6ff6391d4211..78612bf916ee 100644 --- a/client/snapshot/list.go +++ b/client/snapshot/list.go @@ -22,7 +22,7 @@ var ListSnapshotsCmd = &cobra.Command{ return fmt.Errorf("failed to list snapshots: %w", err) } for _, snapshot := range snapshots { - fmt.Println("height:", snapshot.Height, "format:", snapshot.Format, "chunks:", snapshot.Chunks) + cmd.Println("height:", snapshot.Height, "format:", snapshot.Format, "chunks:", snapshot.Chunks) } return nil diff --git a/client/snapshot/load.go b/client/snapshot/load.go index 6797d58bafec..7834aa21e2e7 100644 --- a/client/snapshot/load.go +++ b/client/snapshot/load.go @@ -22,7 +22,7 @@ const SnapshotFileName = "_snapshot" func LoadArchiveCmd() *cobra.Command { return &cobra.Command{ Use: "load ", - Short: "Load a snapshot archive file into snapshot store", + Short: "Load a snapshot archive file (.tar.gz) into snapshot store", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := server.GetServerContextFromCmd(cmd) @@ -70,7 +70,7 @@ func LoadArchiveCmd() *cobra.Command { savedSnapshot, err := snapshotStore.Save(snapshot.Height, snapshot.Format, chunks) if err != nil { - fmt.Println("failed to save snapshot", err) + cmd.Println("failed to save snapshot", err) return } quitChan <- savedSnapshot diff --git a/docs/run-node/run-node.md b/docs/run-node/run-node.md index 502207761d9c..19f2aa6bcf90 100644 --- a/docs/run-node/run-node.md +++ b/docs/run-node/run-node.md @@ -127,15 +127,41 @@ The naive way would be to run the same commands again in separate terminal windo ## State Sync -State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don't want to sync all the blocks in history. You can read more here: https://docs.cometbft.com/v0.37/core/state-sync +State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don't want to sync all the blocks in history. Read more in [CometBFT documentation](https://docs.cometbft.com/v0.34/core/state-sync). + +State sync works thanks to snapshots. Read how the SDK handles snapshots [here](https://github.com/cosmos/cosmos-sdk/blob/825245d/store/snapshots/README.md). ### Local State Sync Local state sync work similar to normal state sync except that it works off a local snapshot of state instead of one provided via the p2p network. The steps to start local state sync are similar to normal state sync with a few different designs. -1. As mentioned in https://docs.cometbft.com/v0.37/core/state-sync, one must set a height and hash in the config.toml along with a few rpc servers (the afromentioned link has instructions on how to do this). -2. Bootsrapping Comet state in order to start the node after the snapshot has been ingested. This can be done with the bootstrap command ` comet bootstrap-state` - -## Next {hide} +1. As mentioned in https://docs.cometbft.com/v0.34/core/state-sync, one must set a height and hash in the config.toml along with a few rpc servers (the afromentioned link has instructions on how to do this). +2. Run ` ` to restore a local snapshot (note: first load it from a file with the *load* command). +3. Bootsrapping Comet state in order to start the node after the snapshot has been ingested. This can be done with the bootstrap command ` tendermint bootstrap-state` + +### Snapshots Commands + +The Cosmos SDK provides commands for managing snapshots. +These commands can be added in an app with the following snippet in `cmd//root.go`: + +```go +import ( + "github.com/cosmos/cosmos-sdk/client/snapshot" +) + +func initRootCmd(/* ... */) { + // ... + rootCmd.AddCommand( + snapshot.Cmd(appCreator), + ) +} +``` + +Then following commands are available at ` snapshots [command]`: -Read about the [Interacting with your Node](./interact-node.md) {hide} +* **list**: list local snapshots +* **load**: Load a snapshot archive file into snapshot store +* **restore**: Restore app state from local snapshot +* **export**: Export app state to snapshot store +* **dump**: Dump the snapshot as portable archive format +* **delete**: Delete a local snapshot diff --git a/server/tm_cmds.go b/server/tm_cmds.go index 3eae9fa43087..9c070d5ef26c 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -210,7 +210,7 @@ func BootstrapStateCmd(appCreator types.AppCreator) *cobra.Command { }, } - cmd.Flags().Int64("height", 0, "Block height to bootstrap state at, if not provided will use the latest block height in app state") + cmd.Flags().Int64("height", 0, "Block height to bootstrap state at, if not provided it uses the latest block height in app state") return cmd } diff --git a/server/util.go b/server/util.go index 019d0132085c..b28e339bff5f 100644 --- a/server/util.go +++ b/server/util.go @@ -273,8 +273,9 @@ func interceptConfigs(rootViper *viper.Viper, customAppTemplate string, customCo // add server commands func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator types.AppCreator, appExport types.AppExporter, addStartFlags types.ModuleInitFlags) { tendermintCmd := &cobra.Command{ - Use: "tendermint", - Short: "Tendermint subcommands", + Use: "tendermint", + Aliases: []string{"comet", "cometbft"}, + Short: "Tendermint subcommands", } tendermintCmd.AddCommand( diff --git a/snapshots/README.md b/snapshots/README.md index 1c80f05d5633..f9fccfc20f38 100644 --- a/snapshots/README.md +++ b/snapshots/README.md @@ -55,16 +55,16 @@ Snapshot settings are optional. However, if set, they have an effect on how prun persisting the heights that are multiples of `state-sync.snapshot-interval` until after the snapshot is complete. If pruning is enabled (not `pruning = "nothing"`), we avoid pruning heights that are multiples of -`state-sync.snapshot-interval` in the regular logic determined by the -pruning settings and applied after every `Commit()`. This is done to prevent a -height from being removed before a snapshot is complete. Therefore, we keep -such heights until after a snapshot is done. At this point, the height is sent to +`state-sync.snapshot-interval` in the regular logic determined by the +pruning settings and applied after every `Commit()`. This is done to prevent a +height from being removed before a snapshot is complete. Therefore, we keep +such heights until after a snapshot is done. At this point, the height is sent to the `pruning.Manager` to be pruned according to the pruning settings after the next `Commit()`. To illustrate, assume that we are currently at height 960 with `pruning-keep-recent = 50`, `pruning-interval = 10`, and `state-sync.snapshot-interval = 100`. Let's assume that the snapshot that was triggered at height `900` **just finishes**. Then, we can prune height -`900` right away (that is, when we call `Commit()` at height 960 because 900 is less than `960 - 50 = 910`. +`900` right away (that is, when we call `Commit()` at height 960 because 900 is less than `960 - 50 = 910`). Let's now assume that all conditions stay the same but the snapshot at height 900 is **not complete yet**. Then, we cannot prune it to avoid deleting a height that is still being snapshotted. Therefore, we keep track @@ -78,23 +78,22 @@ Note that in both examples, if we let current height = C, and previous height P P - `pruning-keep-recent` - `pruning-interval` <= h <= P - `pruning-keep-recent` -we can prune height h. In our first example, all heights 899 - 909 fall in this range and are pruned at height 960 as long as +we can prune height h. In our first example, all heights 899 - 909 fall in this range and are pruned at height 960 as long as h is not a snapshot height (E.g. 900). That is, we always use current height to determine at which height to prune (960) while we use previous to determine which heights are to be pruned (959 - 50 - 10 = 899-909 = 959 - 50). - ## Configuration * `state-sync.snapshot-interval` - * the interval at which to take snapshots. - * the value of 0 disables snapshots. - * if pruning is enabled, it is done after a snapshot is complete for the heights that are multiples of this interval. + * the interval at which to take snapshots. + * the value of 0 disables snapshots. + * if pruning is enabled, it is done after a snapshot is complete for the heights that are multiples of this interval. * `state-sync.snapshot-keep-recent`: - * the number of recent snapshots to keep. - * 0 means keep all. + * the number of recent snapshots to keep. + * 0 means keep all. ## Snapshot Metadata From 7d43a5ab4d9931dc06707cee1cd01b8e1e41ddea Mon Sep 17 00:00:00 2001 From: Daniel Wedul Date: Fri, 2 Jun 2023 14:40:57 -0600 Subject: [PATCH 40/47] Add the quarantine and sanction stores to the import-export sim test. --- simapp/sim_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 61dbf13ff16e..8ee14cc84976 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -11,9 +11,8 @@ import ( "testing" "github.com/spf13/viper" - - storetypes "github.com/cosmos/cosmos-sdk/store/types" "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" @@ -22,6 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/simapp/helpers" "github.com/cosmos/cosmos-sdk/store" + storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -33,6 +33,8 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/cosmos/cosmos-sdk/x/quarantine" + "github.com/cosmos/cosmos-sdk/x/sanction" "github.com/cosmos/cosmos-sdk/x/simulation" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -199,6 +201,8 @@ func TestAppImportExport(t *testing.T) { {app.keys[evidencetypes.StoreKey], newApp.keys[evidencetypes.StoreKey], [][]byte{}}, {app.keys[capabilitytypes.StoreKey], newApp.keys[capabilitytypes.StoreKey], [][]byte{}}, {app.keys[authzkeeper.StoreKey], newApp.keys[authzkeeper.StoreKey], [][]byte{authzkeeper.GrantKey, authzkeeper.GrantQueuePrefix}}, + {app.keys[quarantine.StoreKey], newApp.keys[quarantine.StoreKey], [][]byte{}}, + {app.keys[sanction.StoreKey], newApp.keys[sanction.StoreKey], [][]byte{}}, } for _, skp := range storeKeysPrefixes { From 7ee780988b78c7de9b9d751128eec5615e0d0953 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 6 Jun 2023 18:50:35 +0200 Subject: [PATCH 41/47] refactor: avoid breaking change due to #16415 included in v0.50 (backport #16430) (#16432) Co-authored-by: Julien Robert Co-authored-by: Facundo Medica --- baseapp/circuit.go | 6 ++---- baseapp/msg_service_router.go | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/baseapp/circuit.go b/baseapp/circuit.go index 022ee6632c2e..3db0bc1bdcda 100644 --- a/baseapp/circuit.go +++ b/baseapp/circuit.go @@ -1,10 +1,8 @@ package baseapp -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) +import "context" // CircuitBreaker is an interface that defines the methods for a circuit breaker. type CircuitBreaker interface { - IsAllowed(ctx sdk.Context, typeURL string) bool + IsAllowed(ctx context.Context, typeURL string) (bool, error) } diff --git a/baseapp/msg_service_router.go b/baseapp/msg_service_router.go index a6494eebc6d1..b70864ddd287 100644 --- a/baseapp/msg_service_router.go +++ b/baseapp/msg_service_router.go @@ -125,14 +125,21 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter } else { return nil, err } + } - if msr.circuitBreaker != nil { - msgURL := sdk.MsgTypeURL(req) - if !msr.circuitBreaker.IsAllowed(ctx, msgURL) { - return nil, fmt.Errorf("circuit breaker disables execution of this message: %s", msgURL) - } + if msr.circuitBreaker != nil { + msgURL := sdk.MsgTypeURL(req) + + isAllowed, err := msr.circuitBreaker.IsAllowed(ctx, msgURL) + if err != nil { + return nil, err + } + + if !isAllowed { + return nil, fmt.Errorf("circuit breaker disables execution of this message: %s", msgURL) } } + // Call the method handler from the service description with the handler object. // We don't do any decoding here because the decoding was already done. res, err := methodHandler(handler, sdk.WrapSDKContext(ctx), noopDecoder, interceptor) From d4b7164de5d8391e6aa644d8ea84e07396dd9653 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 8 Jun 2023 11:36:36 +0200 Subject: [PATCH 42/47] chore: prepare v0.46.13 (2/2) (#16443) --- CHANGELOG.md | 12 ++++++------ RELEASE_NOTES.md | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64b9862ff596..946863844363 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] -## [v0.46.13](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.13) - 2022-06-05 +## [v0.46.13](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.13) - 2023-06-08 ## Features @@ -57,11 +57,11 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* Fix [barberry](https://forum.cosmos.network/t/cosmos-sdk-security-advisory-barberry/10825) security vulnerability. * (cli) [#16312](https://github.com/cosmos/cosmos-sdk/pull/16312) Allow any addresses in `client.ValidatePromptAddress`. * (store/iavl) [#15717](https://github.com/cosmos/cosmos-sdk/pull/15717) Upstream error on empty version (this change was present on all version but v0.46). -* (x/gov) [#16331](https://github.com/cosmos/cosmos-sdk/pull/16331) Revert a change that breaks result hash. -## [v0.46.12](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.12) - 2022-04-04 +## [v0.46.12](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.12) - 2023-04-04 ### Features @@ -78,7 +78,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/auth/vesting) [#15383](https://github.com/cosmos/cosmos-sdk/pull/15383) Add extra checks when creating a periodic vesting account. * (x/gov) [#13051](https://github.com/cosmos/cosmos-sdk/pull/13051) In SubmitPropsal, when a legacy msg fails it's handler call, wrap the error as ErrInvalidProposalContent (instead of ErrNoProposalHandlerExists). -## [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11) - 2022-03-03 +## [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11) - 2023-03-03 ### Improvements @@ -90,13 +90,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#15243](https://github.com/cosmos/cosmos-sdk/pull/15243) `LatestBlockResponse` & `BlockByHeightResponse` types' field `sdk_block` was incorrectly cast `proposer_address` bytes to validator operator address, now to consensus address. -## [v0.46.10](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.10) - 2022-02-16 +## [v0.46.10](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.10) - 2023-02-16 ### Improvements * (cli) [#14953](https://github.com/cosmos/cosmos-sdk/pull/14953) Enable profiling block replay during abci handshake with `--cpu-profile`. -## [v0.46.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.9) - 2022-02-07 +## [v0.46.9](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.9) - 2023-02-07 ### Improvements diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c258c002d686..f9afd69295b3 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,9 +1,9 @@ # Cosmos SDK v0.46.13 Release Notes -This release includes a few improvements and bug fixes. -Notably, a bump to [CometBFT v0.34.28](https://github.com/cometbft/cometbft/blob/v0.34.28/CHANGELOG.md#v03428). -Additionally, it includes new commands for snapshots management and bootstrapping from a local snapshot. -Add `snapshot.Cmd(appCreator)` to your chain root command for using it. +This release includes few improvements and bug fixes. +Notably, the [barberry security fix](https://forum.cosmos.network/t/cosmos-sdk-security-advisory-barberry/10825). All chains using Cosmos SDK `<= v0.46.12` must upgrade to `v0.46.13` **immediately**. A chain is safe as soon as **33%+1** of the voting power has upgraded. Coordinate with your validators to upgrade as soon as possible. + +Additionally, it includes new commands for snapshots management and bootstrapping from a local snapshot (add `snapshot.Cmd(appCreator)` to the chain root command for using it). Did you know Cosmos SDK Twilight (a.k.a v0.47) has been released? Upgrade easily by reading the [upgrading guide](https://github.com/cosmos/cosmos-sdk/blob/release/v0.47.x/UPGRADING.md#v047x). @@ -18,4 +18,4 @@ replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.2021 Please see the [CHANGELOG](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/CHANGELOG.md) for an exhaustive list of changes. -**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.12...v0.46.13 \ No newline at end of file +**Full Commit History**: https://github.com/cosmos/cosmos-sdk/compare/v0.46.12...v0.46.13 From fd90480b0a922611e366552751a9037e309d8410 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 8 Jun 2023 18:05:37 +0200 Subject: [PATCH 43/47] fix: patch barberry (#16466) --- RELEASE_NOTES.md | 2 +- x/auth/vesting/types/msgs.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f9afd69295b3..27610b6ec13a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,7 @@ # Cosmos SDK v0.46.13 Release Notes This release includes few improvements and bug fixes. -Notably, the [barberry security fix](https://forum.cosmos.network/t/cosmos-sdk-security-advisory-barberry/10825). All chains using Cosmos SDK `<= v0.46.12` must upgrade to `v0.46.13` **immediately**. A chain is safe as soon as **33%+1** of the voting power has upgraded. Coordinate with your validators to upgrade as soon as possible. +Notably, the [barberry security fix](https://forum.cosmos.network/t/cosmos-sdk-security-advisory-barberry/10825). All chains using Cosmos SDK v0.46.0 and above must upgrade to `v0.46.13` **immediately**. A chain is safe as soon as **33%+1** of the voting power has upgraded. Coordinate with your validators to upgrade as soon as possible. Additionally, it includes new commands for snapshots management and bootstrapping from a local snapshot (add `snapshot.Cmd(appCreator)` to the chain root command for using it). diff --git a/x/auth/vesting/types/msgs.go b/x/auth/vesting/types/msgs.go index fbce860cede4..f2194af5690b 100644 --- a/x/auth/vesting/types/msgs.go +++ b/x/auth/vesting/types/msgs.go @@ -182,6 +182,14 @@ func (msg MsgCreatePeriodicVestingAccount) ValidateBasic() error { } for i, period := range msg.VestingPeriods { + if !period.Amount.IsValid() { + return sdkerrors.ErrInvalidCoins.Wrap(period.Amount.String()) + } + + if !period.Amount.IsAllPositive() { + return sdkerrors.ErrInvalidCoins.Wrap(period.Amount.String()) + } + if period.Length < 1 { return fmt.Errorf("invalid period length of %d in period %d, length must be greater than 0", period.Length, i) } From 8f0c6d230a6c0f2e7d1b59a6b4da5239f5f9c1d7 Mon Sep 17 00:00:00 2001 From: Daniel Wedul Date: Thu, 8 Jun 2023 15:46:03 -0600 Subject: [PATCH 44/47] Better gov prop error handling. --- x/gov/keeper/proposal.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x/gov/keeper/proposal.go b/x/gov/keeper/proposal.go index 64088859c684..b49cd8335042 100644 --- a/x/gov/keeper/proposal.go +++ b/x/gov/keeper/proposal.go @@ -1,6 +1,7 @@ package keeper import ( + "errors" "fmt" "github.com/cosmos/cosmos-sdk/client" @@ -54,7 +55,10 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, messages []sdk.Msg, metadat if msg, ok := msg.(*v1.MsgExecLegacyContent); ok { cacheCtx, _ := ctx.CacheContext() if _, err := handler(cacheCtx, msg); err != nil { - return v1.Proposal{}, sdkerrors.Wrap(types.ErrNoProposalHandlerExists, err.Error()) + if errors.Is(types.ErrNoProposalHandlerExists, err) { + return v1.Proposal{}, err + } + return v1.Proposal{}, sdkerrors.Wrap(types.ErrInvalidProposalContent, err.Error()) } } From 648bf541b4586d63f46ecac368ec728c4d5e3475 Mon Sep 17 00:00:00 2001 From: Daniel Wedul Date: Thu, 8 Jun 2023 16:26:34 -0600 Subject: [PATCH 45/47] Fix the group sims random genesis so it can't pick the same account twice for the group policies since that address is the primary key for the table. Also, output the genesis state after it's randomized just like all the other modules do. --- x/group/simulation/genesis.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/x/group/simulation/genesis.go b/x/group/simulation/genesis.go index 66b471fa5e47..7a4a3646e2c8 100644 --- a/x/group/simulation/genesis.go +++ b/x/group/simulation/genesis.go @@ -1,6 +1,8 @@ package simulation import ( + "encoding/json" + "fmt" "math/rand" "time" @@ -67,9 +69,14 @@ func getGroupMembers(r *rand.Rand, accounts []simtypes.Account) []*group.GroupMe func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.GroupPolicyInfo { groupPolicies := make([]*group.GroupPolicyInfo, 3) - for i := 0; i < 3; i++ { - acc, _ := simtypes.RandomAcc(r, simState.Accounts) - any, err := codectypes.NewAnyWithValue(group.NewThresholdDecisionPolicy("10", time.Second, 0)) + raccs := make([]simtypes.Account, 0, len(simState.Accounts)) + raccs = append(raccs, simState.Accounts...) + r.Shuffle(len(raccs), func(i, j int) { + raccs[i], raccs[j] = raccs[j], raccs[i] + }) + for i := range groupPolicies { + acc := raccs[i] + policy, err := codectypes.NewAnyWithValue(group.NewThresholdDecisionPolicy("10", time.Second, 0)) if err != nil { panic(err) } @@ -78,7 +85,7 @@ func getGroupPolicies(r *rand.Rand, simState *module.SimulationState) []*group.G Admin: acc.Address.String(), Address: acc.Address.String(), Version: 1, - DecisionPolicy: any, + DecisionPolicy: policy, Metadata: simtypes.RandStringOfLength(r, 10), } } @@ -212,4 +219,8 @@ func RandomizedGenState(simState *module.SimulationState) { } simState.GenState[group.ModuleName] = simState.Cdc.MustMarshalJSON(&groupGenesis) + bz, err := json.MarshalIndent(simState.GenState[group.ModuleName], "", " ") + if err == nil { + fmt.Printf("Selected randomly generated group parameters:\n%s\n", bz) + } } From be8a9986491a1aafb64f7343b590f10bceb557c3 Mon Sep 17 00:00:00 2001 From: Daniel Wedul Date: Thu, 8 Jun 2023 17:12:48 -0600 Subject: [PATCH 46/47] Add changelog entries. --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87b3e8aa0169..5ea9865de66f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,14 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Unreleased -* nothing +### Improvements + +* [#572](https://github.com/provenance-io/cosmos-sdk/pull/572) Bring in Cosmos-SDK [v0.46.11](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.11), [v0.46.12](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.12), and [v0.46.13](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.13) changes. +* [#572](https://github.com/provenance-io/cosmos-sdk/pull/572) Add the better legacy gov prop error handling fix back in. + +### Bug Fixes + +* [#572](https://github.com/provenance-io/cosmos-sdk/pull/572) Fix group sims from creating multiple group policies with the same address. --- From ca1fee008b164aa3714b190b4931d456a9603cbe Mon Sep 17 00:00:00 2001 From: Daniel Wedul Date: Thu, 8 Jun 2023 17:19:28 -0600 Subject: [PATCH 47/47] Regen the swagger docs. --- client/docs/swagger-ui/swagger.yaml | 579 +++++++++++++++++++++++----- 1 file changed, 476 insertions(+), 103 deletions(-) diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index 0e0c90874244..f37f8cbe848d 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -4367,7 +4367,7 @@ paths: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. data: type: object properties: @@ -4613,8 +4613,8 @@ paths: type: string format: byte description: >- - Header defines the structure of a - Tendermint block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -4695,7 +4695,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -4719,7 +4719,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -4751,7 +4751,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -5158,8 +5158,8 @@ paths: type: string format: byte description: >- - Header defines the structure of a - Tendermint block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -5240,7 +5240,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -5264,7 +5264,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -5296,7 +5296,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -5678,7 +5678,7 @@ paths: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. data: type: object properties: @@ -5924,8 +5924,8 @@ paths: type: string format: byte description: >- - Header defines the structure of a - Tendermint block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -6006,7 +6006,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -6030,7 +6030,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -6062,7 +6062,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -6469,8 +6469,8 @@ paths: type: string format: byte description: >- - Header defines the structure of a - Tendermint block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -6551,7 +6551,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -6575,7 +6575,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -6607,7 +6607,7 @@ paths: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -19120,7 +19120,7 @@ paths: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. valset: type: array items: @@ -32515,6 +32515,333 @@ paths: type: string tags: - Query + /cosmos/group/v1/groups: + get: + summary: Groups queries all groups in state. + description: 'Since: cosmos-sdk 0.47.1' + operationId: Groups + responses: + '200': + description: A successful response. + schema: + type: object + properties: + groups: + type: array + items: + type: object + properties: + id: + type: string + format: uint64 + description: id is the unique ID of the group. + admin: + type: string + description: admin is the account address of the group's admin. + metadata: + type: string + description: >- + metadata is any arbitrary metadata to attached to the + group. + version: + type: string + format: uint64 + title: >- + version is used to track changes to a group's membership + structure that + + would break existing proposals. Whenever any members + weight is changed, + + or any member is added or removed this version is + incremented and will + + cause proposals based on older versions of this group to + fail + total_weight: + type: string + description: total_weight is the sum of the group members' weights. + created_at: + type: string + format: date-time + description: >- + created_at is a timestamp specifying when a group was + created. + description: >- + GroupInfo represents the high-level on-chain information for + a group. + description: '`groups` is all the groups present in state.' + pagination: + description: pagination defines the pagination in the response. + type: object + properties: + next_key: + type: string + format: byte + description: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently. It will be empty if + there are no more results. + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: |- + QueryGroupsResponse is the Query/Groups response type. + + Since: cosmos-sdk 0.47.1 + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: >- + offset is a numeric offset that can be used when key is unavailable. + + It is less efficient than using key. Only one of offset or key + should + + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in + UIs. + + count_total is only respected when offset is used. It is ignored + when key + + is set. + in: query + required: false + type: boolean + - name: pagination.reverse + description: >- + reverse is set to true if results are to be returned in the + descending order. + + + Since: cosmos-sdk 0.43 + in: query + required: false + type: boolean + tags: + - Query /cosmos/group/v1/groups_by_admin/{admin}: get: summary: GroupsByAdmin queries groups by admin address. @@ -37688,9 +38015,7 @@ definitions: proposer_address: type: string format: byte - description: >- - Header defines the structure of a Tendermint - block header. + description: Header defines the structure of a block header. commit: type: object properties: @@ -37770,7 +38095,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -37794,7 +38119,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -37826,7 +38151,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use with - Tendermint Validators + Validators voting_power: type: string format: int64 @@ -37998,7 +38323,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. data: type: object properties: @@ -38241,8 +38566,8 @@ definitions: type: string format: byte description: >- - Header defines the structure of a Tendermint - block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -38322,7 +38647,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -38346,7 +38671,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -38378,7 +38703,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -38777,8 +39102,8 @@ definitions: type: string format: byte description: >- - Header defines the structure of a Tendermint - block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -38858,7 +39183,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -38882,7 +39207,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -38914,7 +39239,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -39091,7 +39416,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. data: type: object properties: @@ -39334,8 +39659,8 @@ definitions: type: string format: byte description: >- - Header defines the structure of a Tendermint - block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -39415,7 +39740,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -39439,7 +39764,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -39471,7 +39796,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -39870,8 +40195,8 @@ definitions: type: string format: byte description: >- - Header defines the structure of a Tendermint - block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -39951,7 +40276,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -39975,7 +40300,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -40007,7 +40332,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -40958,7 +41283,7 @@ definitions: secp256k1: type: string format: byte - title: PublicKey defines the keys available for use with Tendermint Validators + title: PublicKey defines the keys available for use with Validators tendermint.p2p.DefaultNodeInfo: type: object properties: @@ -41092,7 +41417,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. data: type: object properties: @@ -41333,9 +41658,7 @@ definitions: proposer_address: type: string format: byte - description: >- - Header defines the structure of a Tendermint - block header. + description: Header defines the structure of a block header. commit: type: object properties: @@ -41415,7 +41738,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -41439,7 +41762,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -41471,7 +41794,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use with - Tendermint Validators + Validators voting_power: type: string format: int64 @@ -41999,7 +42322,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. commit: type: object properties: @@ -42079,7 +42402,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use with - Tendermint Validators + Validators voting_power: type: string format: int64 @@ -42103,7 +42426,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use with - Tendermint Validators + Validators voting_power: type: string format: int64 @@ -42133,9 +42456,7 @@ definitions: secp256k1: type: string format: byte - title: >- - PublicKey defines the keys available for use with Tendermint - Validators + title: PublicKey defines the keys available for use with Validators voting_power: type: string format: int64 @@ -42373,9 +42694,7 @@ definitions: proposer_address: type: string format: byte - description: >- - Header defines the structure of a Tendermint block - header. + description: Header defines the structure of a block header. commit: type: object properties: @@ -42455,7 +42774,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -42479,7 +42798,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -42511,7 +42830,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use with - Tendermint Validators + Validators voting_power: type: string format: int64 @@ -42603,7 +42922,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. tendermint.types.LightBlock: type: object properties: @@ -42686,7 +43005,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. commit: type: object properties: @@ -42760,9 +43079,7 @@ definitions: secp256k1: type: string format: byte - title: >- - PublicKey defines the keys available for use with Tendermint - Validators + title: PublicKey defines the keys available for use with Validators voting_power: type: string format: int64 @@ -42784,9 +43101,7 @@ definitions: secp256k1: type: string format: byte - title: >- - PublicKey defines the keys available for use with Tendermint - Validators + title: PublicKey defines the keys available for use with Validators voting_power: type: string format: int64 @@ -42881,7 +43196,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. commit: type: object properties: @@ -42959,7 +43274,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use with - Tendermint Validators + Validators voting_power: type: string format: int64 @@ -42983,7 +43298,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use with - Tendermint Validators + Validators voting_power: type: string format: int64 @@ -43013,9 +43328,7 @@ definitions: secp256k1: type: string format: byte - title: >- - PublicKey defines the keys available for use with Tendermint - Validators + title: PublicKey defines the keys available for use with Validators voting_power: type: string format: int64 @@ -43120,7 +43433,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. commit: type: object properties: @@ -43202,9 +43515,7 @@ definitions: secp256k1: type: string format: byte - title: >- - PublicKey defines the keys available for use with Tendermint - Validators + title: PublicKey defines the keys available for use with Validators voting_power: type: string format: int64 @@ -43231,9 +43542,7 @@ definitions: secp256k1: type: string format: byte - title: >- - PublicKey defines the keys available for use with Tendermint - Validators + title: PublicKey defines the keys available for use with Validators voting_power: type: string format: int64 @@ -43255,9 +43564,7 @@ definitions: secp256k1: type: string format: byte - title: >- - PublicKey defines the keys available for use with Tendermint - Validators + title: PublicKey defines the keys available for use with Validators voting_power: type: string format: int64 @@ -47342,7 +47649,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. valset: type: array items: @@ -48589,7 +48896,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. valset: type: array items: @@ -51744,7 +52051,7 @@ definitions: proposer_address: type: string format: byte - description: Header defines the structure of a Tendermint block header. + description: Header defines the structure of a block header. data: type: object properties: @@ -51987,8 +52294,8 @@ definitions: type: string format: byte description: >- - Header defines the structure of a Tendermint - block header. + Header defines the structure of a block + header. commit: type: object properties: @@ -52068,7 +52375,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -52092,7 +52399,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for - use with Tendermint Validators + use with Validators voting_power: type: string format: int64 @@ -52124,7 +52431,7 @@ definitions: format: byte title: >- PublicKey defines the keys available for use - with Tendermint Validators + with Validators voting_power: type: string format: int64 @@ -59308,6 +59615,72 @@ definitions: was set, its value is undefined otherwise description: QueryGroupsByMemberResponse is the Query/GroupsByMember response type. + cosmos.group.v1.QueryGroupsResponse: + type: object + properties: + groups: + type: array + items: + type: object + properties: + id: + type: string + format: uint64 + description: id is the unique ID of the group. + admin: + type: string + description: admin is the account address of the group's admin. + metadata: + type: string + description: metadata is any arbitrary metadata to attached to the group. + version: + type: string + format: uint64 + title: >- + version is used to track changes to a group's membership + structure that + + would break existing proposals. Whenever any members weight is + changed, + + or any member is added or removed this version is incremented + and will + + cause proposals based on older versions of this group to fail + total_weight: + type: string + description: total_weight is the sum of the group members' weights. + created_at: + type: string + format: date-time + description: created_at is a timestamp specifying when a group was created. + description: >- + GroupInfo represents the high-level on-chain information for a + group. + description: '`groups` is all the groups present in state.' + pagination: + description: pagination defines the pagination in the response. + type: object + properties: + next_key: + type: string + format: byte + description: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently. It will be empty if + there are no more results. + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: |- + QueryGroupsResponse is the Query/Groups response type. + + Since: cosmos-sdk 0.47.1 cosmos.group.v1.QueryProposalResponse: type: object properties: