diff --git a/baseapp/abci.go b/baseapp/abci.go index dcfe431ce0d7..ecd189ea8d21 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -24,6 +24,16 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) +const ( + initialAppVersion = 0 +) + +var ( + errAppVersionIsNotInitial = func(actualVersion uint64) error { + return fmt.Errorf("app version is not initial, was %d, expected %d", actualVersion, initialAppVersion) + } +) + // InitChain implements the ABCI interface. It runs the initialization logic // directly on the CommitMultiStore. func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { @@ -46,7 +56,7 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC app.setDeliverState(initHeader) app.setCheckState(initHeader) - if err := app.SetAppVersion(app.deliverState.ctx, 0); err != nil { + if err := app.SetAppVersion(initialAppVersion); err != nil { panic(err) } @@ -54,6 +64,12 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC // done after the deliver state and context have been set as it's persisted // to state. if req.ConsensusParams != nil { + // When init chain is called, the app version should either be absent and determined by the application + // or set to 0. Panic if it's not. + if req.ConsensusParams.Version != nil && req.ConsensusParams.Version.AppVersion != initialAppVersion { + panic(errAppVersionIsNotInitial(req.ConsensusParams.Version.AppVersion)) + } + app.StoreConsensusParams(app.deliverState.ctx, req.ConsensusParams) } @@ -112,10 +128,8 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo { lastCommitID := app.cms.LastCommitID() - appVersion, err := app.GetAppVersion(app.checkState.ctx) - if err != nil { - app.logger.Error("failed to get app version", err) - } + appVersion, err := app.GetAppVersion() + app.logger.Info("get app version", "app version", appVersion, "error", err) return abci.ResponseInfo{ Data: app.name, diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 177cb59801b6..5580cb126165 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -1,7 +1,6 @@ package baseapp import ( - "errors" "fmt" "reflect" "strings" @@ -310,15 +309,12 @@ func (app *BaseApp) init() error { // needed for the export command which inits from store but never calls initchain app.setCheckState(tmproto.Header{}) - // If there is no app version set in the store, we should set it to 0. - // Panic on any other error. - // If errMsgNoProtocolVersionSet, we assume that appVersion is assigned to be 0. - appVersion, err := app.GetAppVersion(app.checkState.ctx) - if err != nil && !errors.Is(err, errMsgNoProtocolVersionSet) { + appVersion, err := app.GetAppVersion() + if err != nil { return err } - if err := app.SetAppVersion(app.checkState.ctx, appVersion); err != nil { + if err := app.SetAppVersion(appVersion); err != nil { return err } app.Seal() @@ -436,13 +432,13 @@ func (app *BaseApp) GetConsensusParams(ctx sdk.Context) *abci.ConsensusParams { cp.Validator = &vp } - if app.paramStore.Has(ctx, ParamStoreKeyVersionParams) { - var vp tmproto.VersionParams - - app.paramStore.Get(ctx, ParamStoreKeyVersionParams, &vp) - cp.Version = &vp + appVersion, err := app.cms.GetAppVersion() + if err != nil { + panic(err) + } + cp.Version = &tmproto.VersionParams{ + AppVersion: appVersion, } - return cp } @@ -466,9 +462,8 @@ func (app *BaseApp) StoreConsensusParams(ctx sdk.Context, cp *abci.ConsensusPara app.paramStore.Set(ctx, ParamStoreKeyBlockParams, cp.Block) app.paramStore.Set(ctx, ParamStoreKeyEvidenceParams, cp.Evidence) app.paramStore.Set(ctx, ParamStoreKeyValidatorParams, cp.Validator) - app.paramStore.Set(ctx, ParamStoreKeyVersionParams, cp.Version) - // We're explicitly not storing the Tendermint app_version in the param store. It's - // stored instead in the x/upgrade store, with its own bump logic. + // We do not store the version params here because they are + // persisted in a multi-store which is used as the single source of truth. } // getMaximumBlockGas gets the maximum gas from the consensus params. It panics diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 97632cf84a0a..9f658e057037 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -53,8 +53,12 @@ func defaultLogger() log.Logger { } func newBaseApp(name string, options ...func(*BaseApp)) *BaseApp { - logger := defaultLogger() db := dbm.NewMemDB() + return newBaseAppWithDb(name, db, options...) +} + +func newBaseAppWithDb(name string, db dbm.DB, options ...func(*BaseApp)) *BaseApp { + logger := defaultLogger() codec := codec.NewLegacyAmino() registerTestCodec(codec) return NewBaseApp(name, logger, db, testTxDecoder(codec), options...) @@ -482,7 +486,7 @@ func TestInfo(t *testing.T) { assert.Equal(t, int64(0), res.LastBlockHeight) require.Equal(t, []uint8(nil), res.LastBlockAppHash) - appVersion, err := app.GetAppVersion(app.deliverState.ctx) + appVersion, err := app.GetAppVersion() require.NoError(t, err) assert.Equal(t, appVersion, res.AppVersion) @@ -632,7 +636,7 @@ func TestInitChain_ProtocolVersionSetToZero(t *testing.T) { }, ) - protocolVersion, err := app.GetAppVersion(app.deliverState.ctx) + protocolVersion, err := app.GetAppVersion() require.NoError(t, err) require.Equal(t, uint64(0), protocolVersion) } @@ -1823,8 +1827,8 @@ func TestListSnapshots(t *testing.T) { defer teardown() expected := abci.ResponseListSnapshots{Snapshots: []*abci.Snapshot{ - {Height: 4, Format: 1, Chunks: 2}, - {Height: 2, Format: 1, Chunks: 1}, + {Height: 4, Format: 2, Chunks: 2}, + {Height: 2, Format: 2, Chunks: 1}, }} resp := app.ListSnapshots(abci.RequestListSnapshots{}) @@ -1867,7 +1871,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 1, Chunks: 5}, + {Height: 20, Format: 2, Chunks: 5}, }, }, "prune everything with snapshot": { @@ -1879,7 +1883,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningEverything), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 1, Chunks: 5}, + {Height: 20, Format: 2, Chunks: 5}, }, }, "default pruning with snapshot": { @@ -1891,7 +1895,7 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningDefault), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 20, Format: 1, Chunks: 5}, + {Height: 20, Format: 2, Chunks: 5}, }, }, "custom": { @@ -1903,8 +1907,8 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewCustomPruningOptions(12, 12), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 25, Format: 1, Chunks: 6}, - {Height: 20, Format: 1, Chunks: 5}, + {Height: 25, Format: 2, Chunks: 6}, + {Height: 20, Format: 2, Chunks: 5}, }, }, "no snapshots": { @@ -1925,9 +1929,9 @@ func TestSnapshotWithPruning(t *testing.T) { pruningOpts: pruningtypes.NewPruningOptions(pruningtypes.PruningNothing), }, expectedSnapshots: []*abci.Snapshot{ - {Height: 9, Format: 1, Chunks: 2}, - {Height: 6, Format: 1, Chunks: 2}, - {Height: 3, Format: 1, Chunks: 1}, + {Height: 9, Format: 2, Chunks: 2}, + {Height: 6, Format: 2, Chunks: 2}, + {Height: 3, Format: 2, Chunks: 1}, }, }, } @@ -2004,13 +2008,13 @@ func TestLoadSnapshotChunk(t *testing.T) { chunk uint32 expectEmpty bool }{ - "Existing snapshot": {2, 1, 1, false}, - "Missing height": {100, 1, 1, true}, - "Missing format": {2, 2, 1, true}, - "Missing chunk": {2, 1, 9, true}, - "Zero height": {0, 1, 1, true}, + "Existing snapshot": {2, 2, 1, false}, + "Missing height": {100, 2, 1, true}, + "Missing format": {2, 1, 1, true}, + "Missing chunk": {2, 2, 9, true}, + "Zero height": {0, 2, 1, true}, "Zero format": {2, 0, 1, true}, - "Zero chunk": {2, 1, 0, false}, + "Zero chunk": {2, 2, 0, false}, } for name, tc := range testcases { tc := tc @@ -2056,13 +2060,13 @@ func TestOfferSnapshot_Errors(t *testing.T) { Height: 1, Format: 9, Chunks: 3, Hash: hash, Metadata: metadata, }, abci.ResponseOfferSnapshot_REJECT_FORMAT}, "incorrect chunk count": {&abci.Snapshot{ - Height: 1, Format: 1, Chunks: 2, Hash: hash, Metadata: metadata, + Height: 1, Format: 2, Chunks: 2, Hash: hash, Metadata: metadata, }, abci.ResponseOfferSnapshot_REJECT}, "no chunks": {&abci.Snapshot{ - Height: 1, Format: 1, Chunks: 0, Hash: hash, Metadata: metadata, + Height: 1, Format: 2, Chunks: 0, Hash: hash, Metadata: metadata, }, abci.ResponseOfferSnapshot_REJECT}, "invalid metadata serialization": {&abci.Snapshot{ - Height: 1, Format: 1, Chunks: 0, Hash: hash, Metadata: []byte{3, 1, 4}, + Height: 1, Format: 2, Chunks: 0, Hash: hash, Metadata: []byte{3, 1, 4}, }, abci.ResponseOfferSnapshot_REJECT}, } for name, tc := range testcases { @@ -2443,11 +2447,11 @@ func TestBaseApp_Init_PruningAndSnapshot(t *testing.T) { } func TestBaseApp_Init_ProtocolVersion(t *testing.T) { - const versionNotSet = -1 + const versionNotSet = 0 testcases := []struct { name string - protocolVersion int64 + protocolVersion uint64 }{ { name: "no app version was set - set to 0", @@ -2461,29 +2465,23 @@ func TestBaseApp_Init_ProtocolVersion(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - app := newBaseApp(t.Name()) db := dbm.NewMemDB() + app := newBaseAppWithDb(t.Name(), db) - app.SetParamStore(&mock.ParamStore{db}) - - var expectedProtocolVersion uint64 if tc.protocolVersion != versionNotSet { - // Set version on another app with the same param store (db), - // pretending that the app version was set on the app in advance. - oldApp := newBaseApp(t.Name()) - oldApp.SetParamStore(&mock.ParamStore{db}) - require.NoError(t, oldApp.init()) - - expectedProtocolVersion = uint64(tc.protocolVersion) - require.NoError(t, oldApp.SetAppVersion(oldApp.checkState.ctx, expectedProtocolVersion)) + err := app.cms.SetAppVersion(tc.protocolVersion) + require.NoError(t, err) } + // recreate app + app = newBaseAppWithDb(t.Name(), db) + require.NoError(t, app.init()) - actualProtocolVersion, err := app.GetAppVersion(app.checkState.ctx) + actualProtocolVersion, err := app.GetAppVersion() require.NoError(t, err) - require.Equal(t, expectedProtocolVersion, actualProtocolVersion) + require.Equal(t, tc.protocolVersion, actualProtocolVersion) }) } } diff --git a/baseapp/options.go b/baseapp/options.go index 85fb21a8be1d..ab36aed90ea4 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -5,7 +5,6 @@ import ( "fmt" "io" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/codec/types" @@ -17,8 +16,7 @@ import ( ) var ( - errMsgNilParamStore = errors.New("paramStore was nil") - errMsgNoProtocolVersionSet = errors.New("param store did not have the app version set") + errMsgNilParamStore = errors.New("paramStore was nil") ) // File for storing in-package BaseApp optional functions, @@ -107,31 +105,19 @@ func (app *BaseApp) SetVersion(v string) { } // SetAppVersion sets the application's app version -func (app *BaseApp) SetAppVersion(ctx sdk.Context, v uint64) error { - if app.paramStore == nil { - return errMsgNilParamStore - } - - av := &tmproto.VersionParams{AppVersion: v} - app.paramStore.Set(ctx, ParamStoreKeyVersionParams, av) - return nil +func (app *BaseApp) SetAppVersion(v uint64) error { + return app.cms.SetAppVersion(v) } // GetAppVersion gets the application's app version // an error, if any. -func (app *BaseApp) GetAppVersion(ctx sdk.Context) (uint64, error) { - if app.paramStore == nil { - return 0, errMsgNilParamStore - } +func (app *BaseApp) GetAppVersion() (uint64, error) { + appVersion, err := app.cms.GetAppVersion() + if err != nil { + return 0, err - if !app.paramStore.Has(ctx, ParamStoreKeyVersionParams) { - return 0, errMsgNoProtocolVersionSet } - - av := &tmproto.VersionParams{} - app.paramStore.Get(ctx, ParamStoreKeyVersionParams, av) - - return av.AppVersion, nil + return appVersion, nil } func (app *BaseApp) SetDB(db dbm.DB) { diff --git a/baseapp/params.go b/baseapp/params.go index dbfb44fb6aae..b19c155d21ee 100644 --- a/baseapp/params.go +++ b/baseapp/params.go @@ -18,7 +18,6 @@ var ( ParamStoreKeyBlockParams = []byte("BlockParams") ParamStoreKeyEvidenceParams = []byte("EvidenceParams") ParamStoreKeyValidatorParams = []byte("ValidatorParams") - ParamStoreKeyVersionParams = []byte("VersionParams") ) // ParamStore defines the interface the parameter store used by the BaseApp must diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 2cc77554bdda..0652bc2659f9 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -164,6 +164,12 @@ - [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) + - [SnapshotAppVersion](#cosmos.base.snapshots.v1beta1.SnapshotAppVersion) + - [SnapshotExtensionMeta](#cosmos.base.snapshots.v1beta1.SnapshotExtensionMeta) + - [SnapshotExtensionPayload](#cosmos.base.snapshots.v1beta1.SnapshotExtensionPayload) + - [SnapshotIAVLItem](#cosmos.base.snapshots.v1beta1.SnapshotIAVLItem) + - [SnapshotItem](#cosmos.base.snapshots.v1beta1.SnapshotItem) + - [SnapshotStoreItem](#cosmos.base.snapshots.v1beta1.SnapshotStoreItem) - [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) - [CommitID](#cosmos.base.store.v1beta1.CommitID) @@ -173,11 +179,6 @@ - [cosmos/base/store/v1beta1/listening.proto](#cosmos/base/store/v1beta1/listening.proto) - [StoreKVPair](#cosmos.base.store.v1beta1.StoreKVPair) -- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) - - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) - - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) - - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) - - [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) @@ -2720,106 +2721,99 @@ Snapshot contains Tendermint state sync snapshot info. - - + - +### SnapshotAppVersion +SnapshotAppVersion contains the app version. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `version` | [uint64](#uint64) | | | - -

