diff --git a/CHANGELOG.md b/CHANGELOG.md index d77795f8..d632772d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ - (metrics) [#1669] Add performance timing metrics to all Begin/EndBlockers - (community) [#1704] Add module params - (community) [#1706] Add disable inflation upgrade +- (community) [#1745] Enable params update via governance with `MsgUpdateParams` ### Bug Fixes @@ -292,6 +293,7 @@ the [changelog](https://github.com/cosmos/cosmos-sdk/blob/v0.38.4/CHANGELOG.md). - [#257](https://github.com/Kava-Labs/kava/pulls/257) Include scripts to run large-scale simulations remotely using aws-batch +[#1745]: https://github.com/Kava-Labs/kava/pull/1745 [#1707]: https://github.com/Kava-Labs/kava/pull/1707 [#1706]: https://github.com/Kava-Labs/kava/pull/1706 [#1668]: https://github.com/Kava-Labs/kava/pull/1668 diff --git a/app/app.go b/app/app.go index 0e6ddf33..f36b426d 100644 --- a/app/app.go +++ b/app/app.go @@ -251,8 +251,10 @@ var ( ) // Verify app interface at compile time -var _ servertypes.Application = (*App)(nil) -var _ servertypes.ApplicationQueryService = (*App)(nil) +var ( + _ servertypes.Application = (*App)(nil) + _ servertypes.ApplicationQueryService = (*App)(nil) +) // Options bundles several configuration params for an App. type Options struct { @@ -379,6 +381,9 @@ func NewApp( tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) + // Authority for gov proposals, using the x/gov module account address + govAuthorityAddr := authtypes.NewModuleAddress(govtypes.ModuleName) + app := &App{ BaseApp: bApp, legacyAmino: legacyAmino, @@ -485,8 +490,7 @@ func NewApp( appCodec, homePath, app.BaseApp, - // Authority - authtypes.NewModuleAddress(govtypes.ModuleName).String(), + govAuthorityAddr.String(), ) app.evidenceKeeper = *evidencekeeper.NewKeeper( appCodec, @@ -507,8 +511,7 @@ func NewApp( // Create Ethermint keepers app.feeMarketKeeper = feemarketkeeper.NewKeeper( appCodec, - // Authority - authtypes.NewModuleAddress(govtypes.ModuleName), + govAuthorityAddr, keys[feemarkettypes.StoreKey], tkeys[feemarkettypes.TransientKey], feemarketSubspace, @@ -525,8 +528,7 @@ func NewApp( evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper) app.evmKeeper = evmkeeper.NewKeeper( appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], - // Authority - authtypes.NewModuleAddress(govtypes.ModuleName), + govAuthorityAddr, app.accountKeeper, evmBankKeeper, app.stakingKeeper, app.feeMarketKeeper, nil, // precompiled contracts geth.NewEVM, @@ -667,6 +669,7 @@ func NewApp( &app.mintKeeper, &app.kavadistKeeper, app.stakingKeeper, + govAuthorityAddr, ) app.incentiveKeeper = incentivekeeper.NewKeeper( diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 0391fca7..f1e8d197 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -209,6 +209,8 @@ - [kava/community/v1beta1/tx.proto](#kava/community/v1beta1/tx.proto) - [MsgFundCommunityPool](#kava.community.v1beta1.MsgFundCommunityPool) - [MsgFundCommunityPoolResponse](#kava.community.v1beta1.MsgFundCommunityPoolResponse) + - [MsgUpdateParams](#kava.community.v1beta1.MsgUpdateParams) + - [MsgUpdateParamsResponse](#kava.community.v1beta1.MsgUpdateParamsResponse) - [Msg](#kava.community.v1beta1.Msg) @@ -3214,6 +3216,32 @@ MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type. + + + +### MsgUpdateParams +MsgUpdateParams allows an account to update the community module parameters. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authority` | [string](#string) | | authority is the address that controls the module (defaults to x/gov unless overwritten). | +| `params` | [Params](#kava.community.v1beta1.Params) | | params defines the x/community parameters to update. | + + + + + + + + +### MsgUpdateParamsResponse +MsgUpdateParamsResponse defines the Msg/UpdateParams response type. + + + + + @@ -3229,6 +3257,7 @@ Msg defines the community Msg service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | | `FundCommunityPool` | [MsgFundCommunityPool](#kava.community.v1beta1.MsgFundCommunityPool) | [MsgFundCommunityPoolResponse](#kava.community.v1beta1.MsgFundCommunityPoolResponse) | FundCommunityPool defines a method to allow an account to directly fund the community module account. | | +| `UpdateParams` | [MsgUpdateParams](#kava.community.v1beta1.MsgUpdateParams) | [MsgUpdateParamsResponse](#kava.community.v1beta1.MsgUpdateParamsResponse) | UpdateParams defines a method to allow an account to update the community module parameters. | | diff --git a/proto/kava/community/v1beta1/params.proto b/proto/kava/community/v1beta1/params.proto index c09db13f..53c3c118 100644 --- a/proto/kava/community/v1beta1/params.proto +++ b/proto/kava/community/v1beta1/params.proto @@ -9,6 +9,8 @@ option go_package = "github.com/kava-labs/kava/x/community/types"; // Params defines the parameters of the community module. message Params { + option (gogoproto.equal) = true; + // upgrade_time_disable_inflation is the time at which to disable mint and kavadist module inflation. // If set to 0, inflation will be disabled from block 1. google.protobuf.Timestamp upgrade_time_disable_inflation = 1 [ diff --git a/proto/kava/community/v1beta1/tx.proto b/proto/kava/community/v1beta1/tx.proto index 143447e1..6a7f523b 100644 --- a/proto/kava/community/v1beta1/tx.proto +++ b/proto/kava/community/v1beta1/tx.proto @@ -4,6 +4,7 @@ package kava.community.v1beta1; import "cosmos/base/v1beta1/coin.proto"; import "cosmos_proto/cosmos.proto"; import "gogoproto/gogo.proto"; +import "kava/community/v1beta1/params.proto"; option go_package = "github.com/kava-labs/kava/x/community/types"; option (gogoproto.equal_all) = true; @@ -12,6 +13,9 @@ option (gogoproto.equal_all) = true; service Msg { // FundCommunityPool defines a method to allow an account to directly fund the community module account. rpc FundCommunityPool(MsgFundCommunityPool) returns (MsgFundCommunityPoolResponse); + + // UpdateParams defines a method to allow an account to update the community module parameters. + rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); } // MsgFundCommunityPool allows an account to directly fund the community module account. @@ -27,3 +31,17 @@ message MsgFundCommunityPool { // MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type. message MsgFundCommunityPoolResponse {} + +// MsgUpdateParams allows an account to update the community module parameters. +message MsgUpdateParams { + option (gogoproto.goproto_getters) = false; + + // authority is the address that controls the module (defaults to x/gov unless overwritten). + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // params defines the x/community parameters to update. + Params params = 2 [(gogoproto.nullable) = false]; +} + +// MsgUpdateParamsResponse defines the Msg/UpdateParams response type. +message MsgUpdateParamsResponse {} diff --git a/tests/e2e/e2e_community_update_params_test.go b/tests/e2e/e2e_community_update_params_test.go new file mode 100644 index 00000000..5990fe14 --- /dev/null +++ b/tests/e2e/e2e_community_update_params_test.go @@ -0,0 +1,173 @@ +package e2e_test + +import ( + "context" + "encoding/hex" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + + "github.com/kava-labs/kava/tests/e2e/testutil" + "github.com/kava-labs/kava/tests/util" + communitytypes "github.com/kava-labs/kava/x/community/types" +) + +func (suite *IntegrationTestSuite) TestCommunityUpdateParams_NonAuthority() { + // ARRANGE + // setup kava account + funds := ukava(1e5) // .1 KAVA + kavaAcc := suite.Kava.NewFundedAccount("community-non-authority", sdk.NewCoins(funds)) + + gasLimit := int64(2e5) + fee := ukava(200) + + msg := communitytypes.NewMsgUpdateParams( + kavaAcc.SdkAddress, + communitytypes.DefaultParams(), + ) + + // ACT + req := util.KavaMsgRequest{ + Msgs: []sdk.Msg{&msg}, + GasLimit: uint64(gasLimit), + FeeAmount: sdk.NewCoins(fee), + Memo: "this is a failure!", + } + res := kavaAcc.SignAndBroadcastKavaTx(req) + + // ASSERT + _, err := util.WaitForSdkTxCommit(suite.Kava.Tx, res.Result.TxHash, 6*time.Second) + suite.Require().Error(err) + suite.Require().ErrorContains( + err, + govtypes.ErrInvalidSigner.Error(), + "should return with authority check error", + ) +} + +func (suite *IntegrationTestSuite) TestCommunityUpdateParams_Authority() { + // ARRANGE + govParamsRes, err := suite.Kava.Gov.Params(context.Background(), &govv1.QueryParamsRequest{ + ParamsType: govv1.ParamDeposit, + }) + suite.NoError(err) + + // Check initial params + communityParamsResInitial, err := suite.Kava.Community.Params( + context.Background(), + &communitytypes.QueryParamsRequest{}, + ) + suite.Require().NoError(err) + + // setup kava account + // .1 KAVA + min deposit amount for proposal + funds := sdk.NewCoins(ukava(1e5)).Add(govParamsRes.DepositParams.MinDeposit...) + kavaAcc := suite.Kava.NewFundedAccount("community-update-params", funds) + + gasLimit := int64(2e5) + fee := ukava(200) + + upgradeTime := time.Now().Add(24 * time.Hour).UTC() + + // 1. Proposal + updateParamsMsg := communitytypes.NewMsgUpdateParams( + authtypes.NewModuleAddress(govtypes.ModuleName), // authority + communitytypes.NewParams( + upgradeTime, + sdkmath.LegacyNewDec(1111), // stakingRewardsPerSecond + sdkmath.LegacyNewDec(2222), // upgradeTimeSetstakingRewardsPerSecond + ), + ) + + // Make sure we're actually changing the params + suite.NotEqual( + updateParamsMsg.Params, + communityParamsResInitial.Params, + "new params should be different from existing", + ) + + proposalMsg, err := govv1.NewMsgSubmitProposal( + []sdk.Msg{&updateParamsMsg}, + govParamsRes.DepositParams.MinDeposit, + kavaAcc.SdkAddress.String(), + "community-update-params", + ) + suite.NoError(err) + + req := util.KavaMsgRequest{ + Msgs: []sdk.Msg{proposalMsg}, + GasLimit: uint64(gasLimit), + FeeAmount: sdk.NewCoins(fee), + Memo: "this is a proposal please accept me", + } + res := kavaAcc.SignAndBroadcastKavaTx(req) + suite.Require().NoError(res.Err) + + // Wait for proposal to be submitted + txRes, err := util.WaitForSdkTxCommit(suite.Kava.Tx, res.Result.TxHash, 6*time.Second) + suite.Require().NoError(err) + + // Parse tx response to get proposal id + var govRes govv1.MsgSubmitProposalResponse + suite.decodeTxMsgResponse(txRes, &govRes) + + // 2. Vote for proposal from whale account + whale := suite.Kava.GetAccount(testutil.FundedAccountName) + voteMsg := govv1.NewMsgVote( + whale.SdkAddress, + govRes.ProposalId, + govv1.OptionYes, + "", + ) + + voteReq := util.KavaMsgRequest{ + Msgs: []sdk.Msg{voteMsg}, + GasLimit: uint64(gasLimit), + FeeAmount: sdk.NewCoins(fee), + Memo: "voting", + } + voteRes := whale.SignAndBroadcastKavaTx(voteReq) + suite.Require().NoError(voteRes.Err) + + _, err = util.WaitForSdkTxCommit(suite.Kava.Tx, voteRes.Result.TxHash, 6*time.Second) + suite.Require().NoError(err) + + // 3. Wait until proposal passes + suite.Require().Eventually(func() bool { + proposalRes, err := suite.Kava.Gov.Proposal(context.Background(), &govv1.QueryProposalRequest{ + ProposalId: govRes.ProposalId, + }) + suite.NoError(err) + + return proposalRes.Proposal.Status == govv1.StatusPassed + }, 60*time.Second, 1*time.Second) + + // Check parameters are updated + communityParamsRes, err := suite.Kava.Community.Params( + context.Background(), + &communitytypes.QueryParamsRequest{}, + ) + suite.Require().NoError(err) + + suite.Equal(updateParamsMsg.Params, communityParamsRes.Params) +} + +func (suite *IntegrationTestSuite) decodeTxMsgResponse(txRes *sdk.TxResponse, ptr codec.ProtoMarshaler) { + // convert txRes.Data hex string to bytes + txResBytes, err := hex.DecodeString(txRes.Data) + suite.Require().NoError(err) + + // Unmarshal data to TxMsgData + var txMsgData sdk.TxMsgData + suite.Kava.EncodingConfig.Marshaler.MustUnmarshal(txResBytes, &txMsgData) + suite.T().Logf("txData.MsgResponses: %v", txMsgData.MsgResponses) + + // Parse MsgResponse + suite.Kava.EncodingConfig.Marshaler.MustUnmarshal(txMsgData.MsgResponses[0].Value, ptr) + suite.Require().NoError(err) +} diff --git a/tests/e2e/testutil/chain.go b/tests/e2e/testutil/chain.go index 54244100..7a9e5d8f 100644 --- a/tests/e2e/testutil/chain.go +++ b/tests/e2e/testutil/chain.go @@ -14,6 +14,7 @@ import ( txtypes "github.com/cosmos/cosmos-sdk/types/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govv1types "github.com/cosmos/cosmos-sdk/x/gov/types/v1" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/ethereum/go-ethereum" @@ -55,6 +56,7 @@ type Chain struct { Earn earntypes.QueryClient Evm evmtypes.QueryClient Evmutil evmutiltypes.QueryClient + Gov govv1types.QueryClient Tm tmservice.ServiceClient Tx txtypes.ServiceClient Upgrade upgradetypes.QueryClient @@ -91,6 +93,7 @@ func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic chain.Earn = earntypes.NewQueryClient(grpcConn) chain.Evm = evmtypes.NewQueryClient(grpcConn) chain.Evmutil = evmutiltypes.NewQueryClient(grpcConn) + chain.Gov = govv1types.NewQueryClient(grpcConn) chain.Tm = tmservice.NewServiceClient(grpcConn) chain.Tx = txtypes.NewServiceClient(grpcConn) chain.Upgrade = upgradetypes.NewQueryClient(grpcConn) diff --git a/x/community/keeper/keeper.go b/x/community/keeper/keeper.go index f44dc266..e8e5a5a3 100644 --- a/x/community/keeper/keeper.go +++ b/x/community/keeper/keeper.go @@ -25,6 +25,10 @@ type Keeper struct { kavadistKeeper types.KavadistKeeper stakingKeeper types.StakingKeeper + // the address capable of executing a MsgUpdateParams message. Typically, this + // should be the x/gov module account. + authority sdk.AccAddress + legacyCommunityPoolAddress sdk.AccAddress } @@ -40,6 +44,7 @@ func NewKeeper( mk types.MintKeeper, kk types.KavadistKeeper, sk types.StakingKeeper, + authority sdk.AccAddress, ) Keeper { // ensure community module account is set addr := ak.GetModuleAddress(types.ModuleAccountName) @@ -50,6 +55,9 @@ func NewKeeper( if addr == nil { panic("legacy community pool address not found") } + if err := sdk.VerifyAddressFormat(authority); err != nil { + panic(fmt.Sprintf("invalid authority address: %s", err)) + } return Keeper{ key: key, @@ -64,10 +72,16 @@ func NewKeeper( stakingKeeper: sk, moduleAddress: addr, + authority: authority, legacyCommunityPoolAddress: legacyAddr, } } +// GetAuthority returns the x/community module's authority. +func (k Keeper) GetAuthority() sdk.AccAddress { + return k.authority +} + // Logger returns a module-specific logger. func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", "x/"+types.ModuleName) diff --git a/x/community/keeper/keeper_test.go b/x/community/keeper/keeper_test.go index 20916e21..f3d8d7d6 100644 --- a/x/community/keeper/keeper_test.go +++ b/x/community/keeper/keeper_test.go @@ -1,13 +1,18 @@ package keeper_test import ( + "strings" "testing" "time" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/stretchr/testify/suite" + "github.com/kava-labs/kava/x/community/keeper" "github.com/kava-labs/kava/x/community/testutil" "github.com/kava-labs/kava/x/community/types" ) @@ -89,3 +94,95 @@ func (suite *KeeperTestSuite) TestGetAndSetStakingRewardsState() { suite.Equal(validParams, keeper.GetStakingRewardsState(suite.Ctx), "expected fetched state to equal set state") } + +func (suite *KeeperTestSuite) TestGetAuthority_Default() { + suite.Equal( + authtypes.NewModuleAddress(govtypes.ModuleName), + suite.Keeper.GetAuthority(), + "expected fetched authority to equal x/gov address", + ) +} + +func (suite *KeeperTestSuite) TestGetAuthority_Any() { + tests := []struct { + name string + authority sdk.AccAddress + }{ + { + name: "gov", + authority: authtypes.NewModuleAddress(govtypes.ModuleName), + }, + { + name: "random", + authority: sdk.AccAddress("random"), + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + suite.NotPanics(func() { + suite.Keeper = keeper.NewKeeper( + suite.App.AppCodec(), + suite.App.GetKVStoreKey(types.StoreKey), + suite.App.GetAccountKeeper(), + suite.App.GetBankKeeper(), + suite.App.GetCDPKeeper(), + suite.App.GetDistrKeeper(), + suite.App.GetHardKeeper(), + suite.App.GetMintKeeper(), + suite.App.GetKavadistKeeper(), + suite.App.GetStakingKeeper(), + tc.authority, + ) + }) + + suite.Equalf( + tc.authority, + suite.Keeper.GetAuthority(), + "expected fetched authority to equal %s address", + tc.authority, + ) + }) + } +} + +func (suite *KeeperTestSuite) TestNewKeeper_InvalidAuthority() { + tests := []struct { + name string + authority sdk.AccAddress + panicStr string + }{ + { + name: "empty", + authority: sdk.AccAddress{}, + panicStr: "invalid authority address: addresses cannot be empty: unknown address", + }, + { + name: "too long", + authority: sdk.AccAddress(strings.Repeat("a", address.MaxAddrLen+1)), + panicStr: "invalid authority address: address max length is 255, got 256: unknown address", + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + suite.PanicsWithValue( + tc.panicStr, + func() { + suite.Keeper = keeper.NewKeeper( + suite.App.AppCodec(), + suite.App.GetKVStoreKey(types.StoreKey), + suite.App.GetAccountKeeper(), + suite.App.GetBankKeeper(), + suite.App.GetCDPKeeper(), + suite.App.GetDistrKeeper(), + suite.App.GetHardKeeper(), + suite.App.GetMintKeeper(), + suite.App.GetKavadistKeeper(), + suite.App.GetStakingKeeper(), + tc.authority, + ) + }) + }) + } +} diff --git a/x/community/keeper/msg_server.go b/x/community/keeper/msg_server.go index 66e639ec..e3945c96 100644 --- a/x/community/keeper/msg_server.go +++ b/x/community/keeper/msg_server.go @@ -3,7 +3,9 @@ package keeper import ( "context" + "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/kava-labs/kava/x/community/types" ) @@ -47,3 +49,28 @@ func (s msgServer) FundCommunityPool(goCtx context.Context, msg *types.MsgFundCo return &types.MsgFundCommunityPoolResponse{}, nil } + +// UpdateParams handles UpdateParams msgs. +func (s msgServer) UpdateParams( + goCtx context.Context, + msg *types.MsgUpdateParams, +) (*types.MsgUpdateParamsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + if s.keeper.GetAuthority().String() != msg.Authority { + return nil, errors.Wrapf( + govtypes.ErrInvalidSigner, + "invalid authority; expected %s, got %s", + s.keeper.GetAuthority(), + msg.Authority, + ) + } + + if err := msg.Params.Validate(); err != nil { + return nil, errors.Wrap(types.ErrInvalidParams, err.Error()) + } + + s.keeper.SetParams(ctx, msg.Params) + + return &types.MsgUpdateParamsResponse{}, nil +} diff --git a/x/community/keeper/msg_server_test.go b/x/community/keeper/msg_server_test.go index f1df044e..63095161 100644 --- a/x/community/keeper/msg_server_test.go +++ b/x/community/keeper/msg_server_test.go @@ -5,6 +5,8 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/stretchr/testify/suite" "github.com/kava-labs/kava/app" @@ -110,3 +112,59 @@ func (suite *msgServerTestSuite) TestMsgFundCommunityPool() { }) } } + +func (suite *msgServerTestSuite) TestMsgUpdateParams() { + govAddr := authtypes.NewModuleAddress(govtypes.ModuleName) + + testCases := []struct { + name string + msg types.MsgUpdateParams + expectedError error + }{ + { + name: "valid", + msg: types.MsgUpdateParams{ + Authority: govAddr.String(), + Params: types.DefaultParams(), + }, + expectedError: nil, + }, + { + name: "invalid - bad authority", + msg: types.MsgUpdateParams{ + Authority: sdk.AccAddress{1, 2, 3}.String(), + Params: types.DefaultParams(), + }, + expectedError: govtypes.ErrInvalidSigner, + }, + { + name: "invalid - empty authority", + msg: types.MsgUpdateParams{ + Authority: "", + Params: types.DefaultParams(), + }, + expectedError: govtypes.ErrInvalidSigner, + }, + { + name: "invalid - parameters", + msg: types.MsgUpdateParams{ + Authority: govAddr.String(), + Params: types.Params{}, + }, + expectedError: types.ErrInvalidParams, + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + + _, err := suite.msgServer.UpdateParams(sdk.WrapSDKContext(suite.Ctx), &tc.msg) + if tc.expectedError == nil { + suite.NoError(err) + } else { + suite.ErrorIs(err, tc.expectedError) + } + }) + } +} diff --git a/x/community/types/codec.go b/x/community/types/codec.go index a80d6f6a..9c20c18f 100644 --- a/x/community/types/codec.go +++ b/x/community/types/codec.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,7 +13,9 @@ import ( // RegisterLegacyAminoCodec registers all the necessary types and interfaces for the module. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { - cdc.RegisterConcrete(&MsgFundCommunityPool{}, "community/MsgFundCommunityPool", nil) + legacy.RegisterAminoMsg(cdc, &MsgFundCommunityPool{}, "community/MsgFundCommunityPool") + legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "community/MsgUpdateParams") + cdc.RegisterConcrete(&CommunityPoolLendDepositProposal{}, "kava/CommunityPoolLendDepositProposal", nil) cdc.RegisterConcrete(&CommunityPoolLendWithdrawProposal{}, "kava/CommunityPoolLendWithdrawProposal", nil) cdc.RegisterConcrete(&CommunityCDPRepayDebtProposal{}, "kava/CommunityCDPRepayDebtProposal", nil) @@ -24,6 +27,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { func RegisterInterfaces(registry types.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgFundCommunityPool{}, + &MsgUpdateParams{}, ) registry.RegisterImplementations((*govv1beta1.Content)(nil), &CommunityPoolLendDepositProposal{}, diff --git a/x/community/types/errors.go b/x/community/types/errors.go new file mode 100644 index 00000000..64f4b109 --- /dev/null +++ b/x/community/types/errors.go @@ -0,0 +1,5 @@ +package types + +import errorsmod "cosmossdk.io/errors" + +var ErrInvalidParams = errorsmod.Register(ModuleName, 1, "invalid params") diff --git a/x/community/types/msg.go b/x/community/types/msg.go index 16a1fc0e..ff04fb6a 100644 --- a/x/community/types/msg.go +++ b/x/community/types/msg.go @@ -11,6 +11,8 @@ import ( var ( _ sdk.Msg = &MsgFundCommunityPool{} _ legacytx.LegacyMsg = &MsgFundCommunityPool{} + _ sdk.Msg = &MsgUpdateParams{} + _ legacytx.LegacyMsg = &MsgUpdateParams{} ) // NewMsgFundCommunityPool returns a new MsgFundCommunityPool @@ -55,3 +57,46 @@ func (msg MsgFundCommunityPool) GetSigners() []sdk.AccAddress { } return []sdk.AccAddress{depositor} } + +// NewMsgUpdateParams returns a new MsgUpdateParams +func NewMsgUpdateParams(authority sdk.AccAddress, params Params) MsgUpdateParams { + return MsgUpdateParams{ + Authority: authority.String(), + Params: params, + } +} + +// Route return the message type used for routing the message. +func (msg MsgUpdateParams) Route() string { return ModuleName } + +// Type returns a human-readable string for the message, intended for utilization within tags. +func (msg MsgUpdateParams) Type() string { return sdk.MsgTypeURL(&msg) } + +// ValidateBasic does a simple validation check that doesn't require access to any other information. +func (msg MsgUpdateParams) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Authority) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, err.Error()) + } + + if err := msg.Params.Validate(); err != nil { + return errorsmod.Wrap(ErrInvalidParams, err.Error()) + } + + return nil +} + +// GetSignBytes gets the canonical byte representation of the Msg. +func (msg MsgUpdateParams) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign. +func (msg MsgUpdateParams) GetSigners() []sdk.AccAddress { + depositor, err := sdk.AccAddressFromBech32(msg.Authority) + if err != nil { + panic(err) + } + return []sdk.AccAddress{depositor} +} diff --git a/x/community/types/msg_test.go b/x/community/types/msg_test.go index 8a32b874..5629e40f 100644 --- a/x/community/types/msg_test.go +++ b/x/community/types/msg_test.go @@ -7,6 +7,7 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/kava-labs/kava/app" "github.com/kava-labs/kava/x/community/types" ) @@ -74,6 +75,55 @@ func TestFundCommunityPool_ValidateBasic(t *testing.T) { } } +func TestMsgUpdateParams_ValidateBasic(t *testing.T) { + testCases := []struct { + name string + message types.MsgUpdateParams + expectedErr error + }{ + { + name: "valid message", + message: types.NewMsgUpdateParams(app.RandomAddress(), types.DefaultParams()), + expectedErr: nil, + }, + { + name: "invalid - bad authority", + message: types.MsgUpdateParams{ + Authority: "not-an-address", + Params: types.DefaultParams(), + }, + expectedErr: sdkerrors.ErrInvalidAddress, + }, + { + name: "invalid - empty authority", + message: types.MsgUpdateParams{ + Authority: "", + Params: types.DefaultParams(), + }, + expectedErr: sdkerrors.ErrInvalidAddress, + }, + { + name: "invalid - invalid params", + message: types.MsgUpdateParams{ + Authority: app.RandomAddress().String(), + Params: types.Params{}, + }, + expectedErr: types.ErrInvalidParams, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.message.ValidateBasic() + if tc.expectedErr == nil { + require.NoError(t, err) + } else { + require.ErrorIs(t, err, tc.expectedErr) + } + }) + } +} + func TestFundCommunityPool_GetSigners(t *testing.T) { t.Run("valid", func(t *testing.T) { address := app.RandomAddress() @@ -92,3 +142,22 @@ func TestFundCommunityPool_GetSigners(t *testing.T) { }) }) } + +func TestMsgUpdateParams_GetSigners(t *testing.T) { + t.Run("valid", func(t *testing.T) { + address := app.RandomAddress() + signers := types.MsgUpdateParams{ + Authority: address.String(), + }.GetSigners() + require.Len(t, signers, 1) + require.Equal(t, address, signers[0]) + }) + + t.Run("panics when depositor is invalid", func(t *testing.T) { + require.Panics(t, func() { + types.MsgUpdateParams{ + Authority: "not-an-address", + }.GetSigners() + }) + }) +} diff --git a/x/community/types/params.pb.go b/x/community/types/params.pb.go index 8c3052c7..24559641 100644 --- a/x/community/types/params.pb.go +++ b/x/community/types/params.pb.go @@ -90,33 +90,64 @@ func init() { } var fileDescriptor_0a48475520900507 = []byte{ - // 373 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0xc1, 0x4a, 0xc3, 0x30, - 0x18, 0xc7, 0x9b, 0x09, 0x43, 0xeb, 0xad, 0x88, 0xce, 0x0e, 0xda, 0xa1, 0x08, 0x83, 0xb1, 0x84, - 0xe9, 0x1b, 0x8c, 0x79, 0x10, 0x3c, 0x8c, 0xcd, 0x93, 0x97, 0x90, 0xb6, 0x59, 0x16, 0xd6, 0x36, - 0xa5, 0x49, 0xa7, 0x7b, 0x08, 0x61, 0x0f, 0xe3, 0x43, 0xec, 0x38, 0x3c, 0x89, 0x87, 0x29, 0xdb, - 0x23, 0xf8, 0x02, 0xd2, 0xa6, 0x93, 0x09, 0xe2, 0xc1, 0xdb, 0xf7, 0x7d, 0xf9, 0xe7, 0x97, 0xef, - 0x9f, 0xef, 0x33, 0xcf, 0x27, 0x64, 0x4a, 0x90, 0x2f, 0xa2, 0x28, 0x8b, 0xb9, 0x9a, 0xa1, 0x69, - 0xc7, 0xa3, 0x8a, 0x74, 0x50, 0x42, 0x52, 0x12, 0x49, 0x98, 0xa4, 0x42, 0x09, 0xeb, 0x38, 0x17, - 0xc1, 0x6f, 0x11, 0x2c, 0x45, 0xf6, 0xa9, 0x2f, 0x64, 0x24, 0x24, 0x2e, 0x54, 0x48, 0x27, 0xfa, - 0x8a, 0x7d, 0xc4, 0x04, 0x13, 0xba, 0x9e, 0x47, 0x65, 0xd5, 0x65, 0x42, 0xb0, 0x90, 0xa2, 0x22, - 0xf3, 0xb2, 0x11, 0x52, 0x3c, 0xa2, 0x52, 0x91, 0x28, 0xd1, 0x82, 0xb3, 0xcf, 0x8a, 0x59, 0xed, - 0x17, 0x4f, 0x5b, 0xdc, 0x74, 0xb2, 0x84, 0xa5, 0x24, 0xa0, 0x38, 0x57, 0xe1, 0x80, 0x4b, 0xe2, - 0x85, 0x14, 0xf3, 0x78, 0x14, 0x12, 0xc5, 0x45, 0x5c, 0x03, 0x0d, 0xd0, 0x3c, 0xbc, 0xb4, 0xa1, - 0x86, 0xc2, 0x2d, 0x14, 0xde, 0x6d, 0xa1, 0xdd, 0xfd, 0xc5, 0xca, 0x35, 0xe6, 0xef, 0x2e, 0x18, - 0xd4, 0x4b, 0x56, 0x7e, 0xd6, 0xd3, 0xa4, 0x9b, 0x2d, 0xc8, 0x8a, 0x4d, 0x5b, 0x2a, 0x32, 0xe1, - 0x31, 0xc3, 0x29, 0x7d, 0x20, 0x69, 0x20, 0x71, 0x42, 0x53, 0x2c, 0xa9, 0x2f, 0xe2, 0xa0, 0x56, - 0x69, 0x80, 0xe6, 0x41, 0xb7, 0x93, 0xa3, 0xde, 0x56, 0x6e, 0x5d, 0xdb, 0x94, 0xc1, 0x04, 0x72, - 0x81, 0x22, 0xa2, 0xc6, 0xf0, 0x96, 0x32, 0xe2, 0xcf, 0x7a, 0xd4, 0x7f, 0x79, 0x6e, 0x9b, 0xe5, - 0x2f, 0xf4, 0xa8, 0x3f, 0x38, 0x29, 0xa1, 0x03, 0xcd, 0xec, 0xd3, 0x74, 0x58, 0x10, 0xad, 0x27, - 0x60, 0xb6, 0x7e, 0x78, 0x93, 0x54, 0xe1, 0x3f, 0x3a, 0xd8, 0xfb, 0x6f, 0x07, 0x17, 0x3b, 0xae, - 0x87, 0x54, 0x0d, 0x7f, 0xef, 0xa7, 0x7b, 0xbd, 0x58, 0x3b, 0x60, 0xb9, 0x76, 0xc0, 0xc7, 0xda, - 0x01, 0xf3, 0x8d, 0x63, 0x2c, 0x37, 0x8e, 0xf1, 0xba, 0x71, 0x8c, 0xfb, 0x16, 0xe3, 0x6a, 0x9c, - 0x79, 0xf9, 0xec, 0x51, 0xbe, 0x04, 0xed, 0x90, 0x78, 0xb2, 0x88, 0xd0, 0xe3, 0xce, 0xd6, 0xa8, - 0x59, 0x42, 0xa5, 0x57, 0x2d, 0x26, 0x70, 0xf5, 0x15, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x51, 0x6e, - 0xa4, 0x54, 0x02, 0x00, 0x00, + // 386 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0x41, 0x4b, 0xe3, 0x40, + 0x14, 0x80, 0x33, 0xdd, 0xa5, 0xec, 0x66, 0x6f, 0x61, 0xd9, 0xad, 0x29, 0x24, 0x45, 0x11, 0x0a, + 0xa5, 0x33, 0x54, 0x6f, 0x1e, 0x4b, 0x3d, 0x08, 0x1e, 0x4a, 0xeb, 0xc9, 0xcb, 0x30, 0x49, 0xa6, + 0xd3, 0xa1, 0x49, 0x26, 0x64, 0x26, 0xd5, 0xfe, 0x08, 0xa1, 0x3f, 0xc1, 0x1f, 0xe1, 0x8f, 0xe8, + 0xb1, 0x78, 0x12, 0x0f, 0x55, 0xda, 0x8b, 0x7f, 0xc1, 0x9b, 0x24, 0x93, 0x4a, 0x05, 0xf1, 0xe0, + 0xed, 0xbd, 0x97, 0x2f, 0xdf, 0xbc, 0x37, 0xf3, 0xcc, 0x83, 0x09, 0x99, 0x12, 0xe4, 0x8b, 0x28, + 0xca, 0x62, 0xae, 0x66, 0x68, 0xda, 0xf1, 0xa8, 0x22, 0x1d, 0x94, 0x90, 0x94, 0x44, 0x12, 0x26, + 0xa9, 0x50, 0xc2, 0xfa, 0x97, 0x43, 0xf0, 0x1d, 0x82, 0x25, 0x64, 0xef, 0xf9, 0x42, 0x46, 0x42, + 0xe2, 0x82, 0x42, 0x3a, 0xd1, 0xbf, 0xd8, 0x7f, 0x99, 0x60, 0x42, 0xd7, 0xf3, 0xa8, 0xac, 0xba, + 0x4c, 0x08, 0x16, 0x52, 0x54, 0x64, 0x5e, 0x36, 0x42, 0x8a, 0x47, 0x54, 0x2a, 0x12, 0x25, 0x1a, + 0xd8, 0x7f, 0xad, 0x98, 0xd5, 0x7e, 0x71, 0xb4, 0xc5, 0x4d, 0x27, 0x4b, 0x58, 0x4a, 0x02, 0x8a, + 0x73, 0x0a, 0x07, 0x5c, 0x12, 0x2f, 0xa4, 0x98, 0xc7, 0xa3, 0x90, 0x28, 0x2e, 0xe2, 0x1a, 0x68, + 0x80, 0xe6, 0x9f, 0x23, 0x1b, 0x6a, 0x29, 0xdc, 0x4a, 0xe1, 0xc5, 0x56, 0xda, 0xfd, 0xb5, 0x58, + 0xb9, 0xc6, 0xfc, 0xc9, 0x05, 0x83, 0x7a, 0xe9, 0xca, 0xbf, 0xf5, 0xb4, 0xe9, 0x6c, 0x2b, 0xb2, + 0x62, 0xd3, 0x96, 0x8a, 0x4c, 0x78, 0xcc, 0x70, 0x4a, 0xaf, 0x48, 0x1a, 0x48, 0x9c, 0xd0, 0x14, + 0x4b, 0xea, 0x8b, 0x38, 0xa8, 0x55, 0x1a, 0xa0, 0xf9, 0xbb, 0xdb, 0xc9, 0x55, 0x8f, 0x2b, 0xb7, + 0xae, 0xc7, 0x94, 0xc1, 0x04, 0x72, 0x81, 0x22, 0xa2, 0xc6, 0xf0, 0x9c, 0x32, 0xe2, 0xcf, 0x7a, + 0xd4, 0xbf, 0xbf, 0x6b, 0x9b, 0xe5, 0x2d, 0xf4, 0xa8, 0x3f, 0xf8, 0x5f, 0x4a, 0x07, 0xda, 0xd9, + 0xa7, 0xe9, 0xb0, 0x30, 0x5a, 0x37, 0xc0, 0x6c, 0x7d, 0x98, 0x4d, 0x52, 0x85, 0xbf, 0xe8, 0xe0, + 0xc7, 0x77, 0x3b, 0x38, 0xdc, 0x99, 0x7a, 0x48, 0xd5, 0xf0, 0xf3, 0x7e, 0x4e, 0x7e, 0xbe, 0xdc, + 0xba, 0xa0, 0x7b, 0xba, 0x58, 0x3b, 0x60, 0xb9, 0x76, 0xc0, 0xf3, 0xda, 0x01, 0xf3, 0x8d, 0x63, + 0x2c, 0x37, 0x8e, 0xf1, 0xb0, 0x71, 0x8c, 0xcb, 0x16, 0xe3, 0x6a, 0x9c, 0x79, 0xf9, 0x06, 0xa0, + 0x7c, 0x15, 0xda, 0x21, 0xf1, 0x64, 0x11, 0xa1, 0xeb, 0x9d, 0xdd, 0x51, 0xb3, 0x84, 0x4a, 0xaf, + 0x5a, 0xbc, 0xc3, 0xf1, 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x19, 0x03, 0x78, 0xe5, 0x5a, 0x02, + 0x00, 0x00, } +func (this *Params) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Params) + if !ok { + that2, ok := that.(Params) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.UpgradeTimeDisableInflation.Equal(that1.UpgradeTimeDisableInflation) { + return false + } + if !this.StakingRewardsPerSecond.Equal(that1.StakingRewardsPerSecond) { + return false + } + if !this.UpgradeTimeSetStakingRewardsPerSecond.Equal(that1.UpgradeTimeSetStakingRewardsPerSecond) { + return false + } + return true +} func (m *Params) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) diff --git a/x/community/types/tx.pb.go b/x/community/types/tx.pb.go index 7cccf175..ac4b1b26 100644 --- a/x/community/types/tx.pb.go +++ b/x/community/types/tx.pb.go @@ -107,37 +107,123 @@ func (m *MsgFundCommunityPoolResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgFundCommunityPoolResponse proto.InternalMessageInfo +// MsgUpdateParams allows an account to update the community module parameters. +type MsgUpdateParams struct { + // authority is the address that controls the module (defaults to x/gov unless overwritten). + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // params defines the x/community parameters to update. + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` +} + +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_e81067e0fbdaca18, []int{2} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.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 *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +// MsgUpdateParamsResponse defines the Msg/UpdateParams response type. +type MsgUpdateParamsResponse struct { +} + +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_e81067e0fbdaca18, []int{3} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.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 *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgFundCommunityPool)(nil), "kava.community.v1beta1.MsgFundCommunityPool") proto.RegisterType((*MsgFundCommunityPoolResponse)(nil), "kava.community.v1beta1.MsgFundCommunityPoolResponse") + proto.RegisterType((*MsgUpdateParams)(nil), "kava.community.v1beta1.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "kava.community.v1beta1.MsgUpdateParamsResponse") } func init() { proto.RegisterFile("kava/community/v1beta1/tx.proto", fileDescriptor_e81067e0fbdaca18) } var fileDescriptor_e81067e0fbdaca18 = []byte{ - // 348 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0x4e, 0x2c, 0x4b, - 0xd4, 0x4f, 0xce, 0xcf, 0xcd, 0x2d, 0xcd, 0xcb, 0x2c, 0xa9, 0xd4, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, - 0x49, 0x34, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x03, 0x29, 0xd0, - 0x83, 0x2b, 0xd0, 0x83, 0x2a, 0x90, 0x92, 0x4b, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0xd6, 0x4f, 0x4a, - 0x2c, 0x4e, 0x85, 0xeb, 0x4a, 0xce, 0xcf, 0xcc, 0x83, 0xe8, 0x93, 0x92, 0x84, 0xc8, 0xc7, 0x83, - 0x79, 0xfa, 0x10, 0x0e, 0x54, 0x4a, 0x24, 0x3d, 0x3f, 0x3d, 0x1f, 0x22, 0x0e, 0x62, 0x41, 0x44, - 0x95, 0x76, 0x32, 0x72, 0x89, 0xf8, 0x16, 0xa7, 0xbb, 0x95, 0xe6, 0xa5, 0x38, 0xc3, 0x6c, 0x0b, - 0xc8, 0xcf, 0xcf, 0x11, 0x4a, 0xe6, 0x62, 0x4b, 0xcc, 0xcd, 0x2f, 0xcd, 0x2b, 0x91, 0x60, 0x54, - 0x60, 0xd6, 0xe0, 0x36, 0x92, 0xd4, 0x83, 0x9a, 0x06, 0xb2, 0x1a, 0xe6, 0x1e, 0x3d, 0xe7, 0xfc, - 0xcc, 0x3c, 0x27, 0x83, 0x13, 0xf7, 0xe4, 0x19, 0x56, 0xdd, 0x97, 0xd7, 0x48, 0xcf, 0x2c, 0xc9, - 0x28, 0x4d, 0x02, 0x39, 0x1b, 0x6a, 0x35, 0x94, 0xd2, 0x2d, 0x4e, 0xc9, 0xd6, 0x2f, 0xa9, 0x2c, - 0x48, 0x2d, 0x06, 0x6b, 0x28, 0x0e, 0x82, 0x1a, 0x2d, 0x64, 0xc6, 0xc5, 0x99, 0x92, 0x5a, 0x90, - 0x5f, 0x9c, 0x59, 0x92, 0x5f, 0x24, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0xe9, 0x24, 0x71, 0x69, 0x8b, - 0xae, 0x08, 0xd4, 0x2a, 0xc7, 0x94, 0x94, 0xa2, 0xd4, 0xe2, 0xe2, 0xe0, 0x92, 0xa2, 0xcc, 0xbc, - 0xf4, 0x20, 0x84, 0x52, 0x2b, 0x96, 0x8e, 0x05, 0xf2, 0x0c, 0x4a, 0x72, 0x5c, 0x32, 0xd8, 0x9c, - 0x1e, 0x94, 0x5a, 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0x6a, 0x54, 0xc7, 0xc5, 0xec, 0x5b, 0x9c, 0x2e, - 0x54, 0xce, 0x25, 0x88, 0xe9, 0x3d, 0x1d, 0x3d, 0xec, 0x21, 0xac, 0x87, 0xcd, 0x44, 0x29, 0x13, - 0x52, 0x54, 0xc3, 0xec, 0x77, 0xf2, 0x5c, 0xf1, 0x48, 0x8e, 0xf1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, - 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, - 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xb4, 0x91, 0x42, 0x0b, 0x64, 0xba, 0x6e, 0x4e, 0x62, 0x52, 0x31, - 0x98, 0xa5, 0x5f, 0x81, 0x94, 0x34, 0xc0, 0xc1, 0x96, 0xc4, 0x06, 0x8e, 0x2d, 0x63, 0x40, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xc2, 0xe0, 0xfc, 0x03, 0x39, 0x02, 0x00, 0x00, + // 446 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xcd, 0xaa, 0xd3, 0x40, + 0x14, 0xc7, 0x33, 0xde, 0x4b, 0xe1, 0xce, 0x15, 0xc4, 0x50, 0x34, 0x0d, 0x32, 0xb9, 0xd4, 0x85, + 0x05, 0x6d, 0xc6, 0x5b, 0xc5, 0x85, 0xb8, 0x31, 0x05, 0xc1, 0x45, 0xa1, 0x44, 0xdc, 0xb8, 0x91, + 0x49, 0x32, 0xa4, 0xa1, 0x4d, 0x4e, 0xc8, 0x4c, 0x6a, 0xfb, 0x06, 0x6e, 0x04, 0x1f, 0xc1, 0xa5, + 0xb8, 0x76, 0xe3, 0x1b, 0x74, 0x59, 0x5c, 0xb9, 0x52, 0x49, 0x37, 0x3e, 0x86, 0x24, 0x99, 0xd4, + 0xaa, 0xad, 0x1f, 0xab, 0xf9, 0xfa, 0x9f, 0xf3, 0xff, 0x9d, 0x33, 0x07, 0x5b, 0x53, 0x36, 0x67, + 0xd4, 0x87, 0x38, 0xce, 0x93, 0x48, 0x2e, 0xe9, 0xfc, 0xdc, 0xe3, 0x92, 0x9d, 0x53, 0xb9, 0xb0, + 0xd3, 0x0c, 0x24, 0xe8, 0x57, 0x4a, 0x81, 0xbd, 0x15, 0xd8, 0x4a, 0x60, 0x12, 0x1f, 0x44, 0x0c, + 0x82, 0x7a, 0x4c, 0xf0, 0x6d, 0x94, 0x0f, 0x51, 0x52, 0xc7, 0x99, 0x9d, 0xfa, 0xfd, 0x79, 0x75, + 0xa2, 0xf5, 0x41, 0x3d, 0xb5, 0x43, 0x08, 0xa1, 0xbe, 0x2f, 0x77, 0xea, 0xf6, 0xfa, 0x01, 0x92, + 0x94, 0x65, 0x2c, 0x56, 0xa1, 0xdd, 0x0f, 0x08, 0xb7, 0x47, 0x22, 0x7c, 0x94, 0x27, 0xc1, 0xb0, + 0x51, 0x8e, 0x01, 0x66, 0xba, 0x8f, 0x5b, 0x2c, 0x86, 0x3c, 0x91, 0x06, 0x3a, 0x3b, 0xea, 0x9d, + 0x0e, 0x3a, 0xb6, 0xb2, 0x2c, 0xf9, 0x1a, 0x68, 0x7b, 0x08, 0x51, 0xe2, 0xdc, 0x5e, 0x7d, 0xb6, + 0xb4, 0x77, 0x5f, 0xac, 0x5e, 0x18, 0xc9, 0x49, 0xee, 0x95, 0xb5, 0x29, 0x3e, 0xb5, 0xf4, 0x45, + 0x30, 0xa5, 0x72, 0x99, 0x72, 0x51, 0x05, 0x08, 0x57, 0xa5, 0xd6, 0xef, 0xe1, 0x93, 0x80, 0xa7, + 0x20, 0x22, 0x09, 0x99, 0x71, 0xe1, 0x0c, 0xf5, 0x4e, 0x1c, 0xe3, 0xe3, 0xfb, 0x7e, 0x5b, 0x59, + 0x3d, 0x0c, 0x82, 0x8c, 0x0b, 0xf1, 0x44, 0x66, 0x51, 0x12, 0xba, 0x3f, 0xa4, 0xf7, 0x8f, 0x5f, + 0xbe, 0xb1, 0xb4, 0x2e, 0xc1, 0xd7, 0xf6, 0xa1, 0xbb, 0x5c, 0xa4, 0x90, 0x08, 0xde, 0x7d, 0x85, + 0xf0, 0xa5, 0x91, 0x08, 0x9f, 0xa6, 0x01, 0x93, 0x7c, 0x5c, 0x55, 0x5d, 0x3a, 0xb2, 0x5c, 0x4e, + 0x20, 0x8b, 0xe4, 0xd2, 0x40, 0x7f, 0x73, 0xdc, 0x4a, 0xf5, 0x07, 0xb8, 0x55, 0xf7, 0xad, 0xc2, + 0x3c, 0x1d, 0x10, 0x7b, 0xff, 0x37, 0xda, 0xb5, 0x8f, 0x73, 0x5c, 0xf6, 0xc4, 0x55, 0x31, 0x8a, + 0xb7, 0x83, 0xaf, 0xfe, 0x82, 0xd3, 0xa0, 0x0e, 0xbe, 0x21, 0x7c, 0x34, 0x12, 0xa1, 0xfe, 0x02, + 0x5f, 0xfe, 0xfd, 0x2b, 0x6e, 0x1d, 0xf2, 0xda, 0x57, 0xbd, 0x79, 0xf7, 0x7f, 0xd4, 0x0d, 0x80, + 0x3e, 0xc1, 0x17, 0x7f, 0xea, 0xd3, 0x8d, 0x3f, 0x64, 0xd9, 0x15, 0x9a, 0xf4, 0x1f, 0x85, 0x8d, + 0x93, 0xf3, 0xf8, 0x6d, 0x41, 0xd0, 0xaa, 0x20, 0x68, 0x5d, 0x10, 0xf4, 0xb5, 0x20, 0xe8, 0xf5, + 0x86, 0x68, 0xeb, 0x0d, 0xd1, 0x3e, 0x6d, 0x88, 0xf6, 0xec, 0xe6, 0xce, 0x0c, 0x95, 0x89, 0xfb, + 0x33, 0xe6, 0x89, 0x6a, 0x47, 0x17, 0x3b, 0xb3, 0x5c, 0x0d, 0x93, 0xd7, 0xaa, 0x66, 0xf8, 0xce, + 0xf7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x3a, 0x80, 0xec, 0x74, 0x03, 0x00, 0x00, } func (this *MsgFundCommunityPool) Equal(that interface{}) bool { @@ -193,6 +279,54 @@ func (this *MsgFundCommunityPoolResponse) Equal(that interface{}) bool { } return true } +func (this *MsgUpdateParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*MsgUpdateParams) + if !ok { + that2, ok := that.(MsgUpdateParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Authority != that1.Authority { + return false + } + if !this.Params.Equal(&that1.Params) { + return false + } + return true +} +func (this *MsgUpdateParamsResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*MsgUpdateParamsResponse) + if !ok { + that2, ok := that.(MsgUpdateParamsResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} // Reference imports to suppress errors if they are not otherwise used. var _ context.Context @@ -208,6 +342,8 @@ const _ = grpc.SupportPackageIsVersion4 type MsgClient interface { // FundCommunityPool defines a method to allow an account to directly fund the community module account. FundCommunityPool(ctx context.Context, in *MsgFundCommunityPool, opts ...grpc.CallOption) (*MsgFundCommunityPoolResponse, error) + // UpdateParams defines a method to allow an account to update the community module parameters. + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) } type msgClient struct { @@ -227,10 +363,21 @@ func (c *msgClient) FundCommunityPool(ctx context.Context, in *MsgFundCommunityP return out, nil } +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/kava.community.v1beta1.Msg/UpdateParams", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // FundCommunityPool defines a method to allow an account to directly fund the community module account. FundCommunityPool(context.Context, *MsgFundCommunityPool) (*MsgFundCommunityPoolResponse, error) + // UpdateParams defines a method to allow an account to update the community module parameters. + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -240,6 +387,9 @@ type UnimplementedMsgServer struct { func (*UnimplementedMsgServer) FundCommunityPool(ctx context.Context, req *MsgFundCommunityPool) (*MsgFundCommunityPoolResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method FundCommunityPool not implemented") } +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -263,6 +413,24 @@ func _Msg_FundCommunityPool_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/kava.community.v1beta1.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "kava.community.v1beta1.Msg", HandlerType: (*MsgServer)(nil), @@ -271,6 +439,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "FundCommunityPool", Handler: _Msg_FundCommunityPool_Handler, }, + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "kava/community/v1beta1/tx.proto", @@ -343,6 +515,69 @@ func (m *MsgFundCommunityPoolResponse) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } +func (m *MsgUpdateParams) 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 *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.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 *MsgUpdateParamsResponse) 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 *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) 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 @@ -382,6 +617,30 @@ func (m *MsgFundCommunityPoolResponse) Size() (n int) { return n } +func (m *MsgUpdateParams) 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.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) 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 } @@ -554,6 +813,171 @@ func (m *MsgFundCommunityPoolResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgUpdateParams) 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: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: 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 Params", 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.Params.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 *MsgUpdateParamsResponse) 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: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: 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