diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d10be7f1..e866a20b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,8 +4,8 @@ jobs: test: strategy: matrix: - go-version: [1.15.x] - os: [ubuntu-latest] + go-version: [1.15.x, 1.16.x] + os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - name: Install Go @@ -14,5 +14,5 @@ jobs: go-version: ${{ matrix.go-version }} - name: Checkout code uses: actions/checkout@v2 - - name: Run Makefile Tests - run: make github-ci \ No newline at end of file + - name: Run Go Tests + run: go test ./... \ No newline at end of file diff --git a/Makefile b/Makefile index 3cad273e..82b382fd 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,10 @@ BUILD_FLAGS := -tags "$(build_tags)" -ldflags '$(ldflags)' build: go build -mod=readonly $(BUILD_FLAGS) -o build/emd$(BIN_PREFIX) ./cmd/emd + +cosmovisor: + go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@latest + lint: golangci-lint run @@ -59,16 +63,23 @@ fmt: imp: gci -w **/*.go - install: go install -mod=readonly $(BUILD_FLAGS) ./cmd/emd +build-test-upg: + docker run --rm --entrypoint cat emoney/cosmovisor /go/bin/cosmovisor > build/cosmovisor + chmod +x build/cosmovisor + docker run --rm --entrypoint cat emoney/test-upg /go/src/em-ledger/build/emd > "build/emdupg" + chmod +x "build/emdupg" + docker run --rm --entrypoint cat emoney/test-upg /go/src/em-ledger/build/emd-linux > "build/emdupg-linux" + chmod +x "build/emdupg-linux" + build-linux: # Linux images for docker-compose # CGO_ENABLED=0 added to solve this issue: https://stackoverflow.com/a/36308464 - BIN_PREFIX=-linux LEDGER_ENABLED=false GOOS=linux CGO_ENABLED=0 GOARCH=amd64 $(MAKE) build + BIN_PREFIX=-linux LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build -build-all: build-linux +build-all: build-linux build-test-upg $(MAKE) build build-docker: @@ -82,7 +93,7 @@ test: go test -mod=readonly ./... bdd-test: - go test -mod=readonly -v -p 1 -timeout 1h --tags="bdd" bdd_test.go multisigauthority_test.go authority_test.go market_test.go buyback_test.go capacity_test.go staking_test.go bep3swap_test.go + go test -mod=readonly -v -p 1 -timeout 1h --tags="bdd" bdd_test.go multisigauthority_test.go authority_test.go market_test.go buyback_test.go capacity_test.go staking_test.go bep3swap_test.go upgrade_test.go github-ci: build-linux $(MAKE) test @@ -104,7 +115,7 @@ license: GO111MODULE=off go get github.com/google/addlicense/ addlicense -f LICENSE . -.PHONY: build build-linux clean test bdd-test build-docker license +.PHONY: build build-linux build-test-upg cosmovisor clean test bdd-test build-docker license ############################################################################### ### Protobuf ### @@ -133,6 +144,4 @@ proto-lint: proto-check-breaking: @$(DOCKER_BUF) breaking --against-input $(HTTPS_GIT)#branch=master -.PHONY: proto-all proto-gen proto-swagger-gen proto-format proto-lint proto-check-breaking - - +.PHONY: proto-all proto-gen proto-swagger-gen proto-format proto-lint proto-check-breaking \ No newline at end of file diff --git a/app.go b/app.go index 9cac70e7..4fe826b3 100644 --- a/app.go +++ b/app.go @@ -7,6 +7,12 @@ package emoney import ( "encoding/json" "fmt" + "io" + "net/http" + "os" + "path/filepath" + "time" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" "github.com/cosmos/cosmos-sdk/client/rpc" @@ -65,11 +71,6 @@ import ( tmos "github.com/tendermint/tendermint/libs/os" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - "io" - "net/http" - "os" - "path/filepath" - "time" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" @@ -104,7 +105,6 @@ const ( var ( DefaultNodeHome = os.ExpandEnv("$HOME/.emd") - // todo (reviewer) : please check the listed modules carefully. This are the defaults + em modules ModuleBasics = module.NewBasicManager( auth.AppModuleBasic{}, genutil.AppModuleBasic{}, @@ -342,7 +342,7 @@ func NewApp( app.inflationKeeper = inflation.NewKeeper(app.appCodec, keys[inflation.StoreKey], app.bankKeeper, app.accountKeeper, app.stakingKeeper, buyback.AccountName, authtypes.FeeCollectorName) app.lpKeeper = liquidityprovider.NewKeeper(app.appCodec, keys[lptypes.StoreKey], app.bankKeeper) app.issuerKeeper = issuer.NewKeeper(app.appCodec, keys[issuer.StoreKey], app.lpKeeper, app.inflationKeeper) - app.authorityKeeper = authority.NewKeeper(app.appCodec, keys[authority.StoreKey], app.issuerKeeper, app.bankKeeper, app) + app.authorityKeeper = authority.NewKeeper(app.appCodec, keys[authority.StoreKey], app.issuerKeeper, app.bankKeeper, app, &app.upgradeKeeper) app.marketKeeper = market.NewKeeper(app.appCodec, keys[market.StoreKey], memKeys[market.StoreKeyIdx], app.accountKeeper, app.bankKeeper) app.buybackKeeper = buyback.NewKeeper(app.appCodec, keys[buyback.StoreKey], app.marketKeeper, app.accountKeeper, app.stakingKeeper, app.bankKeeper) app.bep3Keeper = bep3.NewKeeper(app.appCodec, keys[bep3.StoreKey], app.bankKeeper, app.accountKeeper, app.paramsKeeper.Subspace(bep3.ModuleName), GetMaccs()) diff --git a/app_test.go b/app_test.go index 9c09df51..a15e83e9 100644 --- a/app_test.go +++ b/app_test.go @@ -2,23 +2,58 @@ package emoney import ( "encoding/json" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/e-money/em-ledger/x/authority" - "github.com/tendermint/tendermint/libs/rand" "os" + "sync" "testing" + "time" + + upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" + "github.com/e-money/em-ledger/x/authority" + apptypes "github.com/e-money/em-ledger/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + authtypes "github.com/e-money/em-ledger/x/authority/types" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/rand" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - - abci "github.com/tendermint/tendermint/abci/types" ) +var configOnce sync.Once + func TestSimAppExportAndBlockedAddrs(t *testing.T) { - encCfg := MakeEncodingConfig() + encCfg, db, app, _ := getEmSimApp(t, rand.Bytes(sdk.AddrLen)) + app.Commit() + + // Making a new app object with the db, so that initchain hasn't been called + app2 := NewApp( + log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, + map[int64]bool{}, t.TempDir(), 0, encCfg, EmptyAppOptions{}, + ) + _, err := app2.ExportAppStateAndValidators(false, []string{}) + require.NoError( + t, err, "ExportAppStateAndValidators should not have an error", + ) +} + +func getEmSimApp( + t *testing.T, authorityAcc sdk.AccAddress, +) (encCfg EncodingConfig, memDB *dbm.MemDB, eMoneyApp *EMoneyApp, homeFolder string) { + t.Helper() + + encCfg = MakeEncodingConfig() db := dbm.NewMemDB() - app := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, t.TempDir(), 0, encCfg, EmptyAppOptions{}) + homeDir := t.TempDir() + t.Log("home dir:", homeDir) + + app := NewApp( + log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, + map[int64]bool{}, homeDir, 0, encCfg, EmptyAppOptions{}, + ) for acc := range maccPerms { require.True( @@ -29,8 +64,9 @@ func TestSimAppExportAndBlockedAddrs(t *testing.T) { } genesisState := ModuleBasics.DefaultGenesis(encCfg.Marshaler) - authorityState := authority.NewGenesisState(rand.Bytes(sdk.AddrLen), sdk.NewDecCoins()) - genesisState[authority.ModuleName] = encCfg.Marshaler.MustMarshalJSON(&authorityState) + authorityState := authtypes.GenesisState{AuthorityKey: authorityAcc.String(), MinGasPrices: sdk.NewDecCoins()} + + genesisState["authority"] = encCfg.Marshaler.MustMarshalJSON(&authorityState) stateBytes, err := json.MarshalIndent(genesisState, "", " ") require.NoError(t, err) @@ -42,12 +78,8 @@ func TestSimAppExportAndBlockedAddrs(t *testing.T) { AppStateBytes: stateBytes, }, ) - app.Commit() - // Making a new app object with the db, so that initchain hasn't been called - app2 := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, t.TempDir(), 0, encCfg, EmptyAppOptions{}) - _, err = app2.ExportAppStateAndValidators(false, []string{}) - require.NoError(t, err, "ExportAppStateAndValidators should not have an error") + return encCfg, db, app, homeFolder } // EmptyAppOptions is a stub implementing AppOptions @@ -57,3 +89,318 @@ type EmptyAppOptions struct{} func (ao EmptyAppOptions) Get(o string) interface{} { return nil } + +type emAppTests struct { + ctx sdk.Context + homeDir string + app *EMoneyApp + authority sdk.AccAddress +} + +func (et emAppTests) initEmApp(t *testing.T) emAppTests { + t.Helper() + + var err error + et.authority, err = sdk.AccAddressFromBech32("emoney1kt0vh0ttget0xx77g6d3ttnvq2lnxx6vp3uyl0") + require.NoError(t, err) + + _, _, app, homeDir := getEmSimApp(t, et.authority) + + et.homeDir = homeDir + et.app = app + et.ctx = app.BaseApp.NewContext(false, tmproto.Header{ + Time: time.Now(), + Height: 10, + }) + + return et +} + +func Test_Upgrade(t *testing.T) { + configOnce.Do(apptypes.ConfigureSDK) + + tests := []struct { + suite emAppTests + name string + plan upgradetypes.Plan + setupUpgCond func(simApp emAppTests, plan *upgradetypes.Plan) + expSchedPass bool + qrySched bool + qryApply bool + }{ + { + name: "successful time schedule", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) { + plan.Time = simApp.ctx.BlockTime().Add(time.Hour) + }, + expSchedPass: true, + }, + { + name: "successful height schedule", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + Height: 123450000, + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) {}, + expSchedPass: true, + }, + { + name: "setting both time and height schedule", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + Height: 123450000, + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) { + plan.Time = simApp.ctx.BlockTime().Add(time.Hour) + }, + expSchedPass: false, + }, + { + name: "successful overwrite", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + Height: 123450000, + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) { + + _, err := simApp.app.authorityKeeper.ScheduleUpgrade( + simApp.ctx, simApp.authority, upgradetypes.Plan{ + Name: "alt-good", + Info: "new text here", + Height: 543210000, + }, + ) + require.NoError(t, err) + }, + expSchedPass: true, + }, + { + name: "successful overwrite future with earlier date", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + Height: 123450000, + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) { + _, err := simApp.app.authorityKeeper.ScheduleUpgrade( + simApp.ctx, simApp.authority, upgradetypes.Plan{ + Name: "alt-good", + Info: "new text here", + Height: 543210000, + }, + ) + require.NoError(t, err) + }, + expSchedPass: true, + }, + { + name: "successful overwrite earlier with future date", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + Height: 543210000, + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) { + _, err := simApp.app.authorityKeeper.ScheduleUpgrade( + simApp.ctx, simApp.authority, upgradetypes.Plan{ + Name: "alt-good", + Info: "new text here", + Height: 123450000, + }, + ) + require.NoError(t, err) + }, + expSchedPass: true, + }, + { + name: "unsuccessful schedule: missing plan name", + plan: upgradetypes.Plan{ + Height: 123450000, + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) {}, + expSchedPass: false, + }, + { + name: "unsuccessful time schedule: initialized, uninitialized due date in past", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) { + plan.Time = simApp.ctx.BlockTime() + }, + expSchedPass: false, + }, + { + name: "unsuccessful height schedule: due date in past", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + Height: 1, + }, + setupUpgCond: func(simApp emAppTests, plan *upgradetypes.Plan) {}, + expSchedPass: false, + }, + { + name: "unsuccessful schedule: schedule already executed", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + Height: 123450000, + }, + setupUpgCond: func(simEmApp emAppTests, plan *upgradetypes.Plan) { + simEmApp.app.upgradeKeeper.SetUpgradeHandler("all-good", func(_ sdk.Context, _ upgradetypes.Plan) {}) + simEmApp.app.upgradeKeeper.ApplyUpgrade( + simEmApp.ctx, upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + Height: 123450000, + }, + ) + }, + expSchedPass: false, + }, + } + for _, tt := range tests { + t.Run( + tt.name, func(t *testing.T) { + tt.suite = emAppTests{}.initEmApp(t) + + // setup test case + tt.setupUpgCond(tt.suite, &tt.plan) + + // schedule upgrade plan + var err error + _, err = tt.suite.app.authorityKeeper.ScheduleUpgrade( + tt.suite.ctx, tt.suite.authority, tt.plan, + ) + schedPlan, hasPlan := tt.suite.app.authorityKeeper.GetUpgradePlan(tt.suite.ctx) + + // validate plan side effect + if tt.expSchedPass { + require.NoError(t, err, "Upgrade() error = %v, expSchedPass %v", err, tt.expSchedPass) + require.Truef(t, hasPlan, "hasPlan: %t there should be a plan", hasPlan) + require.Equalf(t, schedPlan, tt.plan, "queried %v != %v", schedPlan, tt.plan) + } else { + require.Falsef(t, hasPlan, "hasPlan: %t plan should not exist", hasPlan) + require.NotEqualf(t, schedPlan, tt.plan, "queried %v == %v", schedPlan, tt.plan) + } + + // apply and confirm plan deletion + if tt.expSchedPass { + executePlan( + tt.suite.ctx, t, tt.suite.app.upgradeKeeper, + tt.suite.app.authorityKeeper, tt.plan, + ) + } + }, + ) + } +} + +func Test_UpgradeByTime(t *testing.T) { + + configOnce.Do(apptypes.ConfigureSDK) + + tests := []struct { + suite emAppTests + name string + plan upgradetypes.Plan + blockTimes []time.Time + setupUpgCond func(simApp emAppTests, blockTimes []time.Time, plan *upgradetypes.Plan) + expPass bool + qrySched bool + qryApply bool + }{ + { + name: "successful time plan + 1minute", + plan: upgradetypes.Plan{ + Name: "all-good", + Info: "some text here", + }, + setupUpgCond: func(simApp emAppTests, blockTimes []time.Time, plan *upgradetypes.Plan) { + const duration = 10 * time.Minute + plan.Time = simApp.ctx.BlockTime().Add(duration) + blockTimes = []time.Time{ + simApp.ctx.BlockTime(), + simApp.ctx.BlockTime().Add(time.Minute), + plan.Time.Add(-time.Nanosecond), + } + }, + expPass: true, + }, + } + for _, tt := range tests { + t.Run( + tt.name, func(t *testing.T) { + tt.suite = emAppTests{}.initEmApp(t) + + // setup test case + tt.setupUpgCond(tt.suite, tt.blockTimes, &tt.plan) + + // schedule upgrade plan + var err error + _, err = tt.suite.app.authorityKeeper.ScheduleUpgrade( + tt.suite.ctx, tt.suite.authority, tt.plan, + ) + schedPlan, hasPlan := tt.suite.app.authorityKeeper.GetUpgradePlan(tt.suite.ctx) + + // validate plan side effect + if tt.expPass { + require.NoError(t, err, "Upgrade() error = %v, expSchedPass %v", err, tt.expPass) + require.Truef( + t, hasPlan, "hasPlan: %t there should be a plan", + hasPlan, + ) + require.Equalf( + t, schedPlan, tt.plan, "queried %v != %v", schedPlan, + tt.plan, + ) + } else { + require.Falsef( + t, hasPlan, "hasPlan: %t plan should not exist", hasPlan, + ) + require.NotEqualf( + t, schedPlan, tt.plan, "queried %v == %v", schedPlan, + tt.plan, + ) + } + + // advance chain and confirm plan execution + tt.suite.app.authorityKeeper.GetUpgradePlan(tt.suite.ctx) + for _, blockTime := range tt.blockTimes { + tt.suite.ctx = tt.suite.ctx.WithBlockTime(blockTime) + require.Falsef(t, schedPlan.ShouldExecute(tt.suite.ctx), "premature timing for executing plan") + } + // move forward to execution time + tt.suite.ctx = tt.suite.ctx.WithBlockTime(schedPlan.Time) + require.Truef(t, schedPlan.ShouldExecute(tt.suite.ctx), "plan should be ripe for execution") + + executePlan( + tt.suite.ctx, t, tt.suite.app.upgradeKeeper, + tt.suite.app.authorityKeeper, tt.plan, + ) + }, + ) + } +} + +func executePlan( + ctx sdk.Context, t *testing.T, uk upgradekeeper.Keeper, ak authority.Keeper, + plan upgradetypes.Plan, +) { + uk.SetUpgradeHandler(plan.Name, func(_ sdk.Context, _ upgradetypes.Plan) {}) + + uk.ApplyUpgrade(ctx, plan) + + schedPlan, hasPlan := ak.GetUpgradePlan(ctx) + require.Falsef(t, hasPlan, "hasPlan: %t plan should not exist", hasPlan) + require.NotEqualf(t, schedPlan, plan, "queried %v == %v", schedPlan, plan) +} diff --git a/docs/proto/em/proto-docs.md b/docs/proto/em/proto-docs.md index 5fbd8c6d..a2f746b1 100644 --- a/docs/proto/em/proto-docs.md +++ b/docs/proto/em/proto-docs.md @@ -14,6 +14,8 @@ - [em/authority/v1/query.proto](#em/authority/v1/query.proto) - [QueryGasPricesRequest](#em.authority.v1.QueryGasPricesRequest) - [QueryGasPricesResponse](#em.authority.v1.QueryGasPricesResponse) + - [QueryUpgradePlanRequest](#em.authority.v1.QueryUpgradePlanRequest) + - [QueryUpgradePlanResponse](#em.authority.v1.QueryUpgradePlanResponse) - [Query](#em.authority.v1.Query) @@ -24,6 +26,8 @@ - [MsgDestroyIssuerResponse](#em.authority.v1.MsgDestroyIssuerResponse) - [MsgReplaceAuthority](#em.authority.v1.MsgReplaceAuthority) - [MsgReplaceAuthorityResponse](#em.authority.v1.MsgReplaceAuthorityResponse) + - [MsgScheduleUpgrade](#em.authority.v1.MsgScheduleUpgrade) + - [MsgScheduleUpgradeResponse](#em.authority.v1.MsgScheduleUpgradeResponse) - [MsgSetGasPrices](#em.authority.v1.MsgSetGasPrices) - [MsgSetGasPricesResponse](#em.authority.v1.MsgSetGasPricesResponse) @@ -256,6 +260,31 @@ + + + +### QueryUpgradePlanRequest + + + + + + + + + +### QueryUpgradePlanResponse + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `plan` | [cosmos.upgrade.v1beta1.Plan](#cosmos.upgrade.v1beta1.Plan) | | | + + + + + @@ -271,6 +300,7 @@ | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | | `GasPrices` | [QueryGasPricesRequest](#em.authority.v1.QueryGasPricesRequest) | [QueryGasPricesResponse](#em.authority.v1.QueryGasPricesResponse) | | GET|/e-money/authority/v1/gasprices| +| `UpgradePlan` | [QueryUpgradePlanRequest](#em.authority.v1.QueryUpgradePlanRequest) | [QueryUpgradePlanResponse](#em.authority.v1.QueryUpgradePlanResponse) | | GET|/e-money/authority/v1/upgrade_plan| @@ -367,6 +397,32 @@ + + +### MsgScheduleUpgrade + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authority` | [string](#string) | | | +| `plan` | [cosmos.upgrade.v1beta1.Plan](#cosmos.upgrade.v1beta1.Plan) | | | + + + + + + + + +### MsgScheduleUpgradeResponse + + + + + + + ### MsgSetGasPrices @@ -410,6 +466,7 @@ | `DestroyIssuer` | [MsgDestroyIssuer](#em.authority.v1.MsgDestroyIssuer) | [MsgDestroyIssuerResponse](#em.authority.v1.MsgDestroyIssuerResponse) | | | | `SetGasPrices` | [MsgSetGasPrices](#em.authority.v1.MsgSetGasPrices) | [MsgSetGasPricesResponse](#em.authority.v1.MsgSetGasPricesResponse) | | | | `ReplaceAuthority` | [MsgReplaceAuthority](#em.authority.v1.MsgReplaceAuthority) | [MsgReplaceAuthorityResponse](#em.authority.v1.MsgReplaceAuthorityResponse) | | | +| `ScheduleUpgrade` | [MsgScheduleUpgrade](#em.authority.v1.MsgScheduleUpgrade) | [MsgScheduleUpgradeResponse](#em.authority.v1.MsgScheduleUpgradeResponse) | | | diff --git a/multisigauthority_test.go b/multisigauthority_test.go index ae35a723..3b14cd75 100644 --- a/multisigauthority_test.go +++ b/multisigauthority_test.go @@ -101,14 +101,6 @@ var _ = Describe("Authority", func() { ) Expect(err).To(BeNil()) - // create/revoke issuer with both the former and the new authority - // former singlesig first - ok = nt.AuthCreatesIssuer(emcli, keystore.Authority, key1) - Expect(ok).To(BeTrue()) - _, success, err = emcli.AuthorityDestroyIssuer(keystore.Authority, key1) - Expect(success).To(BeTrue()) - Expect(err).ToNot(HaveOccurred()) - // current multisig authority now // create-issuer execAuthMSigTx( diff --git a/networks/.gitignore b/networks/.gitignore new file mode 100644 index 00000000..0763333a --- /dev/null +++ b/networks/.gitignore @@ -0,0 +1 @@ +.emd/ \ No newline at end of file diff --git a/networks/docker/Makefile b/networks/docker/Makefile index e3196410..459c7d14 100644 --- a/networks/docker/Makefile +++ b/networks/docker/Makefile @@ -1,8 +1,16 @@ # Makefile for the "emdnode" docker image. -all: emdnode +all: emdnode cosmovisor test-upg emdnode: docker build --tag emoney/emdnode emdnode -.PHONY: all emdnode \ No newline at end of file +cosmovisor: + docker build cosmovisor --tag emoney/cosmovisor + +test-upg: + docker build test-upg --build-arg branch=$$(git rev-parse --abbrev-ref HEAD) --build-arg version=test-upg-0.2.0 --tag emoney/test-upg + +# todo (reviewer): please note the rest-server is not a command anymore. Please enable `api` section in `app.toml` instead + +.PHONY: all emdnode cosmovisor test-upg \ No newline at end of file diff --git a/networks/docker/cosmovisor/Dockerfile b/networks/docker/cosmovisor/Dockerfile new file mode 100644 index 00000000..d72cac76 --- /dev/null +++ b/networks/docker/cosmovisor/Dockerfile @@ -0,0 +1,7 @@ +# This software is Copyright (c) 2019-2021 e-Money A/S. It is not offered under an open source license. +# +# Please contact partners@e-money.com for licensing related questions. + +FROM golang:1.16-buster AS build-env + +RUN go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@latest \ No newline at end of file diff --git a/networks/docker/emdnode/Dockerfile b/networks/docker/emdnode/Dockerfile index 59ffbe7a..75486c1c 100644 --- a/networks/docker/emdnode/Dockerfile +++ b/networks/docker/emdnode/Dockerfile @@ -2,11 +2,11 @@ # # Please contact partners@e-money.com for licensing related questions. -FROM alpine:3.7 +FROM ubuntu:18.04 -RUN apk update && \ - apk upgrade && \ - apk --no-cache add curl jq file +RUN apt-get update && \ + apt-get -y upgrade && \ + apt-get -y install curl jq file VOLUME /emoney WORKDIR /emoney @@ -15,5 +15,4 @@ ENTRYPOINT ["/usr/bin/wrapper.sh"] CMD ["start"] STOPSIGNAL SIGTERM -COPY wrapper.sh /usr/bin/wrapper.sh - +COPY wrapper.sh /usr/bin/wrapper.sh \ No newline at end of file diff --git a/networks/docker/emdnode/wrapper.sh b/networks/docker/emdnode/wrapper.sh index da42ae87..6e87dd6e 100755 --- a/networks/docker/emdnode/wrapper.sh +++ b/networks/docker/emdnode/wrapper.sh @@ -10,9 +10,6 @@ BINARY=/emoney/${BINARY:-emd-linux} ID=${ID:-0} LOG=${LOG:-emd.log} -# LOGLEVEL=${LOGLEVEL:-emz:info,x/inflation:info,x/liquidityprovider:info,main:info,state:info,*:error} -# TODO (reviewer) : the SDK uses the zap logger now. without fine grained configuration options. There should be an open issue in the repo already -LOGLEVEL=info ## ## Assert linux binary ## @@ -31,11 +28,24 @@ fi ## export EMDHOME="/emoney/node${ID}" -if [ -d "`dirname ${EMDHOME}/${LOG}`" ]; then - "$BINARY" --home "$EMDHOME" "$@" --log_level ${LOGLEVEL} --trace --pruning=nothing | tee "${EMDHOME}/${LOG}" +# setup cosmovisor +mkdir -p "$EMDHOME/cosmovisor/genesis/bin" +cp /emoney/emd-linux "$EMDHOME/cosmovisor/genesis/bin" + +export DAEMON_ALLOW_DOWNLOAD_BINARIES=true +export DAEMON_RESTART_AFTER_UPGRADE=true +export DAEMON_HOME=$EMDHOME +# link chain launcher to cosmovisor with linux emd binary +export DAEMON_NAME=emd-linux +BINARY=/emoney/cosmovisor +UPG_LOC="$EMDHOME"/cosmovisor/upgrades/test-upg-0.2.0/bin +mkdir -p "$UPG_LOC" +cp /emoney/emdupg-linux "$UPG_LOC"/emd-linux + +if [ -d "$(dirname "${EMDHOME}"/"${LOG}")" ]; then + "$BINARY" --home "$EMDHOME" "$@" | tee "${EMDHOME}/${LOG}" else - "$BINARY" --home "$EMDHOME" "$@" --log_level ${LOGLEVEL} --trace --pruning=nothing + "$BINARY" --home "$EMDHOME" "$@" fi -chmod 777 -R /emoney - +chmod 777 -R /emoney \ No newline at end of file diff --git a/networks/docker/test-upg/Dockerfile b/networks/docker/test-upg/Dockerfile new file mode 100644 index 00000000..d8cb6108 --- /dev/null +++ b/networks/docker/test-upg/Dockerfile @@ -0,0 +1,17 @@ +FROM golang:1.16-buster + +ARG branch +ARG version + +# checkout and build linux binary +RUN cd /go/src && \ + git clone https://github.com/e-money/em-ledger.git && \ + cd em-ledger && \ + git checkout $branch && \ + sed -i -e '/bep3.NewKeeper/r networks/upg/upgfunc.txt' app.go && \ + git tag $version && \ + BIN_PREFIX=-linux LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 make build + +# build MacOS binary +WORKDIR /go/src/em-ledger +RUN LEDGER_ENABLED=false GOOS=darwin GOARCH=amd64 make build \ No newline at end of file diff --git a/networks/upg/README.md b/networks/upg/README.md new file mode 100644 index 00000000..58a04c70 --- /dev/null +++ b/networks/upg/README.md @@ -0,0 +1,76 @@ +## Guide for testing the upgrade module +#### Overview +This document is an interactive guide for testing the upgrade module with a single docker-less e-money node. + +Please note if you'd rather test the upgrade module within the **e-money local-testnet** run: + +```shell +cd em-ledger +make build-docker +make build-all +go test -v --tags="bdd" bdd_test.go upgrade_test.go +``` + +Two new docker images defined in em-ledger/networks/docker: + +1. `emoney/cosmovisor` which builds a linux cosmovisor binary for use within the e-money local-testnet. + +2. `emoney/test-upg` which builds a test upgrade mode with a trivial upgrade module handler changing the gas-fees as part of the upgrade migration process. + +Note these scripts at **em-ledger/networks/upg**: +* `README.md` (this doc) +* `startcv` (starts a single e-money node with cosmovisor) +* `upg-sched` schedule an upgrade by passing the upgrade block height +* `upg-sched-srv` optional documentation setup and schedule command for upgrading with server downloaded binary +* `upgfunc.txt` Go snippet to be inserted as the upgrade module handler in the *upgrade* binary. + +### Components installation +Build the revamped Docker, Linux artifacts +```shell +make build-docker +make build-all +``` +As a result these artifacts generate within the build folder +```shell +.rwxrwxr-x 1 15M usr 3 Aug 13:06 cosmovisor +.rwxrwxr-x 1 60M usr 3 Aug 13:06 emd +.rwxrwxr-x 1 61M usr 3 Aug 13:06 emd-linux +.rwxrwxr-x 1 60M usr 3 Aug 13:06 emdupg +.rwxrwxr-x 1 60M usr 3 Aug 13:06 emdupg-linux +``` +`emdupg` is the *upgrade* emd binary* with the migration handler setting the gas-prices upon the chain upgrade. + +**The code for the upgrade handler is checked-in the *`upgrade-emd-test`* branch.* +### Install cosmovisor + +#### For interactive testing and general use +Please note, the cosmovisor binary built above is a `linux` binary for use within the *local-testnet* +```shell +go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@latest + +# test installation success +cosmovisor version +DAEMON_NAME is not set +``` + +### Launch network to upgrade +```shell +# Optionally in a separate pane or terminal tab +cd networks/upg +./startcv + +cd networks/upg +# schedule upgrade at future block height 6 +# if you overshoot retry with lower block height +./upg-sched 6 + +# wait for the upgrade +# check version, upgraded gas-prices +.emd/cosmovisor/current/bin/emd version # test-upg-0.2.0 +.emd/cosmovisor/current/bin/emd q authority gas-prices +min_gas_prices: +- amount: "1.000000000000000000" + denom: ungm + +#success! +``` diff --git a/networks/upg/cpemd b/networks/upg/cpemd new file mode 100755 index 00000000..48ef406a --- /dev/null +++ b/networks/upg/cpemd @@ -0,0 +1,49 @@ +#!/bin/zsh + +# Copying the upgrade and present/soon to be legacy binary in the cosmovisor genesis folder +# Note the cosmovisor folder structure before the upgrade +# em-ledger/networks/upg/.emd/cosmovisor +# ├── current -> /Users/user/go/src/github.com/e-money/em-ledger/networks/upg/.emd/cosmovisor/genesis/bin/emd +# ├── genesis +# │ └── bin +# │ └── emd +# └── upgrades +# └── test-upg-0.2.0 +# └── bin +# └── emd + +set -e + +# cosmovisor constant +export DAEMON_NAME=emd + +mkdir -p .emd +export DAEMON_HOME=$PWD/.emd +pushd -q ../../ +EM_LEDGER_LOC=$PWD +popd -q + +echo "node home: $DAEMON_HOME" + +# copy soon to be the legacy binary +COSMOVISOR_HOME="$EM_LEDGER_LOC"/networks/upg/.emd/cosmovisor + +# clean up previous sticky upgrade +rm -f "$COSMOVISOR_HOME"/current + +mkdir -p "$COSMOVISOR_HOME"/genesis/bin +cp "$EM_LEDGER_LOC"/build/emd "$COSMOVISOR_HOME"/genesis/bin +UPG_LOC="$COSMOVISOR_HOME"/upgrades/test-upg-0.2.0/bin + +mkdir -p "$UPG_LOC" +if [ "$(uname)" = "Linux" ]; then + cp "$EM_LEDGER_LOC"/build/emdupg-linux "$UPG_LOC"/emd +else + cp "$EM_LEDGER_LOC"/build/emdupg "$UPG_LOC"/emd +fi + +echo "legacy or current binary:" +ls "$COSMOVISOR_HOME"/genesis/bin/emd +echo "upgrade binary:" +ls "$UPG_LOC"/emd +echo "current version: $(cosmovisor version)" \ No newline at end of file diff --git a/networks/upg/startcv b/networks/upg/startcv new file mode 100755 index 00000000..3a070e80 --- /dev/null +++ b/networks/upg/startcv @@ -0,0 +1,53 @@ +#!/bin/zsh + +set -ev + +##### em-ledger single node cosmovisor setup +export DAEMON_NAME=emd +export DAEMON_ALLOW_DOWNLOAD_BINARIES=true +export DAEMON_RESTART_AFTER_UPGRADE=true + +# optionally uncomment to copy future upgrade binary in location if +# auto-downloading is not available as a primary or none at all +# by default we assume it is on and the upgrade binary is not available +# locally: DAEMON_RESTART_AFTER_UPGRADE=true +#./cpupgemd + +EMD_NODE=$PWD/.emd +EMD=../../build/emd + +# do not do this in production +# do not delete cosmovisor if it exists +rm -rf "$EMD_NODE"/config +rm -rf "$EMD_NODE"/data +rm -rf "$EMD_NODE"/keyring-test + +./cpemd + +$EMD unsafe-reset-all --home=$EMD_NODE + +$EMD init test --chain-id=test --home="$EMD_NODE" --overwrite +$EMD keys add validator --keyring-backend=test --home="$EMD_NODE" +$EMD add-genesis-account "$($EMD keys show validator -a --keyring-backend=test --home="$EMD_NODE")" 1000000000stake,1000000000ungm --home=$EMD_NODE +$EMD gentx validator 500000000stake --keyring-backend=test --home="$EMD_NODE" --chain-id=test + +# create genesis emoney1xue7fm6es84jze49grm4slhlmr4ffz8a3u7g3t to set the authority later +AUTH_SEED="fuel public electric luxury short upper quit edge ginger need olive gesture time useful stadium exhaust since team pond wool type flat focus narrow" +(echo "$AUTH_SEED"; echo "$AUTH_SEED") | $EMD keys add authoritykey --recover --keyring-backend=test --home="$EMD_NODE" +AUTHORITY_ADDR=$($EMD keys show authoritykey -a --keyring-backend=test --home="$EMD_NODE") +$EMD add-genesis-account "$AUTHORITY_ADDR" 1000000000000ungm --home=$EMD_NODE + +$EMD collect-gentxs --home="$EMD_NODE" + +# set the auth address as the chain authority +AUTHORITY_ADDR_VAL=".app_state.authority.key=\"$AUTHORITY_ADDR\"" +jq $AUTHORITY_ADDR_VAL < "$EMD_NODE"/config/genesis.json > "$EMD_NODE"/config/tmp_genesis.json +mv "$EMD_NODE"/config/tmp_genesis.json "$EMD_NODE"/config/genesis.json + +export DAEMON_HOME=$EMD_NODE + +echo "node home: $DAEMON_HOME" + +cosmovisor version + +cosmovisor start --home="$DAEMON_HOME" \ No newline at end of file diff --git a/networks/upg/upg-sched b/networks/upg/upg-sched new file mode 100755 index 00000000..7ac23143 --- /dev/null +++ b/networks/upg/upg-sched @@ -0,0 +1,22 @@ +#!/bin/bash + +# $1 : choose a future block height to upgrade + +set -e + +EMD=.emd/cosmovisor/current/bin/emd + +$EMD version +$EMD q authority gas-prices --home=.emd --node tcp://localhost:26657 --chain-id test +$EMD q authority upgrade-plan --home=.emd --node tcp://localhost:26657 --chain-id test + +# schedule upgrade +$EMD tx authority schedule-upgrade authoritykey test-upg-0.2.0 --upgrade-height "$1" --yes --from authoritykey --home=".emd" --node tcp://localhost:26657 --chain-id test --keyring-backend test + +# confirm upg plan +$EMD q authority upgrade-plan --home=.emd --node tcp://localhost:26657 --chain-id test + +# ---------- after upgrade ---------> +$EMD q authority gas-prices --home=.emd --node tcp://localhost:26657 --chain-id test +#$EMD q authority upgrade-plan --home=.emd --node tcp://localhost:26657 --chain-id test # is nil again +$EMD version # test-upg-0.2.0 diff --git a/networks/upg/upg-sched-srv b/networks/upg/upg-sched-srv new file mode 100755 index 00000000..e50be5ea --- /dev/null +++ b/networks/upg/upg-sched-srv @@ -0,0 +1,20 @@ +#!/bin/bash + +set -ev + +# Preconditions server auto download: +# export DAEMON_ALLOW_DOWNLOAD_BINARIES=true +# make emdupg +# mkdir -p /srv/upgemd/test-upg-0.2.0 +# cp build/emdupg /srv/upgemd/test-upg-0.2.0 +# zip /srv/upgemd/test-upg-0.2.0/emd.zip /srv/upgemd/test-upg-0.2.0/emd +# save sha value to clipboard +# sha256sum /srv/upgemd/test-upg-0.2.0/emd.zip | xsel -i -b +# cd /srv/upgemd +# start a web server in the +# python3 -m http.server 8765 + +EMD=.emd/cosmovisor/current/bin/emd + +# choose a future height +$EMD tx authority schedule-upgrade authoritykey test-upg-0.2.0 --upgrade-height 6 --upgrade-info '{"binaries":{"linux/amd64":"http://localhost:8765/test-upg-0.2.0/emd.zip?checksum=sha256:cadd5b52fe90a04e20b2cbb93291b0d1d0204f17b64b2215eb09f5dc78a127f1"}}' --yes --from authoritykey --home="$DAEMON_HOME" --node tcp://localhost:26657 --chain-id test --keyring-backend test \ No newline at end of file diff --git a/networks/upg/upgfunc.txt b/networks/upg/upgfunc.txt new file mode 100644 index 00000000..1830bbda --- /dev/null +++ b/networks/upg/upgfunc.txt @@ -0,0 +1,31 @@ + + /* + * This is a test handler for trying out cosmovisor + * Setting gas to One ungm + **/ + const testUpgradeHandler = "test-upg-0.2.0" + app.upgradeKeeper.SetUpgradeHandler(testUpgradeHandler, func(ctx sdk.Context, plan upgradetypes.Plan) { + genesisAuth := app.authorityKeeper.GetAuthoritySet(ctx) + if genesisAuth.Address == "" { + panic("authority should be set in genesis") + } + + authAcc, err := sdk.AccAddressFromBech32(genesisAuth.Address) + if err != nil { + panic(err) + } + + newGas := sdk.DecCoins{ + sdk.NewDecCoin("ungm", sdk.OneInt()), + } + + _, err = app.authorityKeeper.SetGasPrices(ctx, authAcc, newGas) + if err != nil { + panic(err) + } + + gasPrices := app.authorityKeeper.GetGasPrices(ctx) + if gasPrices.Empty() || !gasPrices.IsEqual(newGas) { + panic(fmt.Sprintf("expected Gas: %+v != store Gas: %+v", newGas, gasPrices)) + } + }) diff --git a/networks/utils/startemd b/networks/utils/startemd new file mode 100755 index 00000000..3c10687e --- /dev/null +++ b/networks/utils/startemd @@ -0,0 +1,44 @@ +#!/bin/zsh + +set -ev + +# locate emd binary +if [[ -f $PWD/../../build/emd ]]; then + EMD_NODE=$PWD/.emd + pushd -q ../../build + # save absolute path of emd required by cosmovisor + EMD=$PWD/emd + popd -q +else + echo "emd binary not found in $PWD. Please run make to create the emd binary" + exit 1 +fi + +# destructive +# do not do this in production +rm -rf "$EMD_NODE"/config +rm -rf "$EMD_NODE"/data +rm -rf "$EMD_NODE"/keyring-test +# do not delete cosmovisor if it exists + +$EMD unsafe-reset-all --home=$EMD_NODE + +$EMD init test --chain-id=test --home="$EMD_NODE" --overwrite +$EMD keys add validator --keyring-backend=test --home="$EMD_NODE" +$EMD add-genesis-account "$($EMD keys show validator -a --keyring-backend=test --home="$EMD_NODE")" 1000000000stake,1000000000ungm --home=$EMD_NODE +$EMD gentx validator 500000000stake --keyring-backend=test --home="$EMD_NODE" --chain-id=test + +# create genesis emoney1xue7fm6es84jze49grm4slhlmr4ffz8a3u7g3t to set the authority later +AUTH_SEED="fuel public electric luxury short upper quit edge ginger need olive gesture time useful stadium exhaust since team pond wool type flat focus narrow" +(echo "$AUTH_SEED"; echo "$AUTH_SEED") | $EMD keys add authoritykey --recover --keyring-backend=test --home="$EMD_NODE" +AUTHORITY_ADDR=$($EMD keys show authoritykey -a --keyring-backend=test --home="$EMD_NODE") +$EMD add-genesis-account "$AUTHORITY_ADDR" 1000000000000ungm --home=$EMD_NODE + +$EMD collect-gentxs --home="$EMD_NODE" + +# set the auth address as the chain authority +AUTHORITY_ADDR_VAL=".app_state.authority.key=\"$AUTHORITY_ADDR\"" +jq $AUTHORITY_ADDR_VAL < "$EMD_NODE"/config/genesis.json > "$EMD_NODE"/config/tmp_genesis.json +mv "$EMD_NODE"/config/tmp_genesis.json "$EMD_NODE"/config/genesis.json + +$EMD start --home="$EMD_NODE" \ No newline at end of file diff --git a/networktest/emcli.go b/networktest/emcli.go index 76671dc3..a5a7e830 100644 --- a/networktest/emcli.go +++ b/networktest/emcli.go @@ -51,6 +51,12 @@ func (cli Emcli) AuthorityCreateIssuer(authority, issuer Key, denoms ...string) return execCmdWithInput(args, KeyPwd) } +func (cli Emcli) UpgSchedByHeight(authority Key, planName string, height int64) (string, bool, error) { + args := cli.addTransactionFlags("tx", "authority", "schedule-upgrade", + authority.name, planName, "--upgrade-height", strconv.FormatInt(height, 10)) + return execCmdWithInput(args, KeyPwd) +} + func (cli Emcli) AuthorityDestroyIssuer(authority, issuer Key) (string, bool, error) { args := cli.addTransactionFlags("tx", "authority", "destroy-issuer", authority.name, issuer.GetAddress()) return execCmdWithInput(args, KeyPwd) @@ -63,6 +69,7 @@ func (cli Emcli) CustomCommand(params ...string) (string, error) { for _, param := range params { if re.MatchString(param) { checkTxRes = false + break } } args := cli.addTransactionFlags(params...) @@ -81,6 +88,11 @@ func (cli Emcli) AuthoritySetMinGasPrices(authority Key, minGasPrices string, pa return execCmdWithInput(args, KeyPwd) } +func (cli Emcli) QueryUpgSched() ([]byte, error) { + args := cli.addQueryFlags("query", "authority", "upgrade-plan") + return execCmdAndCollectResponse(args) +} + func (cli Emcli) QueryBuybackBalance() ([]byte, error) { args := cli.addQueryFlags("query", "buyback", "balance") return execCmdAndCollectResponse(args) diff --git a/proto/em/authority/v1/query.proto b/proto/em/authority/v1/query.proto index e942eddf..9bacb134 100644 --- a/proto/em/authority/v1/query.proto +++ b/proto/em/authority/v1/query.proto @@ -4,6 +4,7 @@ package em.authority.v1; import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; import "google/api/annotations.proto"; +import "cosmos/upgrade/v1beta1/upgrade.proto"; option go_package = "github.com/e-money/em-ledger/x/authority/types"; @@ -11,6 +12,10 @@ service Query { rpc GasPrices(QueryGasPricesRequest) returns (QueryGasPricesResponse) { option (google.api.http).get = "/e-money/authority/v1/gasprices"; }; + + rpc UpgradePlan(QueryUpgradePlanRequest) returns (QueryUpgradePlanResponse){ + option (google.api.http).get = "/e-money/authority/v1/upgrade_plan"; + } } message QueryGasPricesRequest {} @@ -24,3 +29,12 @@ message QueryGasPricesResponse { (gogoproto.nullable) = false ]; } + +message QueryUpgradePlanRequest {} + +message QueryUpgradePlanResponse { + cosmos.upgrade.v1beta1.Plan plan = 1 [ + (gogoproto.moretags) = "yaml:\"plan\"", + (gogoproto.nullable) = false + ]; +} \ No newline at end of file diff --git a/proto/em/authority/v1/tx.proto b/proto/em/authority/v1/tx.proto index f95d77db..1dd46a20 100644 --- a/proto/em/authority/v1/tx.proto +++ b/proto/em/authority/v1/tx.proto @@ -3,6 +3,7 @@ package em.authority.v1; import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; +import "cosmos/upgrade/v1beta1/upgrade.proto"; option go_package = "github.com/e-money/em-ledger/x/authority/types"; @@ -15,6 +16,8 @@ service Msg { rpc SetGasPrices(MsgSetGasPrices) returns (MsgSetGasPricesResponse); rpc ReplaceAuthority(MsgReplaceAuthority) returns (MsgReplaceAuthorityResponse); + + rpc ScheduleUpgrade(MsgScheduleUpgrade) returns (MsgScheduleUpgradeResponse); } message MsgCreateIssuer { @@ -51,4 +54,14 @@ message MsgReplaceAuthority { message MsgReplaceAuthorityResponse { string new_authority_address = 1 [ (gogoproto.moretags) = "yaml:\"new_authority_address\"" ]; -} \ No newline at end of file +} + +message MsgScheduleUpgrade { + string authority = 1 [ (gogoproto.moretags) = "yaml:\"authority\"" ]; + cosmos.upgrade.v1beta1.Plan plan = 2 [ + (gogoproto.moretags) = "yaml:\"plan\"", + (gogoproto.nullable) = false + ]; +} + +message MsgScheduleUpgradeResponse {} \ No newline at end of file diff --git a/upgrade_test.go b/upgrade_test.go new file mode 100644 index 00000000..3d9b4061 --- /dev/null +++ b/upgrade_test.go @@ -0,0 +1,67 @@ +// This software is Copyright (c) 2019-2020 e-Money A/S. It is not offered under an open source license. +// +// Please contact partners@e-money.com for licensing related questions. + +// +build bdd + +package emoney_test + +import ( + nt "github.com/e-money/em-ledger/networktest" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/tidwall/gjson" +) + +var _ = Describe("Upgrade", func() { + emcli := testnet.NewEmcli() + + var Authority = testnet.Keystore.Authority + + Describe("Authority manages issuers", func() { + It("creates a new testnet", createNewTestnet) + + It("upgrade nodes and confirm", func() { + const ( + name = "test-upg-0.2.0" + ) + + chainHeight, err := nt.GetHeight() + Expect(err).ToNot(HaveOccurred()) + + const upgDelta = 5 + upgHeight := chainHeight + upgDelta + + _, success, err := emcli.UpgSchedByHeight(Authority, name, + upgHeight, + ) + Expect(err).ToNot(HaveOccurred()) + Expect(success).To(BeTrue()) + + bz, err := emcli.QueryUpgSched() + Expect(err).ToNot(HaveOccurred()) + + upgPlan := gjson.ParseBytes(bz).Get("plan") + + resName := upgPlan.Get("name").Str + Expect(resName).To(Equal(name)) + resUpgHeight := upgPlan.Get("height").Int() + Expect(resUpgHeight).To(BeEquivalentTo(upgHeight)) + + // wait till the upgrade + newHeight, err := nt.IncChain(upgDelta + 1) + Expect(err).ToNot(HaveOccurred()) + Expect(newHeight > chainHeight+upgDelta).To(BeTrue()) + + // if we made it here, the upgrade succeeded + bz, err = emcli.QueryUpgSched() + Expect(err).ToNot(HaveOccurred()) + + // assert that the upgrade plan zeroed out + upgPlan = gjson.ParseBytes(bz).Get("plan") + + resName = upgPlan.Get("name").Str + Expect(resName).To(HaveLen(0)) + }) + }) +}) diff --git a/x/authority/client/cli/query.go b/x/authority/client/cli/query.go index b31faf9b..6aacfccf 100644 --- a/x/authority/client/cli/query.go +++ b/x/authority/client/cli/query.go @@ -22,6 +22,7 @@ func GetQueryCmd() *cobra.Command { cmd.AddCommand( GetGasPricesCmd(), + GetUpgradePlanCmd(), ) return cmd @@ -50,3 +51,27 @@ func GetGasPricesCmd() *cobra.Command { flags.AddQueryFlagsToCmd(cmd) return cmd } + +func GetUpgradePlanCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "upgrade-plan", + Short: "Query the current upgrade plan", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.UpgradePlan(cmd.Context(), &types.QueryUpgradePlanRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/authority/client/cli/tx.go b/x/authority/client/cli/tx.go index df4a9e27..6022a5b6 100644 --- a/x/authority/client/cli/tx.go +++ b/x/authority/client/cli/tx.go @@ -5,10 +5,15 @@ package cli import ( + "time" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" + upgtypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/e-money/em-ledger/util" "github.com/e-money/em-ledger/x/authority/types" "github.com/spf13/cobra" @@ -26,6 +31,7 @@ func GetTxCmd() *cobra.Command { getCmdDestroyIssuer(), getCmdSetGasPrices(), GetCmdReplaceAuthority(), + GetCmdScheduleUpgrade(), ) return authorityCmds @@ -171,3 +177,88 @@ For a 24-hour grace period the former authority key is equivalent to the new one flags.AddTxFlagsToCmd(cmd) return cmd } + +const ( + UpgHeight = "upgrade-height" + UpgTime = "upgrade-time" + UpgInfo = "upgrade-info" +) + +func GetCmdScheduleUpgrade() *cobra.Command { + var ( + upgHeightVal int64 + upgInfoVal string + ) + + cmd := &cobra.Command{ + Use: "schedule-upgrade [authority_key_or_address] plan_name", + Short: "Schedule a software upgrade", + Example: `emd tx authority schedule-upgrade someplan --upgrade-height 2001 --from emoney1xue7fm6es84jze49grm4slhlmr4ffz8a3u7g3t 0.43 +emd tx authority schedule-upgrade sdk-v0.43.0 --upgrade-height 2001 --from emoney1xue7fm6es84jze49grm4slhlmr4ffz8a3u7g3t --upgrade-info '{"binaries":{"linux/amd64":"http://localhost:8765/test-upg-0.2.0/emd.zip?checksum=sha256:cadd5b52fe90a04e20b2cbb93291b0d1d0204f17b64b2215eb09f5dc78a127f1"}}'`, + Long: `Schedule a software upgrade by submitting a unique plan name that + has not been used before with either an absolute block height or block time. An +upgrade handler should be defined at the upgraded binary. Optionally If you set DAEMON_ALLOW_DOWNLOAD_BINARIES=on pass +the upgraded binary download url with the --upgrade-info flag i.e., --upgrade-info '{"binaries":{"linux/amd64":"http://localhost:8765/test-upg-0.2.0/emd.zip?checksum=sha256:cadd5b52fe90a04e20b2cbb93291b0d1d0204f17b64b2215eb09f5dc78a127f1"}}'`, + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + if err := validateUpgFlags(UpgHeight, upgHeightVal); err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := &types.MsgScheduleUpgrade{ + Authority: clientCtx.GetFromAddress().String(), + Plan: upgtypes.Plan{ + Name: args[1], + Time: time.Unix(0, 0), + Height: upgHeightVal, + Info: upgInfoVal, + }, + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + f := cmd.Flags() + f.Int64VarP(&upgHeightVal, UpgHeight, "n", 0, "Upgrade block height number") + f.StringVarP( + &upgInfoVal, UpgInfo, "i", "", "Upgrade info", + ) + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +func validateUpgFlags(upgHeight string, upgHeightVal int64) error { + if upgHeightVal == 0 { + return sdkerrors.Wrapf( + types.ErrMissingFlag, + "need to specify --%s", upgHeight, + ) + } + + flagsSet := 0 + if upgHeightVal != 0 { + flagsSet++ + } + if flagsSet != 1 { + return sdkerrors.Wrapf( + sdkerrors.ErrInvalidRequest, + "specify only one of the flags: --%s", upgHeight) + } + + return nil +} diff --git a/x/authority/client/cli/tx_test.go b/x/authority/client/cli/tx_replace_test.go similarity index 93% rename from x/authority/client/cli/tx_test.go rename to x/authority/client/cli/tx_replace_test.go index 5c54424e..974209ed 100644 --- a/x/authority/client/cli/tx_test.go +++ b/x/authority/client/cli/tx_replace_test.go @@ -3,11 +3,14 @@ package cli_test import ( "bytes" "fmt" + "sort" + "strings" + bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" "github.com/e-money/em-ledger/x/authority/client/cli" "github.com/e-money/em-ledger/x/authority/types" - "sort" - "strings" + + "testing" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/hd" @@ -20,22 +23,21 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtest "github.com/cosmos/cosmos-sdk/x/auth/client/testutil" "github.com/stretchr/testify/suite" - "testing" ) -type IntegrationTestSuite struct { +type ReplacementTestSuite struct { suite.Suite cfg network.Config network *network.Network } -func (s *IntegrationTestSuite) SetupSuite() { +func (s *ReplacementTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") cfg := network.DefaultConfig() cfg.LegacyAmino.RegisterConcrete(&types.MsgReplaceAuthority{}, "MsgReplaceAuthority", nil) - cfg.InterfaceRegistry.RegisterImplementations((*sdk.Msg)(nil),&types.MsgReplaceAuthority{}) + cfg.InterfaceRegistry.RegisterImplementations((*sdk.Msg)(nil), &types.MsgReplaceAuthority{}) cfg.NumValidators = 2 s.cfg = cfg @@ -59,12 +61,12 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) } -func (s *IntegrationTestSuite) TearDownSuite() { +func (s *ReplacementTestSuite) TearDownSuite() { s.T().Log("tearing down integration test suite") s.network.Cleanup() } -func (s *IntegrationTestSuite) TestReplaceAuth() { +func (s *ReplacementTestSuite) TestReplaceAuth() { val1 := *s.network.Validators[0] // Generate 2 accounts and a multisig. @@ -109,7 +111,7 @@ func (s *IntegrationTestSuite) TestReplaceAuth() { authkeys := []string{acc1UID, acc2UID, acc3UID} multisigThreshold := len(authkeys) - 1 // generate new multisig authority key - for _, keyname := range authkeys{ + for _, keyname := range authkeys { k, err := kb.Key(keyname) s.Require().NoError(err) @@ -130,7 +132,7 @@ func (s *IntegrationTestSuite) TestReplaceAuth() { fmt.Println("New authority multisig key:", newAuthMultiSigAcc.GetAddress().String()) - // set the multisig acount in the state + // set the multisig account in the state sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10) _, err = bankcli.MsgSendExec( val1.ClientCtx, @@ -153,7 +155,7 @@ func (s *IntegrationTestSuite) TestReplaceAuth() { fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), } - multiGeneratedTx, err := sdkcli.ExecTestCLICmd(val1.ClientCtx, cli.GetCmdReplaceAuthority(),args) + multiGeneratedTx, err := sdkcli.ExecTestCLICmd(val1.ClientCtx, cli.GetCmdReplaceAuthority(), args) s.Require().NoError(err) // Save tx to file @@ -208,6 +210,6 @@ func (s *IntegrationTestSuite) TestReplaceAuth() { s.Require().NoError(s.network.WaitForNextBlock()) } -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} \ No newline at end of file +func TestReplacementTestSuite(t *testing.T) { + suite.Run(t, new(ReplacementTestSuite)) +} diff --git a/x/authority/client/cli/tx_upg_test.go b/x/authority/client/cli/tx_upg_test.go new file mode 100644 index 00000000..205b546c --- /dev/null +++ b/x/authority/client/cli/tx_upg_test.go @@ -0,0 +1,172 @@ +package cli_test + +import ( + "fmt" + "strings" + + bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" + "github.com/e-money/em-ledger/x/authority/client/cli" + "github.com/e-money/em-ledger/x/authority/types" + + "testing" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/testutil" + sdkcli "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + authtest "github.com/cosmos/cosmos-sdk/x/auth/client/testutil" + "github.com/stretchr/testify/suite" +) + +type UpgTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network +} + +func (s *UpgTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + cfg.LegacyAmino.RegisterConcrete(&types.MsgScheduleUpgrade{}, "MsgScheduleUpgrade", nil) + cfg.InterfaceRegistry.RegisterImplementations((*sdk.Msg)(nil), &types.MsgScheduleUpgrade{}) + cfg.NumValidators = 2 + + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + kb := s.network.Validators[0].ClientCtx.Keyring + _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + + account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + + account2, _, err := kb.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + + // Create multisig authority key + multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{account1.GetPubKey(), account2.GetPubKey()}) + _, err = kb.SaveMultisig("multi", multi) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *UpgTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *UpgTestSuite) TestScheduleUpgrade() { + val1 := *s.network.Validators[0] + + // Generate 2 accounts and a multisig. + const ( + acc1UID = "newAccount1" + acc2UID = "newAccount2" + msigUID = "multi" + ) + + account1, err := val1.ClientCtx.Keyring.Key(acc1UID) + s.Require().NoError(err) + fmt.Println("acc 1:", account1.GetAddress().String()) + + account2, err := val1.ClientCtx.Keyring.Key(acc2UID) + s.Require().NoError(err) + fmt.Println("acc 2:", account2.GetAddress().String()) + + authMultiSigAcc, err := val1.ClientCtx.Keyring.Key(msigUID) + s.Require().NoError(err) + s.Require().Equal(keyring.TypeMulti, authMultiSigAcc.GetType()) + fmt.Println("multi:", authMultiSigAcc.GetAddress().String()) + + // set the multisig account in the state + sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10) + _, err = bankcli.MsgSendExec( + val1.ClientCtx, + val1.Address, + authMultiSigAcc.GetAddress(), + sdk.NewCoins(sendTokens), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), + ) + + // Generate the unsigned multisig transaction json with the existing authority key. + args := []string{ + authMultiSigAcc.GetAddress().String(), + "test1", + fmt.Sprintf("--%s=100", cli.UpgHeight), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + } + + multiGeneratedTx, err := sdkcli.ExecTestCLICmd(val1.ClientCtx, cli.GetCmdScheduleUpgrade(), args) + s.Require().NoError(err) + + // Save tx to file + multiGeneratedTxFile := testutil.WriteToNewTempFile(s.T(), multiGeneratedTx.String()) + + // Sign with account1 + val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1) + account1Signature, err := authtest.TxSignExec( + val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), + "--multisig", authMultiSigAcc.GetAddress().String(), + ) + s.Require().NoError(err) + + sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String()) + + // Sign with account2 + account2Signature, err := authtest.TxSignExec( + val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), + "--multisig", authMultiSigAcc.GetAddress().String(), + ) + s.Require().NoError(err) + + sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String()) + + // Does not work in offline mode. + _, err = authtest.TxMultiSignExec( + val1.ClientCtx, authMultiSigAcc.GetName(), multiGeneratedTxFile.Name(), + "--offline", sign1File.Name(), sign2File.Name(), + ) + s.Require().EqualError( + err, + "couldn't verify signature: unable to verify single signer signature", + ) + + val1.ClientCtx.Offline = false + multiSigWith2Signatures, err := authtest.TxMultiSignExec( + val1.ClientCtx, authMultiSigAcc.GetName(), multiGeneratedTxFile.Name(), + sign1File.Name(), sign2File.Name(), + ) + s.Require().NoError(err) + + // Write the output to disk + signedTxFile := testutil.WriteToNewTempFile(s.T(), multiSigWith2Signatures.String()) + + _, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) + s.Require().NoError(err) + + val1.ClientCtx.BroadcastMode = flags.BroadcastBlock + _, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) + s.Require().NoError(err) + + s.Require().NoError(s.network.WaitForNextBlock()) +} + +func TestUpgTestSuite(t *testing.T) { + suite.Run(t, new(UpgTestSuite)) +} diff --git a/x/authority/handler.go b/x/authority/handler.go index e86827dd..f39a0f92 100644 --- a/x/authority/handler.go +++ b/x/authority/handler.go @@ -36,6 +36,10 @@ func newHandler(k Keeper) sdk.Handler { res, err := msgServer.ReplaceAuthority(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgScheduleUpgrade: + res, err := msgServer.ScheduleUpgrade(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) } diff --git a/x/authority/keeper/grpc_query.go b/x/authority/keeper/grpc_query.go index fb1823b9..541de1cb 100644 --- a/x/authority/keeper/grpc_query.go +++ b/x/authority/keeper/grpc_query.go @@ -2,6 +2,7 @@ package keeper import ( "context" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/e-money/em-ledger/x/authority/types" "google.golang.org/grpc/codes" @@ -18,3 +19,14 @@ func (k Keeper) GasPrices(c context.Context, req *types.QueryGasPricesRequest) ( gasPrices := k.GetGasPrices(ctx) return &types.QueryGasPricesResponse{MinGasPrices: gasPrices}, nil } + +func (k Keeper) UpgradePlan(c context.Context, req *types.QueryUpgradePlanRequest) (*types.QueryUpgradePlanResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + plan, _ := k.GetUpgradePlan(ctx) + + return &types.QueryUpgradePlanResponse{Plan: plan}, nil +} diff --git a/x/authority/keeper/grpc_query_test.go b/x/authority/keeper/grpc_query_test.go index 4acd1267..4981718f 100644 --- a/x/authority/keeper/grpc_query_test.go +++ b/x/authority/keeper/grpc_query_test.go @@ -3,6 +3,8 @@ package keeper import ( "testing" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/e-money/em-ledger/x/authority/types" @@ -41,3 +43,39 @@ func TestQueryGasPrices(t *testing.T) { }) } } + +func TestQueryUpgradePlan(t *testing.T) { + encConfig := MakeTestEncodingConfig() + ctx, keeper, _, _ := createTestComponentWithEncodingConfig(t, encConfig) + + authority := mustParseAddress("emoney1kt0vh0ttget0xx77g6d3ttnvq2lnxx6vp3uyl0") + keeper.BootstrapAuthority(ctx, authority) + + expPlan := upgradetypes.Plan{ + Name: "expPlan 8", + Height: 1000, + } + _, err := keeper.ScheduleUpgrade(ctx, authority, expPlan) + require.NoError(t, err) + + queryHelper := baseapp.NewQueryServerTestHelper(ctx, encConfig.InterfaceRegistry) + types.RegisterQueryServer(queryHelper, keeper) + queryClient := types.NewQueryClient(queryHelper) + + specs := map[string]struct { + req *types.QueryUpgradePlanRequest + }{ + "all good": { + req: &types.QueryUpgradePlanRequest{}, + }, + "nil param": {}, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + gotRsp, gotErr := queryClient.UpgradePlan(sdk.WrapSDKContext(ctx), spec.req) + require.NoError(t, gotErr) + require.NotNil(t, gotRsp) + assert.Equal(t, expPlan, gotRsp.Plan) + }) + } +} diff --git a/x/authority/keeper/keeper.go b/x/authority/keeper/keeper.go index 1c106066..ba4958f9 100644 --- a/x/authority/keeper/keeper.go +++ b/x/authority/keeper/keeper.go @@ -8,6 +8,8 @@ import ( "errors" "sync" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/cosmos/cosmos-sdk/codec" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/e-money/em-ledger/x/authority/types" @@ -24,22 +26,28 @@ const ( var _ authorityKeeper = Keeper{} type Keeper struct { - cdc codec.BinaryMarshaler - storeKey sdk.StoreKey - ik issuer.Keeper - bankKeeper types.BankKeeper - gpk types.GasPricesKeeper + cdc codec.BinaryMarshaler + storeKey sdk.StoreKey + ik issuer.Keeper + bankKeeper types.BankKeeper + upgradeKeeper types.UpgradeKeeper + gpk types.GasPricesKeeper gasPricesInit *sync.Once } -func NewKeeper(cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, issuerKeeper issuer.Keeper, bankKeeper types.BankKeeper, gasPricesKeeper types.GasPricesKeeper) Keeper { +func NewKeeper( + cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, + issuerKeeper issuer.Keeper, bankKeeper types.BankKeeper, + gasPricesKeeper types.GasPricesKeeper, upgradeKeeper types.UpgradeKeeper, +) Keeper { return Keeper{ - cdc: cdc, - ik: issuerKeeper, - bankKeeper: bankKeeper, - gpk: gasPricesKeeper, - storeKey: storeKey, + cdc: cdc, + ik: issuerKeeper, + bankKeeper: bankKeeper, + gpk: gasPricesKeeper, + storeKey: storeKey, + upgradeKeeper: upgradeKeeper, gasPricesInit: new(sync.Once), } @@ -207,3 +215,22 @@ func (k Keeper) replaceAuthority(ctx sdk.Context, authority, newAuthority sdk.Ac return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil } + +func (k Keeper) ScheduleUpgrade( + ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan, +) (*sdk.Result, error) { + if err := k.ValidateAuthority(ctx, authority); err != nil { + return nil, err + } + + if err := k.upgradeKeeper.ScheduleUpgrade(ctx, plan); err != nil { + return nil, err + } + + return &sdk.Result{Events: ctx.EventManager().ABCIEvents()}, nil +} + +func (k Keeper) GetUpgradePlan(ctx sdk.Context) (plan upgradetypes.Plan, havePlan bool) { + + return k.upgradeKeeper.GetUpgradePlan(ctx) +} diff --git a/x/authority/keeper/keeper_test.go b/x/authority/keeper/keeper_test.go index e75737f8..ac4250df 100644 --- a/x/authority/keeper/keeper_test.go +++ b/x/authority/keeper/keeper_test.go @@ -7,6 +7,10 @@ package keeper import ( "testing" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" + "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" simappparams "github.com/cosmos/cosmos-sdk/simapp/params" @@ -392,6 +396,7 @@ func createTestComponentWithEncodingConfig(t *testing.T, encConfig simappparams. tkeyParams = sdk.NewTransientStoreKey("transient_params") keyIssuer = sdk.NewKVStoreKey(issuer.ModuleName) keyLp = sdk.NewKVStoreKey(liquidityprovider.ModuleName) + keyUpg = sdk.NewKVStoreKey(upgradetypes.StoreKey) blockedAddr = make(map[string]bool) ) @@ -403,6 +408,7 @@ func createTestComponentWithEncodingConfig(t *testing.T, encConfig simappparams. ms.MountStoreWithDB(bankKey, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyIssuer, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyLp, sdk.StoreTypeIAVL, db) + ms.MountStoreWithDB(keyUpg, sdk.StoreTypeIAVL, db) err := ms.LoadLatestVersion() require.NoError(t, err) @@ -422,6 +428,8 @@ func createTestComponentWithEncodingConfig(t *testing.T, encConfig simappparams. ) lpk = liquidityprovider.NewKeeper(encConfig.Marshaler, keyLp, bk) ik = issuer.NewKeeper(encConfig.Marshaler, keyIssuer, lpk, mockInflationKeeper{}) + + upgK = upgradekeeper.NewKeeper(map[int64]bool{}, keyUpg, encConfig.Marshaler, t.TempDir()) ) bk.SetSupply(ctx, banktypes.NewSupply( @@ -431,7 +439,7 @@ func createTestComponentWithEncodingConfig(t *testing.T, encConfig simappparams. ))) gpk := new(mockGasPricesKeeper) - keeper := NewKeeper(encConfig.Marshaler, authKey, ik, bk, gpk) + keeper := NewKeeper(encConfig.Marshaler, authKey, ik, bk, gpk, upgK) return ctx, keeper, ik, gpk } diff --git a/x/authority/keeper/msg_server.go b/x/authority/keeper/msg_server.go index a3a6ebb4..36f11943 100644 --- a/x/authority/keeper/msg_server.go +++ b/x/authority/keeper/msg_server.go @@ -2,6 +2,9 @@ package keeper import ( "context" + "fmt" + + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -15,6 +18,8 @@ type authorityKeeper interface { destroyIssuer(ctx sdk.Context, authority sdk.AccAddress, issuerAddress sdk.AccAddress) (*sdk.Result, error) replaceAuthority(ctx sdk.Context, authority, newAuthority sdk.AccAddress) (*sdk.Result, error) SetGasPrices(ctx sdk.Context, authority sdk.AccAddress, gasprices sdk.DecCoins) (*sdk.Result, error) + ScheduleUpgrade(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) + GetUpgradePlan(ctx sdk.Context) (plan upgradetypes.Plan, havePlan bool) } type msgServer struct { k authorityKeeper @@ -108,3 +113,33 @@ func (m msgServer) ReplaceAuthority(goCtx context.Context, msg *types.MsgReplace return &types.MsgReplaceAuthorityResponse{}, nil } + +func (m msgServer) ScheduleUpgrade( + goCtx context.Context, msg *types.MsgScheduleUpgrade, +) (*types.MsgScheduleUpgradeResponse, error) { + + ctx := sdk.UnwrapSDKContext(goCtx) + + authority, err := sdk.AccAddressFromBech32(msg.Authority) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "authority") + } + + if msg.Plan.Time.Unix() != 0 { + return nil, sdkerrors.Wrap( + types.ErrPlanTimeIsSet, + fmt.Sprintf("Plan time: %s", msg.Plan.Time.String()), + ) + } + + result, err := m.k.ScheduleUpgrade(ctx, authority, msg.Plan) + if err != nil { + return nil, err + } + + for _, e := range result.Events { + ctx.EventManager().EmitEvent(sdk.Event(e)) + } + + return &types.MsgScheduleUpgradeResponse{}, nil +} diff --git a/x/authority/keeper/msg_server_test.go b/x/authority/keeper/msg_server_test.go index 399ec124..b06a8833 100644 --- a/x/authority/keeper/msg_server_test.go +++ b/x/authority/keeper/msg_server_test.go @@ -4,6 +4,9 @@ import ( "context" "errors" "testing" + "time" + + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/e-money/em-ledger/x/authority/types" @@ -284,6 +287,136 @@ func TestSetGasPrices(t *testing.T) { }) } } + +func TestScheduleUpgrade(t *testing.T) { + var ( + authorityAddr = mustParseAddress("emoney1kt0vh0ttget0xx77g6d3ttnvq2lnxx6vp3uyl0") + gotAuthority sdk.AccAddress + gotPlan upgradetypes.Plan + ) + + keeper := authorityKeeperMock{} + svr := NewMsgServerImpl(&keeper) + + specs := map[string]struct { + req *types.MsgScheduleUpgrade + mockFn func(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) + expErr bool + expEvents sdk.Events + }{ + "all good": { + req: &types.MsgScheduleUpgrade{ + Authority: authorityAddr.String(), + Plan: upgradetypes.Plan{ + Name: "plan8", + Height: 100, + Time: time.Unix(0, 0), + }, + }, + mockFn: func(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) { + gotAuthority, gotPlan = authority, plan + return &sdk.Result{ + Events: []abcitypes.Event{{ + Type: "testing", + Attributes: []abcitypes.EventAttribute{{Key: []byte("foo"), Value: []byte("bar")}}, + }}, + }, nil + }, + expEvents: sdk.Events{{ + Type: "testing", + Attributes: []abcitypes.EventAttribute{{Key: []byte("foo"), Value: []byte("bar")}}, + }}, + }, + "authority missing": { + req: &types.MsgScheduleUpgrade{ + Plan: upgradetypes.Plan{ + Name: "test1", + Height: 100, + }, + }, + expErr: true, + }, + "authority invalid": { + req: &types.MsgScheduleUpgrade{ + Authority: "invalid", + Plan: upgradetypes.Plan{ + Name: "test1", + Height: 100, + }, + }, + expErr: true, + }, + "invalid height value": { + req: &types.MsgScheduleUpgrade{ + Authority: authorityAddr.String(), + Plan: upgradetypes.Plan{ + Name: "test1", + Height: -100, + }, + }, + mockFn: func(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) { + return nil, errors.New("testing") + }, + expErr: true, + }, + "missing height": { + req: &types.MsgScheduleUpgrade{ + Authority: authorityAddr.String(), + Plan: upgradetypes.Plan{ + Name: "test1", + }, + }, + mockFn: func(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) { + return nil, errors.New("testing") + }, + expErr: true, + }, + "missing plan name": { + req: &types.MsgScheduleUpgrade{ + Authority: authorityAddr.String(), + Plan: upgradetypes.Plan{ + Height: 1, + }, + }, + mockFn: func(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) { + return nil, errors.New("testing") + }, + expErr: true, + }, + "featuring both time and height": { + req: &types.MsgScheduleUpgrade{ + Authority: authorityAddr.String(), + Plan: upgradetypes.Plan{ + Name: "test1", + Time: time.Now(), + Height: 1, + }, + }, + mockFn: func(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) { + return nil, errors.New("testing") + }, + expErr: true, + }, + } + + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + keeper.scheduleUpgradefn = spec.mockFn + eventManager := sdk.NewEventManager() + ctx := sdk.Context{}.WithContext(context.Background()).WithEventManager(eventManager) + _, gotErr := svr.ScheduleUpgrade(sdk.WrapSDKContext(ctx), spec.req) + if spec.expErr { + require.Error(t, gotErr) + return + } + require.NoError(t, gotErr) + assert.Equal(t, spec.expEvents, eventManager.Events()) + assert.Equal(t, spec.req.Authority, gotAuthority.String()) + assert.Equal(t, spec.req.Plan, gotPlan) + }) + } +} + func TestReplaceAuth(t *testing.T) { var ( authorityAddr = mustParseAddress("emoney1kt0vh0ttget0xx77g6d3ttnvq2lnxx6vp3uyl0") @@ -400,6 +533,9 @@ type authorityKeeperMock struct { destroyIssuerfn func(ctx sdk.Context, authority sdk.AccAddress, issuerAddress sdk.AccAddress) (*sdk.Result, error) SetGasPricesfn func(ctx sdk.Context, authority sdk.AccAddress, gasprices sdk.DecCoins) (*sdk.Result, error) replaceAuthorityfn func(ctx sdk.Context, authority, newAuthority sdk.AccAddress) (*sdk.Result, error) + scheduleUpgradefn func(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) + getUpgradePlanfn func(ctx sdk.Context) (plan upgradetypes.Plan, havePlan bool) + applyUpgradefn func(ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan) (*sdk.Result, error) } func (a authorityKeeperMock) createIssuer(ctx sdk.Context, authority sdk.AccAddress, issuerAddress sdk.AccAddress, denoms []string) (*sdk.Result, error) { @@ -430,3 +566,31 @@ func (a authorityKeeperMock) replaceAuthority(ctx sdk.Context, authority, newAut return a.replaceAuthorityfn(ctx, authority, newAuthority) } + +func (a authorityKeeperMock) ScheduleUpgrade( + ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan, +) (*sdk.Result, error) { + if a.scheduleUpgradefn == nil { + panic("not expected to be called") + } + + return a.scheduleUpgradefn(ctx, authority, plan) +} + +func (a authorityKeeperMock) GetUpgradePlan(ctx sdk.Context) (plan upgradetypes.Plan, havePlan bool) { + if a.getUpgradePlanfn == nil { + panic("not expected to be called") + } + + return a.getUpgradePlanfn(ctx) +} + +func (a authorityKeeperMock) ApplyUpgrade( + ctx sdk.Context, authority sdk.AccAddress, plan upgradetypes.Plan, +) (*sdk.Result, error) { + if a.applyUpgradefn == nil { + panic("not expected to be called") + } + + return a.applyUpgradefn(ctx, authority, plan) +} diff --git a/x/authority/types/codec.go b/x/authority/types/codec.go index b3633d6f..14d21e74 100644 --- a/x/authority/types/codec.go +++ b/x/authority/types/codec.go @@ -26,6 +26,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgDestroyIssuer{}, "e-money/MsgDestroyIssuer", nil) cdc.RegisterConcrete(&MsgSetGasPrices{}, "e-money/MsgSetGasPrices", nil) cdc.RegisterConcrete(&MsgReplaceAuthority{}, "e-money/MsgReplaceAuthority", nil) + cdc.RegisterConcrete(&MsgScheduleUpgrade{}, "e-money/MsgScheduleUpgrade", nil) } func RegisterInterfaces(registry types.InterfaceRegistry) { @@ -34,6 +35,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { &MsgDestroyIssuer{}, &MsgSetGasPrices{}, &MsgReplaceAuthority{}, + &MsgScheduleUpgrade{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/authority/types/errors.go b/x/authority/types/errors.go index 17df36a5..622cc3b6 100644 --- a/x/authority/types/errors.go +++ b/x/authority/types/errors.go @@ -9,11 +9,12 @@ import ( ) var ( - ErrNotAuthority = sdkerrors.Register(ModuleName, 1, "not an authority") - ErrNoDenomsSpecified = sdkerrors.Register(ModuleName, 2, "No denominations specified in authority call") - ErrInvalidDenom = sdkerrors.Register(ModuleName, 3, "Invalid denomination found") - ErrNoAuthorityConfigured = sdkerrors.Register(ModuleName, 4, "No authority configured") - ErrInvalidGasPrices = sdkerrors.Register(ModuleName, 5, "Invalid gas prices") - ErrUnknownDenom = sdkerrors.Register(ModuleName, 6, "Unknown denomination specified") - ErrSameAuthorityConfigured = sdkerrors.Register(ModuleName, 7, "Authority already configured") + ErrNotAuthority = sdkerrors.Register(ModuleName, 1, "not an authority") + ErrNoDenomsSpecified = sdkerrors.Register(ModuleName, 2, "No denominations specified in authority call") + ErrInvalidDenom = sdkerrors.Register(ModuleName, 3, "Invalid denomination found") + ErrNoAuthorityConfigured = sdkerrors.Register(ModuleName, 4, "No authority configured") + ErrInvalidGasPrices = sdkerrors.Register(ModuleName, 5, "Invalid gas prices") + ErrUnknownDenom = sdkerrors.Register(ModuleName, 6, "Unknown denomination specified") + ErrMissingFlag = sdkerrors.Register(ModuleName, 7, "missing flag") + ErrPlanTimeIsSet = sdkerrors.Register(ModuleName, 8, "upgrade plan cannot set time") ) diff --git a/x/authority/types/expected_keepers.go b/x/authority/types/expected_keepers.go index 79c34c7e..cc5103b6 100644 --- a/x/authority/types/expected_keepers.go +++ b/x/authority/types/expected_keepers.go @@ -7,6 +7,7 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/bank/exported" + "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) type ( @@ -17,4 +18,12 @@ type ( BankKeeper interface { GetSupply(ctx sdk.Context) exported.SupplyI } + + UpgradeKeeper interface { + ApplyUpgrade(ctx sdk.Context, plan types.Plan) + GetUpgradePlan(ctx sdk.Context) (plan types.Plan, havePlan bool) + HasHandler(name string) bool + ScheduleUpgrade(ctx sdk.Context, plan types.Plan) error + SetUpgradeHandler(name string, upgradeHandler types.UpgradeHandler) + } ) diff --git a/x/authority/types/msgs.go b/x/authority/types/msgs.go index fe61de93..832942c7 100644 --- a/x/authority/types/msgs.go +++ b/x/authority/types/msgs.go @@ -14,6 +14,7 @@ var ( _ sdk.Msg = &MsgDestroyIssuer{} _ sdk.Msg = &MsgSetGasPrices{} _ sdk.Msg = &MsgReplaceAuthority{} + _ sdk.Msg = &MsgScheduleUpgrade{} ) func (msg MsgDestroyIssuer) Type() string { return "destroy_issuer" } @@ -24,6 +25,8 @@ func (msg MsgSetGasPrices) Type() string { return "set_gas_prices" } func (msg MsgReplaceAuthority) Type() string { return "replace_authority" } +func (msg MsgScheduleUpgrade) Type() string { return "schedule_upgrade" } + func (msg MsgDestroyIssuer) ValidateBasic() error { if _, err := sdk.AccAddressFromBech32(msg.Issuer); err != nil { return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid issuer address (%s)", err) @@ -76,6 +79,18 @@ func (msg MsgReplaceAuthority) ValidateBasic() error { return nil } +func (msg MsgScheduleUpgrade) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid authority address (%s)", err) + } + + if err := msg.Plan.ValidateBasic(); err != nil { + return err + } + + return nil +} + func (msg MsgDestroyIssuer) GetSigners() []sdk.AccAddress { from, err := sdk.AccAddressFromBech32(msg.Authority) if err != nil { @@ -108,6 +123,14 @@ func (msg MsgReplaceAuthority) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{from} } +func (msg MsgScheduleUpgrade) GetSigners() []sdk.AccAddress { + from, err := sdk.AccAddressFromBech32(msg.Authority) + if err != nil { + panic(err) + } + return []sdk.AccAddress{from} +} + func (msg MsgDestroyIssuer) GetSignBytes() []byte { return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) } @@ -124,6 +147,10 @@ func (msg MsgReplaceAuthority) GetSignBytes() []byte { return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) } +func (msg MsgScheduleUpgrade) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) +} + func (msg MsgDestroyIssuer) Route() string { return ModuleName } func (msg MsgCreateIssuer) Route() string { return ModuleName } @@ -131,3 +158,5 @@ func (msg MsgCreateIssuer) Route() string { return ModuleName } func (msg MsgSetGasPrices) Route() string { return ModuleName } func (msg MsgReplaceAuthority) Route() string { return ModuleName } + +func (msg MsgScheduleUpgrade) Route() string { return ModuleName } diff --git a/x/authority/types/query.pb.go b/x/authority/types/query.pb.go index a2c00546..0c7c15e3 100644 --- a/x/authority/types/query.pb.go +++ b/x/authority/types/query.pb.go @@ -8,6 +8,7 @@ import ( fmt "fmt" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" + types1 "github.com/cosmos/cosmos-sdk/x/upgrade/types" _ "github.com/gogo/protobuf/gogoproto" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" @@ -110,39 +111,127 @@ func (m *QueryGasPricesResponse) GetMinGasPrices() github_com_cosmos_cosmos_sdk_ return nil } +type QueryUpgradePlanRequest struct { +} + +func (m *QueryUpgradePlanRequest) Reset() { *m = QueryUpgradePlanRequest{} } +func (m *QueryUpgradePlanRequest) String() string { return proto.CompactTextString(m) } +func (*QueryUpgradePlanRequest) ProtoMessage() {} +func (*QueryUpgradePlanRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_d766145e8bc7b365, []int{2} +} +func (m *QueryUpgradePlanRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUpgradePlanRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUpgradePlanRequest.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 *QueryUpgradePlanRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUpgradePlanRequest.Merge(m, src) +} +func (m *QueryUpgradePlanRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryUpgradePlanRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUpgradePlanRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUpgradePlanRequest proto.InternalMessageInfo + +type QueryUpgradePlanResponse struct { + Plan types1.Plan `protobuf:"bytes,1,opt,name=plan,proto3" json:"plan" yaml:"plan"` +} + +func (m *QueryUpgradePlanResponse) Reset() { *m = QueryUpgradePlanResponse{} } +func (m *QueryUpgradePlanResponse) String() string { return proto.CompactTextString(m) } +func (*QueryUpgradePlanResponse) ProtoMessage() {} +func (*QueryUpgradePlanResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_d766145e8bc7b365, []int{3} +} +func (m *QueryUpgradePlanResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUpgradePlanResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUpgradePlanResponse.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 *QueryUpgradePlanResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUpgradePlanResponse.Merge(m, src) +} +func (m *QueryUpgradePlanResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryUpgradePlanResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUpgradePlanResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUpgradePlanResponse proto.InternalMessageInfo + +func (m *QueryUpgradePlanResponse) GetPlan() types1.Plan { + if m != nil { + return m.Plan + } + return types1.Plan{} +} + func init() { proto.RegisterType((*QueryGasPricesRequest)(nil), "em.authority.v1.QueryGasPricesRequest") proto.RegisterType((*QueryGasPricesResponse)(nil), "em.authority.v1.QueryGasPricesResponse") + proto.RegisterType((*QueryUpgradePlanRequest)(nil), "em.authority.v1.QueryUpgradePlanRequest") + proto.RegisterType((*QueryUpgradePlanResponse)(nil), "em.authority.v1.QueryUpgradePlanResponse") } func init() { proto.RegisterFile("em/authority/v1/query.proto", fileDescriptor_d766145e8bc7b365) } var fileDescriptor_d766145e8bc7b365 = []byte{ - // 379 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0xbf, 0x8b, 0x13, 0x41, - 0x14, 0xc7, 0x77, 0xfc, 0x05, 0xae, 0xa2, 0xb0, 0x18, 0x95, 0x18, 0x76, 0x75, 0x0b, 0x23, 0x48, - 0x66, 0xd8, 0xd8, 0xa5, 0x8c, 0x82, 0x16, 0x16, 0x9a, 0xd2, 0x26, 0xcc, 0x6e, 0x1e, 0x93, 0xc1, - 0xcc, 0xbc, 0xcd, 0xce, 0x6c, 0x70, 0x5b, 0xc1, 0xda, 0x80, 0x8d, 0xa5, 0xb5, 0x9d, 0xff, 0x45, - 0xca, 0x80, 0xcd, 0x55, 0xb9, 0x23, 0xb9, 0xbf, 0xe0, 0xfe, 0x82, 0x23, 0xbb, 0x49, 0x48, 0xc2, - 0xc1, 0x55, 0xbb, 0xf0, 0x79, 0x7c, 0xe7, 0xfb, 0x79, 0xcf, 0x7d, 0x06, 0x8a, 0xf1, 0xdc, 0x0e, - 0x31, 0x93, 0xb6, 0x60, 0x93, 0x88, 0x8d, 0x73, 0xc8, 0x0a, 0x9a, 0x66, 0x68, 0xd1, 0x7b, 0x08, - 0x8a, 0xee, 0x20, 0x9d, 0x44, 0xf5, 0x47, 0x02, 0x05, 0x96, 0x8c, 0xad, 0xff, 0xaa, 0xb1, 0xba, - 0x9f, 0xa0, 0x51, 0x68, 0x58, 0xcc, 0x0d, 0xb0, 0x49, 0x14, 0x83, 0xe5, 0x11, 0x4b, 0x50, 0xea, - 0x0d, 0x6f, 0x08, 0x44, 0x31, 0x02, 0xc6, 0x53, 0xc9, 0xb8, 0xd6, 0x68, 0xb9, 0x95, 0xa8, 0x4d, - 0x45, 0xc3, 0x27, 0x6e, 0xed, 0xf3, 0xfa, 0xcd, 0xf7, 0xdc, 0x7c, 0xca, 0x64, 0x02, 0xa6, 0x07, - 0xe3, 0x1c, 0x8c, 0x0d, 0xff, 0x11, 0xf7, 0xf1, 0x31, 0x31, 0x29, 0x6a, 0x03, 0xde, 0x94, 0xb8, - 0x0f, 0x94, 0xd4, 0x7d, 0xc1, 0x4d, 0x3f, 0x2d, 0xd1, 0x53, 0xf2, 0xfc, 0xe6, 0xab, 0x7b, 0xed, - 0x06, 0xad, 0xba, 0xd0, 0x75, 0x17, 0xba, 0xe9, 0x42, 0xdf, 0x41, 0xf2, 0x16, 0xa5, 0xee, 0x7e, - 0x9c, 0x2d, 0x02, 0xe7, 0x62, 0x11, 0xd4, 0x0a, 0xae, 0x46, 0x9d, 0xf0, 0x30, 0x21, 0xfc, 0x7b, - 0x1a, 0xbc, 0x16, 0xd2, 0x0e, 0xf3, 0x98, 0x26, 0xa8, 0xd8, 0x46, 0xaa, 0xfa, 0xb4, 0xcc, 0xe0, - 0x2b, 0xb3, 0x45, 0x0a, 0x66, 0x1b, 0x66, 0x7a, 0xf7, 0x95, 0xd4, 0xbb, 0x6a, 0x9d, 0x5b, 0xbf, - 0xff, 0x04, 0x4e, 0xfb, 0x27, 0x71, 0x6f, 0x97, 0x9d, 0xbd, 0x1f, 0xc4, 0xbd, 0xbb, 0xa3, 0xde, - 0x4b, 0x7a, 0xb4, 0x4a, 0x7a, 0xa5, 0x73, 0xbd, 0x79, 0xed, 0x5c, 0xb5, 0x81, 0xb0, 0xf9, 0xfd, - 0xff, 0xf9, 0xaf, 0x1b, 0x2f, 0xbc, 0x80, 0x41, 0x4b, 0xa1, 0x86, 0xe2, 0xf0, 0x8a, 0x82, 0x9b, - 0xca, 0xaa, 0xfb, 0x61, 0xb6, 0xf4, 0xc9, 0x7c, 0xe9, 0x93, 0xb3, 0xa5, 0x4f, 0xa6, 0x2b, 0xdf, - 0x99, 0xaf, 0x7c, 0xe7, 0x64, 0xe5, 0x3b, 0x5f, 0xe8, 0x9e, 0xec, 0x36, 0x04, 0x54, 0x6b, 0x04, - 0x03, 0x01, 0x19, 0xfb, 0xb6, 0x17, 0x58, 0x8a, 0xc7, 0x77, 0xca, 0x7b, 0xbd, 0xb9, 0x0c, 0x00, - 0x00, 0xff, 0xff, 0x25, 0x0c, 0xa6, 0x7e, 0x33, 0x02, 0x00, 0x00, + // 478 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x3f, 0x6f, 0xd3, 0x40, + 0x18, 0xc6, 0x7d, 0xa5, 0x20, 0x71, 0x45, 0x20, 0x19, 0x4a, 0x43, 0xa8, 0xec, 0x62, 0x55, 0xb4, + 0x80, 0x72, 0xa7, 0x94, 0xad, 0x63, 0x00, 0xc1, 0xc0, 0x50, 0x22, 0xb1, 0xb0, 0x44, 0x17, 0xe7, + 0xd5, 0xf5, 0x84, 0xef, 0xce, 0xf5, 0x9d, 0x23, 0xbc, 0x22, 0xb1, 0xa2, 0x4a, 0x2c, 0x8c, 0x9d, + 0xd9, 0xf8, 0x16, 0x1d, 0x2b, 0xb1, 0x30, 0x15, 0x94, 0xf0, 0x09, 0xf8, 0x04, 0xc8, 0xf6, 0x39, + 0xa4, 0x6d, 0x24, 0x98, 0x12, 0xeb, 0x79, 0xff, 0xfc, 0x9e, 0xe7, 0x5e, 0x7c, 0x17, 0x24, 0x65, + 0xb9, 0xdd, 0xd7, 0x99, 0xb0, 0x05, 0x1d, 0x77, 0xe9, 0x41, 0x0e, 0x59, 0x41, 0xd2, 0x4c, 0x5b, + 0xed, 0xdf, 0x00, 0x49, 0x66, 0x22, 0x19, 0x77, 0xdb, 0xb7, 0xb8, 0xe6, 0xba, 0xd2, 0x68, 0xf9, + 0xaf, 0x2e, 0x6b, 0x07, 0xb1, 0x36, 0x52, 0x1b, 0x3a, 0x64, 0x06, 0xe8, 0xb8, 0x3b, 0x04, 0xcb, + 0xba, 0x34, 0xd6, 0x42, 0x39, 0x7d, 0x9d, 0x6b, 0xcd, 0x13, 0xa0, 0x2c, 0x15, 0x94, 0x29, 0xa5, + 0x2d, 0xb3, 0x42, 0x2b, 0xe3, 0xd4, 0x4d, 0xd7, 0x9d, 0xa7, 0x3c, 0x63, 0xa3, 0xbf, 0x03, 0xdc, + 0x77, 0x5d, 0x15, 0xad, 0xe1, 0xd5, 0x57, 0x25, 0xd9, 0x73, 0x66, 0xf6, 0x32, 0x11, 0x83, 0xe9, + 0xc3, 0x41, 0x0e, 0xc6, 0x46, 0x5f, 0x11, 0xbe, 0x7d, 0x5e, 0x31, 0xa9, 0x56, 0x06, 0xfc, 0x43, + 0x84, 0xaf, 0x4b, 0xa1, 0x06, 0x9c, 0x99, 0x41, 0x5a, 0x49, 0x2d, 0xb4, 0x71, 0x69, 0x7b, 0x65, + 0x67, 0x9d, 0xd4, 0x3b, 0x49, 0x49, 0x4c, 0xdc, 0x42, 0xf2, 0x14, 0xe2, 0x27, 0x5a, 0xa8, 0xde, + 0xcb, 0xe3, 0xd3, 0xd0, 0xfb, 0x7d, 0x1a, 0xae, 0x16, 0x4c, 0x26, 0xbb, 0xd1, 0xd9, 0x09, 0xd1, + 0x97, 0x1f, 0xe1, 0x23, 0x2e, 0xec, 0x7e, 0x3e, 0x24, 0xb1, 0x96, 0xd4, 0xc1, 0xd7, 0x3f, 0x1d, + 0x33, 0x7a, 0x4b, 0x6d, 0x91, 0x82, 0x69, 0x86, 0x99, 0xfe, 0x35, 0x29, 0xd4, 0x0c, 0x6d, 0x77, + 0xf9, 0xf3, 0x51, 0xe8, 0x45, 0x77, 0xf0, 0x5a, 0x85, 0xfc, 0xba, 0xb6, 0xb8, 0x97, 0x30, 0xd5, + 0xd8, 0x61, 0xb8, 0x75, 0x51, 0x72, 0x7e, 0x9e, 0xe1, 0xe5, 0x34, 0x61, 0xaa, 0x85, 0x36, 0xd0, + 0xbc, 0x89, 0x26, 0xa8, 0xc6, 0x47, 0xd9, 0xd3, 0xbb, 0xe9, 0x4c, 0xac, 0xd4, 0x26, 0xca, 0xbe, + 0xa8, 0x5f, 0xb5, 0xef, 0x1c, 0x2d, 0xe1, 0xcb, 0xd5, 0x0e, 0xff, 0x03, 0xc2, 0x57, 0x67, 0x6c, + 0xfe, 0x7d, 0x72, 0xee, 0xb9, 0xc9, 0xc2, 0xc4, 0xdb, 0x5b, 0xff, 0xac, 0xab, 0x79, 0xa3, 0xad, + 0xf7, 0xdf, 0x7e, 0x7d, 0x5a, 0xba, 0xe7, 0x87, 0x14, 0x3a, 0x52, 0x2b, 0x28, 0xce, 0x5e, 0x1a, + 0x67, 0xa6, 0xce, 0xd4, 0xff, 0x88, 0xf0, 0xca, 0x9c, 0x61, 0x7f, 0x7b, 0xf1, 0x86, 0x8b, 0x71, + 0xb5, 0x1f, 0xfc, 0x47, 0xa5, 0xa3, 0x79, 0x58, 0xd1, 0x6c, 0xfa, 0xd1, 0x62, 0x1a, 0x97, 0xe2, + 0xa0, 0x8c, 0xa8, 0xf7, 0xe2, 0x78, 0x12, 0xa0, 0x93, 0x49, 0x80, 0x7e, 0x4e, 0x02, 0x74, 0x38, + 0x0d, 0xbc, 0x93, 0x69, 0xe0, 0x7d, 0x9f, 0x06, 0xde, 0x1b, 0x32, 0xf7, 0xf6, 0xcd, 0x1c, 0x90, + 0x9d, 0x04, 0x46, 0x1c, 0x32, 0xfa, 0x6e, 0x6e, 0x66, 0x75, 0x07, 0xc3, 0x2b, 0xd5, 0xf9, 0x3e, + 0xfe, 0x13, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x52, 0x20, 0x32, 0x68, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -158,6 +247,7 @@ const _ = grpc.SupportPackageIsVersion4 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type QueryClient interface { GasPrices(ctx context.Context, in *QueryGasPricesRequest, opts ...grpc.CallOption) (*QueryGasPricesResponse, error) + UpgradePlan(ctx context.Context, in *QueryUpgradePlanRequest, opts ...grpc.CallOption) (*QueryUpgradePlanResponse, error) } type queryClient struct { @@ -177,9 +267,19 @@ func (c *queryClient) GasPrices(ctx context.Context, in *QueryGasPricesRequest, return out, nil } +func (c *queryClient) UpgradePlan(ctx context.Context, in *QueryUpgradePlanRequest, opts ...grpc.CallOption) (*QueryUpgradePlanResponse, error) { + out := new(QueryUpgradePlanResponse) + err := c.cc.Invoke(ctx, "/em.authority.v1.Query/UpgradePlan", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { GasPrices(context.Context, *QueryGasPricesRequest) (*QueryGasPricesResponse, error) + UpgradePlan(context.Context, *QueryUpgradePlanRequest) (*QueryUpgradePlanResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -189,6 +289,9 @@ type UnimplementedQueryServer struct { func (*UnimplementedQueryServer) GasPrices(ctx context.Context, req *QueryGasPricesRequest) (*QueryGasPricesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GasPrices not implemented") } +func (*UnimplementedQueryServer) UpgradePlan(ctx context.Context, req *QueryUpgradePlanRequest) (*QueryUpgradePlanResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpgradePlan not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -212,6 +315,24 @@ func _Query_GasPrices_Handler(srv interface{}, ctx context.Context, dec func(int return interceptor(ctx, in, info, handler) } +func _Query_UpgradePlan_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryUpgradePlanRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).UpgradePlan(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/em.authority.v1.Query/UpgradePlan", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).UpgradePlan(ctx, req.(*QueryUpgradePlanRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "em.authority.v1.Query", HandlerType: (*QueryServer)(nil), @@ -220,6 +341,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "GasPrices", Handler: _Query_GasPrices_Handler, }, + { + MethodName: "UpgradePlan", + Handler: _Query_UpgradePlan_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "em/authority/v1/query.proto", @@ -285,6 +410,62 @@ func (m *QueryGasPricesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } +func (m *QueryUpgradePlanRequest) 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 *QueryUpgradePlanRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUpgradePlanRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryUpgradePlanResponse) 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 *QueryUpgradePlanResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUpgradePlanResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Plan.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 @@ -320,6 +501,26 @@ func (m *QueryGasPricesResponse) Size() (n int) { return n } +func (m *QueryUpgradePlanRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryUpgradePlanResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Plan.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -460,6 +661,139 @@ func (m *QueryGasPricesResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryUpgradePlanRequest) 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: QueryUpgradePlanRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUpgradePlanRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryUpgradePlanResponse) 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: QueryUpgradePlanResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUpgradePlanResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Plan", 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 err := m.Plan.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/authority/types/query.pb.gw.go b/x/authority/types/query.pb.gw.go index d0945e5a..56e60801 100644 --- a/x/authority/types/query.pb.gw.go +++ b/x/authority/types/query.pb.gw.go @@ -51,6 +51,24 @@ func local_request_Query_GasPrices_0(ctx context.Context, marshaler runtime.Mars } +func request_Query_UpgradePlan_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUpgradePlanRequest + var metadata runtime.ServerMetadata + + msg, err := client.UpgradePlan(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UpgradePlan_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUpgradePlanRequest + var metadata runtime.ServerMetadata + + msg, err := server.UpgradePlan(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. @@ -80,6 +98,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_UpgradePlan_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_UpgradePlan_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_UpgradePlan_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -141,13 +182,37 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_UpgradePlan_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_UpgradePlan_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_UpgradePlan_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } var ( pattern_Query_GasPrices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"e-money", "authority", "v1", "gasprices"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_UpgradePlan_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"e-money", "authority", "v1", "upgrade_plan"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( forward_Query_GasPrices_0 = runtime.ForwardResponseMessage + + forward_Query_UpgradePlan_0 = runtime.ForwardResponseMessage ) diff --git a/x/authority/types/tx.pb.go b/x/authority/types/tx.pb.go index ada314cd..ac06bf9f 100644 --- a/x/authority/types/tx.pb.go +++ b/x/authority/types/tx.pb.go @@ -8,6 +8,7 @@ import ( fmt "fmt" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" + types1 "github.com/cosmos/cosmos-sdk/x/upgrade/types" _ "github.com/gogo/protobuf/gogoproto" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" @@ -398,6 +399,94 @@ func (m *MsgReplaceAuthorityResponse) GetNewAuthorityAddress() string { return "" } +type MsgScheduleUpgrade struct { + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty" yaml:"authority"` + Plan types1.Plan `protobuf:"bytes,2,opt,name=plan,proto3" json:"plan" yaml:"plan"` +} + +func (m *MsgScheduleUpgrade) Reset() { *m = MsgScheduleUpgrade{} } +func (m *MsgScheduleUpgrade) String() string { return proto.CompactTextString(m) } +func (*MsgScheduleUpgrade) ProtoMessage() {} +func (*MsgScheduleUpgrade) Descriptor() ([]byte, []int) { + return fileDescriptor_1601f633ca5d263c, []int{8} +} +func (m *MsgScheduleUpgrade) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgScheduleUpgrade) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgScheduleUpgrade.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 *MsgScheduleUpgrade) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgScheduleUpgrade.Merge(m, src) +} +func (m *MsgScheduleUpgrade) XXX_Size() int { + return m.Size() +} +func (m *MsgScheduleUpgrade) XXX_DiscardUnknown() { + xxx_messageInfo_MsgScheduleUpgrade.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgScheduleUpgrade proto.InternalMessageInfo + +func (m *MsgScheduleUpgrade) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgScheduleUpgrade) GetPlan() types1.Plan { + if m != nil { + return m.Plan + } + return types1.Plan{} +} + +type MsgScheduleUpgradeResponse struct { +} + +func (m *MsgScheduleUpgradeResponse) Reset() { *m = MsgScheduleUpgradeResponse{} } +func (m *MsgScheduleUpgradeResponse) String() string { return proto.CompactTextString(m) } +func (*MsgScheduleUpgradeResponse) ProtoMessage() {} +func (*MsgScheduleUpgradeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1601f633ca5d263c, []int{9} +} +func (m *MsgScheduleUpgradeResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgScheduleUpgradeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgScheduleUpgradeResponse.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 *MsgScheduleUpgradeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgScheduleUpgradeResponse.Merge(m, src) +} +func (m *MsgScheduleUpgradeResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgScheduleUpgradeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgScheduleUpgradeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgScheduleUpgradeResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgCreateIssuer)(nil), "em.authority.v1.MsgCreateIssuer") proto.RegisterType((*MsgCreateIssuerResponse)(nil), "em.authority.v1.MsgCreateIssuerResponse") @@ -407,48 +496,55 @@ func init() { proto.RegisterType((*MsgSetGasPricesResponse)(nil), "em.authority.v1.MsgSetGasPricesResponse") proto.RegisterType((*MsgReplaceAuthority)(nil), "em.authority.v1.MsgReplaceAuthority") proto.RegisterType((*MsgReplaceAuthorityResponse)(nil), "em.authority.v1.MsgReplaceAuthorityResponse") + proto.RegisterType((*MsgScheduleUpgrade)(nil), "em.authority.v1.MsgScheduleUpgrade") + proto.RegisterType((*MsgScheduleUpgradeResponse)(nil), "em.authority.v1.MsgScheduleUpgradeResponse") } func init() { proto.RegisterFile("em/authority/v1/tx.proto", fileDescriptor_1601f633ca5d263c) } var fileDescriptor_1601f633ca5d263c = []byte{ - // 569 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x54, 0xc1, 0x6e, 0xd3, 0x40, - 0x10, 0x8d, 0x1b, 0xa9, 0x52, 0x97, 0x46, 0x6d, 0xdd, 0x20, 0x8c, 0xa9, 0xec, 0xb0, 0xe2, 0x90, - 0x0a, 0xe2, 0x55, 0xc2, 0x01, 0x09, 0x89, 0x43, 0xd3, 0x4a, 0x94, 0x43, 0x24, 0x64, 0x38, 0x45, - 0x42, 0x91, 0xe3, 0x0c, 0xae, 0x45, 0xec, 0x0d, 0x9e, 0x4d, 0xda, 0xdc, 0x41, 0xe2, 0xc8, 0x6f, - 0xc0, 0x97, 0xf4, 0x82, 0xd4, 0x23, 0x27, 0x83, 0x92, 0x3f, 0xc8, 0x17, 0xa0, 0x7a, 0x13, 0x27, - 0x0e, 0x96, 0x8a, 0x7a, 0xe0, 0x94, 0xc8, 0xef, 0xbd, 0x99, 0x37, 0x3b, 0x6f, 0x97, 0x68, 0x10, - 0x30, 0x67, 0x28, 0xce, 0x78, 0xe4, 0x8b, 0x31, 0x1b, 0xd5, 0x99, 0xb8, 0xb0, 0x06, 0x11, 0x17, - 0x5c, 0xdd, 0x81, 0xc0, 0x4a, 0x11, 0x6b, 0x54, 0xd7, 0xcb, 0x1e, 0xf7, 0x78, 0x82, 0xb1, 0xeb, - 0x7f, 0x92, 0xa6, 0x1b, 0x2e, 0xc7, 0x80, 0x23, 0xeb, 0x3a, 0x08, 0x6c, 0x54, 0xef, 0x82, 0x70, - 0xea, 0xcc, 0xe5, 0x7e, 0x28, 0x71, 0xfa, 0x4d, 0x21, 0x3b, 0x2d, 0xf4, 0x8e, 0x23, 0x70, 0x04, - 0xbc, 0x42, 0x1c, 0x42, 0xa4, 0x36, 0xc8, 0x56, 0x5a, 0x59, 0x53, 0x2a, 0x4a, 0x75, 0xab, 0x59, - 0x9e, 0xc5, 0xe6, 0xee, 0xd8, 0x09, 0xfa, 0xcf, 0x69, 0x0a, 0x51, 0x7b, 0x49, 0x53, 0x0f, 0xc9, - 0xa6, 0x9f, 0xa8, 0xb5, 0x8d, 0x44, 0xb0, 0x37, 0x8b, 0xcd, 0x92, 0x14, 0xc8, 0xef, 0xd4, 0x9e, - 0x13, 0xd4, 0x67, 0xa4, 0xd4, 0x83, 0x90, 0x07, 0x7e, 0xe8, 0x08, 0x9f, 0x87, 0xa8, 0x15, 0x2b, - 0xc5, 0xac, 0x22, 0x81, 0x91, 0xda, 0x59, 0x1e, 0xbd, 0x4f, 0xee, 0xad, 0x59, 0xb5, 0x01, 0x07, - 0x3c, 0x44, 0xa0, 0x1f, 0xc9, 0x6e, 0x0b, 0xbd, 0x13, 0x40, 0x11, 0xf1, 0xf1, 0x7f, 0x19, 0x83, - 0xea, 0x44, 0x5b, 0x6f, 0x99, 0xda, 0xf9, 0x21, 0x4f, 0xf5, 0x0d, 0x88, 0x97, 0x0e, 0xbe, 0x8e, - 0x7c, 0x17, 0xf0, 0x56, 0x76, 0x3e, 0x2b, 0x84, 0x78, 0x0e, 0x76, 0x06, 0x49, 0x09, 0x6d, 0xa3, - 0x52, 0xac, 0xde, 0x69, 0x1c, 0x58, 0x72, 0xa7, 0xd6, 0xf5, 0x4e, 0xad, 0xf9, 0x4e, 0xad, 0x13, - 0x70, 0x8f, 0xb9, 0x1f, 0x36, 0x4f, 0x2f, 0x63, 0xb3, 0x30, 0x8b, 0xcd, 0x3d, 0x59, 0x77, 0xa9, - 0xa6, 0xdf, 0x7f, 0x99, 0x8f, 0x3d, 0x5f, 0x9c, 0x0d, 0xbb, 0x96, 0xcb, 0x03, 0x36, 0x0f, 0x86, - 0xfc, 0xa9, 0x61, 0xef, 0x03, 0x13, 0xe3, 0x01, 0xe0, 0xa2, 0x10, 0xda, 0x5b, 0xde, 0xc2, 0xfb, - 0xfc, 0xe4, 0x57, 0xc7, 0x49, 0x47, 0xfd, 0xa2, 0x90, 0xfd, 0x16, 0x7a, 0x36, 0x0c, 0xfa, 0x8e, - 0x0b, 0x47, 0xa9, 0xf5, 0xdb, 0x8c, 0xfb, 0x82, 0x94, 0x42, 0x38, 0xef, 0x2c, 0x75, 0x72, 0x09, - 0xda, 0x2c, 0x36, 0xcb, 0x52, 0x97, 0x81, 0xa9, 0xbd, 0x1d, 0xc2, 0x79, 0xda, 0x92, 0x22, 0x79, - 0x90, 0xe3, 0x64, 0xe1, 0x54, 0x7d, 0x4b, 0xee, 0x66, 0xe4, 0x1d, 0xa7, 0xd7, 0x8b, 0x00, 0x71, - 0xee, 0xae, 0x32, 0x8b, 0xcd, 0x83, 0x9c, 0x2e, 0x0b, 0x1a, 0xb5, 0xf7, 0x57, 0xbb, 0x1d, 0xc9, - 0xaf, 0x8d, 0x4f, 0x45, 0x52, 0x6c, 0xa1, 0xa7, 0xb6, 0xc9, 0x76, 0xe6, 0x12, 0x55, 0xac, 0xb5, - 0x0b, 0x6a, 0xad, 0x65, 0x57, 0xaf, 0xde, 0xc4, 0x48, 0x9d, 0xbf, 0x23, 0xa5, 0x6c, 0xb4, 0x1f, - 0xe6, 0x49, 0x33, 0x14, 0xfd, 0xf0, 0x46, 0x4a, 0x5a, 0xbe, 0x4d, 0xb6, 0x33, 0x49, 0xcd, 0xb5, - 0xbe, 0xca, 0xc8, 0xb7, 0x9e, 0x17, 0x0f, 0xf5, 0x3d, 0xd9, 0xfd, 0x2b, 0x1a, 0x8f, 0xf2, 0xd4, - 0xeb, 0x2c, 0xfd, 0xc9, 0xbf, 0xb0, 0x16, 0x7d, 0x9a, 0xa7, 0x97, 0x13, 0x43, 0xb9, 0x9a, 0x18, - 0xca, 0xef, 0x89, 0xa1, 0x7c, 0x9d, 0x1a, 0x85, 0xab, 0xa9, 0x51, 0xf8, 0x39, 0x35, 0x0a, 0x6d, - 0x6b, 0x25, 0xf3, 0x50, 0x0b, 0x78, 0x08, 0x63, 0x06, 0x41, 0xad, 0x0f, 0x3d, 0x0f, 0x22, 0x76, - 0xb1, 0xf2, 0xbc, 0x26, 0xf9, 0xef, 0x6e, 0x26, 0x0f, 0xe3, 0xd3, 0x3f, 0x01, 0x00, 0x00, 0xff, - 0xff, 0x3b, 0x36, 0x40, 0x46, 0x7b, 0x05, 0x00, 0x00, + // 656 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4f, 0x4f, 0xd4, 0x4e, + 0x18, 0xde, 0xb2, 0xbf, 0x90, 0x30, 0xb0, 0x01, 0x0a, 0xbf, 0x58, 0x2b, 0x69, 0xd7, 0x91, 0x03, + 0x04, 0x69, 0xb3, 0x78, 0x30, 0x31, 0xf1, 0xc0, 0x82, 0x11, 0x0f, 0x9b, 0x90, 0xaa, 0x17, 0x12, + 0x43, 0x66, 0xdb, 0xd7, 0xd2, 0xd8, 0x76, 0x6a, 0xa7, 0x0b, 0xec, 0x07, 0x30, 0xf1, 0xa6, 0x5f, + 0x43, 0x3f, 0x09, 0x17, 0x13, 0x8e, 0x9e, 0xaa, 0x81, 0x93, 0xd7, 0xfd, 0x04, 0x66, 0x3b, 0x6d, + 0xb7, 0x2d, 0x4d, 0x20, 0x7b, 0xf0, 0xb4, 0xdb, 0x79, 0x9f, 0xe7, 0x7d, 0x9f, 0xf7, 0xdf, 0x0c, + 0x92, 0xc0, 0xd3, 0xc9, 0x20, 0x3a, 0xa1, 0xa1, 0x13, 0x0d, 0xf5, 0xd3, 0x8e, 0x1e, 0x9d, 0x6b, + 0x41, 0x48, 0x23, 0x2a, 0x2e, 0x82, 0xa7, 0xe5, 0x16, 0xed, 0xb4, 0x23, 0xaf, 0xda, 0xd4, 0xa6, + 0x89, 0x4d, 0x1f, 0xff, 0xe3, 0x30, 0x59, 0x31, 0x29, 0xf3, 0x28, 0xd3, 0xfb, 0x84, 0x81, 0x7e, + 0xda, 0xe9, 0x43, 0x44, 0x3a, 0xba, 0x49, 0x1d, 0x3f, 0xb5, 0xaf, 0xa7, 0xf6, 0x41, 0x60, 0x87, + 0xc4, 0x9a, 0x40, 0xd2, 0x6f, 0x8e, 0xc2, 0xdf, 0x04, 0xb4, 0xd8, 0x63, 0xf6, 0x5e, 0x08, 0x24, + 0x82, 0x57, 0x8c, 0x0d, 0x20, 0x14, 0x77, 0xd0, 0x5c, 0x1e, 0x5f, 0x12, 0xda, 0xc2, 0xc6, 0x5c, + 0x77, 0x75, 0x14, 0xab, 0x4b, 0x43, 0xe2, 0xb9, 0xcf, 0x70, 0x6e, 0xc2, 0xc6, 0x04, 0x26, 0x6e, + 0xa2, 0x59, 0x27, 0x61, 0x4b, 0x33, 0x09, 0x61, 0x79, 0x14, 0xab, 0x2d, 0x4e, 0xe0, 0xe7, 0xd8, + 0x48, 0x01, 0xe2, 0x53, 0xd4, 0xb2, 0xc0, 0xa7, 0x9e, 0xe3, 0x93, 0xc8, 0xa1, 0x3e, 0x93, 0x9a, + 0xed, 0x66, 0x99, 0x91, 0x98, 0x19, 0x36, 0xca, 0x38, 0x7c, 0x1f, 0xdd, 0xab, 0x48, 0x35, 0x80, + 0x05, 0xd4, 0x67, 0x80, 0x3f, 0xa2, 0xa5, 0x1e, 0xb3, 0xf7, 0x81, 0x45, 0x21, 0x1d, 0xfe, 0x93, + 0x34, 0xb0, 0x8c, 0xa4, 0x6a, 0xc8, 0x5c, 0xce, 0x0f, 0x5e, 0xd5, 0xd7, 0x10, 0xbd, 0x24, 0xec, + 0x30, 0x74, 0x4c, 0x60, 0x53, 0xc9, 0xf9, 0x24, 0x20, 0x64, 0x13, 0x76, 0x1c, 0x24, 0x2e, 0xa4, + 0x99, 0x76, 0x73, 0x63, 0x7e, 0x67, 0x4d, 0xe3, 0x9d, 0xd5, 0xc6, 0x9d, 0xd7, 0xd2, 0xb6, 0x6a, + 0xfb, 0x60, 0xee, 0x51, 0xc7, 0xef, 0x1e, 0x5c, 0xc4, 0x6a, 0x63, 0x14, 0xab, 0xcb, 0xdc, 0xef, + 0x84, 0x8d, 0xbf, 0xff, 0x52, 0xb7, 0x6c, 0x27, 0x3a, 0x19, 0xf4, 0x35, 0x93, 0x7a, 0x7a, 0x3a, + 0x1e, 0xfc, 0x67, 0x9b, 0x59, 0x1f, 0xf4, 0x68, 0x18, 0x00, 0xcb, 0x1c, 0x31, 0x63, 0xce, 0xce, + 0xb4, 0xa7, 0x95, 0x2f, 0xa6, 0x93, 0xa7, 0xfa, 0x59, 0x40, 0x2b, 0x3d, 0x66, 0x1b, 0x10, 0xb8, + 0xc4, 0x84, 0xdd, 0x5c, 0xfa, 0x34, 0xe9, 0x3e, 0x47, 0x2d, 0x1f, 0xce, 0x8e, 0x27, 0x3c, 0xde, + 0x04, 0x69, 0x14, 0xab, 0xab, 0x9c, 0x57, 0x32, 0x63, 0x63, 0xc1, 0x87, 0xb3, 0x3c, 0x24, 0x66, + 0xe8, 0x41, 0x8d, 0x92, 0x4c, 0xa9, 0xf8, 0x06, 0xfd, 0x5f, 0xa2, 0x1f, 0x13, 0xcb, 0x0a, 0x81, + 0xb1, 0x54, 0x5d, 0x7b, 0x14, 0xab, 0x6b, 0x35, 0x51, 0x32, 0x18, 0x36, 0x56, 0x8a, 0xd1, 0x76, + 0xd3, 0xd3, 0x2f, 0x02, 0x12, 0xc7, 0xb5, 0x31, 0x4f, 0xc0, 0x1a, 0xb8, 0xf0, 0x96, 0x6f, 0xd7, + 0x54, 0xe9, 0xbf, 0x40, 0xff, 0x05, 0x2e, 0xf1, 0x93, 0xac, 0x0b, 0x6d, 0xce, 0x16, 0x36, 0xeb, + 0xf4, 0xa1, 0x4b, 0xfc, 0xee, 0x4a, 0xda, 0xe6, 0x79, 0xee, 0x70, 0xcc, 0xc3, 0x46, 0x42, 0xc7, + 0x6b, 0x48, 0xbe, 0x29, 0x28, 0xab, 0xc2, 0xce, 0x9f, 0x26, 0x6a, 0xf6, 0x98, 0x2d, 0x1e, 0xa1, + 0x85, 0xd2, 0xd2, 0xb7, 0xb5, 0xca, 0xb5, 0xa3, 0x55, 0x76, 0x4d, 0xde, 0xb8, 0x0d, 0x91, 0x57, + 0xfa, 0x1d, 0x6a, 0x95, 0x57, 0xf1, 0x61, 0x1d, 0xb5, 0x04, 0x91, 0x37, 0x6f, 0x85, 0xe4, 0xee, + 0x8f, 0xd0, 0x42, 0x69, 0xb3, 0x6a, 0xa5, 0x17, 0x11, 0xf5, 0xd2, 0xeb, 0xc6, 0x59, 0x7c, 0x8f, + 0x96, 0x6e, 0x8c, 0xf2, 0x7a, 0x1d, 0xbb, 0x8a, 0x92, 0x1f, 0xdf, 0x05, 0x95, 0xc7, 0x31, 0xd1, + 0x62, 0x75, 0x64, 0x1e, 0xd5, 0x8a, 0x2c, 0x83, 0xe4, 0xad, 0x3b, 0x80, 0xb2, 0x20, 0xdd, 0x83, + 0x8b, 0x2b, 0x45, 0xb8, 0xbc, 0x52, 0x84, 0xdf, 0x57, 0x8a, 0xf0, 0xf5, 0x5a, 0x69, 0x5c, 0x5e, + 0x2b, 0x8d, 0x9f, 0xd7, 0x4a, 0xe3, 0x48, 0x2b, 0x5c, 0x04, 0xb0, 0xed, 0x51, 0x1f, 0x86, 0x3a, + 0x78, 0xdb, 0x2e, 0x58, 0x36, 0x84, 0xfa, 0x79, 0xe1, 0x65, 0x4a, 0x2e, 0x85, 0xfe, 0x6c, 0xf2, + 0x5a, 0x3c, 0xf9, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x82, 0x0d, 0xef, 0xdc, 0xb6, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -467,6 +563,7 @@ type MsgClient interface { DestroyIssuer(ctx context.Context, in *MsgDestroyIssuer, opts ...grpc.CallOption) (*MsgDestroyIssuerResponse, error) SetGasPrices(ctx context.Context, in *MsgSetGasPrices, opts ...grpc.CallOption) (*MsgSetGasPricesResponse, error) ReplaceAuthority(ctx context.Context, in *MsgReplaceAuthority, opts ...grpc.CallOption) (*MsgReplaceAuthorityResponse, error) + ScheduleUpgrade(ctx context.Context, in *MsgScheduleUpgrade, opts ...grpc.CallOption) (*MsgScheduleUpgradeResponse, error) } type msgClient struct { @@ -513,12 +610,22 @@ func (c *msgClient) ReplaceAuthority(ctx context.Context, in *MsgReplaceAuthorit return out, nil } +func (c *msgClient) ScheduleUpgrade(ctx context.Context, in *MsgScheduleUpgrade, opts ...grpc.CallOption) (*MsgScheduleUpgradeResponse, error) { + out := new(MsgScheduleUpgradeResponse) + err := c.cc.Invoke(ctx, "/em.authority.v1.Msg/ScheduleUpgrade", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { CreateIssuer(context.Context, *MsgCreateIssuer) (*MsgCreateIssuerResponse, error) DestroyIssuer(context.Context, *MsgDestroyIssuer) (*MsgDestroyIssuerResponse, error) SetGasPrices(context.Context, *MsgSetGasPrices) (*MsgSetGasPricesResponse, error) ReplaceAuthority(context.Context, *MsgReplaceAuthority) (*MsgReplaceAuthorityResponse, error) + ScheduleUpgrade(context.Context, *MsgScheduleUpgrade) (*MsgScheduleUpgradeResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -537,6 +644,9 @@ func (*UnimplementedMsgServer) SetGasPrices(ctx context.Context, req *MsgSetGasP func (*UnimplementedMsgServer) ReplaceAuthority(ctx context.Context, req *MsgReplaceAuthority) (*MsgReplaceAuthorityResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ReplaceAuthority not implemented") } +func (*UnimplementedMsgServer) ScheduleUpgrade(ctx context.Context, req *MsgScheduleUpgrade) (*MsgScheduleUpgradeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ScheduleUpgrade not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -614,6 +724,24 @@ func _Msg_ReplaceAuthority_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _Msg_ScheduleUpgrade_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgScheduleUpgrade) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ScheduleUpgrade(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/em.authority.v1.Msg/ScheduleUpgrade", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ScheduleUpgrade(ctx, req.(*MsgScheduleUpgrade)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "em.authority.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -634,6 +762,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "ReplaceAuthority", Handler: _Msg_ReplaceAuthority_Handler, }, + { + MethodName: "ScheduleUpgrade", + Handler: _Msg_ScheduleUpgrade_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "em/authority/v1/tx.proto", @@ -902,6 +1034,69 @@ func (m *MsgReplaceAuthorityResponse) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } +func (m *MsgScheduleUpgrade) 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 *MsgScheduleUpgrade) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgScheduleUpgrade) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Plan.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgScheduleUpgradeResponse) 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 *MsgScheduleUpgradeResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgScheduleUpgradeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -1029,6 +1224,30 @@ func (m *MsgReplaceAuthorityResponse) Size() (n int) { return n } +func (m *MsgScheduleUpgrade) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Plan.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgScheduleUpgradeResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1757,6 +1976,171 @@ func (m *MsgReplaceAuthorityResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgScheduleUpgrade) 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 ErrIntOverflowTx + } + 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: MsgScheduleUpgrade: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgScheduleUpgrade: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Plan", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Plan.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgScheduleUpgradeResponse) 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 ErrIntOverflowTx + } + 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: MsgScheduleUpgradeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgScheduleUpgradeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0