Top

-## cosmos/base/store/v1beta1/commit_info.proto - + -### CommitID -CommitID defines the committment information when a specific store is -committed. +### SnapshotExtensionMeta +SnapshotExtensionMeta contains metadata about an external snapshotter. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `hash` | [bytes](#bytes) | | | +| `name` | [string](#string) | | | +| `format` | [uint32](#uint32) | | | - + -### CommitInfo -CommitInfo defines commit information used by the multi-store when committing -a version/height. +### SnapshotExtensionPayload +SnapshotExtensionPayload contains payloads of an external snapshotter. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | +| `payload` | [bytes](#bytes) | | | - + -### StoreInfo -StoreInfo defines store-specific commit information. It contains a reference -between a store name and the commit ID. +### SnapshotIAVLItem +SnapshotIAVLItem is an exported IAVL node. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | +| `version` | [int64](#int64) | | version is block height | +| `height` | [int32](#int32) | | height is depth of the tree. | - - + - +### SnapshotItem +SnapshotItem is an item contained in a rootmulti.Store snapshot. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `store` | [SnapshotStoreItem](#cosmos.base.snapshots.v1beta1.SnapshotStoreItem) | | | +| `iavl` | [SnapshotIAVLItem](#cosmos.base.snapshots.v1beta1.SnapshotIAVLItem) | | | +| `extension` | [SnapshotExtensionMeta](#cosmos.base.snapshots.v1beta1.SnapshotExtensionMeta) | | | +| `extension_payload` | [SnapshotExtensionPayload](#cosmos.base.snapshots.v1beta1.SnapshotExtensionPayload) | | | +| `app_version` | [SnapshotAppVersion](#cosmos.base.snapshots.v1beta1.SnapshotAppVersion) | | | - -

Top

-## cosmos/base/store/v1beta1/listening.proto - + -### StoreKVPair -StoreKVPair is a KVStore KVPair used for listening to state changes (Sets and Deletes) -It optionally includes the StoreKey for the originating KVStore and a Boolean flag to distinguish between Sets and -Deletes - -Since: cosmos-sdk 0.43 +### SnapshotStoreItem +SnapshotStoreItem contains metadata about a snapshotted store. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `store_key` | [string](#string) | | the store key for the KVStore this pair originates from | -| `delete` | [bool](#bool) | | true indicates a delete operation, false indicates a set operation | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | +| `name` | [string](#string) | | | @@ -2835,56 +2829,96 @@ Since: cosmos-sdk 0.43 - +

Top

-## cosmos/base/store/v1beta1/snapshot.proto +## cosmos/base/store/v1beta1/commit_info.proto - + -### SnapshotIAVLItem -SnapshotIAVLItem is an exported IAVL node. +### CommitID +CommitID defines the committment information when a specific store is +committed. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | | `version` | [int64](#int64) | | | -| `height` | [int32](#int32) | | | +| `hash` | [bytes](#bytes) | | | - + -### SnapshotItem -SnapshotItem is an item contained in a rootmulti.Store snapshot. +### CommitInfo +CommitInfo defines commit information used by the multi-store when committing +a version/height. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | -| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | +| `version` | [int64](#int64) | | | +| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | - + -### SnapshotStoreItem -SnapshotStoreItem contains metadata about a snapshotted store. +### StoreInfo +StoreInfo defines store-specific commit information. It contains a reference +between a store name and the commit ID. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `name` | [string](#string) | | | +| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | + + + + + + + + + + + + + + + + +

Top

+ +## cosmos/base/store/v1beta1/listening.proto + + + + + +### StoreKVPair +StoreKVPair is a KVStore KVPair used for listening to state changes (Sets and Deletes) +It optionally includes the StoreKey for the originating KVStore and a Boolean flag to distinguish between Sets and +Deletes + +Since: cosmos-sdk 0.43 + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `store_key` | [string](#string) | | the store key for the KVStore this pair originates from | +| `delete` | [bool](#bool) | | true indicates a delete operation, false indicates a set operation | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | diff --git a/proto/cosmos/base/snapshots/v1beta1/snapshot.proto b/proto/cosmos/base/snapshots/v1beta1/snapshot.proto index 6dcc4a933aa9..b268c222fec2 100644 --- a/proto/cosmos/base/snapshots/v1beta1/snapshot.proto +++ b/proto/cosmos/base/snapshots/v1beta1/snapshot.proto @@ -27,6 +27,7 @@ message SnapshotItem { SnapshotIAVLItem iavl = 2 [(gogoproto.customname) = "IAVL"]; SnapshotExtensionMeta extension = 3; SnapshotExtensionPayload extension_payload = 4; + SnapshotAppVersion app_version = 5; } } @@ -55,3 +56,8 @@ message SnapshotExtensionMeta { message SnapshotExtensionPayload { bytes payload = 1; } + +// SnapshotAppVersion contains the app version. +message SnapshotAppVersion { + uint64 version = 1; +} diff --git a/proto/cosmos/gov/v1beta1/gov.proto b/proto/cosmos/gov/v1beta1/gov.proto index fd3960aafe39..01aebf950cf3 100644 --- a/proto/cosmos/gov/v1beta1/gov.proto +++ b/proto/cosmos/gov/v1beta1/gov.proto @@ -198,18 +198,3 @@ message TallyParams { (gogoproto.moretags) = "yaml:\"veto_threshold\"" ]; } -<<<<<<< HEAD -======= - -// ProposalVotingPeriod defines custom voting periods for a unique governance -// proposal type. -message ProposalVotingPeriod { - string proposal_type = 1; // e.g. "cosmos.params.v1beta1.ParameterChangeProposal" - google.protobuf.Duration voting_period = 2 [ - (gogoproto.nullable) = false, - (gogoproto.stdduration) = true, - (gogoproto.jsontag) = "voting_period,omitempty", - (gogoproto.moretags) = "yaml:\"voting_period\"" - ]; -} ->>>>>>> 46bb6247d (fix: Add supply offsets to genesis (#253)) diff --git a/server/mock/store.go b/server/mock/store.go index 0bd5de3b138a..110e873bee48 100644 --- a/server/mock/store.go +++ b/server/mock/store.go @@ -143,6 +143,14 @@ func (ms multiStore) Restore( panic("not implemented") } +func (ms multiStore) SetAppVersion(_ uint64) error { + panic("not implemented") +} + +func (ms multiStore) GetAppVersion() (uint64, error) { + panic("not implemented") +} + var _ sdk.KVStore = kvStore{} type kvStore struct { diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index 323f810c5981..6cf6fdc8d37b 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -50,7 +50,7 @@ var DefaultConsensusParams = &abci.ConsensusParams{ }, }, Version: &tmproto.VersionParams{ - AppVersion: 10, + AppVersion: 0, // must be 0 during chain initialization. }, } diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 256fd036125d..3204471ab1d1 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -152,11 +152,11 @@ func (m *mockSnapshotter) SetSnapshotInterval(snapshotInterval uint64) { } func (m *mockSnapshotter) SnapshotFormat() uint32 { - return 1 + return 2 } func (m *mockSnapshotter) SupportedFormats() []uint32 { - return []uint32{1} + return []uint32{2} } // setupBusyManager creates a manager with an empty store that is busy creating a snapshot at height 1. diff --git a/snapshots/manager_test.go b/snapshots/manager_test.go index 17fc61a8ab9d..5bed02629da5 100644 --- a/snapshots/manager_test.go +++ b/snapshots/manager_test.go @@ -161,7 +161,7 @@ func TestManager_Restore(t *testing.T) { // Restore errors on chunk and chunkhashes mismatch err = manager.Restore(types.Snapshot{ Height: 3, - Format: 1, + Format: 2, Hash: []byte{1, 2, 3}, Chunks: 4, Metadata: types.Metadata{ChunkHashes: checksums(chunks)}, @@ -171,7 +171,7 @@ func TestManager_Restore(t *testing.T) { // Starting a restore works err = manager.Restore(types.Snapshot{ Height: 3, - Format: 1, + Format: 2, Hash: []byte{1, 2, 3}, Chunks: 1, Metadata: types.Metadata{ChunkHashes: checksums(chunks)}, @@ -221,7 +221,7 @@ func TestManager_Restore(t *testing.T) { target.items = nil err = manager.Restore(types.Snapshot{ Height: 3, - Format: 1, + Format: 2, Hash: []byte{1, 2, 3}, Chunks: 1, Metadata: types.Metadata{ChunkHashes: checksums(chunks)}, diff --git a/snapshots/types/format.go b/snapshots/types/format.go index edfdb36d7bfc..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 = 1 +const CurrentFormat uint32 = 2 diff --git a/snapshots/types/snapshot.pb.go b/snapshots/types/snapshot.pb.go index 5a70e5eb8d4d..bc37d780d84e 100644 --- a/snapshots/types/snapshot.pb.go +++ b/snapshots/types/snapshot.pb.go @@ -154,6 +154,7 @@ type SnapshotItem struct { // *SnapshotItem_IAVL // *SnapshotItem_Extension // *SnapshotItem_ExtensionPayload + // *SnapshotItem_AppVersion Item isSnapshotItem_Item `protobuf_oneof:"item"` } @@ -208,11 +209,15 @@ type SnapshotItem_Extension struct { type SnapshotItem_ExtensionPayload struct { ExtensionPayload *SnapshotExtensionPayload `protobuf:"bytes,4,opt,name=extension_payload,json=extensionPayload,proto3,oneof" json:"extension_payload,omitempty"` } +type SnapshotItem_AppVersion struct { + AppVersion *SnapshotAppVersion `protobuf:"bytes,5,opt,name=app_version,json=appVersion,proto3,oneof" json:"app_version,omitempty"` +} func (*SnapshotItem_Store) isSnapshotItem_Item() {} func (*SnapshotItem_IAVL) isSnapshotItem_Item() {} func (*SnapshotItem_Extension) isSnapshotItem_Item() {} func (*SnapshotItem_ExtensionPayload) isSnapshotItem_Item() {} +func (*SnapshotItem_AppVersion) isSnapshotItem_Item() {} func (m *SnapshotItem) GetItem() isSnapshotItem_Item { if m != nil { @@ -249,6 +254,13 @@ func (m *SnapshotItem) GetExtensionPayload() *SnapshotExtensionPayload { return nil } +func (m *SnapshotItem) GetAppVersion() *SnapshotAppVersion { + if x, ok := m.GetItem().(*SnapshotItem_AppVersion); ok { + return x.AppVersion + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*SnapshotItem) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -256,6 +268,7 @@ func (*SnapshotItem) XXX_OneofWrappers() []interface{} { (*SnapshotItem_IAVL)(nil), (*SnapshotItem_Extension)(nil), (*SnapshotItem_ExtensionPayload)(nil), + (*SnapshotItem_AppVersion)(nil), } } @@ -306,10 +319,12 @@ func (m *SnapshotStoreItem) GetName() string { // SnapshotIAVLItem is an exported IAVL node. type SnapshotIAVLItem struct { - Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - Version int64 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` - Height int32 `protobuf:"varint,4,opt,name=height,proto3" json:"height,omitempty"` + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + // version is block height + Version int64 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` + // height is depth of the tree. + Height int32 `protobuf:"varint,4,opt,name=height,proto3" json:"height,omitempty"` } func (m *SnapshotIAVLItem) Reset() { *m = SnapshotIAVLItem{} } @@ -471,6 +486,51 @@ func (m *SnapshotExtensionPayload) GetPayload() []byte { return nil } +// SnapshotAppVersion contains the app version. +type SnapshotAppVersion struct { + Version uint64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` +} + +func (m *SnapshotAppVersion) Reset() { *m = SnapshotAppVersion{} } +func (m *SnapshotAppVersion) String() string { return proto.CompactTextString(m) } +func (*SnapshotAppVersion) ProtoMessage() {} +func (*SnapshotAppVersion) Descriptor() ([]byte, []int) { + return fileDescriptor_dd7a3c9b0a19e1ee, []int{7} +} +func (m *SnapshotAppVersion) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SnapshotAppVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SnapshotAppVersion.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 *SnapshotAppVersion) XXX_Merge(src proto.Message) { + xxx_messageInfo_SnapshotAppVersion.Merge(m, src) +} +func (m *SnapshotAppVersion) XXX_Size() int { + return m.Size() +} +func (m *SnapshotAppVersion) XXX_DiscardUnknown() { + xxx_messageInfo_SnapshotAppVersion.DiscardUnknown(m) +} + +var xxx_messageInfo_SnapshotAppVersion proto.InternalMessageInfo + +func (m *SnapshotAppVersion) GetVersion() uint64 { + if m != nil { + return m.Version + } + return 0 +} + func init() { proto.RegisterType((*Snapshot)(nil), "cosmos.base.snapshots.v1beta1.Snapshot") proto.RegisterType((*Metadata)(nil), "cosmos.base.snapshots.v1beta1.Metadata") @@ -479,6 +539,7 @@ func init() { proto.RegisterType((*SnapshotIAVLItem)(nil), "cosmos.base.snapshots.v1beta1.SnapshotIAVLItem") proto.RegisterType((*SnapshotExtensionMeta)(nil), "cosmos.base.snapshots.v1beta1.SnapshotExtensionMeta") proto.RegisterType((*SnapshotExtensionPayload)(nil), "cosmos.base.snapshots.v1beta1.SnapshotExtensionPayload") + proto.RegisterType((*SnapshotAppVersion)(nil), "cosmos.base.snapshots.v1beta1.SnapshotAppVersion") } func init() { @@ -486,40 +547,42 @@ func init() { } var fileDescriptor_dd7a3c9b0a19e1ee = []byte{ - // 513 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xd1, 0x6e, 0xd3, 0x30, - 0x14, 0x8d, 0xd7, 0xb4, 0x74, 0x37, 0x41, 0xea, 0xac, 0x81, 0x22, 0x24, 0xb2, 0x92, 0x97, 0xf5, - 0x61, 0x4b, 0x58, 0x99, 0xc4, 0x33, 0x45, 0xa0, 0x54, 0x02, 0x81, 0x3c, 0xc4, 0x03, 0x2f, 0x93, - 0xdb, 0x7a, 0x4d, 0xd4, 0x26, 0xae, 0x6a, 0xb7, 0xa2, 0x7f, 0xc1, 0xaf, 0xf0, 0x17, 0x7b, 0xdc, - 0x23, 0x4f, 0x13, 0x6a, 0x3f, 0x80, 0x5f, 0x40, 0xb6, 0x93, 0x30, 0x8d, 0x0d, 0xb6, 0xa7, 0xde, - 0x73, 0x7a, 0xee, 0xf1, 0xf5, 0xc9, 0x35, 0x1c, 0x0c, 0xb9, 0xc8, 0xb8, 0x88, 0x06, 0x54, 0xb0, - 0x48, 0xe4, 0x74, 0x26, 0x12, 0x2e, 0x45, 0xb4, 0x3c, 0x1a, 0x30, 0x49, 0x8f, 0x2a, 0x26, 0x9c, - 0xcd, 0xb9, 0xe4, 0xf8, 0xa9, 0x51, 0x87, 0x4a, 0x1d, 0x56, 0xea, 0xb0, 0x50, 0x3f, 0xd9, 0x1d, - 0xf3, 0x31, 0xd7, 0xca, 0x48, 0x55, 0xa6, 0x29, 0xf8, 0x8e, 0xa0, 0x79, 0x52, 0x68, 0xf1, 0x63, - 0x68, 0x24, 0x2c, 0x1d, 0x27, 0xd2, 0x43, 0x6d, 0xd4, 0xb1, 0x49, 0x81, 0x14, 0x7f, 0xc6, 0xe7, - 0x19, 0x95, 0xde, 0x56, 0x1b, 0x75, 0x1e, 0x92, 0x02, 0x29, 0x7e, 0x98, 0x2c, 0xf2, 0x89, 0xf0, - 0x6a, 0x86, 0x37, 0x08, 0x63, 0xb0, 0x13, 0x2a, 0x12, 0xcf, 0x6e, 0xa3, 0x8e, 0x4b, 0x74, 0x8d, - 0xfb, 0xd0, 0xcc, 0x98, 0xa4, 0x23, 0x2a, 0xa9, 0x57, 0x6f, 0xa3, 0x8e, 0xd3, 0xdd, 0x0f, 0xff, - 0x39, 0x70, 0xf8, 0xbe, 0x90, 0xf7, 0xec, 0xf3, 0xcb, 0x3d, 0x8b, 0x54, 0xed, 0xc1, 0x21, 0x34, - 0xcb, 0xff, 0xf0, 0x33, 0x70, 0xf5, 0xa1, 0xa7, 0xea, 0x10, 0x26, 0x3c, 0xd4, 0xae, 0x75, 0x5c, - 0xe2, 0x68, 0x2e, 0xd6, 0x54, 0xf0, 0x6b, 0x0b, 0xdc, 0xf2, 0x8a, 0x7d, 0xc9, 0x32, 0x1c, 0x43, - 0x5d, 0x48, 0x3e, 0x67, 0xfa, 0x96, 0x4e, 0xf7, 0xf9, 0x7f, 0xe6, 0x28, 0x7b, 0x4f, 0x54, 0x8f, - 0x32, 0x88, 0x2d, 0x62, 0x0c, 0xf0, 0x07, 0xb0, 0x53, 0xba, 0x9c, 0xea, 0x58, 0x9c, 0x6e, 0x74, - 0x47, 0xa3, 0xfe, 0xab, 0xcf, 0xef, 0x94, 0x4f, 0xaf, 0xb9, 0xbe, 0xdc, 0xb3, 0x15, 0x8a, 0x2d, - 0xa2, 0x8d, 0xf0, 0x27, 0xd8, 0x66, 0x5f, 0x25, 0xcb, 0x45, 0xca, 0x73, 0x1d, 0xaa, 0xd3, 0x3d, - 0xbe, 0xa3, 0xeb, 0x9b, 0xb2, 0x4f, 0x65, 0x13, 0x5b, 0xe4, 0x8f, 0x11, 0x3e, 0x83, 0x9d, 0x0a, - 0x9c, 0xce, 0xe8, 0x6a, 0xca, 0xe9, 0x48, 0x7f, 0x1c, 0xa7, 0xfb, 0xf2, 0xbe, 0xee, 0x1f, 0x4d, - 0x7b, 0x6c, 0x91, 0x16, 0xbb, 0xc6, 0xf5, 0x1a, 0x60, 0xa7, 0x92, 0x65, 0xc1, 0x3e, 0xec, 0xfc, - 0x15, 0x9a, 0x5a, 0x8a, 0x9c, 0x66, 0x26, 0xf4, 0x6d, 0xa2, 0xeb, 0x60, 0x0a, 0xad, 0xeb, 0xa1, - 0xe0, 0x16, 0xd4, 0x26, 0x6c, 0xa5, 0x65, 0x2e, 0x51, 0x25, 0xde, 0x85, 0xfa, 0x92, 0x4e, 0x17, - 0x4c, 0xc7, 0xec, 0x12, 0x03, 0xb0, 0x07, 0x0f, 0x96, 0x6c, 0x5e, 0x05, 0x55, 0x23, 0x25, 0xbc, - 0xb2, 0xc6, 0xea, 0x8e, 0xf5, 0x72, 0x8d, 0x83, 0xd7, 0xf0, 0xe8, 0xc6, 0xb0, 0x6e, 0x1a, 0xed, - 0xb6, 0x9d, 0x0f, 0x8e, 0xc1, 0xbb, 0x2d, 0x13, 0x35, 0x52, 0x99, 0xae, 0x19, 0xbf, 0x84, 0xbd, - 0xb7, 0xe7, 0x6b, 0x1f, 0x5d, 0xac, 0x7d, 0xf4, 0x73, 0xed, 0xa3, 0x6f, 0x1b, 0xdf, 0xba, 0xd8, - 0xf8, 0xd6, 0x8f, 0x8d, 0x6f, 0x7d, 0x39, 0x18, 0xa7, 0x32, 0x59, 0x0c, 0xc2, 0x21, 0xcf, 0xa2, - 0xe2, 0xb9, 0x9b, 0x9f, 0x43, 0x31, 0x9a, 0x5c, 0x79, 0xf4, 0x72, 0x35, 0x63, 0x62, 0xd0, 0xd0, - 0xaf, 0xf6, 0xc5, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6c, 0x90, 0xf8, 0x1f, 0x1a, 0x04, 0x00, - 0x00, + // 551 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0xb6, 0x89, 0x53, 0xd2, 0xb1, 0x91, 0xd2, 0x55, 0x41, 0x16, 0x12, 0x6e, 0xf0, 0xa5, 0x39, + 0xb4, 0x36, 0x09, 0x95, 0x38, 0x37, 0x08, 0xe4, 0x48, 0x20, 0xd0, 0xb6, 0xea, 0x81, 0x4b, 0xb4, + 0x49, 0xb6, 0x71, 0x94, 0x38, 0x6b, 0x65, 0x37, 0x11, 0x79, 0x0b, 0x5e, 0x85, 0x87, 0x40, 0xea, + 0xb1, 0x47, 0x4e, 0x15, 0x4a, 0x5e, 0x04, 0xed, 0xae, 0x37, 0x44, 0xfd, 0x81, 0x70, 0xca, 0x7c, + 0x93, 0x6f, 0xbe, 0x9d, 0xfd, 0xc6, 0xb3, 0x70, 0xd4, 0x63, 0x3c, 0x63, 0x3c, 0xee, 0x12, 0x4e, + 0x63, 0x3e, 0x21, 0x39, 0x4f, 0x99, 0xe0, 0xf1, 0xbc, 0xd1, 0xa5, 0x82, 0x34, 0xd6, 0x99, 0x28, + 0x9f, 0x32, 0xc1, 0xd0, 0x0b, 0xcd, 0x8e, 0x24, 0x3b, 0x5a, 0xb3, 0xa3, 0x82, 0xfd, 0x7c, 0x7f, + 0xc0, 0x06, 0x4c, 0x31, 0x63, 0x19, 0xe9, 0xa2, 0xf0, 0xbb, 0x0d, 0x95, 0xb3, 0x82, 0x8b, 0x9e, + 0xc1, 0x4e, 0x4a, 0x87, 0x83, 0x54, 0xf8, 0x76, 0xcd, 0xae, 0x3b, 0xb8, 0x40, 0x32, 0x7f, 0xc9, + 0xa6, 0x19, 0x11, 0xfe, 0xa3, 0x9a, 0x5d, 0x7f, 0x82, 0x0b, 0x24, 0xf3, 0xbd, 0x74, 0x36, 0x19, + 0x71, 0xbf, 0xa4, 0xf3, 0x1a, 0x21, 0x04, 0x4e, 0x4a, 0x78, 0xea, 0x3b, 0x35, 0xbb, 0xee, 0x61, + 0x15, 0xa3, 0x36, 0x54, 0x32, 0x2a, 0x48, 0x9f, 0x08, 0xe2, 0x97, 0x6b, 0x76, 0xdd, 0x6d, 0x1e, + 0x46, 0x7f, 0x6d, 0x38, 0xfa, 0x58, 0xd0, 0x5b, 0xce, 0xd5, 0xcd, 0x81, 0x85, 0xd7, 0xe5, 0xe1, + 0x31, 0x54, 0xcc, 0x7f, 0xe8, 0x25, 0x78, 0xea, 0xd0, 0x8e, 0x3c, 0x84, 0x72, 0xdf, 0xae, 0x95, + 0xea, 0x1e, 0x76, 0x55, 0x2e, 0x51, 0xa9, 0xf0, 0x47, 0x09, 0x3c, 0x73, 0xc5, 0xb6, 0xa0, 0x19, + 0x4a, 0xa0, 0xcc, 0x05, 0x9b, 0x52, 0x75, 0x4b, 0xb7, 0xf9, 0xea, 0x1f, 0x7d, 0x98, 0xda, 0x33, + 0x59, 0x23, 0x05, 0x12, 0x0b, 0x6b, 0x01, 0xf4, 0x09, 0x9c, 0x21, 0x99, 0x8f, 0x95, 0x2d, 0x6e, + 0x33, 0xde, 0x52, 0xa8, 0x7d, 0x7a, 0xf1, 0x41, 0xea, 0xb4, 0x2a, 0xcb, 0x9b, 0x03, 0x47, 0xa2, + 0xc4, 0xc2, 0x4a, 0x08, 0x9d, 0xc3, 0x2e, 0xfd, 0x2a, 0xe8, 0x84, 0x0f, 0xd9, 0x44, 0x99, 0xea, + 0x36, 0x4f, 0xb6, 0x54, 0x7d, 0x67, 0xea, 0xa4, 0x37, 0x89, 0x85, 0xff, 0x08, 0xa1, 0x4b, 0xd8, + 0x5b, 0x83, 0x4e, 0x4e, 0x16, 0x63, 0x46, 0xfa, 0x6a, 0x38, 0x6e, 0xf3, 0xcd, 0xff, 0xaa, 0x7f, + 0xd6, 0xe5, 0x89, 0x85, 0xab, 0xf4, 0x56, 0x0e, 0x9d, 0x83, 0x4b, 0xf2, 0xbc, 0x33, 0xa7, 0x53, + 0xd5, 0xbf, 0x1e, 0x73, 0x63, 0xcb, 0x13, 0x4e, 0xf3, 0xfc, 0x42, 0x17, 0x26, 0x16, 0x06, 0xb2, + 0x46, 0xad, 0x1d, 0x70, 0x86, 0x82, 0x66, 0xe1, 0x21, 0xec, 0xdd, 0x19, 0x85, 0xfc, 0xd4, 0x26, + 0x24, 0xd3, 0xa3, 0xdc, 0xc5, 0x2a, 0x0e, 0xc7, 0x50, 0xbd, 0x6d, 0x35, 0xaa, 0x42, 0x69, 0x44, + 0x17, 0x8a, 0xe6, 0x61, 0x19, 0xa2, 0x7d, 0x28, 0xcf, 0xc9, 0x78, 0x46, 0xd5, 0xf0, 0x3c, 0xac, + 0x01, 0xf2, 0xe1, 0xb1, 0x69, 0x5f, 0xda, 0x5f, 0xc2, 0x06, 0x6e, 0x2c, 0x87, 0x74, 0xae, 0x6c, + 0x96, 0x23, 0x7c, 0x0b, 0x4f, 0xef, 0x1d, 0xc1, 0x7d, 0xad, 0x3d, 0xb4, 0x49, 0xe1, 0x09, 0xf8, + 0x0f, 0x39, 0x2d, 0x5b, 0x32, 0x33, 0xd3, 0xed, 0x1b, 0x18, 0x46, 0x80, 0xee, 0xba, 0xb7, 0x79, + 0x05, 0xbd, 0xc6, 0x06, 0xb6, 0xde, 0x5f, 0x2d, 0x03, 0xfb, 0x7a, 0x19, 0xd8, 0xbf, 0x96, 0x81, + 0xfd, 0x6d, 0x15, 0x58, 0xd7, 0xab, 0xc0, 0xfa, 0xb9, 0x0a, 0xac, 0x2f, 0x47, 0x83, 0xa1, 0x48, + 0x67, 0xdd, 0xa8, 0xc7, 0xb2, 0xb8, 0x78, 0x74, 0xf4, 0xcf, 0x31, 0xef, 0x8f, 0x36, 0x9e, 0x1e, + 0xb1, 0xc8, 0x29, 0xef, 0xee, 0xa8, 0xb7, 0xe3, 0xf5, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, + 0xc7, 0x49, 0x41, 0xa0, 0x04, 0x00, 0x00, } func (m *Snapshot) Marshal() (dAtA []byte, err error) { @@ -725,6 +788,27 @@ func (m *SnapshotItem_ExtensionPayload) MarshalToSizedBuffer(dAtA []byte) (int, } return len(dAtA) - i, nil } +func (m *SnapshotItem_AppVersion) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SnapshotItem_AppVersion) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.AppVersion != nil { + { + size, err := m.AppVersion.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintSnapshot(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} func (m *SnapshotStoreItem) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -867,6 +951,34 @@ func (m *SnapshotExtensionPayload) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *SnapshotAppVersion) 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 *SnapshotAppVersion) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SnapshotAppVersion) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Version != 0 { + i = encodeVarintSnapshot(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintSnapshot(dAtA []byte, offset int, v uint64) int { offset -= sovSnapshot(v) base := offset @@ -977,6 +1089,18 @@ func (m *SnapshotItem_ExtensionPayload) Size() (n int) { } return n } +func (m *SnapshotItem_AppVersion) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AppVersion != nil { + l = m.AppVersion.Size() + n += 1 + l + sovSnapshot(uint64(l)) + } + return n +} func (m *SnapshotStoreItem) Size() (n int) { if m == nil { return 0 @@ -1042,6 +1166,18 @@ func (m *SnapshotExtensionPayload) Size() (n int) { return n } +func (m *SnapshotAppVersion) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Version != 0 { + n += 1 + sovSnapshot(uint64(m.Version)) + } + return n +} + func sovSnapshot(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1473,6 +1609,41 @@ func (m *SnapshotItem) Unmarshal(dAtA []byte) error { } m.Item = &SnapshotItem_ExtensionPayload{v} iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppVersion", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSnapshot + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthSnapshot + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthSnapshot + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SnapshotAppVersion{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Item = &SnapshotItem_AppVersion{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipSnapshot(dAtA[iNdEx:]) @@ -1917,6 +2088,75 @@ func (m *SnapshotExtensionPayload) Unmarshal(dAtA []byte) error { } return nil } +func (m *SnapshotAppVersion) 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 ErrIntOverflowSnapshot + } + 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: SnapshotAppVersion: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SnapshotAppVersion: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSnapshot + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipSnapshot(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthSnapshot + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipSnapshot(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/store/rootmulti/snapshot_test.go b/store/rootmulti/snapshot_test.go index ff97c85a791a..6356f85cb651 100644 --- a/store/rootmulti/snapshot_test.go +++ b/store/rootmulti/snapshot_test.go @@ -122,13 +122,13 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) { format uint32 chunkHashes []string }{ - {1, []string{ - "503e5b51b657055b77e88169fadae543619368744ad15f1de0736c0a20482f24", - "e1a0daaa738eeb43e778aefd2805e3dd720798288a410b06da4b8459c4d8f72e", - "aa048b4ee0f484965d7b3b06822cf0772cdcaad02f3b1b9055e69f2cb365ef3c", - "7921eaa3ed4921341e504d9308a9877986a879fe216a099c86e8db66fcba4c63", - "a4a864e6c02c9fca5837ec80dc84f650b25276ed7e4820cf7516ced9f9901b86", - "ca2879ac6e7205d257440131ba7e72bef784cd61642e32b847729e543c1928b9", + {2, []string{ + "9c22e62a24bf69177c1ed7116b47ba73200d7e77b3fea6a486b21591eefe331f", + "5395363de5e10b03bbc2907af1843d3c8ed52fc16b01292d0db0157b47172e97", + "71a0b594863b63f6341092ceee1a8d508722af4bed2db1fb3f1c58775b95459c", + "0864b7d52db6d2e6fee11db2399d042b52179221012eb20f969e28843a2e20ad", + "7e57a64b4a344e58fa95549f07a784a1247dca38a7db5b034ee2bd2f2011936f", + "534b87533ca86f404b59c34f0dc451b36c02a2dacfc51abf2863668bd40e0d04", }}, } for _, tc := range testcases { @@ -179,7 +179,11 @@ func TestMultistoreSnapshot_Errors(t *testing.T) { } func TestMultistoreSnapshotRestore(t *testing.T) { + const expectedAppVersion = uint64(10) + source := newMultiStoreWithMixedMountsAndBasicData(dbm.NewMemDB()) + require.NoError(t, source.SetAppVersion(expectedAppVersion)) + target := newMultiStoreWithMixedMounts(dbm.NewMemDB()) version := uint64(source.LastCommitID().Version) require.EqualValues(t, 3, version) @@ -210,6 +214,11 @@ func TestMultistoreSnapshotRestore(t *testing.T) { require.NoError(t, err) require.Equal(t, *dummyExtensionItem.GetExtension(), *nextItem.GetExtension()) + // check that the app version is restored from snapshot. + appVersion, err := target.GetAppVersion() + require.NoError(t, err) + require.Equal(t, expectedAppVersion, appVersion) + assert.Equal(t, source.LastCommitID(), target.LastCommitID()) for key, sourceStore := range source.GetStores() { targetStore := target.GetStoreByName(key.Name()).(types.CommitKVStore) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 2a395799c719..ace12668ee26 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -5,6 +5,7 @@ import ( "io" "math" "sort" + "strconv" "strings" "sync" @@ -34,6 +35,7 @@ import ( const ( latestVersionKey = "s/latest" commitInfoKeyFmt = "s/%d" // s/ + appVersionKey = "s/appversion" proofsPath = "proofs" ) @@ -705,6 +707,22 @@ func (rs *Store) Snapshot(height uint64, protoWriter protoio.Writer) error { return strings.Compare(stores[i].name, stores[j].name) == -1 }) + appVersion, err := rs.GetAppVersion() + if err != nil { + return err + } + + err = protoWriter.WriteMsg(&snapshottypes.SnapshotItem{ + Item: &snapshottypes.SnapshotItem_AppVersion{ + AppVersion: &snapshottypes.SnapshotAppVersion{ + Version: appVersion, + }, + }, + }) + if err != nil { + return err + } + // Export each IAVL store. Stores are serialized as a stream of SnapshotItem Protobuf // messages. The first item contains a SnapshotStore with store metadata (i.e. name), // and the following messages contain a SnapshotNode (i.e. an ExportNode). Store changes @@ -819,6 +837,13 @@ loop: return snapshottypes.SnapshotItem{}, sdkerrors.Wrap(err, "IAVL node import failed") } + case *snapshottypes.SnapshotItem_AppVersion: + // App version + err := rs.SetAppVersion(uint64(item.AppVersion.Version)) + if err != nil { + return snapshottypes.SnapshotItem{}, sdkerrors.Wrap(err, "IAVL node import failed - error saving app version from received snapshot") + } + default: break loop } @@ -975,6 +1000,29 @@ func (rs *Store) getCommitInfoFromDb(ver int64) (*types.CommitInfo, error) { return cInfo, nil } +func (rs *Store) SetAppVersion(appVersion uint64) error { + if err := rs.db.SetSync([]byte(appVersionKey), []byte(strconv.Itoa(int(appVersion)))); err != nil { + return fmt.Errorf("error on write %w", err) + } + return nil +} + +func (rs *Store) GetAppVersion() (uint64, error) { + bz, err := rs.db.Get([]byte(appVersionKey)) + if err != nil { + return 0, errors.Wrap(err, "failed to get app version") + } else if bz == nil { + return 0, nil + } + + appVersion, err := strconv.ParseUint(string(bz), 10, 64) + if err != nil { + return 0, err + } + + return appVersion, nil +} + func (rs *Store) doProofsQuery(req abci.RequestQuery) abci.ResponseQuery { commitInfo, err := rs.getCommitInfoFromDb(req.Height) if err != nil { diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index cb97e42d0952..337906c8581a 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -3,10 +3,12 @@ package rootmulti import ( "bytes" "encoding/binary" + "errors" "fmt" "math/rand" "testing" + "github.com/golang/mock/gomock" "github.com/tendermint/tendermint/libs/log" "github.com/stretchr/testify/require" @@ -15,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" codecTypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/pruning/mock" pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" "github.com/cosmos/cosmos-sdk/store/cachemulti" "github.com/cosmos/cosmos-sdk/store/iavl" @@ -24,6 +27,8 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) +const dbErr = "db error" + func TestStoreType(t *testing.T) { db := dbm.NewMemDB() store := NewStore(db, log.NewNopLogger()) @@ -769,6 +774,95 @@ func TestCacheWraps(t *testing.T) { require.IsType(t, cachemulti.Store{}, cacheWrappedWithListeners) } +func TestSetAppVersion(t *testing.T) { + testcases := map[string]struct { + expectError bool + }{ + "no error": {}, + "error": { + expectError: true, + }, + } + + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + var db dbm.DB + if tc.expectError { + ctrl := gomock.NewController(t) + dbMock := mock.NewMockDB(ctrl) + dbMock.EXPECT().SetSync(gomock.Any(), gomock.Any()).Return(errors.New(dbErr)).Times(1) + db = dbMock + } else { + db = dbm.NewMemDB() + } + + store := newMultiStoreWithMounts(db, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)) + + err := store.SetAppVersion(0) + + if tc.expectError { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + +func TestGetAppVersion(t *testing.T) { + testcases := map[string]struct { + store *Store + isPreSet bool + expectedVerson uint64 + expectError bool + }{ + "no app version pre-set": { + store: newMultiStoreWithMounts(dbm.NewMemDB(), pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)), + expectedVerson: 0, + }, + "app version pre-set": { + store: newMultiStoreWithMounts(dbm.NewMemDB(), pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)), + expectedVerson: 5, + isPreSet: true, + }, + "db err": { + expectError: true, + expectedVerson: 5, + }, + } + + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + + var db dbm.DB + if tc.expectError { + ctrl := gomock.NewController(t) + dbMock := mock.NewMockDB(ctrl) + dbMock.EXPECT().Get(gomock.Any()).Return(nil, errors.New(dbErr)).Times(1) + db = dbMock + } else { + db = dbm.NewMemDB() + } + + store := newMultiStoreWithMounts(db, pruningtypes.NewPruningOptions(pruningtypes.PruningNothing)) + + if tc.isPreSet { + require.NoError(t, store.SetAppVersion(5)) + } + + appVersion, err := store.GetAppVersion() + + if tc.expectError { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Equal(t, tc.expectedVerson, appVersion) + }) + } +} + //----------------------------------------------------------------------- // utils diff --git a/store/types/store.go b/store/types/store.go index 511a547e2f68..86d338945df6 100644 --- a/store/types/store.go +++ b/store/types/store.go @@ -41,6 +41,12 @@ type Queryable interface { Query(abci.RequestQuery) abci.ResponseQuery } +// ProtocolVersionManager defines the interface which allows managing the appVersion field. +type ProtocolVersionManager interface { + GetAppVersion() (uint64, error) + SetAppVersion(version uint64) error +} + //---------------------------------------- // MultiStore @@ -151,6 +157,7 @@ type CommitMultiStore interface { Committer MultiStore snapshottypes.Snapshotter + ProtocolVersionManager // Mount a store of type using the given db. // If db == nil, the new store will use the CommitMultiStore db. diff --git a/x/params/keeper/consensus_params.go b/x/params/keeper/consensus_params.go index 30921ede639f..5ce8d340d0d9 100644 --- a/x/params/keeper/consensus_params.go +++ b/x/params/keeper/consensus_params.go @@ -24,10 +24,5 @@ func ConsensusParamsKeyTable() types.KeyTable { types.NewParamSetPair( baseapp.ParamStoreKeyValidatorParams, tmproto.ValidatorParams{}, baseapp.ValidateValidatorParams, ), - // This param is stored in the param store in order to send it to Tendermint after state sync. - // If this param is modified by governance, it will be reset by the upgrade module. - types.NewParamSetPair( - baseapp.ParamStoreKeyVersionParams, tmproto.VersionParams{}, baseapp.ValidateValidatorParams, - ), ) } diff --git a/x/simulation/simulate.go b/x/simulation/simulate.go index e1ff8f1826b6..8363e43fe3b8 100644 --- a/x/simulation/simulate.go +++ b/x/simulation/simulate.go @@ -40,6 +40,8 @@ func initChain( ConsensusParams: consensusParams, Time: genesisTimestamp, } + // Valid app version can only be zeron on app initialization. + req.ConsensusParams.Version.AppVersion = 0 res := app.InitChain(req) validators := newMockValidators(r, res.Validators, params) diff --git a/x/upgrade/exported/exported.go b/x/upgrade/exported/exported.go index 36eb7a803f10..ee6e0c31a73a 100644 --- a/x/upgrade/exported/exported.go +++ b/x/upgrade/exported/exported.go @@ -1,9 +1,7 @@ package exported -import sdk "github.com/cosmos/cosmos-sdk/types" - // ProtocolVersionManager defines the interface which allows managing the appVersion field. type ProtocolVersionManager interface { - GetAppVersion(ctx sdk.Context) (uint64, error) - SetAppVersion(ctx sdk.Context, version uint64) error + GetAppVersion() (uint64, error) + SetAppVersion(version uint64) error } diff --git a/x/upgrade/keeper/keeper.go b/x/upgrade/keeper/keeper.go index 20abc1ef10ed..f6f43dc502e4 100644 --- a/x/upgrade/keeper/keeper.go +++ b/x/upgrade/keeper/keeper.go @@ -85,7 +85,7 @@ func (k Keeper) SetModuleVersionMap(ctx sdk.Context, vm module.VersionMap) { // SetAppVersion sets app version to version func (k Keeper) SetAppVersion(ctx sdk.Context, version uint64) error { - return k.versionManager.SetAppVersion(ctx, version) + return k.versionManager.SetAppVersion(version) } // GetModuleVersionMap returns a map of key module name and value module consensus version @@ -292,11 +292,11 @@ func (k Keeper) ApplyUpgrade(ctx sdk.Context, plan types.Plan) { if k.versionManager != nil { // increment the app version and set it in state and baseapp - appVersion, err := k.versionManager.GetAppVersion(ctx) + appVersion, err := k.versionManager.GetAppVersion() if err != nil { panic(err) } - if err := k.versionManager.SetAppVersion(ctx, appVersion+1); err != nil { + if err := k.versionManager.SetAppVersion(appVersion + 1); err != nil { panic(err) } } diff --git a/x/upgrade/keeper/keeper_test.go b/x/upgrade/keeper/keeper_test.go index 7dc1baad743f..08e49c7de07b 100644 --- a/x/upgrade/keeper/keeper_test.go +++ b/x/upgrade/keeper/keeper_test.go @@ -197,8 +197,9 @@ func (s *KeeperTestSuite) TestSetUpgradedClient() { // Test that the app version successfully increments after an // upgrade and is successfully set on BaseApp's appVersion. func (s *KeeperTestSuite) TestIncrementAppVersion() { - oldAppVersion, err := s.app.BaseApp.GetAppVersion(s.ctx) + oldAppVersion, err := s.app.BaseApp.GetAppVersion() s.Require().NoError(err) + s.Require().Equal(uint64(0), oldAppVersion) s.app.UpgradeKeeper.SetUpgradeHandler("dummy", func(_ sdk.Context, _ types.Plan, vm module.VersionMap) (module.VersionMap, error) { return vm, nil }) dummyPlan := types.Plan{ Name: "dummy", @@ -206,9 +207,8 @@ func (s *KeeperTestSuite) TestIncrementAppVersion() { Height: 100, } s.app.UpgradeKeeper.ApplyUpgrade(s.ctx, dummyPlan) - upgradedAppVersion, err := s.app.BaseApp.GetAppVersion(s.ctx) + upgradedAppVersion, err := s.app.BaseApp.GetAppVersion() s.Require().NoError(err) - s.Require().Equal(oldAppVersion+1, upgradedAppVersion) }