From b13eeef8571cda181cbb8efbcb8d75c337dbcdac Mon Sep 17 00:00:00 2001 From: Marius Poke Date: Mon, 8 May 2023 12:08:59 +0200 Subject: [PATCH] Merge pull request from GHSA-chqw-ff63-95r8 * squash commit of multisig fix + everything involving denom fix * fixes * proto gen * remove param boilerplate --------- Co-authored-by: Shawn <44221603+smarshall-spitzbart@users.noreply.github.com> --- app/provider/app.go | 28 +- .../ccv/consumer/v1/consumer.proto | 7 + .../ccv/provider/v1/provider.proto | 1 + .../ccv/provider/v1/query.proto | 12 + .../ccv/provider/v1/tx.proto | 24 +- tests/difference/core/driver/setup.go | 2 + tests/e2e/distribution.go | 99 +++- tests/integration/actions.go | 30 ++ tests/integration/config.go | 23 +- tests/integration/main.go | 5 +- tests/integration/state.go | 50 +- tests/integration/steps.go | 8 + tests/integration/steps_democracy.go | 41 ++ tests/integration/steps_reward_denom.go | 281 ++++++++++ testutil/e2e/interfaces.go | 5 + testutil/keeper/mocks.go | 51 ++ testutil/keeper/unit_test_helpers.go | 31 +- x/ccv/consumer/keeper/distribution.go | 69 ++- x/ccv/consumer/keeper/distribution_test.go | 23 + x/ccv/consumer/keeper/params.go | 14 + x/ccv/consumer/keeper/params_test.go | 6 +- x/ccv/consumer/types/consumer.pb.go | 207 ++++++-- x/ccv/consumer/types/genesis_test.go | 4 + x/ccv/consumer/types/params.go | 43 +- x/ccv/consumer/types/params_test.go | 26 +- x/ccv/provider/client/cli/query.go | 36 ++ x/ccv/provider/client/cli/tx.go | 48 +- x/ccv/provider/handler.go | 3 + x/ccv/provider/handler_test.go | 32 +- x/ccv/provider/ibc_module.go | 2 +- x/ccv/provider/ibc_module_test.go | 4 +- x/ccv/provider/keeper/distribution.go | 75 ++- x/ccv/provider/keeper/genesis_test.go | 2 + x/ccv/provider/keeper/grpc_query.go | 14 + x/ccv/provider/keeper/keeper.go | 57 +- x/ccv/provider/keeper/msg_server.go | 75 ++- x/ccv/provider/keeper/params.go | 7 + x/ccv/provider/keeper/params_test.go | 5 +- x/ccv/provider/keeper/proposal.go | 3 + x/ccv/provider/keeper/proposal_test.go | 25 +- x/ccv/provider/module.go | 2 + x/ccv/provider/module_test.go | 4 +- x/ccv/provider/proposal_handler_test.go | 10 +- x/ccv/provider/types/codec.go | 5 + x/ccv/provider/types/errors.go | 2 + x/ccv/provider/types/keys.go | 11 + x/ccv/provider/types/keys_test.go | 1 + x/ccv/provider/types/msg.go | 90 +++- x/ccv/provider/types/params.go | 29 +- x/ccv/provider/types/params_test.go | 6 + x/ccv/provider/types/provider.pb.go | 180 +++---- x/ccv/provider/types/query.pb.go | 501 +++++++++++++++--- x/ccv/provider/types/query.pb.gw.go | 65 +++ x/ccv/provider/types/tx.pb.go | 465 ++++++++++++++-- x/ccv/types/events.go | 16 +- x/ccv/types/expected_keepers.go | 6 +- 56 files changed, 2408 insertions(+), 463 deletions(-) create mode 100644 tests/integration/steps_reward_denom.go diff --git a/app/provider/app.go b/app/provider/app.go index 2037ee131a..a70583ee37 100644 --- a/app/provider/app.go +++ b/app/provider/app.go @@ -154,13 +154,14 @@ var ( // module account permissions maccPerms = map[string][]string{ - authtypes.FeeCollectorName: nil, - distrtypes.ModuleName: nil, - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - govtypes.ModuleName: {authtypes.Burner}, - ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + authtypes.FeeCollectorName: nil, + distrtypes.ModuleName: nil, + minttypes.ModuleName: {authtypes.Minter}, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + govtypes.ModuleName: {authtypes.Burner}, + ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + providertypes.ConsumerRewardsPool: nil, } ) @@ -309,12 +310,14 @@ func New( maccPerms, ) - // Remove the fee-pool from the group of blocked recipient addresses in bank + // Remove the ConsumerRewardsPool from the group of blocked recipient addresses in bank // this is required for the provider chain to be able to receive tokens from // the consumer chain bankBlockedAddrs := app.ModuleAccountAddrs() delete(bankBlockedAddrs, authtypes.NewModuleAddress( - authtypes.FeeCollectorName).String()) + providertypes.ConsumerRewardsPool).String()) + + // bankBlockedAddrs := make(map[string]bool) app.BankKeeper = bankkeeper.NewBaseKeeper( appCodec, @@ -410,6 +413,8 @@ func New( app.SlashingKeeper, app.AccountKeeper, app.EvidenceKeeper, + app.DistrKeeper, + app.BankKeeper, authtypes.FeeCollectorName, ) @@ -778,6 +783,11 @@ func (app *App) GetE2eDistributionKeeper() e2e.E2eDistributionKeeper { return app.DistrKeeper } +// GetTestAccountKeeper implements the ProviderApp interface. +func (app *App) GetE2eAccountKeeper() e2e.E2eAccountKeeper { + return app.AccountKeeper +} + // TestingApp functions // GetBaseApp implements the TestingApp interface. diff --git a/proto/interchain_security/ccv/consumer/v1/consumer.proto b/proto/interchain_security/ccv/consumer/v1/consumer.proto index 170c146cfd..7766133788 100644 --- a/proto/interchain_security/ccv/consumer/v1/consumer.proto +++ b/proto/interchain_security/ccv/consumer/v1/consumer.proto @@ -52,6 +52,13 @@ message Params { // which should be smaller than that of the provider in general. google.protobuf.Duration unbonding_period = 9 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + + // Reward denoms. These are the denominations which are allowed to be sent to the provider as rewards. + repeated string reward_denoms = 10; + + // Provider-originated reward denoms. These are denoms coming from the provider + // which are allowed to be used as rewards. e.g. "uatom" + repeated string provider_reward_denoms = 11; } // LastTransmissionBlockHeight is the last time validator holding diff --git a/proto/interchain_security/ccv/provider/v1/provider.proto b/proto/interchain_security/ccv/provider/v1/provider.proto index 16f3a7bff6..0f96f15dcd 100644 --- a/proto/interchain_security/ccv/provider/v1/provider.proto +++ b/proto/interchain_security/ccv/provider/v1/provider.proto @@ -11,6 +11,7 @@ import "ibc/core/client/v1/client.proto"; import "ibc/lightclients/tendermint/v1/tendermint.proto"; import "tendermint/crypto/keys.proto"; import "cosmos/evidence/v1beta1/evidence.proto"; +import "cosmos/base/v1beta1/coin.proto"; // ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain. // If it passes, then all validators on the provider chain are expected to validate the consumer chain at spawn time diff --git a/proto/interchain_security/ccv/provider/v1/query.proto b/proto/interchain_security/ccv/provider/v1/query.proto index b1ef9a620c..3100502699 100644 --- a/proto/interchain_security/ccv/provider/v1/query.proto +++ b/proto/interchain_security/ccv/provider/v1/query.proto @@ -68,6 +68,12 @@ service Query { returns (QueryThrottledConsumerPacketDataResponse) { option (google.api.http).get = "/interchain_security/ccv/provider/pending_consumer_packets"; } + + // QueryRegisteredConsumerRewardDenoms returns a list of consumer reward denoms that are registered + rpc QueryRegisteredConsumerRewardDenoms(QueryRegisteredConsumerRewardDenomsRequest) + returns (QueryRegisteredConsumerRewardDenomsResponse) { + option (google.api.http).get = "/interchain_security/ccv/provider/registered_consumer_reward_denoms"; + } } message QueryConsumerGenesisRequest { string chain_id = 1; } @@ -169,3 +175,9 @@ message ThrottledPacketDataWrapper { interchain_security.ccv.v1.VSCMaturedPacketData vsc_matured_packet = 2; } } + +message QueryRegisteredConsumerRewardDenomsRequest {} + +message QueryRegisteredConsumerRewardDenomsResponse { + repeated string denoms = 1; +} diff --git a/proto/interchain_security/ccv/provider/v1/tx.proto b/proto/interchain_security/ccv/provider/v1/tx.proto index 567a7d9daa..f69bb93e08 100644 --- a/proto/interchain_security/ccv/provider/v1/tx.proto +++ b/proto/interchain_security/ccv/provider/v1/tx.proto @@ -11,6 +11,7 @@ import "google/protobuf/any.proto"; // Msg defines the Msg service. service Msg { rpc AssignConsumerKey(MsgAssignConsumerKey) returns (MsgAssignConsumerKeyResponse); + rpc RegisterConsumerRewardDenom(MsgRegisterConsumerRewardDenom) returns (MsgRegisterConsumerRewardDenomResponse); } message MsgAssignConsumerKey { @@ -21,9 +22,24 @@ message MsgAssignConsumerKey { // The validator address on the provider string provider_addr = 2 [ (gogoproto.moretags) = "yaml:\"address\"" ]; - // The consensus public key to use on the consumer - google.protobuf.Any consumer_key = 3 - [ (cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey" ]; + // The consensus public key to use on the consumer. + // in json string format corresponding to proto-any, ex: + // `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is="}` + string consumer_key = 3; } -message MsgAssignConsumerKeyResponse {} \ No newline at end of file +message MsgAssignConsumerKeyResponse {} + +// MsgRegisterConsumerRewardDenom allows an account to register +// a consumer reward denom, i.e., add it to the list of denoms +// accepted by the provider as rewards. +message MsgRegisterConsumerRewardDenom { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string denom = 1; + string depositor = 2; +} + +// MsgRegisterConsumerRewardDenomResponse defines the Msg/RegisterConsumerRewardDenom response type. +message MsgRegisterConsumerRewardDenomResponse {} \ No newline at end of file diff --git a/tests/difference/core/driver/setup.go b/tests/difference/core/driver/setup.go index 9c917a5ce8..b5f481df22 100644 --- a/tests/difference/core/driver/setup.go +++ b/tests/difference/core/driver/setup.go @@ -520,6 +520,8 @@ func (b *Builder) createConsumerGenesis(client *ibctmtypes.ClientState) *consume consumertypes.DefaultConsumerRedistributeFrac, consumertypes.DefaultHistoricalEntries, b.initState.UnbondingC, + []string{}, + []string{}, ) return consumertypes.NewInitialGenesisState(client, providerConsState, valUpdates, params) } diff --git a/tests/e2e/distribution.go b/tests/e2e/distribution.go index 0c247e14a2..a8450a884d 100644 --- a/tests/e2e/distribution.go +++ b/tests/e2e/distribution.go @@ -5,8 +5,10 @@ import ( 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" transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" + providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" ) @@ -21,6 +23,11 @@ func (s *CCVTestSuite) TestRewardsDistribution() { delegate(s, delAddr, bondAmt) s.providerChain.NextBlock() + // register a consumer reward denom + params := s.consumerApp.GetConsumerKeeper().GetParams(s.consumerCtx()) + params.RewardDenoms = []string{sdk.DefaultBondDenom} + s.consumerApp.GetConsumerKeeper().SetParams(s.consumerCtx(), params) + // relay VSC packets from provider to consumer relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 1) @@ -30,7 +37,9 @@ func (s *CCVTestSuite) TestRewardsDistribution() { s.consumerChain.NextBlock() consumerAccountKeeper := s.consumerApp.GetE2eAccountKeeper() + providerAccountKeeper := s.providerApp.GetE2eAccountKeeper() consumerBankKeeper := s.consumerApp.GetE2eBankKeeper() + providerBankKeeper := s.providerApp.GetE2eBankKeeper() //send coins to the fee pool which is used for reward distribution consumerFeePoolAddr := consumerAccountKeeper.GetModuleAccount(s.consumerCtx(), authtypes.FeeCollectorName).GetAddress() @@ -58,22 +67,73 @@ func (s *CCVTestSuite) TestRewardsDistribution() { providerTokens := consumerBankKeeper.GetAllBalances(s.consumerCtx(), providerRedistributeAddr) s.Require().Equal(providerExpectedRewards.AmountOf(sdk.DefaultBondDenom), providerTokens.AmountOf(sdk.DefaultBondDenom)) - //send the reward to provider chain after 2 blocks - + // send the reward to provider chain after 2 blocks s.consumerChain.NextBlock() providerTokens = consumerBankKeeper.GetAllBalances(s.consumerCtx(), providerRedistributeAddr) s.Require().Equal(0, len(providerTokens)) relayAllCommittedPackets(s, s.consumerChain, s.transferPath, transfertypes.PortID, s.transferPath.EndpointA.ChannelID, 1) s.providerChain.NextBlock() - communityCoins := s.providerApp.GetE2eDistributionKeeper().GetFeePoolCommunityCoins(s.providerCtx()) + + // Since consumer reward denom is not yet registered, the coins never get into the fee pool, staying in the ConsumerRewardsPool + rewardPool := providerAccountKeeper.GetModuleAccount(s.providerCtx(), providertypes.ConsumerRewardsPool).GetAddress() + rewardCoins := providerBankKeeper.GetAllBalances(s.providerCtx(), rewardPool) + ibcCoinIndex := -1 - for i, coin := range communityCoins { + for i, coin := range rewardCoins { if strings.HasPrefix(coin.Denom, "ibc") { ibcCoinIndex = i } } + + // Check that we found an ibc denom in the reward pool s.Require().Greater(ibcCoinIndex, -1) + + // Check that the coins got into the ConsumerRewardsPool + s.Require().True(rewardCoins[ibcCoinIndex].Amount.Equal(providerExpectedRewards[0].Amount)) + + // Attempt to register the consumer reward denom, but fail because the account has no coins + + // Get the balance of delAddr to send it out + senderCoins := providerBankKeeper.GetAllBalances(s.providerCtx(), delAddr) + + // Send the coins to the governance module just to have a place to send them + providerBankKeeper.SendCoinsFromAccountToModule(s.providerCtx(), delAddr, govtypes.ModuleName, senderCoins) + + // Attempt to register the consumer reward denom, but fail because the account has no coins + err = s.providerApp.GetProviderKeeper().RegisterConsumerRewardDenom(s.providerCtx(), rewardCoins[ibcCoinIndex].Denom, delAddr) + s.Require().Error(err) + + // Advance a block and check that the coins are still in the ConsumerRewardsPool + s.providerChain.NextBlock() + rewardCoins = providerBankKeeper.GetAllBalances(s.providerCtx(), rewardPool) + s.Require().True(rewardCoins[ibcCoinIndex].Amount.Equal(providerExpectedRewards[0].Amount)) + + // Successfully register the consumer reward denom this time + + // Send the coins back to the delAddr + providerBankKeeper.SendCoinsFromModuleToAccount(s.providerCtx(), govtypes.ModuleName, delAddr, senderCoins) + + // log the sender's coins + senderCoins1 := providerBankKeeper.GetAllBalances(s.providerCtx(), delAddr) + + // Register the consumer reward denom + err = s.providerApp.GetProviderKeeper().RegisterConsumerRewardDenom(s.providerCtx(), rewardCoins[ibcCoinIndex].Denom, delAddr) + s.Require().NoError(err) + + // Check that the delAddr has the right amount less money in it after paying the fee + senderCoins2 := providerBankKeeper.GetAllBalances(s.providerCtx(), delAddr) + consumerRewardDenomRegistrationFee := s.providerApp.GetProviderKeeper().GetConsumerRewardDenomRegistrationFee(s.providerCtx()) + s.Require().Equal(senderCoins1.Sub(senderCoins2), sdk.NewCoins(consumerRewardDenomRegistrationFee)) + + s.providerChain.NextBlock() + + // Check that the reward pool has no more coins because they were transferred to the fee pool + rewardCoins = providerBankKeeper.GetAllBalances(s.providerCtx(), rewardPool) + s.Require().Equal(0, len(rewardCoins)) + + // check that the fee pool has the expected amount of coins + communityCoins := s.providerApp.GetE2eDistributionKeeper().GetFeePoolCommunityCoins(s.providerCtx()) s.Require().True(communityCoins[ibcCoinIndex].Amount.Equal(sdk.NewDecCoinFromCoin(providerExpectedRewards[0]).Amount)) } @@ -90,6 +150,11 @@ func (s *CCVTestSuite) TestSendRewardsRetries() { delegate(s, delAddr, bondAmt) s.providerChain.NextBlock() + // Register denom on consumer chain + params := s.consumerApp.GetConsumerKeeper().GetParams(s.consumerCtx()) + params.RewardDenoms = []string{sdk.DefaultBondDenom} + s.consumerApp.GetConsumerKeeper().SetParams(s.consumerCtx(), params) + // relay VSC packets from provider to consumer relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 1) @@ -159,12 +224,14 @@ func (s *CCVTestSuite) TestEndBlockRD() { corruptTransChannel bool expLBThUpdated bool expEscrowBalanceChanged bool + denomRegistered bool }{ { name: "should not update LBTH before blocks per dist trans block are passed", prepareRewardDist: false, corruptTransChannel: false, expLBThUpdated: false, + denomRegistered: true, expEscrowBalanceChanged: false, }, { @@ -172,6 +239,7 @@ func (s *CCVTestSuite) TestEndBlockRD() { prepareRewardDist: true, corruptTransChannel: false, expLBThUpdated: true, + denomRegistered: true, expEscrowBalanceChanged: true, }, { @@ -179,8 +247,25 @@ func (s *CCVTestSuite) TestEndBlockRD() { prepareRewardDist: true, corruptTransChannel: true, expLBThUpdated: true, + denomRegistered: true, expEscrowBalanceChanged: false, }, + { + name: "should not change escrow balance when denom is not registered", + prepareRewardDist: true, + corruptTransChannel: false, + expLBThUpdated: true, + denomRegistered: false, + expEscrowBalanceChanged: false, + }, + { + name: "should change escrow balance when denom is registered", + prepareRewardDist: true, + corruptTransChannel: false, + expLBThUpdated: true, + denomRegistered: true, + expEscrowBalanceChanged: true, + }, } for _, tc := range testCases { @@ -195,6 +280,12 @@ func (s *CCVTestSuite) TestEndBlockRD() { delegate(s, delAddr, bondAmt) s.providerChain.NextBlock() + if tc.denomRegistered { + params := s.consumerApp.GetConsumerKeeper().GetParams(s.consumerCtx()) + params.RewardDenoms = []string{sdk.DefaultBondDenom} + s.consumerApp.GetConsumerKeeper().SetParams(s.consumerCtx(), params) + } + // relay VSC packets from provider to consumer relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 1) diff --git a/tests/integration/actions.go b/tests/integration/actions.go index 379488ab34..92d8d0eb67 100644 --- a/tests/integration/actions.go +++ b/tests/integration/actions.go @@ -1166,6 +1166,36 @@ func (tr TestRun) registerRepresentative( wg.Wait() } +type registerConsumerRewardDenomAction struct { + chain chainID + from validatorID + denom string +} + +func (tr TestRun) registerConsumerRewardDenom(action registerConsumerRewardDenomAction, verbose bool) { + //#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments. + bz, err := exec.Command("docker", "exec", tr.containerConfig.instanceName, tr.chainConfigs[action.chain].binaryName, + "tx", "provider", "register-consumer-reward-denom", action.denom, + + `--from`, `validator`+fmt.Sprint(action.from), + `--chain-id`, string(action.chain), + `--home`, tr.getValidatorHome(action.chain, action.from), + `--node`, tr.getValidatorNode(action.chain, action.from), + `--gas`, "9000000", + `--keyring-backend`, `test`, + `-b`, `block`, + `-y`, + ).CombinedOutput() + + if verbose { + fmt.Println("redelegate cmd:", string(bz)) + } + + if err != nil { + log.Fatal(err, "\n", string(bz)) + } +} + // Creates an additional node on selected chain // by copying an existing validator's home folder // diff --git a/tests/integration/config.go b/tests/integration/config.go index e2f36c7b0d..0ed51616d5 100644 --- a/tests/integration/config.go +++ b/tests/integration/config.go @@ -219,7 +219,19 @@ func DefaultTestRun() TestRun { } } -func DemocracyTestRun() TestRun { +func DemocracyTestRun(allowReward bool) TestRun { + consumerGenChanges := ".app_state.ccvconsumer.params.blocks_per_distribution_transmission = \"20\" | " + + ".app_state.gov.voting_params.voting_period = \"10s\" | " + + ".app_state.slashing.params.signed_blocks_window = \"2\" | " + + ".app_state.slashing.params.min_signed_per_window = \"0.500000000000000000\" | " + + ".app_state.slashing.params.downtime_jail_duration = \"2s\" | " + + ".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\"" + + if allowReward { + // This allows the consumer chain to send rewards in the stake denom + consumerGenChanges += " | .app_state.ccvconsumer.params.reward_denoms = [\"stake\"]" + } + return TestRun{ name: "democracy", containerConfig: ContainerConfig{ @@ -242,19 +254,14 @@ func DemocracyTestRun() TestRun { ".app_state.slashing.params.min_signed_per_window = \"0.500000000000000000\" | " + ".app_state.slashing.params.downtime_jail_duration = \"2s\" | " + ".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\" | " + - ".app_state.provider.params.slash_meter_replenish_fraction = \"1.0\"", // This disables slash packet throttling + ".app_state.provider.params.slash_meter_replenish_fraction = \"1.0\"", }, chainID("democ"): { chainId: chainID("democ"), binaryName: "interchain-security-cdd", ipPrefix: "7.7.9", votingWaitTime: 20, - genesisChanges: ".app_state.ccvconsumer.params.blocks_per_distribution_transmission = \"20\" | " + - ".app_state.gov.voting_params.voting_period = \"10s\" | " + - ".app_state.slashing.params.signed_blocks_window = \"2\" | " + - ".app_state.slashing.params.min_signed_per_window = \"0.500000000000000000\" | " + - ".app_state.slashing.params.downtime_jail_duration = \"2s\" | " + - ".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\"", + genesisChanges: consumerGenChanges, }, }, tendermintConfigOverride: `s/timeout_commit = "5s"/timeout_commit = "1s"/;` + diff --git a/tests/integration/main.go b/tests/integration/main.go index 82e457a3bc..657bd90aae 100644 --- a/tests/integration/main.go +++ b/tests/integration/main.go @@ -35,7 +35,8 @@ func main() { testRuns := []testRunWithSteps{ {DefaultTestRun(), happyPathSteps}, - {DemocracyTestRun(), democracySteps}, + {DemocracyTestRun(true), democracySteps}, + {DemocracyTestRun(false), rewardDenomConsumerSteps}, {SlashThrottleTestRun(), slashThrottleSteps}, } if includeMultiConsumer != nil && *includeMultiConsumer { @@ -133,6 +134,8 @@ func (tr *TestRun) runStep(step Step, verbose bool) { tr.waitForSlashThrottleDequeue(action, verbose) case startHermesAction: tr.startHermes(action, verbose) + case registerConsumerRewardDenomAction: + tr.registerConsumerRewardDenom(action, verbose) default: log.Fatalf("unknown action in testRun %s: %#v", tr.name, action) } diff --git a/tests/integration/state.go b/tests/integration/state.go index ae35767f05..3691017a68 100644 --- a/tests/integration/state.go +++ b/tests/integration/state.go @@ -16,17 +16,18 @@ import ( type State map[chainID]ChainState type ChainState struct { - ValBalances *map[validatorID]uint - Proposals *map[uint]Proposal - ValPowers *map[validatorID]uint - RepresentativePowers *map[validatorID]uint - Params *[]Param - Rewards *Rewards - ConsumerChains *map[chainID]bool - AssignedKeys *map[validatorID]string - ProviderKeys *map[validatorID]string // validatorID: validator provider key - ConsumerChainQueueSizes *map[chainID]uint - GlobalSlashQueueSize *uint + ValBalances *map[validatorID]uint + Proposals *map[uint]Proposal + ValPowers *map[validatorID]uint + RepresentativePowers *map[validatorID]uint + Params *[]Param + Rewards *Rewards + ConsumerChains *map[chainID]bool + AssignedKeys *map[validatorID]string + ProviderKeys *map[validatorID]string // validatorID: validator provider key + ConsumerChainQueueSizes *map[chainID]uint + GlobalSlashQueueSize *uint + RegisteredConsumerRewardDenoms *[]string } type Proposal interface { @@ -167,6 +168,11 @@ func (tr TestRun) getChainState(chain chainID, modelState ChainState) ChainState chainState.ConsumerChainQueueSizes = &consumerChainQueueSizes } + if modelState.RegisteredConsumerRewardDenoms != nil { + registeredConsumerRewardDenoms := tr.getRegisteredConsumerRewardDenoms(chain) + chainState.RegisteredConsumerRewardDenoms = ®isteredConsumerRewardDenoms + } + return chainState } @@ -647,6 +653,28 @@ func (tr TestRun) getConsumerChainPacketQueueSize(consumerChain chainID) uint { return uint(size) } +func (tr TestRun) getRegisteredConsumerRewardDenoms(chain chainID) []string { + //#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments. + cmd := exec.Command("docker", "exec", tr.containerConfig.instanceName, tr.chainConfigs[chain].binaryName, + + "query", "provider", "registered-consumer-reward-denoms", + `--node`, tr.getQueryNode(chain), + `-o`, `json`, + ) + bz, err := cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + denoms := gjson.Get(string(bz), "denoms").Array() + rewardDenoms := make([]string, len(denoms)) + for i, d := range denoms { + rewardDenoms[i] = d.String() + } + + return rewardDenoms +} + func (tr TestRun) getValidatorNode(chain chainID, validator validatorID) string { return "tcp://" + tr.getValidatorIP(chain, validator) + ":26658" } diff --git a/tests/integration/steps.go b/tests/integration/steps.go index 448b6d3bce..1ee13d644b 100644 --- a/tests/integration/steps.go +++ b/tests/integration/steps.go @@ -43,6 +43,14 @@ var democracySteps = concatSteps( stepsDemocracy("democ"), ) +var rewardDenomConsumerSteps = concatSteps( + // democracySteps requires a transfer channel + stepsStartChains([]string{"democ"}, true), + // delegation needs to happen so the first VSC packet can be delivered + stepsDelegate("democ"), + stepsRewardDenomConsumer("democ"), +) + var multipleConsumers = concatSteps( stepsStartChains([]string{"consu", "densu"}, false), stepsMultiConsumerDelegate("consu", "densu"), diff --git a/tests/integration/steps_democracy.go b/tests/integration/steps_democracy.go index fd01fc38a8..a0649177a8 100644 --- a/tests/integration/steps_democracy.go +++ b/tests/integration/steps_democracy.go @@ -105,6 +105,47 @@ func stepsDemocracy(consumerName string) []Step { }, }, }, + { + action: relayRewardPacketsToProviderAction{ + consumerChain: chainID(consumerName), + providerChain: chainID("provi"), + port: "transfer", + channel: 1, + }, + state: State{ + chainID("provi"): ChainState{ + // Check that tokens are not distributed before the denom has been registered + Rewards: &Rewards{ + IsRewarded: map[validatorID]bool{ + validatorID("alice"): false, + validatorID("bob"): false, + validatorID("carol"): false, + }, + IsIncrementalReward: false, + IsNativeDenom: false, + }, + // Check that the denom is not registered on provider chain + RegisteredConsumerRewardDenoms: &[]string{}, + }, + }, + }, + { + action: registerConsumerRewardDenomAction{ + chain: chainID("provi"), + from: validatorID("bob"), + denom: "ibc/3C3D7B3BE4ECC85A0E5B52A3AEC3B7DFC2AA9CA47C37821E57020D6807043BE9", + }, + state: State{ + chainID("provi"): ChainState{ + // Check that the denom is registered on provider chain + RegisteredConsumerRewardDenoms: &[]string{"ibc/3C3D7B3BE4ECC85A0E5B52A3AEC3B7DFC2AA9CA47C37821E57020D6807043BE9"}, + ValBalances: &map[validatorID]uint{ + // make sure that bob's account was debited + validatorID("bob"): 9490000000, + }, + }, + }, + }, { action: relayRewardPacketsToProviderAction{ consumerChain: chainID(consumerName), diff --git a/tests/integration/steps_reward_denom.go b/tests/integration/steps_reward_denom.go new file mode 100644 index 0000000000..51cabf427c --- /dev/null +++ b/tests/integration/steps_reward_denom.go @@ -0,0 +1,281 @@ +package main + +func stepsRewardDenomConsumer(consumerName string) []Step { + return []Step{ + { + action: registerRepresentativeAction{ + chain: chainID(consumerName), + representatives: []validatorID{validatorID("alice"), validatorID("bob")}, + stakes: []uint{100000000, 40000000}, + }, + state: State{ + chainID(consumerName): ChainState{ + RepresentativePowers: &map[validatorID]uint{ + validatorID("alice"): 100000000, + validatorID("bob"): 40000000, + }, + Rewards: &Rewards{ + IsRewarded: map[validatorID]bool{ + validatorID("alice"): true, + validatorID("bob"): true, + validatorID("carol"): false, + }, + IsIncrementalReward: true, + IsNativeDenom: true, + }, + }, + }, + }, + { + action: delegateTokensAction{ + chain: chainID(consumerName), + from: validatorID("carol"), + to: validatorID("alice"), + amount: 500000, + }, + state: State{ + chainID(consumerName): ChainState{ + //Check that delegators on gov-consumer chain can change representative powers + RepresentativePowers: &map[validatorID]uint{ + validatorID("alice"): 100500000, + validatorID("bob"): 40000000, + }, + // Check that delegating on gov-consumer does not change validator powers + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + validatorID("bob"): 500, + validatorID("carol"): 500, + }, + //Check that tokens are minted and distributed to representatives and their delegators + Rewards: &Rewards{ + IsRewarded: map[validatorID]bool{ + validatorID("alice"): true, + validatorID("bob"): true, + validatorID("carol"): true, + }, + IsIncrementalReward: true, + IsNativeDenom: true, + }, + }, + }, + }, + { + action: submitParamChangeProposalAction{ + chain: chainID(consumerName), + from: validatorID("alice"), + deposit: 10000001, + subspace: "staking", + key: "MaxValidators", + value: 105, + }, + state: State{ + chainID(consumerName): ChainState{ + ValBalances: &map[validatorID]uint{ + validatorID("alice"): 9889999998, + validatorID("bob"): 9960000001, + }, + Proposals: &map[uint]Proposal{ + 1: ParamsProposal{ + Deposit: 10000001, + Status: "PROPOSAL_STATUS_VOTING_PERIOD", + Subspace: "staking", + Key: "MaxValidators", + Value: "105", + }, + }, + }, + }, + }, + { + //Have accounts vote on something on the gov-consumer chain + action: voteGovProposalAction{ + chain: chainID(consumerName), + from: []validatorID{validatorID("alice"), validatorID("bob")}, + vote: []string{"yes", "no"}, + propNumber: 1, + }, + state: State{ + chainID(consumerName): ChainState{ + ValBalances: &map[validatorID]uint{ + validatorID("alice"): 9899999999, + validatorID("bob"): 9960000001, + }, + //Check that the parameter is changed on gov-consumer chain + Params: &([]Param{{Subspace: "staking", Key: "MaxValidators", Value: "105"}}), + }, + }, + }, + { + action: relayRewardPacketsToProviderAction{ + consumerChain: chainID(consumerName), + providerChain: chainID("provi"), + port: "transfer", + channel: 1, + }, + state: State{ + chainID("provi"): ChainState{ + // Check that tokens are not distributed before the denom has been registered + Rewards: &Rewards{ + IsRewarded: map[validatorID]bool{ + validatorID("alice"): false, + validatorID("bob"): false, + validatorID("carol"): false, + }, + IsIncrementalReward: false, + IsNativeDenom: false, + }, + // Check that the denom is not registered on provider chain + RegisteredConsumerRewardDenoms: &[]string{}, + }, + }, + }, + { + action: registerConsumerRewardDenomAction{ + chain: chainID("provi"), + from: validatorID("bob"), + denom: "ibc/3C3D7B3BE4ECC85A0E5B52A3AEC3B7DFC2AA9CA47C37821E57020D6807043BE9", + }, + state: State{ + chainID("provi"): ChainState{ + // Check that the denom is registered on provider chain + RegisteredConsumerRewardDenoms: &[]string{"ibc/3C3D7B3BE4ECC85A0E5B52A3AEC3B7DFC2AA9CA47C37821E57020D6807043BE9"}, + ValBalances: &map[validatorID]uint{ + // make sure that bob's account was debited + validatorID("bob"): 9490000000, + }, + }, + }, + }, + { + action: relayRewardPacketsToProviderAction{ + consumerChain: chainID(consumerName), + providerChain: chainID("provi"), + port: "transfer", + channel: 1, + }, + state: State{ + chainID("provi"): ChainState{ + //Check that tokens are not minted and sent to provider chain and distributed to validators and their delegators on provider chain + Rewards: &Rewards{ + IsRewarded: map[validatorID]bool{ + validatorID("alice"): false, + validatorID("bob"): false, + validatorID("carol"): false, + }, + IsIncrementalReward: false, + IsNativeDenom: false, + }, + }, + }, + }, + { + action: downtimeSlashAction{ + chain: chainID(consumerName), + validator: validatorID("bob"), + }, + state: State{ + // validator should be slashed on consumer, powers not affected on either chain yet + chainID("provi"): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + validatorID("bob"): 500, + validatorID("carol"): 500, + }, + }, + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + validatorID("bob"): 500, + validatorID("carol"): 500, + }, + }, + }, + }, + { + action: relayPacketsAction{ + chain: chainID("provi"), + port: "provider", + channel: 0, + }, + state: State{ + chainID("provi"): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + // Downtime jailing and corresponding voting power change are processed by provider + validatorID("bob"): 0, + validatorID("carol"): 500, + }, + }, + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + validatorID("bob"): 500, + validatorID("carol"): 500, + }, + }, + }, + }, + // A block is incremented each action, hence why VSC is committed on provider, + // and can now be relayed as packet to consumer + { + action: relayPacketsAction{ + chain: chainID("provi"), + port: "provider", + channel: 0, + }, + state: State{ + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + // VSC now seen on consumer + validatorID("bob"): 0, + validatorID("carol"): 500, + }, + }, + }, + }, + { + action: unjailValidatorAction{ + provider: chainID("provi"), + validator: validatorID("bob"), + }, + state: State{ + chainID("provi"): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + validatorID("bob"): 500, + validatorID("carol"): 500, + }, + }, + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + validatorID("bob"): 0, + validatorID("carol"): 500, + }, + }, + }, + }, + { + action: relayPacketsAction{ + chain: chainID("provi"), + port: "provider", + channel: 0, + }, + state: State{ + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 511, + validatorID("bob"): 500, + validatorID("carol"): 500, + }, + //Check that slashing on the gov-consumer chain does not result in slashing for the representatives or their delegators + RepresentativePowers: &map[validatorID]uint{ + validatorID("alice"): 100500000, + validatorID("bob"): 40000000, + }, + }, + }, + }, + } +} diff --git a/testutil/e2e/interfaces.go b/testutil/e2e/interfaces.go index a5b8e1962f..1c33cbdb47 100644 --- a/testutil/e2e/interfaces.go +++ b/testutil/e2e/interfaces.go @@ -24,6 +24,7 @@ import ( // This is a wrapper around the ibc testing app interface with additional constraints. type ProviderApp interface { ibctesting.TestingApp + GetSubspace(moduleName string) paramstypes.Subspace // // Keeper getters @@ -38,6 +39,8 @@ type ProviderApp interface { GetE2eSlashingKeeper() E2eSlashingKeeper // Returns a distribution keeper interface with more capabilities than the expected_keepers interface GetE2eDistributionKeeper() E2eDistributionKeeper + // Tests an account keeper interface with more capabilities than the expected_keepers interface + GetE2eAccountKeeper() E2eAccountKeeper } // The interface that any consumer app must implement to be compatible with e2e tests @@ -104,6 +107,8 @@ type E2eBankKeeper interface { ccvtypes.BankKeeper SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, + recipientAddr sdk.AccAddress, amt sdk.Coins) error } type E2eAccountKeeper interface { diff --git a/testutil/keeper/mocks.go b/testutil/keeper/mocks.go index 66fc77dbce..3c20f90825 100644 --- a/testutil/keeper/mocks.go +++ b/testutil/keeper/mocks.go @@ -46,6 +46,20 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder { return m.recorder } +// BondDenom mocks base method. +func (m *MockStakingKeeper) BondDenom(ctx types.Context) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BondDenom", ctx) + ret0, _ := ret[0].(string) + return ret0 +} + +// BondDenom indicates an expected call of BondDenom. +func (mr *MockStakingKeeperMockRecorder) BondDenom(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BondDenom", reflect.TypeOf((*MockStakingKeeper)(nil).BondDenom), ctx) +} + // GetLastTotalPower mocks base method. func (m *MockStakingKeeper) GetLastTotalPower(ctx types.Context) types.Int { m.ctrl.T.Helper() @@ -616,6 +630,43 @@ func (mr *MockClientKeeperMockRecorder) GetSelfConsensusState(ctx, height interf return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSelfConsensusState", reflect.TypeOf((*MockClientKeeper)(nil).GetSelfConsensusState), ctx, height) } +// MockDistributionKeeper is a mock of DistributionKeeper interface. +type MockDistributionKeeper struct { + ctrl *gomock.Controller + recorder *MockDistributionKeeperMockRecorder +} + +// MockDistributionKeeperMockRecorder is the mock recorder for MockDistributionKeeper. +type MockDistributionKeeperMockRecorder struct { + mock *MockDistributionKeeper +} + +// NewMockDistributionKeeper creates a new mock instance. +func NewMockDistributionKeeper(ctrl *gomock.Controller) *MockDistributionKeeper { + mock := &MockDistributionKeeper{ctrl: ctrl} + mock.recorder = &MockDistributionKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDistributionKeeper) EXPECT() *MockDistributionKeeperMockRecorder { + return m.recorder +} + +// FundCommunityPool mocks base method. +func (m *MockDistributionKeeper) FundCommunityPool(ctx types.Context, amount types.Coins, sender types.AccAddress) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FundCommunityPool", ctx, amount, sender) + ret0, _ := ret[0].(error) + return ret0 +} + +// FundCommunityPool indicates an expected call of FundCommunityPool. +func (mr *MockDistributionKeeperMockRecorder) FundCommunityPool(ctx, amount, sender interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FundCommunityPool", reflect.TypeOf((*MockDistributionKeeper)(nil).FundCommunityPool), ctx, amount, sender) +} + // MockConsumerHooks is a mock of ConsumerHooks interface. type MockConsumerHooks struct { ctrl *gomock.Controller diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index 3dd5d98299..476c25fa32 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -87,23 +87,25 @@ type MockedKeepers struct { *MockIBCTransferKeeper *MockIBCCoreKeeper *MockEvidenceKeeper + *MockDistributionKeeper } // NewMockedKeepers instantiates a struct with pointers to properly instantiated mocked keepers. func NewMockedKeepers(ctrl *gomock.Controller) MockedKeepers { return MockedKeepers{ - MockScopedKeeper: NewMockScopedKeeper(ctrl), - MockChannelKeeper: NewMockChannelKeeper(ctrl), - MockPortKeeper: NewMockPortKeeper(ctrl), - MockConnectionKeeper: NewMockConnectionKeeper(ctrl), - MockClientKeeper: NewMockClientKeeper(ctrl), - MockStakingKeeper: NewMockStakingKeeper(ctrl), - MockSlashingKeeper: NewMockSlashingKeeper(ctrl), - MockAccountKeeper: NewMockAccountKeeper(ctrl), - MockBankKeeper: NewMockBankKeeper(ctrl), - MockIBCTransferKeeper: NewMockIBCTransferKeeper(ctrl), - MockIBCCoreKeeper: NewMockIBCCoreKeeper(ctrl), - MockEvidenceKeeper: NewMockEvidenceKeeper(ctrl), + MockScopedKeeper: NewMockScopedKeeper(ctrl), + MockChannelKeeper: NewMockChannelKeeper(ctrl), + MockPortKeeper: NewMockPortKeeper(ctrl), + MockConnectionKeeper: NewMockConnectionKeeper(ctrl), + MockClientKeeper: NewMockClientKeeper(ctrl), + MockStakingKeeper: NewMockStakingKeeper(ctrl), + MockSlashingKeeper: NewMockSlashingKeeper(ctrl), + MockAccountKeeper: NewMockAccountKeeper(ctrl), + MockBankKeeper: NewMockBankKeeper(ctrl), + MockIBCTransferKeeper: NewMockIBCTransferKeeper(ctrl), + MockIBCCoreKeeper: NewMockIBCCoreKeeper(ctrl), + MockEvidenceKeeper: NewMockEvidenceKeeper(ctrl), + MockDistributionKeeper: NewMockDistributionKeeper(ctrl), } } @@ -122,6 +124,8 @@ func NewInMemProviderKeeper(params InMemKeeperParams, mocks MockedKeepers) provi mocks.MockSlashingKeeper, mocks.MockAccountKeeper, mocks.MockEvidenceKeeper, + mocks.MockDistributionKeeper, + mocks.MockBankKeeper, "", ) } @@ -226,8 +230,9 @@ func SetupForStoppingConsumerChain(t *testing.T, ctx sdk.Context, "chainID", clienttypes.NewHeight(4, 5)) expectations = append(expectations, GetMocksForSetConsumerChain(ctx, &mocks, "chainID")...) expectations = append(expectations, GetMocksForStopConsumerChain(ctx, &mocks)...) + expectations = append(expectations, mocks.MockStakingKeeper.EXPECT().BondDenom(gomock.Any()).Return("stake").AnyTimes()) - gomock.InOrder(expectations...) + gomock.InAnyOrder(expectations) prop := GetTestConsumerAdditionProp() err := providerKeeper.CreateConsumerClient(ctx, prop) diff --git a/x/ccv/consumer/keeper/distribution.go b/x/ccv/consumer/keeper/distribution.go index f2a534cd14..8d67b2488f 100644 --- a/x/ccv/consumer/keeper/distribution.go +++ b/x/ccv/consumer/keeper/distribution.go @@ -107,23 +107,34 @@ func (k Keeper) SendRewardsToProvider(ctx sdk.Context) error { if found && transferChannel.State == channeltypes.OPEN { tstProviderAddr := k.authKeeper.GetModuleAccount(ctx, types.ConsumerToSendToProviderName).GetAddress() - tstProviderTokens := k.bankKeeper.GetAllBalances(ctx, tstProviderAddr) providerAddr := k.GetProviderFeePoolAddrStr(ctx) timeoutHeight := clienttypes.ZeroHeight() transferTimeoutPeriod := k.GetTransferTimeoutPeriod(ctx) timeoutTimestamp := uint64(ctx.BlockTime().Add(transferTimeoutPeriod).UnixNano()) - for _, token := range tstProviderTokens { - err := k.ibcTransferKeeper.SendTransfer(ctx, - transfertypes.PortID, - ch, - token, - tstProviderAddr, - providerAddr, - timeoutHeight, - timeoutTimestamp, - ) - if err != nil { - return err + + sentCoins := sdk.NewCoins() + + // iterate over all whitelisted reward denoms + for _, denom := range k.AllowedRewardDenoms(ctx) { + // get the balance of the denom in the toSendToProviderTokens address + balance := k.bankKeeper.GetBalance(ctx, tstProviderAddr, denom) + + // if the balance is not zero, + if !balance.IsZero() { + // send the balance to the provider + err := k.ibcTransferKeeper.SendTransfer(ctx, + transfertypes.PortID, + ch, + balance, + tstProviderAddr, + providerAddr, + timeoutHeight, + timeoutTimestamp, + ) + if err != nil { + return err + } + sentCoins = sentCoins.Add(balance) } } @@ -132,7 +143,7 @@ func (k Keeper) SendRewardsToProvider(ctx sdk.Context) error { k.Logger(ctx).Info("sent block rewards to provider", "total fee pool", fpTokens.String(), - "sent", tstProviderTokens.String(), + "sent", sentCoins.String(), ) currentHeight := ctx.BlockHeight() ctx.EventManager().EmitEvent( @@ -143,7 +154,7 @@ func (k Keeper) SendRewardsToProvider(ctx sdk.Context) error { sdk.NewAttribute(ccv.AttributeDistributionNextHeight, strconv.Itoa(int(currentHeight+k.GetBlocksPerDistributionTransmission(ctx)))), sdk.NewAttribute(ccv.AttributeDistributionFraction, (k.GetConsumerRedistributionFrac(ctx))), sdk.NewAttribute(ccv.AttributeDistributionTotal, fpTokens.String()), - sdk.NewAttribute(ccv.AttributeDistributionToProvider, tstProviderTokens.String()), + sdk.NewAttribute(ccv.AttributeDistributionToProvider, sentCoins.String()), ), ) } @@ -151,6 +162,34 @@ func (k Keeper) SendRewardsToProvider(ctx sdk.Context) error { return nil } +// AllowedRewardDenoms returns a list of all denoms that are allowed +// to be sent to the provider as rewards +func (k Keeper) AllowedRewardDenoms(ctx sdk.Context) []string { + var rewardDenoms []string + + // first, append the native reward denoms + rewardDenoms = append(rewardDenoms, k.GetRewardDenoms(ctx)...) + + // then, append the provider-originated reward denoms + for _, denom := range k.GetProviderRewardDenoms(ctx) { + // every provider denom was sent over IBC, + // so we must prefix the denom + sourcePrefix := transfertypes.GetDenomPrefix( + transfertypes.PortID, + k.GetDistributionTransmissionChannel(ctx), + ) + // NOTE: sourcePrefix contains the trailing "/" + prefixedDenom := sourcePrefix + denom + // construct the denomination trace from the full raw denomination + denomTrace := transfertypes.ParseDenomTrace(prefixedDenom) + + // append the IBC denom to the list of allowed reward denoms + rewardDenoms = append(rewardDenoms, denomTrace.IBCDenom()) + } + + return rewardDenoms +} + func (k Keeper) GetLastTransmissionBlockHeight(ctx sdk.Context) types.LastTransmissionBlockHeight { store := ctx.KVStore(k.storeKey) bz := store.Get(types.LastDistributionTransmissionKey()) diff --git a/x/ccv/consumer/keeper/distribution_test.go b/x/ccv/consumer/keeper/distribution_test.go index 842e190877..f1e4c92e69 100644 --- a/x/ccv/consumer/keeper/distribution_test.go +++ b/x/ccv/consumer/keeper/distribution_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "strings" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -65,3 +66,25 @@ func TestGetEstimatedNextFeeDistribution(t *testing.T) { require.NotEmpty(t, res) require.EqualValues(t, expect, res, "fee distribution data does not match") } + +func TestAllowedRewardDenoms(t *testing.T) { + keeperParams := testkeeper.NewInMemKeeperParams(t) + ctx := keeperParams.Ctx + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mocks := testkeeper.NewMockedKeepers(ctrl) + consumerKeeper := testkeeper.NewInMemConsumerKeeper(keeperParams, mocks) + params := types.DefaultParams() + params.RewardDenoms = []string{"ustake"} + params.ProviderRewardDenoms = []string{"uatom"} + consumerKeeper.SetParams(ctx, params) + + transferChannelID := "channel-5" + consumerKeeper.SetDistributionTransmissionChannel(ctx, transferChannelID) + + allowedDenoms := consumerKeeper.AllowedRewardDenoms(ctx) + require.Len(t, allowedDenoms, 2) + require.Equal(t, allowedDenoms[0], "ustake") + require.True(t, strings.HasPrefix(allowedDenoms[1], "ibc/")) +} diff --git a/x/ccv/consumer/keeper/params.go b/x/ccv/consumer/keeper/params.go index 8fd20ad2f8..2344818ba8 100644 --- a/x/ccv/consumer/keeper/params.go +++ b/x/ccv/consumer/keeper/params.go @@ -21,6 +21,8 @@ func (k Keeper) GetParams(ctx sdk.Context) types.Params { k.GetConsumerRedistributionFrac(ctx), k.GetHistoricalEntries(ctx), k.GetUnbondingPeriod(ctx), + k.GetRewardDenoms(ctx), + k.GetProviderRewardDenoms(ctx), ) } @@ -106,3 +108,15 @@ func (k Keeper) GetUnbondingPeriod(ctx sdk.Context) time.Duration { k.paramStore.Get(ctx, types.KeyConsumerUnbondingPeriod, &period) return period } + +func (k Keeper) GetRewardDenoms(ctx sdk.Context) []string { + var denoms []string + k.paramStore.Get(ctx, types.KeyRewardDenoms, &denoms) + return denoms +} + +func (k Keeper) GetProviderRewardDenoms(ctx sdk.Context) []string { + var denoms []string + k.paramStore.Get(ctx, types.KeyProviderRewardDenoms, &denoms) + return denoms +} diff --git a/x/ccv/consumer/keeper/params_test.go b/x/ccv/consumer/keeper/params_test.go index 2d2061e2a1..b6a8fe09d0 100644 --- a/x/ccv/consumer/keeper/params_test.go +++ b/x/ccv/consumer/keeper/params_test.go @@ -17,6 +17,8 @@ func TestParams(t *testing.T) { defer ctrl.Finish() consumerKeeper.SetParams(ctx, types.DefaultParams()) + var rewardDenoms []string + var provideRewardDenoms []string expParams := types.NewParams( false, 1000, @@ -27,6 +29,8 @@ func TestParams(t *testing.T) { consumertypes.DefaultConsumerRedistributeFrac, consumertypes.DefaultHistoricalEntries, consumertypes.DefaultConsumerUnbondingPeriod, + rewardDenoms, + provideRewardDenoms, ) // these are the default params, IBC suite independently sets enabled=true params := consumerKeeper.GetParams(ctx) @@ -34,7 +38,7 @@ func TestParams(t *testing.T) { newParams := types.NewParams(false, 1000, "channel-2", "cosmos19pe9pg5dv9k5fzgzmsrgnw9rl9asf7ddwhu7lm", - 7*24*time.Hour, 25*time.Hour, "0.5", 500, 24*21*time.Hour) + 7*24*time.Hour, 25*time.Hour, "0.5", 500, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}) consumerKeeper.SetParams(ctx, newParams) params = consumerKeeper.GetParams(ctx) require.Equal(t, newParams, params) diff --git a/x/ccv/consumer/types/consumer.pb.go b/x/ccv/consumer/types/consumer.pb.go index 5d20bfce95..d679447a0a 100644 --- a/x/ccv/consumer/types/consumer.pb.go +++ b/x/ccv/consumer/types/consumer.pb.go @@ -63,6 +63,11 @@ type Params struct { // Unbonding period for the consumer, // which should be smaller than that of the provider in general. UnbondingPeriod time.Duration `protobuf:"bytes,9,opt,name=unbonding_period,json=unbondingPeriod,proto3,stdduration" json:"unbonding_period"` + // Reward denoms. These are the denominations which are allowed to be sent to the provider as rewards. + RewardDenoms []string `protobuf:"bytes,10,rep,name=reward_denoms,json=rewardDenoms,proto3" json:"reward_denoms,omitempty"` + // Provider-originated reward denoms. These are denoms coming from the provider + // which are allowed to be used as rewards. e.g. "uatom" + ProviderRewardDenoms []string `protobuf:"bytes,11,rep,name=provider_reward_denoms,json=providerRewardDenoms,proto3" json:"provider_reward_denoms,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -161,6 +166,20 @@ func (m *Params) GetUnbondingPeriod() time.Duration { return 0 } +func (m *Params) GetRewardDenoms() []string { + if m != nil { + return m.RewardDenoms + } + return nil +} + +func (m *Params) GetProviderRewardDenoms() []string { + if m != nil { + return m.ProviderRewardDenoms + } + return nil +} + // LastTransmissionBlockHeight is the last time validator holding // pools were transmitted to the provider chain type LastTransmissionBlockHeight struct { @@ -334,52 +353,54 @@ func init() { } var fileDescriptor_5b27a82b276e7f93 = []byte{ - // 709 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcf, 0x4e, 0xdb, 0x48, - 0x18, 0x8f, 0x17, 0x08, 0x30, 0xb0, 0x5a, 0xf0, 0x66, 0xc1, 0x64, 0x25, 0x27, 0x64, 0x39, 0xe4, - 0x82, 0x23, 0x82, 0xf6, 0xc2, 0x8d, 0x84, 0x45, 0xb0, 0xfd, 0x97, 0x9a, 0x88, 0x43, 0x7b, 0xb0, - 0xc6, 0xe3, 0x89, 0x33, 0xc2, 0x9e, 0xb1, 0x66, 0xc6, 0x6e, 0xfd, 0x16, 0x1c, 0xfb, 0x08, 0x7d, - 0x80, 0x3e, 0x04, 0xea, 0x89, 0x63, 0x4f, 0xb4, 0x82, 0x37, 0xa8, 0xfa, 0x00, 0x95, 0x3d, 0x76, - 0x20, 0x50, 0x24, 0x6e, 0xdf, 0xa7, 0xdf, 0x1f, 0xcf, 0xf7, 0xf3, 0x37, 0x03, 0xba, 0x84, 0x4a, - 0xcc, 0xd1, 0x18, 0x12, 0xea, 0x08, 0x8c, 0x62, 0x4e, 0x64, 0xda, 0x41, 0x28, 0xe9, 0x20, 0x46, - 0x45, 0x1c, 0x62, 0xde, 0x49, 0x76, 0x26, 0xb5, 0x15, 0x71, 0x26, 0x99, 0xfe, 0xcf, 0x2f, 0x34, - 0x16, 0x42, 0x89, 0x35, 0xe1, 0x25, 0x3b, 0xf5, 0xad, 0xc7, 0x8c, 0x33, 0x3f, 0x94, 0x28, 0xab, - 0xfa, 0x86, 0xcf, 0x98, 0x1f, 0xe0, 0x4e, 0xde, 0xb9, 0xf1, 0xa8, 0x03, 0x69, 0x5a, 0x40, 0x35, - 0x9f, 0xf9, 0x2c, 0x2f, 0x3b, 0x59, 0x55, 0x0a, 0x10, 0x13, 0x21, 0x13, 0x8e, 0x02, 0x54, 0x53, - 0x40, 0xe6, 0x7d, 0x2f, 0x2f, 0xe6, 0x50, 0x12, 0x46, 0x0b, 0xbc, 0x71, 0x1f, 0x97, 0x24, 0xc4, - 0x42, 0xc2, 0x30, 0x52, 0x84, 0xd6, 0x8f, 0x59, 0x50, 0x1d, 0x40, 0x0e, 0x43, 0xa1, 0x1b, 0x60, - 0x1e, 0x53, 0xe8, 0x06, 0xd8, 0x33, 0xb4, 0xa6, 0xd6, 0x5e, 0xb0, 0xcb, 0x56, 0x7f, 0x05, 0xb6, - 0xdc, 0x80, 0xa1, 0x33, 0xe1, 0x44, 0x98, 0x3b, 0x1e, 0x11, 0x92, 0x13, 0x37, 0xce, 0x3e, 0xe3, - 0x48, 0x0e, 0xa9, 0x08, 0x89, 0x10, 0x84, 0x51, 0xe3, 0xb7, 0xa6, 0xd6, 0x9e, 0xb1, 0x37, 0x15, - 0x77, 0x80, 0xf9, 0xc1, 0x1d, 0xe6, 0xf0, 0x0e, 0x51, 0xff, 0x1f, 0x6c, 0x3e, 0xea, 0xe2, 0xa0, - 0x31, 0xa4, 0x14, 0x07, 0xc6, 0x4c, 0x53, 0x6b, 0x2f, 0xda, 0x0d, 0xef, 0x11, 0x93, 0xbe, 0xa2, - 0xe9, 0x7b, 0xa0, 0x1e, 0x71, 0x96, 0x10, 0x0f, 0x73, 0x67, 0x84, 0xb1, 0x13, 0x31, 0x16, 0x38, - 0xd0, 0xf3, 0xb8, 0x23, 0x24, 0x37, 0x66, 0x73, 0x93, 0xb5, 0x92, 0x71, 0x88, 0xf1, 0x80, 0xb1, - 0x60, 0xdf, 0xf3, 0xf8, 0x89, 0xe4, 0xfa, 0x6b, 0xa0, 0x23, 0x94, 0x38, 0x59, 0x28, 0x2c, 0x96, - 0xd9, 0x74, 0x84, 0x79, 0xc6, 0x5c, 0x53, 0x6b, 0x2f, 0x75, 0x37, 0x2c, 0x95, 0x9d, 0x55, 0x66, - 0x67, 0x1d, 0x14, 0xd9, 0xf6, 0x16, 0x2e, 0xae, 0x1a, 0x95, 0x0f, 0x5f, 0x1b, 0x9a, 0xbd, 0x82, - 0x50, 0x32, 0x54, 0xea, 0x41, 0x2e, 0xd6, 0xdf, 0x82, 0xf5, 0x7c, 0x9a, 0x11, 0xe6, 0xf7, 0x7d, - 0xab, 0x4f, 0xf7, 0xfd, 0xab, 0xf4, 0x98, 0x36, 0x3f, 0x02, 0xcd, 0x72, 0xdf, 0x1c, 0x8e, 0xa7, - 0x22, 0x1c, 0x71, 0x88, 0xb2, 0xc2, 0x98, 0xcf, 0x27, 0x36, 0x4b, 0x9e, 0x3d, 0x45, 0x3b, 0x2c, - 0x58, 0xfa, 0x36, 0xd0, 0xc7, 0x44, 0x48, 0xc6, 0x09, 0x82, 0x81, 0x83, 0xa9, 0xe4, 0x04, 0x0b, - 0x63, 0x21, 0xff, 0x81, 0xab, 0xb7, 0xc8, 0x7f, 0x0a, 0xd0, 0x5f, 0x82, 0x95, 0x98, 0xba, 0x8c, - 0x7a, 0x84, 0xfa, 0xe5, 0x38, 0x8b, 0x4f, 0x1f, 0xe7, 0x8f, 0x89, 0x58, 0x0d, 0xd2, 0xfa, 0x17, - 0xfc, 0xfd, 0x1c, 0x0a, 0x79, 0xf7, 0x7f, 0xf6, 0xb2, 0xad, 0x39, 0xc2, 0xc4, 0x1f, 0x4b, 0x7d, - 0x0d, 0x54, 0xc7, 0x79, 0x95, 0x6f, 0xe2, 0x8c, 0x5d, 0x74, 0xad, 0x8f, 0x1a, 0xf8, 0xb3, 0xcf, - 0x99, 0x10, 0xfd, 0xec, 0x8e, 0x9d, 0xc2, 0x80, 0x78, 0x50, 0x32, 0x9e, 0xad, 0x6e, 0xf6, 0xc7, - 0xb1, 0x10, 0xb9, 0x60, 0xd9, 0x2e, 0x5b, 0xbd, 0x06, 0xe6, 0x22, 0xf6, 0x0e, 0xf3, 0x62, 0x37, - 0x55, 0xa3, 0x43, 0x50, 0x8d, 0x62, 0xf7, 0x0c, 0xa7, 0xf9, 0x92, 0x2d, 0x75, 0x6b, 0x0f, 0x86, - 0xd8, 0xa7, 0x69, 0x6f, 0xf7, 0xfb, 0x55, 0x63, 0x3d, 0x85, 0x61, 0xb0, 0xd7, 0xca, 0xd2, 0xc4, - 0x54, 0xc4, 0xc2, 0x51, 0xba, 0xd6, 0xe7, 0x4f, 0xdb, 0xb5, 0xe2, 0x26, 0x22, 0x9e, 0x46, 0x92, - 0x59, 0x83, 0xd8, 0x7d, 0x86, 0x53, 0xbb, 0x30, 0x6e, 0x49, 0xb0, 0xfa, 0x02, 0xca, 0x98, 0x13, - 0xea, 0x9f, 0x9e, 0xf4, 0x07, 0x10, 0x9d, 0x61, 0x99, 0x9d, 0x26, 0x11, 0xe8, 0x58, 0x5d, 0xb0, - 0x59, 0x5b, 0x35, 0xfa, 0x31, 0xf8, 0x3d, 0xcc, 0xa9, 0x32, 0xcd, 0x57, 0x26, 0x3f, 0xeb, 0x52, - 0xb7, 0xfe, 0xe0, 0x50, 0xc3, 0xf2, 0xf2, 0xaa, 0x68, 0xcf, 0xb3, 0x68, 0x97, 0x4b, 0x69, 0x06, - 0xf6, 0x86, 0x17, 0xd7, 0xa6, 0x76, 0x79, 0x6d, 0x6a, 0xdf, 0xae, 0x4d, 0xed, 0xfc, 0xc6, 0xac, - 0x5c, 0xde, 0x98, 0x95, 0x2f, 0x37, 0x66, 0xe5, 0xcd, 0x9e, 0x4f, 0xe4, 0x38, 0x76, 0x2d, 0xc4, - 0xc2, 0xe2, 0x09, 0xe9, 0xdc, 0xbe, 0x56, 0xdb, 0x93, 0xd7, 0xea, 0xfd, 0xf4, 0x43, 0x28, 0xd3, - 0x08, 0x0b, 0xb7, 0x9a, 0x9f, 0x60, 0xf7, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, 0xde, 0xaf, 0xcf, - 0x76, 0x39, 0x05, 0x00, 0x00, + // 748 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcd, 0x6e, 0xdb, 0x36, + 0x1c, 0xb7, 0xe6, 0xc6, 0x4d, 0xe8, 0x14, 0x6b, 0x39, 0xaf, 0x55, 0x3d, 0x40, 0x76, 0xdd, 0x1e, + 0x7c, 0x89, 0x8c, 0xba, 0xdb, 0x25, 0xb7, 0xda, 0x59, 0xd1, 0xee, 0xd3, 0x53, 0x8c, 0x1c, 0xb6, + 0x03, 0x41, 0x51, 0xb4, 0x4c, 0x44, 0x22, 0x05, 0x92, 0x52, 0xa6, 0xb7, 0xc8, 0x71, 0x8f, 0xb0, + 0x07, 0xd8, 0x43, 0x04, 0xbb, 0x2c, 0xc7, 0x9d, 0xb2, 0x21, 0x79, 0x83, 0x3d, 0xc1, 0x20, 0x4a, + 0x72, 0xec, 0xa4, 0x01, 0x72, 0xe3, 0x5f, 0xbf, 0x0f, 0xf1, 0xff, 0xc1, 0x3f, 0x18, 0x33, 0xae, + 0xa9, 0x24, 0x4b, 0xcc, 0x38, 0x52, 0x94, 0xa4, 0x92, 0xe9, 0x7c, 0x44, 0x48, 0x36, 0x22, 0x82, + 0xab, 0x34, 0xa6, 0x72, 0x94, 0xbd, 0x5e, 0x9d, 0xdd, 0x44, 0x0a, 0x2d, 0xe0, 0xcb, 0x8f, 0x68, + 0x5c, 0x42, 0x32, 0x77, 0xc5, 0xcb, 0x5e, 0x77, 0x5f, 0xdd, 0x65, 0x5c, 0xf8, 0x91, 0xac, 0xb4, + 0xea, 0x3e, 0x0f, 0x85, 0x08, 0x23, 0x3a, 0x32, 0x91, 0x9f, 0x2e, 0x46, 0x98, 0xe7, 0x15, 0xd4, + 0x09, 0x45, 0x28, 0xcc, 0x71, 0x54, 0x9c, 0x6a, 0x01, 0x11, 0x2a, 0x16, 0x0a, 0x95, 0x40, 0x19, + 0x54, 0x90, 0x73, 0xd3, 0x2b, 0x48, 0x25, 0xd6, 0x4c, 0xf0, 0x0a, 0xef, 0xdd, 0xc4, 0x35, 0x8b, + 0xa9, 0xd2, 0x38, 0x4e, 0x4a, 0xc2, 0xe0, 0xaf, 0x2d, 0xd0, 0x9a, 0x61, 0x89, 0x63, 0x05, 0x6d, + 0xf0, 0x90, 0x72, 0xec, 0x47, 0x34, 0xb0, 0xad, 0xbe, 0x35, 0xdc, 0xf6, 0xea, 0x10, 0xfe, 0x08, + 0x5e, 0xf9, 0x91, 0x20, 0xc7, 0x0a, 0x25, 0x54, 0xa2, 0x80, 0x29, 0x2d, 0x99, 0x9f, 0x16, 0xbf, + 0x41, 0x5a, 0x62, 0xae, 0x62, 0xa6, 0x14, 0x13, 0xdc, 0xfe, 0xa4, 0x6f, 0x0d, 0x9b, 0xde, 0x8b, + 0x92, 0x3b, 0xa3, 0xf2, 0x60, 0x8d, 0x39, 0x5f, 0x23, 0xc2, 0x6f, 0xc0, 0x8b, 0x3b, 0x5d, 0x10, + 0x59, 0x62, 0xce, 0x69, 0x64, 0x37, 0xfb, 0xd6, 0x70, 0xc7, 0xeb, 0x05, 0x77, 0x98, 0x4c, 0x4b, + 0x1a, 0xdc, 0x07, 0xdd, 0x44, 0x8a, 0x8c, 0x05, 0x54, 0xa2, 0x05, 0xa5, 0x28, 0x11, 0x22, 0x42, + 0x38, 0x08, 0x24, 0x52, 0x5a, 0xda, 0x0f, 0x8c, 0xc9, 0xd3, 0x9a, 0xf1, 0x8e, 0xd2, 0x99, 0x10, + 0xd1, 0xdb, 0x20, 0x90, 0x87, 0x5a, 0xc2, 0x9f, 0x00, 0x24, 0x24, 0x43, 0x45, 0x51, 0x44, 0xaa, + 0x8b, 0xec, 0x98, 0x08, 0xec, 0xad, 0xbe, 0x35, 0x6c, 0x8f, 0x9f, 0xbb, 0x65, 0xed, 0xdc, 0xba, + 0x76, 0xee, 0x41, 0x55, 0xdb, 0xc9, 0xf6, 0xd9, 0x45, 0xaf, 0xf1, 0xdb, 0x3f, 0x3d, 0xcb, 0x7b, + 0x4c, 0x48, 0x36, 0x2f, 0xd5, 0x33, 0x23, 0x86, 0xbf, 0x80, 0x67, 0x26, 0x9b, 0x05, 0x95, 0x37, + 0x7d, 0x5b, 0xf7, 0xf7, 0xfd, 0xbc, 0xf6, 0xd8, 0x34, 0x7f, 0x0f, 0xfa, 0xf5, 0xbc, 0x21, 0x49, + 0x37, 0x4a, 0xb8, 0x90, 0x98, 0x14, 0x07, 0xfb, 0xa1, 0xc9, 0xd8, 0xa9, 0x79, 0xde, 0x06, 0xed, + 0x5d, 0xc5, 0x82, 0x7b, 0x00, 0x2e, 0x99, 0xd2, 0x42, 0x32, 0x82, 0x23, 0x44, 0xb9, 0x96, 0x8c, + 0x2a, 0x7b, 0xdb, 0x34, 0xf0, 0xc9, 0x35, 0xf2, 0x75, 0x09, 0xc0, 0x1f, 0xc0, 0xe3, 0x94, 0xfb, + 0x82, 0x07, 0x8c, 0x87, 0x75, 0x3a, 0x3b, 0xf7, 0x4f, 0xe7, 0xd3, 0x95, 0xb8, 0x4a, 0xe4, 0x25, + 0x78, 0x24, 0xe9, 0x09, 0x96, 0x01, 0x0a, 0x28, 0x17, 0xb1, 0xb2, 0x41, 0xbf, 0x39, 0xdc, 0xf1, + 0x76, 0xcb, 0x8f, 0x07, 0xe6, 0x1b, 0xfc, 0x12, 0xac, 0xfa, 0x86, 0x36, 0xd9, 0x6d, 0xc3, 0xee, + 0xd4, 0xa8, 0xb7, 0xa6, 0x1a, 0x7c, 0x05, 0xbe, 0xf8, 0x0e, 0x2b, 0xbd, 0x3e, 0x2a, 0x93, 0x62, + 0x20, 0xdf, 0x53, 0x16, 0x2e, 0x35, 0x7c, 0x0a, 0x5a, 0x4b, 0x73, 0x32, 0x43, 0xde, 0xf4, 0xaa, + 0x68, 0xf0, 0xbb, 0x05, 0x3e, 0x9b, 0x4a, 0xa1, 0xd4, 0xb4, 0x78, 0xbe, 0x47, 0x38, 0x62, 0x01, + 0xd6, 0x42, 0x16, 0xaf, 0xa2, 0x18, 0x26, 0xaa, 0x94, 0x11, 0xec, 0x7a, 0x75, 0x08, 0x3b, 0x60, + 0x2b, 0x11, 0x27, 0x54, 0x56, 0x63, 0x5f, 0x06, 0x10, 0x83, 0x56, 0x92, 0xfa, 0xc7, 0x34, 0x37, + 0xf3, 0xdb, 0x1e, 0x77, 0x6e, 0xd5, 0xe7, 0x2d, 0xcf, 0x27, 0x6f, 0xfe, 0xbb, 0xe8, 0x3d, 0xcb, + 0x71, 0x1c, 0xed, 0x0f, 0x8a, 0x46, 0x51, 0xae, 0x52, 0x85, 0x4a, 0xdd, 0xe0, 0xcf, 0x3f, 0xf6, + 0x3a, 0xd5, 0x23, 0x27, 0x32, 0x4f, 0xb4, 0x70, 0x67, 0xa9, 0xff, 0x2d, 0xcd, 0xbd, 0xca, 0x78, + 0xa0, 0xc1, 0x93, 0xef, 0xb1, 0x4e, 0x25, 0xe3, 0xe1, 0xd1, 0xe1, 0x74, 0x86, 0xc9, 0x31, 0xd5, + 0xc5, 0x6d, 0x32, 0x45, 0x3e, 0x94, 0x6f, 0xf7, 0x81, 0x57, 0x06, 0xf0, 0x03, 0x78, 0x14, 0x1b, + 0xaa, 0xce, 0xcd, 0x34, 0x9a, 0xbb, 0xb6, 0xc7, 0xdd, 0x5b, 0x97, 0x9a, 0xd7, 0x7b, 0xa1, 0xec, + 0xda, 0x69, 0xd1, 0xb5, 0xdd, 0x5a, 0x5a, 0x80, 0x93, 0xf9, 0xd9, 0xa5, 0x63, 0x9d, 0x5f, 0x3a, + 0xd6, 0xbf, 0x97, 0x8e, 0x75, 0x7a, 0xe5, 0x34, 0xce, 0xaf, 0x9c, 0xc6, 0xdf, 0x57, 0x4e, 0xe3, + 0xe7, 0xfd, 0x90, 0xe9, 0x65, 0xea, 0xbb, 0x44, 0xc4, 0xd5, 0x76, 0x1a, 0x5d, 0x2f, 0xc2, 0xbd, + 0xd5, 0x22, 0xfc, 0x75, 0x73, 0xc7, 0xea, 0x3c, 0xa1, 0xca, 0x6f, 0x99, 0x1b, 0xbc, 0xf9, 0x3f, + 0x00, 0x00, 0xff, 0xff, 0x85, 0xd4, 0x08, 0x3e, 0x94, 0x05, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -402,6 +423,24 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ProviderRewardDenoms) > 0 { + for iNdEx := len(m.ProviderRewardDenoms) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ProviderRewardDenoms[iNdEx]) + copy(dAtA[i:], m.ProviderRewardDenoms[iNdEx]) + i = encodeVarintConsumer(dAtA, i, uint64(len(m.ProviderRewardDenoms[iNdEx]))) + i-- + dAtA[i] = 0x5a + } + } + if len(m.RewardDenoms) > 0 { + for iNdEx := len(m.RewardDenoms) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.RewardDenoms[iNdEx]) + copy(dAtA[i:], m.RewardDenoms[iNdEx]) + i = encodeVarintConsumer(dAtA, i, uint64(len(m.RewardDenoms[iNdEx]))) + i-- + dAtA[i] = 0x52 + } + } n1, err1 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.UnbondingPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.UnbondingPeriod):]) if err1 != nil { return 0, err1 @@ -625,6 +664,18 @@ func (m *Params) Size() (n int) { } l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.UnbondingPeriod) n += 1 + l + sovConsumer(uint64(l)) + if len(m.RewardDenoms) > 0 { + for _, s := range m.RewardDenoms { + l = len(s) + n += 1 + l + sovConsumer(uint64(l)) + } + } + if len(m.ProviderRewardDenoms) > 0 { + for _, s := range m.ProviderRewardDenoms { + l = len(s) + n += 1 + l + sovConsumer(uint64(l)) + } + } return n } @@ -962,6 +1013,70 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardDenoms", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConsumer + } + 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 ErrInvalidLengthConsumer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthConsumer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardDenoms = append(m.RewardDenoms, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProviderRewardDenoms", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConsumer + } + 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 ErrInvalidLengthConsumer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthConsumer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProviderRewardDenoms = append(m.ProviderRewardDenoms, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipConsumer(dAtA[iNdEx:]) diff --git a/x/ccv/consumer/types/genesis_test.go b/x/ccv/consumer/types/genesis_test.go index a0046a5387..0b68f5ae0c 100644 --- a/x/ccv/consumer/types/genesis_test.go +++ b/x/ccv/consumer/types/genesis_test.go @@ -217,6 +217,8 @@ func TestValidateInitialGenesisState(t *testing.T) { types.DefaultConsumerRedistributeFrac, types.DefaultHistoricalEntries, types.DefaultConsumerUnbondingPeriod, + []string{}, + []string{}, )), true, }, @@ -412,6 +414,8 @@ func TestValidateRestartGenesisState(t *testing.T) { types.DefaultConsumerRedistributeFrac, types.DefaultHistoricalEntries, types.DefaultConsumerUnbondingPeriod, + []string{}, + []string{}, )), true, }, diff --git a/x/ccv/consumer/types/params.go b/x/ccv/consumer/types/params.go index 7a0a96832e..8cba6f3eec 100644 --- a/x/ccv/consumer/types/params.go +++ b/x/ccv/consumer/types/params.go @@ -1,8 +1,10 @@ package types import ( + fmt "fmt" time "time" + sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" @@ -47,6 +49,8 @@ var ( KeyConsumerRedistributionFrac = []byte("ConsumerRedistributionFraction") KeyHistoricalEntries = []byte("HistoricalEntries") KeyConsumerUnbondingPeriod = []byte("UnbondingPeriod") + KeyRewardDenoms = []byte("RewardDenoms") + KeyProviderRewardDenoms = []byte("ProviderRewardDenoms") ) // ParamKeyTable type declaration for parameters @@ -59,7 +63,7 @@ func NewParams(enabled bool, blocksPerDistributionTransmission int64, distributionTransmissionChannel, providerFeePoolAddrStr string, ccvTimeoutPeriod time.Duration, transferTimeoutPeriod time.Duration, consumerRedistributionFraction string, historicalEntries int64, - consumerUnbondingPeriod time.Duration) Params { + consumerUnbondingPeriod time.Duration, rewardDenoms []string, providerRewardDenoms []string) Params { return Params{ Enabled: enabled, BlocksPerDistributionTransmission: blocksPerDistributionTransmission, @@ -70,11 +74,15 @@ func NewParams(enabled bool, blocksPerDistributionTransmission int64, ConsumerRedistributionFraction: consumerRedistributionFraction, HistoricalEntries: historicalEntries, UnbondingPeriod: consumerUnbondingPeriod, + RewardDenoms: rewardDenoms, + ProviderRewardDenoms: providerRewardDenoms, } } // DefaultParams is the default params for the consumer module func DefaultParams() Params { + var rewardDenoms []string + var provideRewardDenoms []string return NewParams( false, DefaultBlocksPerDistributionTransmission, @@ -85,6 +93,8 @@ func DefaultParams() Params { DefaultConsumerRedistributeFrac, DefaultHistoricalEntries, DefaultConsumerUnbondingPeriod, + rewardDenoms, + provideRewardDenoms, ) } @@ -117,6 +127,12 @@ func (p Params) Validate() error { if err := ccvtypes.ValidateDuration(p.UnbondingPeriod); err != nil { return err } + if err := validateDenoms(p.RewardDenoms); err != nil { + return err + } + if err := validateDenoms(p.ProviderRewardDenoms); err != nil { + return err + } return nil } @@ -140,6 +156,10 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { p.HistoricalEntries, ccvtypes.ValidatePositiveInt64), paramtypes.NewParamSetPair(KeyConsumerUnbondingPeriod, p.UnbondingPeriod, ccvtypes.ValidateDuration), + paramtypes.NewParamSetPair(KeyRewardDenoms, + p.RewardDenoms, validateDenoms), + paramtypes.NewParamSetPair(KeyProviderRewardDenoms, + p.ProviderRewardDenoms, validateDenoms), } } @@ -160,3 +180,24 @@ func validateProviderFeePoolAddrStr(i interface{}) error { // Otherwise validate as usual for a bech32 address return ccvtypes.ValidateBech32(i) } + +func validateDenoms(i interface{}) error { + v, ok := i.([]string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + // iterate over the denoms, turning them into coins and validating them + for _, denom := range v { + coin := sdk.Coin{ + Denom: denom, + Amount: sdk.NewInt(0), + } + + if err := coin.Validate(); err != nil { + return err + } + } + + return nil +} diff --git a/x/ccv/consumer/types/params_test.go b/x/ccv/consumer/types/params_test.go index 0fd7f87eb2..c4e7104fc0 100644 --- a/x/ccv/consumer/types/params_test.go +++ b/x/ccv/consumer/types/params_test.go @@ -19,27 +19,31 @@ func TestValidateParams(t *testing.T) { }{ {"default params", consumertypes.DefaultParams(), true}, {"custom valid params", - consumertypes.NewParams(true, 5, "", "", 1004, 1005, "0.5", 1000, 24*21*time.Hour), true}, + consumertypes.NewParams(true, 5, "", "", 1004, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), true}, {"custom invalid params, block per dist transmission", - consumertypes.NewParams(true, -5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour), false}, + consumertypes.NewParams(true, -5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, dist transmission channel", - consumertypes.NewParams(true, 5, "badchannel/", "", 5, 1005, "0.5", 1000, 24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "badchannel/", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, provider fee pool addr string", - consumertypes.NewParams(true, 5, "", "imabadaddress", 5, 1005, "0.5", 1000, 24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "", "imabadaddress", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, ccv timeout", - consumertypes.NewParams(true, 5, "", "", -5, 1005, "0.5", 1000, 24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "", "", -5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, transfer timeout", - consumertypes.NewParams(true, 5, "", "", 1004, -7, "0.5", 1000, 24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "", "", 1004, -7, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, consumer redist fraction is negative", - consumertypes.NewParams(true, 5, "", "", 5, 1005, "-0.5", 1000, 24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "", "", 5, 1005, "-0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, consumer redist fraction is over 1", - consumertypes.NewParams(true, 5, "", "", 5, 1005, "1.2", 1000, 24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "", "", 5, 1005, "1.2", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, bad consumer redist fraction ", - consumertypes.NewParams(true, 5, "", "", 5, 1005, "notFrac", 1000, 24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "", "", 5, 1005, "notFrac", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, negative num historical entries", - consumertypes.NewParams(true, 5, "", "", 5, 1005, "0.5", -100, 24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "", "", 5, 1005, "0.5", -100, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, {"custom invalid params, negative unbonding period", - consumertypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, -24*21*time.Hour), false}, + consumertypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, -24*21*time.Hour, []string{"untrn"}, []string{"uatom"}), false}, + {"custom invalid params, invalid reward denom", + consumertypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"u"}, []string{}), false}, + {"custom invalid params, invalid provider reward denom", + consumertypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{"a"}), false}, } for _, tc := range testCases { diff --git a/x/ccv/provider/client/cli/query.go b/x/ccv/provider/client/cli/query.go index 922fccd49f..18109db18c 100644 --- a/x/ccv/provider/client/cli/query.go +++ b/x/ccv/provider/client/cli/query.go @@ -32,6 +32,7 @@ func NewQueryCmd() *cobra.Command { cmd.AddCommand(CmdProviderValidatorKey()) cmd.AddCommand(CmdThrottleState()) cmd.AddCommand(CmdThrottledConsumerPacketData()) + cmd.AddCommand(CmdRegisteredConsumerRewardDenoms()) return cmd } @@ -320,3 +321,38 @@ $ %s query provider throttled-consumer-packet-data foochain return cmd } + +func CmdRegisteredConsumerRewardDenoms() *cobra.Command { + cmd := &cobra.Command{ + Use: "registered-consumer-reward-denoms", + Short: "Query registered consumer reward denoms", + Long: strings.TrimSpace( + fmt.Sprintf(`Returns the registered consumer reward denoms. +Example: +$ %s query provider registered-consumer-reward-denoms +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + req := &types.QueryRegisteredConsumerRewardDenomsRequest{} + res, err := queryClient.QueryRegisteredConsumerRewardDenoms(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index edd230e15c..fd7a1468b5 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -1,14 +1,15 @@ package cli import ( - "github.com/spf13/cobra" - "fmt" + "strings" + + "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/version" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/interchain-security/x/ccv/provider/types" @@ -25,6 +26,7 @@ func GetTxCmd() *cobra.Command { } cmd.AddCommand(NewAssignConsumerKeyCmd()) + cmd.AddCommand(NewRegisterConsumerRewardDenomCmd()) return cmd } @@ -44,12 +46,8 @@ func NewAssignConsumerKeyCmd() *cobra.Command { WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever) providerValAddr := clientCtx.GetFromAddress() - var consumerPubKey cryptotypes.PubKey - if err := clientCtx.Codec.UnmarshalInterfaceJSON([]byte(args[1]), &consumerPubKey); err != nil { - return err - } - msg, err := types.NewMsgAssignConsumerKey(args[0], sdk.ValAddress(providerValAddr), consumerPubKey) + msg, err := types.NewMsgAssignConsumerKey(args[0], sdk.ValAddress(providerValAddr), args[1]) if err != nil { return err } @@ -67,3 +65,37 @@ func NewAssignConsumerKeyCmd() *cobra.Command { return cmd } + +func NewRegisterConsumerRewardDenomCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "register-consumer-reward-denom [denom]", + Args: cobra.ExactArgs(1), + Short: "Registers a denom that can be sent from consumer chains to all validators and delegators as a reward", + Long: strings.TrimSpace( + fmt.Sprintf(`Registers a denom that can be sent from consumer chains to all validators and delegators as a reward. + +Costs a fee, which is constant at 10,000,000 of the default bond denom. Will fail if the sending account has an insufficient balance. + +Example: +$ %s tx provider register-consumer-reward-denom untrn --from mykey +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + depositorAddr := clientCtx.GetFromAddress() + + msg := types.NewMsgRegisterConsumerRewardDenom(args[0], depositorAddr) + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/ccv/provider/handler.go b/x/ccv/provider/handler.go index 4751b8460c..253c1bf118 100644 --- a/x/ccv/provider/handler.go +++ b/x/ccv/provider/handler.go @@ -17,6 +17,9 @@ func NewHandler(k *keeper.Keeper) sdk.Handler { case *types.MsgAssignConsumerKey: res, err := msgServer.AssignConsumerKey(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) + case *types.MsgRegisterConsumerRewardDenom: + res, err := msgServer.RegisterConsumerRewardDenom(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) } diff --git a/x/ccv/provider/handler_test.go b/x/ccv/provider/handler_test.go index bfe108e4af..f78ceb130b 100644 --- a/x/ccv/provider/handler_test.go +++ b/x/ccv/provider/handler_test.go @@ -1,6 +1,7 @@ package provider_test import ( + "encoding/base64" "strings" "testing" @@ -15,7 +16,7 @@ import ( testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/provider" keeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" - "github.com/cosmos/interchain-security/x/ccv/provider/types" + providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" ) func TestInvalidMsg(t *testing.T) { @@ -29,8 +30,13 @@ func TestInvalidMsg(t *testing.T) { func TestAssignConsensusKeyForConsumerChain(t *testing.T) { - testValProvider := testcrypto.NewCryptoIdentityFromIntSeed(0) - testValConsumer := testcrypto.NewCryptoIdentityFromIntSeed(1) + providerCryptoId := testcrypto.NewCryptoIdentityFromIntSeed(0) + providerConsAddr := providerCryptoId.SDKValConsAddress() + + consumerCryptoId := testcrypto.NewCryptoIdentityFromIntSeed(1) + consumerConsAddr := consumerCryptoId.SDKValConsAddress() + consumerKeyBz := base64.StdEncoding.EncodeToString(consumerCryptoId.ConsensusSDKPubKey().Bytes()) + consumerKey := `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"` + consumerKeyBz + `"}` testCases := []struct { name string @@ -46,11 +52,11 @@ func TestAssignConsensusKeyForConsumerChain(t *testing.T) { gomock.InOrder( mocks.MockStakingKeeper.EXPECT().GetValidator( - ctx, testValProvider.SDKValOpAddress(), + ctx, providerCryptoId.SDKValOpAddress(), // Return a valid validator, found! - ).Return(testValProvider.SDKStakingValidator(), true).Times(1), + ).Return(providerCryptoId.SDKStakingValidator(), true).Times(1), mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, - testValConsumer.SDKValConsAddress(), + consumerConsAddr, ).Return(stakingtypes.Validator{}, false), ) }, @@ -64,7 +70,7 @@ func TestAssignConsensusKeyForConsumerChain(t *testing.T) { gomock.InOrder( mocks.MockStakingKeeper.EXPECT().GetValidator( - ctx, testValProvider.SDKValOpAddress(), + ctx, providerCryptoId.SDKValOpAddress(), // return false: not found! ).Return(stakingtypes.Validator{}, false).Times(1), ) @@ -78,15 +84,15 @@ func TestAssignConsensusKeyForConsumerChain(t *testing.T) { k keeper.Keeper, mocks testkeeper.MockedKeepers) { // Use the consumer key already - k.SetValidatorByConsumerAddr(ctx, "chainid", testValConsumer.SDKValConsAddress(), testValProvider.SDKValConsAddress()) + k.SetValidatorByConsumerAddr(ctx, "chainid", consumerConsAddr, providerConsAddr) gomock.InOrder( mocks.MockStakingKeeper.EXPECT().GetValidator( - ctx, testValProvider.SDKValOpAddress(), + ctx, providerCryptoId.SDKValOpAddress(), // Return a valid validator, found! - ).Return(testValProvider.SDKStakingValidator(), true).Times(1), + ).Return(providerCryptoId.SDKStakingValidator(), true).Times(1), mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, - testValConsumer.SDKValConsAddress(), + consumerConsAddr, ).Return(stakingtypes.Validator{}, false), ) }, @@ -102,8 +108,8 @@ func TestAssignConsensusKeyForConsumerChain(t *testing.T) { tc.setup(ctx, k, mocks) - msg, err := types.NewMsgAssignConsumerKey(tc.chainID, - testValProvider.SDKValOpAddress(), testValConsumer.ConsensusSDKPubKey(), + msg, err := providertypes.NewMsgAssignConsumerKey(tc.chainID, + providerCryptoId.SDKValOpAddress(), consumerKey, ) require.NoError(t, err) diff --git a/x/ccv/provider/ibc_module.go b/x/ccv/provider/ibc_module.go index 5261ef7572..9e1fe31d2d 100644 --- a/x/ccv/provider/ibc_module.go +++ b/x/ccv/provider/ibc_module.go @@ -86,7 +86,7 @@ func (am AppModule) OnChanOpenTry( // the consumer chain must be excluded from the blocked addresses // blacklist or all all ibc-transfers from the consumer chain to the // provider chain will fail - ProviderFeePoolAddr: am.keeper.GetFeeCollectorAddressStr(ctx), + ProviderFeePoolAddr: am.keeper.GetConsumerRewardsPoolAddressStr(ctx), Version: ccv.Version, } mdBz, err := (&md).Marshal() diff --git a/x/ccv/provider/ibc_module_test.go b/x/ccv/provider/ibc_module_test.go index ab41a7b530..98d9affaee 100644 --- a/x/ccv/provider/ibc_module_test.go +++ b/x/ccv/provider/ibc_module_test.go @@ -135,7 +135,7 @@ func TestOnChanOpenTry(t *testing.T) { // Expected mock calls moduleAcct := authtypes.ModuleAccount{BaseAccount: &authtypes.BaseAccount{}} - moduleAcct.BaseAccount.Address = authtypes.NewModuleAddress(authtypes.FeeCollectorName).String() + moduleAcct.BaseAccount.Address = authtypes.NewModuleAddress(providertypes.ConsumerRewardsPool).String() // Number of calls is not asserted, since not all code paths are hit for failures gomock.InOrder( @@ -147,7 +147,7 @@ func TestOnChanOpenTry(t *testing.T) { mocks.MockClientKeeper.EXPECT().GetClientState(ctx, "clientIDToConsumer").Return( &ibctmtypes.ClientState{ChainId: "consumerChainID"}, true, ).AnyTimes(), - mocks.MockAccountKeeper.EXPECT().GetModuleAccount(ctx, "").Return(&moduleAcct).AnyTimes(), + mocks.MockAccountKeeper.EXPECT().GetModuleAccount(ctx, providertypes.ConsumerRewardsPool).Return(&moduleAcct).AnyTimes(), ) tc.mutateParams(¶ms, &providerKeeper) diff --git a/x/ccv/provider/keeper/distribution.go b/x/ccv/provider/keeper/distribution.go index b00ec81deb..80e59280c7 100644 --- a/x/ccv/provider/keeper/distribution.go +++ b/x/ccv/provider/keeper/distribution.go @@ -2,9 +2,80 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/interchain-security/x/ccv/provider/types" ) -func (k Keeper) GetFeeCollectorAddressStr(ctx sdk.Context) string { +// EndBlockRD executes EndBlock logic for the Reward Distribution sub-protocol. +// Reward Distribution follows a simple model: send tokens to the ConsumerRewardsPool, +// from where they sent to the fee collector address +func (k Keeper) EndBlockRD(ctx sdk.Context) { + // transfers all whitelisted consumer rewards to the fee collector address + k.TransferRewardsToFeeCollector(ctx) +} + +func (k Keeper) RegisterConsumerRewardDenom(ctx sdk.Context, denom string, sender sdk.AccAddress) error { + // Send the consumer reward denom registration fee to the community pool + err := k.distributionKeeper.FundCommunityPool(ctx, sdk.NewCoins(k.GetConsumerRewardDenomRegistrationFee(ctx)), sender) + if err != nil { + return err + } + k.SetConsumerRewardDenom(ctx, denom) + k.Logger(ctx).Info("new consumer reward denom registered:", "denom", denom, "sender", sender.String()) + return nil +} + +func (k Keeper) GetConsumerRewardsPoolAddressStr(ctx sdk.Context) string { return k.accountKeeper.GetModuleAccount( - ctx, k.feeCollectorName).GetAddress().String() + ctx, types.ConsumerRewardsPool).GetAddress().String() +} + +func (k Keeper) SetConsumerRewardDenom( + ctx sdk.Context, + denom string, +) { + store := ctx.KVStore(k.storeKey) + store.Set(types.ConsumerRewardDenomsKey(denom), []byte{}) +} + +func (k Keeper) GetAllConsumerRewardDenoms(ctx sdk.Context) (consumerRewardDenoms []string) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{types.ConsumerRewardDenomsBytePrefix}) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + key := iterator.Key()[1:] + consumerRewardDenoms = append(consumerRewardDenoms, string(key)) + } + + return consumerRewardDenoms +} + +// TransferRewardsToFeeCollector transfers all consumer rewards to the fee collector address +func (k Keeper) TransferRewardsToFeeCollector(ctx sdk.Context) { + // 1. Get the denom whitelist from the store + denoms := k.GetAllConsumerRewardDenoms(ctx) + + // 2. Iterate over the whitelist + for _, denom := range denoms { + // 3. For each denom, retrieve the balance from the consumer rewards pool + balance := k.bankKeeper.GetBalance( + ctx, + k.accountKeeper.GetModuleAccount(ctx, types.ConsumerRewardsPool).GetAddress(), + denom, + ) + + // if the balance is not zero, + if !balance.IsZero() { + // 4. Transfer the balance to the fee collector address + err := k.bankKeeper.SendCoinsFromModuleToModule( + ctx, + types.ConsumerRewardsPool, + k.feeCollectorName, + sdk.NewCoins(balance), + ) + if err != nil { + k.Logger(ctx).Error("cannot sent consumer rewards to fee collector:", "reward", balance.String()) + } + } + } } diff --git a/x/ccv/provider/keeper/genesis_test.go b/x/ccv/provider/keeper/genesis_test.go index 251be0de1e..7480a7cdc6 100644 --- a/x/ccv/provider/keeper/genesis_test.go +++ b/x/ccv/provider/keeper/genesis_test.go @@ -109,6 +109,8 @@ func TestInitAndExportGenesis(t *testing.T) { ).Return(nil, true).Times(1), mocks.MockStakingKeeper.EXPECT().GetLastTotalPower( ctx).Return(sdk.NewInt(100)).Times(1), // Return total voting power as 100 + mocks.MockStakingKeeper.EXPECT().BondDenom( + ctx).Return("stake").AnyTimes(), // Return bond denom as "stake" ) // init provider chain diff --git a/x/ccv/provider/keeper/grpc_query.go b/x/ccv/provider/keeper/grpc_query.go index 261c5b04d9..afffc12bd2 100644 --- a/x/ccv/provider/keeper/grpc_query.go +++ b/x/ccv/provider/keeper/grpc_query.go @@ -236,3 +236,17 @@ func (k Keeper) getSlashPacketData(ctx sdk.Context, consumerChainID string, ibcS return packet, true } + +func (k Keeper) QueryRegisteredConsumerRewardDenoms(goCtx context.Context, req *types.QueryRegisteredConsumerRewardDenomsRequest) (*types.QueryRegisteredConsumerRewardDenomsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + + denoms := k.GetAllConsumerRewardDenoms(ctx) + + return &types.QueryRegisteredConsumerRewardDenomsResponse{ + Denoms: denoms, + }, nil +} diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index dc612b110a..4c2046b397 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -27,19 +27,21 @@ import ( // Keeper defines the Cross-Chain Validation Provider Keeper type Keeper struct { - storeKey sdk.StoreKey - cdc codec.BinaryCodec - paramSpace paramtypes.Subspace - scopedKeeper ccv.ScopedKeeper - channelKeeper ccv.ChannelKeeper - portKeeper ccv.PortKeeper - connectionKeeper ccv.ConnectionKeeper - accountKeeper ccv.AccountKeeper - clientKeeper ccv.ClientKeeper - stakingKeeper ccv.StakingKeeper - slashingKeeper ccv.SlashingKeeper - evidenceKeeper ccv.EvidenceKeeper - feeCollectorName string + storeKey sdk.StoreKey + cdc codec.BinaryCodec + paramSpace paramtypes.Subspace + scopedKeeper ccv.ScopedKeeper + channelKeeper ccv.ChannelKeeper + portKeeper ccv.PortKeeper + connectionKeeper ccv.ConnectionKeeper + accountKeeper ccv.AccountKeeper + bankKeeper ccv.BankKeeper + distributionKeeper ccv.DistributionKeeper + clientKeeper ccv.ClientKeeper + stakingKeeper ccv.StakingKeeper + slashingKeeper ccv.SlashingKeeper + evidenceKeeper ccv.EvidenceKeeper + feeCollectorName string } // NewKeeper creates a new provider Keeper instance @@ -49,6 +51,7 @@ func NewKeeper( connectionKeeper ccv.ConnectionKeeper, clientKeeper ccv.ClientKeeper, stakingKeeper ccv.StakingKeeper, slashingKeeper ccv.SlashingKeeper, accountKeeper ccv.AccountKeeper, evidenceKeeper ccv.EvidenceKeeper, + distributionKeeper ccv.DistributionKeeper, bankKeeper ccv.BankKeeper, feeCollectorName string, ) Keeper { // set KeyTable if it has not already been set @@ -57,19 +60,21 @@ func NewKeeper( } return Keeper{ - cdc: cdc, - storeKey: key, - paramSpace: paramSpace, - scopedKeeper: scopedKeeper, - channelKeeper: channelKeeper, - portKeeper: portKeeper, - connectionKeeper: connectionKeeper, - accountKeeper: accountKeeper, - clientKeeper: clientKeeper, - stakingKeeper: stakingKeeper, - slashingKeeper: slashingKeeper, - evidenceKeeper: evidenceKeeper, - feeCollectorName: feeCollectorName, + cdc: cdc, + storeKey: key, + paramSpace: paramSpace, + scopedKeeper: scopedKeeper, + channelKeeper: channelKeeper, + portKeeper: portKeeper, + connectionKeeper: connectionKeeper, + accountKeeper: accountKeeper, + clientKeeper: clientKeeper, + stakingKeeper: stakingKeeper, + slashingKeeper: slashingKeeper, + evidenceKeeper: evidenceKeeper, + distributionKeeper: distributionKeeper, + bankKeeper: bankKeeper, + feeCollectorName: feeCollectorName, } } diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index 9bb23ddae9..cd9bb4b673 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -2,15 +2,14 @@ package keeper import ( "context" + "encoding/base64" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/interchain-security/x/ccv/provider/types" ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" - tmstrings "github.com/tendermint/tendermint/libs/strings" + tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" ) type msgServer struct { @@ -46,44 +45,84 @@ func (k msgServer) AssignConsumerKey(goCtx context.Context, msg *types.MsgAssign return nil, stakingtypes.ErrNoValidatorFound } - // make sure the consumer key is in the correct format - consumerSDKPublicKey, ok := msg.ConsumerKey.GetCachedValue().(cryptotypes.PubKey) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "Expecting cryptotypes.PubKey, got %T", consumerSDKPublicKey) + // parse consumer key as long as it's in the right format + pkType, keyStr, err := types.ParseConsumerKeyFromJson(msg.ConsumerKey) + if err != nil { + return nil, err } + // Note: the correct way to decide if a key type is supported is to check the + // consensus params. However this functionality was disabled in https://github.com/cosmos/interchain-security/pull/916 + // as a quick way to get ed25519 working, avoiding amino/proto-any marshalling issues. + // make sure the consumer key type is supported - cp := ctx.ConsensusParams() - if cp != nil && cp.Validator != nil { - if !tmstrings.StringInSlice(consumerSDKPublicKey.Type(), cp.Validator.PubKeyTypes) { - return nil, sdkerrors.Wrapf( - stakingtypes.ErrValidatorPubKeyTypeNotSupported, - "got: %s, expected: %s", consumerSDKPublicKey.Type(), cp.Validator.PubKeyTypes, - ) - } + // cp := ctx.ConsensusParams() + // if cp != nil && cp.Validator != nil { + // if !tmstrings.StringInSlice(pkType, cp.Validator.PubKeyTypes) { + // return nil, sdkerrors.Wrapf( + // stakingtypes.ErrValidatorPubKeyTypeNotSupported, + // "got: %s, expected one of: %s", pkType, cp.Validator.PubKeyTypes, + // ) + // } + // } + + // For now, only accept ed25519. + // TODO: decide what types should be supported. + if pkType != "/cosmos.crypto.ed25519.PubKey" { + return nil, sdkerrors.Wrapf( + stakingtypes.ErrValidatorPubKeyTypeNotSupported, + "got: %s, expected: %s", pkType, "/cosmos.crypto.ed25519.PubKey", + ) } - consumerTMPublicKey, err := cryptocodec.ToTmProtoPublicKey(consumerSDKPublicKey) + pubKeyBytes, err := base64.StdEncoding.DecodeString(keyStr) if err != nil { return nil, err } + consumerTMPublicKey := tmprotocrypto.PublicKey{ + Sum: &tmprotocrypto.PublicKey_Ed25519{ + Ed25519: pubKeyBytes, + }, + } + if err := k.Keeper.AssignConsumerKey(ctx, msg.ChainId, validator, consumerTMPublicKey); err != nil { return nil, err } k.Logger(ctx).Info("assigned consumer key", "consumer chainID", msg.ChainId, "validator operator addr", msg.ProviderAddr, - "consumer pubkey", consumerSDKPublicKey.String(), + "consumer tm pubkey", consumerTMPublicKey.String(), ) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( ccvtypes.EventTypeAssignConsumerKey, sdk.NewAttribute(ccvtypes.AttributeProviderValidatorAddress, msg.ProviderAddr), - sdk.NewAttribute(ccvtypes.AttributeConsumerConsensusPubKey, consumerSDKPublicKey.String()), + sdk.NewAttribute(ccvtypes.AttributeConsumerConsensusPubKey, consumerTMPublicKey.String()), ), }) return &types.MsgAssignConsumerKeyResponse{}, nil } + +func (k msgServer) RegisterConsumerRewardDenom(goCtx context.Context, msg *types.MsgRegisterConsumerRewardDenom) (*types.MsgRegisterConsumerRewardDenomResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + depositer, err := sdk.AccAddressFromBech32(msg.Depositor) + if err != nil { + return nil, err + } + + if err := k.Keeper.RegisterConsumerRewardDenom(ctx, msg.Denom, depositer); err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent(sdk.NewEvent( + ccvtypes.EventTypeRegisterConsumerRewardDenom, + sdk.NewAttribute(ccvtypes.AttributeConsumerRewardDenom, msg.Denom), + sdk.NewAttribute(ccvtypes.AttributeConsumerRewardDepositor, msg.Depositor), + )) + + return &types.MsgRegisterConsumerRewardDenomResponse{}, nil +} diff --git a/x/ccv/provider/keeper/params.go b/x/ccv/provider/keeper/params.go index 8484dd2426..4b3b486e50 100644 --- a/x/ccv/provider/keeper/params.go +++ b/x/ccv/provider/keeper/params.go @@ -77,6 +77,13 @@ func (k Keeper) GetMaxThrottledPackets(ctx sdk.Context) int64 { return p } +func (k Keeper) GetConsumerRewardDenomRegistrationFee(ctx sdk.Context) sdk.Coin { + // This should be a param, but due to difficulties adding params in migrations during coordinated upgrades, + // we will hardcode the value for now. A future scheduled upgrade will change this to the above code and + // run migrations to add the param. This will allow us to change the fee by governance, but for now it is set at 10 Atoms. + return sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), sdk.NewInt(10000000)) +} + // GetParams returns the paramset for the provider module func (k Keeper) GetParams(ctx sdk.Context) types.Params { return types.NewParams( diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index d67c85d586..07a49d480c 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -9,6 +9,7 @@ import ( ibctmtypes "github.com/cosmos/ibc-go/v4/modules/light-clients/07-tendermint/types" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) @@ -17,7 +18,9 @@ func TestParams(t *testing.T) { // Construct an in-mem keeper with registered key table keeperParams := testkeeper.NewInMemKeeperParams(t) - providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + gomock.InAnyOrder(mocks.MockStakingKeeper.EXPECT().BondDenom( + ctx).Return("stake").AnyTimes()) defer ctrl.Finish() defaultParams := providertypes.DefaultParams() diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index e3d1541f98..15afdbdcae 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -311,6 +311,9 @@ func (k Keeper) MakeConsumerGenesis( prop.ConsumerRedistributionFraction, prop.HistoricalEntries, prop.UnbondingPeriod, + // TODO: this is built on top of v1.1.x, but v1.2.x has another param here (the soft opt-out threshold) + []string{}, + []string{}, ) gen = *consumertypes.NewInitialGenesisState( diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go index 9e9580e6b9..fa7a0846f8 100644 --- a/x/ccv/provider/keeper/proposal_test.go +++ b/x/ccv/provider/keeper/proposal_test.go @@ -105,8 +105,9 @@ func TestHandleConsumerAdditionProposal(t *testing.T) { if tc.expAppendProp { // Mock calls are only asserted if we expect a client to be created. - gomock.InOrder( - testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, tc.prop.ChainId, clienttypes.NewHeight(2, 3))..., + gomock.InAnyOrder( + append(testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, tc.prop.ChainId, clienttypes.NewHeight(2, 3)), + mocks.MockStakingKeeper.EXPECT().BondDenom(gomock.Any()).Return("stake").AnyTimes()), ) } @@ -150,9 +151,10 @@ func TestCreateConsumerClient(t *testing.T) { setup: func(providerKeeper *providerkeeper.Keeper, ctx sdk.Context, mocks *testkeeper.MockedKeepers) { // Valid client creation is asserted with mock expectations here - gomock.InOrder( - testkeeper.GetMocksForCreateConsumerClient(ctx, mocks, "chainID", clienttypes.NewHeight(4, 5))..., - ) + gomock.InAnyOrder(append( + testkeeper.GetMocksForCreateConsumerClient(ctx, mocks, "chainID", clienttypes.NewHeight(4, 5)), + mocks.MockStakingKeeper.EXPECT().BondDenom(ctx).Return("stake").AnyTimes(), + )) }, expClientCreated: true, }, @@ -854,7 +856,7 @@ func TestMakeConsumerGenesis(t *testing.T) { actualGenesis, _, err := providerKeeper.MakeConsumerGenesis(ctx, &prop) require.NoError(t, err) - jsonString := `{"params":{"enabled":true, "blocks_per_distribution_transmission":1000, "ccv_timeout_period":2419200000000000, "transfer_timeout_period": 3600000000000, "consumer_redistribution_fraction":"0.75", "historical_entries":10000, "unbonding_period": 1728000000000000},"new_chain":true,"provider_client_state":{"chain_id":"testchain1","trust_level":{"numerator":1,"denominator":3},"trusting_period":1197504000000000,"unbonding_period":1814400000000000,"max_clock_drift":10000000000,"frozen_height":{},"latest_height":{"revision_height":5},"proof_specs":[{"leaf_spec":{"hash":1,"prehash_value":1,"length":1,"prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":33,"min_prefix_length":4,"max_prefix_length":12,"hash":1}},{"leaf_spec":{"hash":1,"prehash_value":1,"length":1,"prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":32,"min_prefix_length":1,"max_prefix_length":1,"hash":1}}],"upgrade_path":["upgrade","upgradedIBCState"],"allow_update_after_expiry":true,"allow_update_after_misbehaviour":true},"provider_consensus_state":{"timestamp":"2020-01-02T00:00:10Z","root":{"hash":"LpGpeyQVLUo9HpdsgJr12NP2eCICspcULiWa5u9udOA="},"next_validators_hash":"E30CE736441FB9101FADDAF7E578ABBE6DFDB67207112350A9A904D554E1F5BE"},"unbonding_sequences":null,"initial_val_set":[{"pub_key":{"type":"tendermint/PubKeyEd25519","value":"dcASx5/LIKZqagJWN0frOlFtcvz91frYmj/zmoZRWro="},"power":1}]}` + jsonString := `{"params":{"enabled":true, "blocks_per_distribution_transmission":1000, "ccv_timeout_period":2419200000000000, "transfer_timeout_period": 3600000000000, "consumer_redistribution_fraction":"0.75", "historical_entries":10000, "unbonding_period": 1728000000000000, "reward_denoms": [], "provider_reward_denoms": []},"new_chain":true,"provider_client_state":{"chain_id":"testchain1","trust_level":{"numerator":1,"denominator":3},"trusting_period":1197504000000000,"unbonding_period":1814400000000000,"max_clock_drift":10000000000,"frozen_height":{},"latest_height":{"revision_height":5},"proof_specs":[{"leaf_spec":{"hash":1,"prehash_value":1,"length":1,"prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":33,"min_prefix_length":4,"max_prefix_length":12,"hash":1}},{"leaf_spec":{"hash":1,"prehash_value":1,"length":1,"prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":32,"min_prefix_length":1,"max_prefix_length":1,"hash":1}}],"upgrade_path":["upgrade","upgradedIBCState"],"allow_update_after_expiry":true,"allow_update_after_misbehaviour":true},"provider_consensus_state":{"timestamp":"2020-01-02T00:00:10Z","root":{"hash":"LpGpeyQVLUo9HpdsgJr12NP2eCICspcULiWa5u9udOA="},"next_validators_hash":"E30CE736441FB9101FADDAF7E578ABBE6DFDB67207112350A9A904D554E1F5BE"},"unbonding_sequences":null,"initial_val_set":[{"pub_key":{"type":"tendermint/PubKeyEd25519","value":"dcASx5/LIKZqagJWN0frOlFtcvz91frYmj/zmoZRWro="},"power":1}]}` var expectedGenesis consumertypes.GenesisState err = json.Unmarshal([]byte(jsonString), &expectedGenesis) @@ -927,9 +929,11 @@ func TestBeginBlockInit(t *testing.T) { } // Expect client creation for only for the 1st and second proposals (spawn time already passed and valid) - gomock.InOrder( - append(testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain1", clienttypes.NewHeight(3, 4)), - testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain2", clienttypes.NewHeight(3, 4))...)..., + gomock.InAnyOrder( + append(append(testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain1", clienttypes.NewHeight(3, 4)), + testkeeper.GetMocksForCreateConsumerClient(ctx, &mocks, "chain2", clienttypes.NewHeight(3, 4))...), + mocks.MockStakingKeeper.EXPECT().BondDenom(gomock.Any()).Return("stake").AnyTimes(), + ), ) for _, prop := range pendingProps { @@ -995,8 +999,9 @@ func TestBeginBlockCCR(t *testing.T) { // Only first two consumer chains should be stopped expectations = append(expectations, testkeeper.GetMocksForStopConsumerChain(ctx, &mocks)...) expectations = append(expectations, testkeeper.GetMocksForStopConsumerChain(ctx, &mocks)...) + expectations = append(expectations, mocks.MockStakingKeeper.EXPECT().BondDenom(ctx).Return("stake").AnyTimes()) - gomock.InOrder(expectations...) + gomock.InAnyOrder(expectations) // // Remaining setup diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go index cba9af2ae7..39347f9709 100644 --- a/x/ccv/provider/module.go +++ b/x/ccv/provider/module.go @@ -163,6 +163,8 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V am.keeper.EndBlockCCR(ctx) // EndBlock logic needed for the Validator Set Update sub-protocol am.keeper.EndBlockVSU(ctx) + // EndBlock logic need for the Reward Distribution sub-protocol + am.keeper.EndBlockRD(ctx) return []abci.ValidatorUpdate{} } diff --git a/x/ccv/provider/module_test.go b/x/ccv/provider/module_test.go index 1830309f9a..e64a73b5ae 100644 --- a/x/ccv/provider/module_test.go +++ b/x/ccv/provider/module_test.go @@ -123,6 +123,8 @@ func TestInitGenesis(t *testing.T) { &capabilitytypes.Capability{}, tc.isBound, // Capability is returned successfully if port capability is already bound to this module. ), + mocks.MockStakingKeeper.EXPECT().BondDenom( + ctx).Return("stake").AnyTimes(), } // If port capability is not already bound, port will be bound and capability claimed. @@ -145,7 +147,7 @@ func TestInitGenesis(t *testing.T) { ) } - gomock.InOrder(orderedCalls...) + gomock.InAnyOrder(orderedCalls) // // Execute method, then assert expected results diff --git a/x/ccv/provider/proposal_handler_test.go b/x/ccv/provider/proposal_handler_test.go index 0929ea90ef..129a9f3158 100644 --- a/x/ccv/provider/proposal_handler_test.go +++ b/x/ccv/provider/proposal_handler_test.go @@ -95,16 +95,20 @@ func TestProviderProposalHandler(t *testing.T) { // Mock expectations depending on expected outcome switch { case tc.expValidConsumerAddition: - gomock.InOrder(testkeeper.GetMocksForCreateConsumerClient( + gomock.InAnyOrder(append(testkeeper.GetMocksForCreateConsumerClient( ctx, &mocks, "chainID", clienttypes.NewHeight(2, 3), - )...) + ), mocks.MockStakingKeeper.EXPECT().BondDenom( + gomock.Any()).Return("stake").AnyTimes())) case tc.expValidConsumerRemoval: testkeeper.SetupForStoppingConsumerChain(t, ctx, &providerKeeper, mocks) case tc.expValidEquivocation: providerKeeper.SetSlashLog(ctx, equivocation.GetConsensusAddress()) - mocks.MockEvidenceKeeper.EXPECT().HandleEquivocationEvidence(ctx, equivocation) + gomock.InAnyOrder([]*gomock.Call{ + mocks.MockEvidenceKeeper.EXPECT().HandleEquivocationEvidence(ctx, equivocation), + mocks.MockStakingKeeper.EXPECT().BondDenom(gomock.Any()).Return("stake").AnyTimes(), + }) } // Execution diff --git a/x/ccv/provider/types/codec.go b/x/ccv/provider/types/codec.go index 97772e7f00..3e4b34dd42 100644 --- a/x/ccv/provider/types/codec.go +++ b/x/ccv/provider/types/codec.go @@ -27,10 +27,15 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { (*sdk.Msg)(nil), &MsgAssignConsumerKey{}, ) + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgRegisterConsumerRewardDenom{}, + ) registry.RegisterImplementations( (*govtypes.Content)(nil), &EquivocationProposal{}, ) + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/ccv/provider/types/errors.go b/x/ccv/provider/types/errors.go index 21af516878..01e0473049 100644 --- a/x/ccv/provider/types/errors.go +++ b/x/ccv/provider/types/errors.go @@ -18,4 +18,6 @@ var ( ErrConsumerKeyInUse = sdkerrors.Register(ModuleName, 10, "consumer key is already in use by a validator") ErrInvalidConsumerParams = sdkerrors.Register(ModuleName, 11, "invalid consumer params") ErrInvalidProviderAddress = sdkerrors.Register(ModuleName, 12, "invalid provider address") + ErrInvalidConsumerRewardDenom = sdkerrors.Register(ModuleName, 14, "invalid consumer reward denom") + ErrInvalidDepositorAddress = sdkerrors.Register(ModuleName, 15, "invalid depositor address") ) diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 3a3e1151e8..dcdbb29167 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -28,6 +28,9 @@ const ( // Default validator set update ID DefaultValsetUpdateID = 1 + + // This address receives rewards from consumer chains + ConsumerRewardsPool = "consumer_rewards_pool" ) // Iota generated keys/byte prefixes (as a byte), supports 256 possible values @@ -127,6 +130,9 @@ const ( // SlashLogBytePrefix is the byte prefix that will store the mapping from provider address to boolean // denoting whether the provider address has commited any double signign infractions SlashLogBytePrefix + + // ConsumerRewardDenomsBytePrefix is the byte prefix that will store a list of consumer reward denoms + ConsumerRewardDenomsBytePrefix ) // PortKey returns the key to the port ID in the store @@ -351,6 +357,11 @@ func MustParseGlobalSlashEntryKey(bz []byte) ( return recvTime, chainID, ibcSeqNum } +// ConsumerRewardDenomsKey returns the key under which consumer reward denoms are stored +func ConsumerRewardDenomsKey(denom string) []byte { + return append([]byte{ConsumerRewardDenomsBytePrefix}, []byte(denom)...) +} + // ChainIdAndTsKey returns the key with the following format: // bytePrefix | len(chainID) | chainID | timestamp func ChainIdAndTsKey(prefix byte, chainID string, timestamp time.Time) []byte { diff --git a/x/ccv/provider/types/keys_test.go b/x/ccv/provider/types/keys_test.go index a9e3448510..5cb24a15e2 100644 --- a/x/ccv/provider/types/keys_test.go +++ b/x/ccv/provider/types/keys_test.go @@ -66,6 +66,7 @@ func getSingleByteKeys() [][]byte { keys[i], i = []byte{providertypes.ThrottledPacketDataSizeBytePrefix}, i+1 keys[i], i = []byte{providertypes.ThrottledPacketDataBytePrefix}, i+1 keys[i], i = []byte{providertypes.GlobalSlashEntryBytePrefix}, i+1 + keys[i], i = []byte{providertypes.ConsumerRewardDenomsBytePrefix}, i+1 return keys[:i] } diff --git a/x/ccv/provider/types/msg.go b/x/ccv/provider/types/msg.go index 55c0bd40b5..67ad99d10c 100644 --- a/x/ccv/provider/types/msg.go +++ b/x/ccv/provider/types/msg.go @@ -1,38 +1,29 @@ package types import ( + "encoding/json" "strings" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" ) // provider message types const ( - TypeMsgAssignConsumerKey = "assign_consumer_key" + TypeMsgAssignConsumerKey = "assign_consumer_key" + TypeMsgRegisterConsumerRewardDenom = "register_consumer_reward_denom" ) -var ( - _ sdk.Msg = &MsgAssignConsumerKey{} - _ codectypes.UnpackInterfacesMessage = (*MsgAssignConsumerKey)(nil) -) +var _ sdk.Msg = &MsgAssignConsumerKey{} // NewMsgAssignConsumerKey creates a new MsgAssignConsumerKey instance. // Delegator address and validator address are the same. func NewMsgAssignConsumerKey(chainID string, providerValidatorAddress sdk.ValAddress, - consumerConsensusPubKey cryptotypes.PubKey) (*MsgAssignConsumerKey, error) { - var keyAsAny *codectypes.Any - if consumerConsensusPubKey != nil { - var err error - if keyAsAny, err = codectypes.NewAnyWithValue(consumerConsensusPubKey); err != nil { - return nil, err - } - } + consumerConsensusPubKey string, +) (*MsgAssignConsumerKey, error) { return &MsgAssignConsumerKey{ ChainId: chainID, ProviderAddr: providerValidatorAddress.String(), - ConsumerKey: keyAsAny, + ConsumerKey: consumerConsensusPubKey, }, nil } @@ -80,14 +71,71 @@ func (msg MsgAssignConsumerKey) ValidateBasic() error { if err != nil { return ErrInvalidProviderAddress } - if msg.ConsumerKey == nil { + if msg.ConsumerKey == "" { + return ErrInvalidConsumerConsensusPubKey + } + if _, _, err := ParseConsumerKeyFromJson(msg.ConsumerKey); err != nil { return ErrInvalidConsumerConsensusPubKey } return nil } -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (msg MsgAssignConsumerKey) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var pubKey cryptotypes.PubKey - return unpacker.UnpackAny(msg.ConsumerKey, &pubKey) +// ParseConsumerKeyFromJson parses the consumer key from a JSON string, +// this replaces deserializing a protobuf any. +func ParseConsumerKeyFromJson(jsonStr string) (pkType, key string, err error) { + type PubKey struct { + Type string `json:"@type"` + Key string `json:"key"` + } + var pubKey PubKey + err = json.Unmarshal([]byte(jsonStr), &pubKey) + if err != nil { + return "", "", err + } + return pubKey.Type, pubKey.Key, nil +} + +// NewMsgRegisterConsumerRewardDenom returns a new MsgRegisterConsumerRewardDenom with a sender and +// a funding amount. +func NewMsgRegisterConsumerRewardDenom(denom string, depositor sdk.AccAddress) *MsgRegisterConsumerRewardDenom { + return &MsgRegisterConsumerRewardDenom{ + Denom: denom, + Depositor: depositor.String(), + } +} + +// Route returns the MsgRegisterConsumerRewardDenom message route. +func (msg MsgRegisterConsumerRewardDenom) Route() string { return ModuleName } + +// Type returns the MsgRegisterConsumerRewardDenom message type. +func (msg MsgRegisterConsumerRewardDenom) Type() string { return TypeMsgRegisterConsumerRewardDenom } + +// GetSigners returns the signer addresses that are expected to sign the result +// of GetSignBytes. +func (msg MsgRegisterConsumerRewardDenom) GetSigners() []sdk.AccAddress { + depoAddr, err := sdk.AccAddressFromBech32(msg.Depositor) + if err != nil { + panic(err) + } + return []sdk.AccAddress{depoAddr} +} + +// GetSignBytes returns the raw bytes for a MsgRegisterConsumerRewardDenom message that +// the expected signer needs to sign. +func (msg MsgRegisterConsumerRewardDenom) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// ValidateBasic performs basic MsgRegisterConsumerRewardDenom message validation. +func (msg MsgRegisterConsumerRewardDenom) ValidateBasic() error { + if !sdk.NewCoin(msg.Denom, sdk.NewInt(0)).IsValid() { + return ErrInvalidConsumerRewardDenom + } + _, err := sdk.AccAddressFromBech32(msg.Depositor) + if err != nil { + return ErrInvalidDepositorAddress + } + + return nil } diff --git a/x/ccv/provider/types/params.go b/x/ccv/provider/types/params.go index eb7e47ba1d..360fa65989 100644 --- a/x/ccv/provider/types/params.go +++ b/x/ccv/provider/types/params.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v4/modules/core/23-commitment/types" @@ -42,13 +43,14 @@ const ( // Reflection based keys for params subspace var ( - KeyTemplateClient = []byte("TemplateClient") - KeyTrustingPeriodFraction = []byte("TrustingPeriodFraction") - KeyInitTimeoutPeriod = []byte("InitTimeoutPeriod") - KeyVscTimeoutPeriod = []byte("VscTimeoutPeriod") - KeySlashMeterReplenishPeriod = []byte("SlashMeterReplenishPeriod") - KeySlashMeterReplenishFraction = []byte("SlashMeterReplenishFraction") - KeyMaxThrottledPackets = []byte("MaxThrottledPackets") + KeyTemplateClient = []byte("TemplateClient") + KeyTrustingPeriodFraction = []byte("TrustingPeriodFraction") + KeyInitTimeoutPeriod = []byte("InitTimeoutPeriod") + KeyVscTimeoutPeriod = []byte("VscTimeoutPeriod") + KeySlashMeterReplenishPeriod = []byte("SlashMeterReplenishPeriod") + KeySlashMeterReplenishFraction = []byte("SlashMeterReplenishFraction") + KeyMaxThrottledPackets = []byte("MaxThrottledPackets") + KeyConsumerRewardDenomRegistrationFee = []byte("ConsumerRewardDenomRegistrationFee") ) // ParamKeyTable returns a key table with the necessary registered provider params @@ -178,3 +180,16 @@ func validateTemplateClient(i interface{}) error { } return nil } + +func validateCoin(i interface{}) error { + v, ok := i.(sdk.Coin) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if !v.IsValid() { + return fmt.Errorf("invalid consumer reward denom registration fee: %s", v) + } + + return nil +} diff --git a/x/ccv/provider/types/params_test.go b/x/ccv/provider/types/params_test.go index acee7abe11..f6c5901f5f 100644 --- a/x/ccv/provider/types/params_test.go +++ b/x/ccv/provider/types/params_test.go @@ -50,6 +50,12 @@ func TestValidateParams(t *testing.T) { {"negative max pending slash packets", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), "0.33", time.Hour, time.Hour, 24*time.Hour, time.Hour, "0.1", -100), false}, + {"invalid consumer reward denom registration fee denom", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + "0.33", time.Hour, time.Hour, 24*time.Hour, time.Hour, "0.1", -100), false}, + {"invalid consumer reward denom registration fee amount", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + "0.33", time.Hour, time.Hour, 24*time.Hour, time.Hour, "0.1", -100), false}, } for _, tc := range testCases { diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index a52166adf3..f9ccfbfe5c 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types" types1 "github.com/cosmos/cosmos-sdk/x/evidence/types" types "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" types2 "github.com/cosmos/ibc-go/v4/modules/light-clients/07-tendermint/types" @@ -1021,95 +1022,96 @@ func init() { } var fileDescriptor_f22ec409a72b7b72 = []byte{ - // 1406 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0x4b, 0x6f, 0xdb, 0xc6, - 0x16, 0x36, 0x2d, 0xf9, 0xa1, 0x91, 0x9f, 0xb4, 0x93, 0xd0, 0xb9, 0xbe, 0xb2, 0xa2, 0xdc, 0x7b, - 0xa1, 0x8b, 0x20, 0x14, 0xec, 0x6c, 0x0a, 0xa3, 0x45, 0x61, 0x2b, 0x0f, 0xbb, 0x6e, 0x12, 0x87, - 0x76, 0x5d, 0xb4, 0x5d, 0x10, 0xc3, 0xe1, 0x58, 0x1a, 0x98, 0xe4, 0x30, 0x33, 0x23, 0x26, 0xfa, - 0x07, 0x5d, 0xa6, 0xe8, 0x26, 0x40, 0x37, 0xf9, 0x07, 0xfd, 0x1b, 0x59, 0x66, 0xd9, 0x55, 0x5a, - 0x38, 0xcb, 0xee, 0xfa, 0x0b, 0x8a, 0x99, 0xe1, 0x43, 0x54, 0x1c, 0xc0, 0x41, 0xdb, 0x1d, 0xe7, - 0x9c, 0xef, 0x7c, 0xf3, 0x38, 0xe7, 0x7c, 0x33, 0x04, 0x5b, 0x24, 0x12, 0x98, 0xa1, 0x3e, 0x24, - 0x91, 0xcb, 0x31, 0x1a, 0x30, 0x22, 0x86, 0x1d, 0x84, 0x92, 0x4e, 0xcc, 0x68, 0x42, 0x7c, 0xcc, - 0x3a, 0xc9, 0x66, 0xfe, 0x6d, 0xc7, 0x8c, 0x0a, 0x6a, 0xde, 0xbc, 0x20, 0xc6, 0x46, 0x28, 0xb1, - 0x73, 0x5c, 0xb2, 0x79, 0x7d, 0xb5, 0x47, 0x7b, 0x54, 0xe1, 0x3b, 0xf2, 0x4b, 0x87, 0x5e, 0xdf, - 0xe8, 0x51, 0xda, 0x0b, 0x70, 0x47, 0x8d, 0xbc, 0xc1, 0x69, 0x47, 0x90, 0x10, 0x73, 0x01, 0xc3, - 0x38, 0x05, 0x34, 0xc6, 0x01, 0xfe, 0x80, 0x41, 0x41, 0x68, 0x94, 0x11, 0x10, 0x0f, 0x75, 0x10, - 0x65, 0xb8, 0x83, 0x02, 0x82, 0x23, 0x21, 0x97, 0xa7, 0xbf, 0x52, 0x40, 0x47, 0x02, 0x02, 0xd2, - 0xeb, 0x0b, 0x6d, 0xe6, 0x1d, 0x81, 0x23, 0x1f, 0xb3, 0x90, 0x68, 0x70, 0x31, 0x4a, 0x03, 0xd6, - 0x47, 0xfc, 0x88, 0x0d, 0x63, 0x41, 0x3b, 0x67, 0x78, 0xc8, 0x53, 0xef, 0xff, 0x10, 0xe5, 0x21, - 0xe5, 0x1d, 0x2c, 0x37, 0x16, 0x21, 0xdc, 0x49, 0x36, 0x3d, 0x2c, 0xe0, 0x66, 0x6e, 0xd0, 0xb8, - 0xd6, 0x8f, 0xd3, 0xc0, 0xea, 0xd2, 0x88, 0x0f, 0x42, 0xcc, 0x76, 0x7c, 0x9f, 0xc8, 0x25, 0x1f, - 0x32, 0x1a, 0x53, 0x0e, 0x03, 0x73, 0x15, 0x4c, 0x09, 0x22, 0x02, 0x6c, 0x19, 0x4d, 0xa3, 0x5d, - 0x73, 0xf4, 0xc0, 0x6c, 0x82, 0xba, 0x8f, 0x39, 0x62, 0x24, 0x96, 0x60, 0x6b, 0x52, 0xf9, 0x46, - 0x4d, 0xe6, 0x1a, 0x98, 0xd5, 0xa7, 0x4c, 0x7c, 0xab, 0xa2, 0xdc, 0x33, 0x6a, 0xbc, 0xef, 0x9b, - 0x0f, 0xc0, 0x02, 0x89, 0x88, 0x20, 0x30, 0x70, 0xfb, 0x58, 0xee, 0xd6, 0xaa, 0x36, 0x8d, 0x76, - 0x7d, 0xeb, 0xba, 0x4d, 0x3c, 0x64, 0xcb, 0x03, 0xb2, 0xd3, 0x63, 0x49, 0x36, 0xed, 0x3d, 0x85, - 0xd8, 0xad, 0xbe, 0x7e, 0xbb, 0x31, 0xe1, 0xcc, 0xa7, 0x71, 0xda, 0x68, 0xde, 0x00, 0x73, 0x3d, - 0x1c, 0x61, 0x4e, 0xb8, 0xdb, 0x87, 0xbc, 0x6f, 0x4d, 0x35, 0x8d, 0xf6, 0x9c, 0x53, 0x4f, 0x6d, - 0x7b, 0x90, 0xf7, 0xcd, 0x0d, 0x50, 0xf7, 0x48, 0x04, 0xd9, 0x50, 0x23, 0xa6, 0x15, 0x02, 0x68, - 0x93, 0x02, 0x74, 0x01, 0xe0, 0x31, 0x7c, 0x16, 0xb9, 0x32, 0x9b, 0xd6, 0x4c, 0xba, 0x10, 0x9d, - 0x49, 0x3b, 0xcb, 0xa4, 0x7d, 0x9c, 0xa5, 0x7a, 0x77, 0x56, 0x2e, 0xe4, 0xc5, 0xaf, 0x1b, 0x86, - 0x53, 0x53, 0x71, 0xd2, 0x63, 0x3e, 0x02, 0x4b, 0x83, 0xc8, 0xa3, 0x91, 0x4f, 0xa2, 0x9e, 0x1b, - 0x63, 0x46, 0xa8, 0x6f, 0xcd, 0x2a, 0xaa, 0xb5, 0xf7, 0xa8, 0xee, 0xa6, 0x45, 0xa1, 0x99, 0x5e, - 0x4a, 0xa6, 0xc5, 0x3c, 0xf8, 0x50, 0xc5, 0x9a, 0x4f, 0x80, 0x89, 0x50, 0xa2, 0x96, 0x44, 0x07, - 0x22, 0x63, 0xac, 0x5d, 0x9e, 0x71, 0x09, 0xa1, 0xe4, 0x58, 0x47, 0xa7, 0x94, 0xdf, 0x81, 0x6b, - 0x82, 0xc1, 0x88, 0x9f, 0x62, 0x36, 0xce, 0x0b, 0x2e, 0xcf, 0x7b, 0x25, 0xe3, 0x28, 0x93, 0xef, - 0x81, 0x26, 0x4a, 0x0b, 0xc8, 0x65, 0xd8, 0x27, 0x5c, 0x30, 0xe2, 0x0d, 0x64, 0xac, 0x7b, 0xca, - 0x20, 0x52, 0x35, 0x52, 0x57, 0x45, 0xd0, 0xc8, 0x70, 0x4e, 0x09, 0x76, 0x3f, 0x45, 0x99, 0x8f, - 0xc1, 0x7f, 0xbc, 0x80, 0xa2, 0x33, 0x2e, 0x17, 0xe7, 0x96, 0x98, 0xd4, 0xd4, 0x21, 0xe1, 0x5c, - 0xb2, 0xcd, 0x35, 0x8d, 0x76, 0xc5, 0xb9, 0xa1, 0xb1, 0x87, 0x98, 0xdd, 0x1d, 0x41, 0x1e, 0x8f, - 0x00, 0xcd, 0xdb, 0xc0, 0xec, 0x13, 0x2e, 0x28, 0x23, 0x08, 0x06, 0x2e, 0x8e, 0x04, 0x23, 0x98, - 0x5b, 0xf3, 0x2a, 0x7c, 0xb9, 0xf0, 0xdc, 0xd3, 0x8e, 0xed, 0xd9, 0xef, 0x5f, 0x6d, 0x4c, 0xbc, - 0x7c, 0xb5, 0x31, 0xd1, 0xfa, 0xd9, 0x00, 0xd7, 0xba, 0xf9, 0x62, 0x43, 0x9a, 0xc0, 0xe0, 0x9f, - 0x6c, 0x8a, 0x1d, 0x50, 0xe3, 0x82, 0xc6, 0xba, 0x0c, 0xab, 0x1f, 0x51, 0x86, 0xb3, 0x32, 0x4c, - 0x3a, 0x5a, 0x3f, 0x19, 0x60, 0xf5, 0xde, 0xd3, 0x01, 0x49, 0x28, 0x82, 0x7f, 0x4b, 0x0f, 0x1f, - 0x80, 0x79, 0x3c, 0xc2, 0xc7, 0xad, 0x4a, 0xb3, 0xd2, 0xae, 0x6f, 0xfd, 0xd7, 0xd6, 0xc2, 0x62, - 0xe7, 0x3a, 0x92, 0x0a, 0x8b, 0x3d, 0x3a, 0xbb, 0x53, 0x8e, 0x6d, 0xfd, 0x6e, 0x80, 0xa5, 0x07, - 0x01, 0xf5, 0x60, 0x70, 0x14, 0x40, 0xde, 0x97, 0x07, 0x3e, 0x94, 0xbb, 0x66, 0x38, 0xad, 0x74, - 0xb5, 0xba, 0x4b, 0xef, 0x5a, 0x86, 0xa9, 0xde, 0xfb, 0x1c, 0x2c, 0xe7, 0xb5, 0x97, 0x1f, 0xae, - 0xda, 0xcc, 0xee, 0xca, 0xf9, 0xdb, 0x8d, 0xc5, 0x2c, 0x87, 0x5d, 0x75, 0xd0, 0x77, 0x9d, 0x45, - 0x54, 0x32, 0xf8, 0x66, 0x03, 0xd4, 0x89, 0x87, 0x5c, 0x8e, 0x9f, 0xba, 0xd1, 0x20, 0x54, 0x79, - 0xa9, 0x3a, 0x35, 0xe2, 0xa1, 0x23, 0xfc, 0xf4, 0xd1, 0x20, 0x34, 0xef, 0x80, 0xab, 0xd9, 0xe5, - 0xe0, 0x26, 0x30, 0x70, 0x65, 0xbc, 0x0b, 0x7d, 0x9f, 0xa9, 0x34, 0xcd, 0x39, 0x2b, 0x99, 0xf7, - 0x04, 0x06, 0x72, 0xb2, 0x1d, 0xdf, 0x67, 0xad, 0x3f, 0xaa, 0x60, 0xfa, 0x10, 0x32, 0x18, 0x72, - 0xf3, 0x18, 0x2c, 0x0a, 0x1c, 0xc6, 0x01, 0x14, 0xd8, 0xd5, 0xba, 0x96, 0xee, 0xf4, 0x96, 0xd2, - 0xbb, 0x51, 0xbd, 0xb7, 0x47, 0x14, 0x3e, 0xd9, 0xb4, 0xbb, 0xca, 0x7a, 0x24, 0xa0, 0xc0, 0xce, - 0x42, 0xc6, 0xa1, 0x8d, 0xe6, 0x27, 0xc0, 0x12, 0x6c, 0xc0, 0x45, 0xa1, 0x38, 0x45, 0xab, 0xe9, - 0x54, 0x5e, 0xcd, 0xfc, 0xba, 0x49, 0xf3, 0x16, 0xbb, 0x58, 0x5c, 0x2a, 0x7f, 0x45, 0x5c, 0x8e, - 0xc0, 0x8a, 0x54, 0xe6, 0x71, 0xce, 0xea, 0xe5, 0x39, 0x97, 0x65, 0x7c, 0x99, 0xf4, 0x09, 0x30, - 0x13, 0x8e, 0xc6, 0x39, 0xa7, 0x3e, 0x62, 0x9d, 0x09, 0x47, 0x65, 0x4a, 0x1f, 0xac, 0x73, 0x59, - 0x7c, 0x6e, 0x88, 0x85, 0x92, 0xaa, 0x38, 0xc0, 0x11, 0xe1, 0xfd, 0x8c, 0x7c, 0xfa, 0xf2, 0xe4, - 0x6b, 0x8a, 0xe8, 0xa1, 0xe4, 0x71, 0x32, 0x9a, 0x74, 0x96, 0x2e, 0x68, 0x5c, 0x3c, 0x4b, 0x9e, - 0xa0, 0x19, 0x95, 0xa0, 0x7f, 0x5d, 0x40, 0x91, 0x67, 0x69, 0x0b, 0x5c, 0x09, 0xe1, 0x73, 0x57, - 0xf4, 0x19, 0x15, 0x22, 0xc0, 0xbe, 0x1b, 0x43, 0x74, 0x86, 0x05, 0x57, 0xf7, 0x4a, 0xc5, 0x59, - 0x09, 0xe1, 0xf3, 0xe3, 0xcc, 0x77, 0xa8, 0x5d, 0x2d, 0x0f, 0x2c, 0xef, 0xc1, 0xc8, 0xe7, 0x7d, - 0x78, 0x86, 0x1f, 0x62, 0x01, 0x7d, 0x28, 0x60, 0xa9, 0x7c, 0x4f, 0x31, 0x76, 0x63, 0x4a, 0x03, - 0x5d, 0xbe, 0x5a, 0x0d, 0xf2, 0xf2, 0xbd, 0x8f, 0xf1, 0x21, 0xa5, 0x81, 0x2c, 0x5f, 0xd3, 0x02, - 0x33, 0x09, 0x66, 0xbc, 0x28, 0xa6, 0x6c, 0xd8, 0xfa, 0x3f, 0xa8, 0xa9, 0xfe, 0xdd, 0x41, 0x67, - 0xdc, 0x5c, 0x07, 0x35, 0xc9, 0x84, 0x39, 0xc7, 0xdc, 0x32, 0x9a, 0x95, 0x76, 0xcd, 0x29, 0x0c, - 0x2d, 0x01, 0xd6, 0x3e, 0xf4, 0xac, 0xe0, 0xe6, 0xd7, 0x60, 0x26, 0xc6, 0xea, 0xce, 0x53, 0x81, - 0xf5, 0xad, 0xcf, 0xec, 0x4b, 0x3c, 0xcd, 0xec, 0x0f, 0x11, 0x3a, 0x19, 0x5b, 0x8b, 0x15, 0x8f, - 0x99, 0x31, 0xd9, 0xe6, 0xe6, 0xc9, 0xf8, 0xa4, 0x9f, 0x7e, 0xd4, 0xa4, 0x63, 0x7c, 0xc5, 0x9c, - 0xb7, 0x40, 0x7d, 0x47, 0x6f, 0xfb, 0x4b, 0xc2, 0xc5, 0xfb, 0xc7, 0x32, 0x37, 0x7a, 0x2c, 0x5f, - 0x80, 0x85, 0x6e, 0x1f, 0x46, 0x11, 0x0e, 0x8e, 0xa9, 0xd2, 0x20, 0xf3, 0xdf, 0x00, 0x20, 0x6d, - 0x91, 0xda, 0xa5, 0xd3, 0x52, 0x4b, 0x2d, 0xfb, 0x7e, 0xe9, 0xd6, 0x98, 0x2c, 0xdd, 0x1a, 0x2d, - 0x07, 0x2c, 0x9e, 0x70, 0xf4, 0x55, 0xf6, 0x7c, 0x78, 0x1c, 0x73, 0xf3, 0x0a, 0x98, 0x96, 0x6d, - 0x93, 0x12, 0x55, 0x9d, 0xa9, 0x84, 0xa3, 0x7d, 0xdf, 0x6c, 0x8f, 0x3e, 0x51, 0x68, 0xec, 0x12, - 0x9f, 0x5b, 0x93, 0xcd, 0x4a, 0xbb, 0xea, 0x2c, 0x0c, 0x8a, 0xf0, 0x7d, 0x9f, 0xb7, 0xbe, 0x01, - 0xf5, 0x11, 0x42, 0x73, 0x01, 0x4c, 0xe6, 0x5c, 0x93, 0xc4, 0x37, 0xb7, 0xc1, 0x5a, 0x41, 0x54, - 0x56, 0x5e, 0xcd, 0x58, 0x73, 0xae, 0xe5, 0x80, 0x92, 0xf8, 0xf2, 0xd6, 0x63, 0xb0, 0xba, 0x5f, - 0xf4, 0x79, 0xae, 0xeb, 0xa5, 0x1d, 0x1a, 0xe5, 0x7b, 0x71, 0x1d, 0xd4, 0xf2, 0x77, 0xb6, 0xda, - 0x7d, 0xd5, 0x29, 0x0c, 0xad, 0x10, 0x2c, 0x9d, 0x70, 0x74, 0x84, 0x23, 0xbf, 0x20, 0xfb, 0xc0, - 0x01, 0xec, 0x8e, 0x13, 0x5d, 0xfa, 0x9d, 0x57, 0x4c, 0xf7, 0x83, 0x01, 0xac, 0x03, 0x3c, 0xdc, - 0xe1, 0x9c, 0xf4, 0xa2, 0x10, 0x47, 0x42, 0xf6, 0x2d, 0x44, 0x58, 0x7e, 0x9a, 0x37, 0xc1, 0x7c, - 0xde, 0x68, 0x79, 0x7f, 0xcd, 0x39, 0x73, 0x99, 0x51, 0x35, 0xd6, 0x36, 0x00, 0x31, 0xc3, 0x89, - 0x8b, 0xdc, 0x33, 0x3c, 0x4c, 0x97, 0xb1, 0x3e, 0x2a, 0xfb, 0xfa, 0x19, 0x6f, 0x1f, 0x0e, 0xbc, - 0x80, 0xa0, 0x03, 0x3c, 0x74, 0x66, 0x25, 0xbe, 0x7b, 0x80, 0x87, 0xf2, 0x1a, 0x8f, 0xe9, 0x33, - 0xcc, 0x94, 0x56, 0x57, 0x1c, 0x3d, 0xd8, 0x3d, 0x7e, 0x7d, 0xde, 0x30, 0xde, 0x9c, 0x37, 0x8c, - 0xdf, 0xce, 0x1b, 0xc6, 0x8b, 0x77, 0x8d, 0x89, 0x37, 0xef, 0x1a, 0x13, 0xbf, 0xbc, 0x6b, 0x4c, - 0x7c, 0xbb, 0xdd, 0x23, 0xa2, 0x3f, 0xf0, 0x6c, 0x44, 0xc3, 0x4e, 0xfa, 0x2b, 0x50, 0x54, 0xfb, - 0xed, 0xfc, 0x8f, 0xe9, 0x79, 0xf9, 0x9f, 0x49, 0x0c, 0x63, 0xcc, 0xbd, 0x69, 0x75, 0x24, 0x77, - 0xfe, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x9f, 0x8d, 0x5d, 0x93, 0x64, 0x0d, 0x00, 0x00, + // 1415 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0x4b, 0x6f, 0xdc, 0xb6, + 0x16, 0xb6, 0x3c, 0xe3, 0xc7, 0x70, 0xfc, 0x94, 0x9d, 0x44, 0xce, 0xf5, 0x1d, 0x4f, 0x26, 0xf7, + 0x5e, 0xcc, 0x45, 0x10, 0x0d, 0xec, 0x6c, 0x0a, 0xa3, 0x45, 0x61, 0x4f, 0x1e, 0x76, 0xdd, 0x24, + 0x8e, 0xec, 0xba, 0x68, 0xbb, 0x10, 0x28, 0x8a, 0x9e, 0x21, 0x2c, 0x89, 0x0a, 0xc9, 0x51, 0x32, + 0xff, 0xa0, 0xcb, 0x14, 0xdd, 0x04, 0xe8, 0x26, 0xff, 0xa0, 0x7f, 0x23, 0xcb, 0x2c, 0xbb, 0x4a, + 0x0b, 0x67, 0xd9, 0x5d, 0x7f, 0x41, 0x41, 0x52, 0x8f, 0xd1, 0xc4, 0x01, 0x1c, 0xb4, 0xdd, 0x89, + 0xe7, 0x7c, 0xe7, 0xe3, 0xe1, 0x79, 0x91, 0x02, 0x5b, 0x24, 0x12, 0x98, 0xa1, 0x3e, 0x24, 0x91, + 0xcb, 0x31, 0x1a, 0x30, 0x22, 0x86, 0x1d, 0x84, 0x92, 0x4e, 0xcc, 0x68, 0x42, 0x7c, 0xcc, 0x3a, + 0xc9, 0x66, 0xfe, 0x6d, 0xc7, 0x8c, 0x0a, 0x6a, 0xde, 0xbc, 0xc0, 0xc6, 0x46, 0x28, 0xb1, 0x73, + 0x5c, 0xb2, 0x79, 0x7d, 0xb5, 0x47, 0x7b, 0x54, 0xe1, 0x3b, 0xf2, 0x4b, 0x9b, 0x5e, 0xdf, 0xe8, + 0x51, 0xda, 0x0b, 0x70, 0x47, 0xad, 0xbc, 0xc1, 0x69, 0x47, 0x90, 0x10, 0x73, 0x01, 0xc3, 0x38, + 0x05, 0x34, 0xc6, 0x01, 0xfe, 0x80, 0x41, 0x41, 0x68, 0x94, 0x11, 0x10, 0x0f, 0x75, 0x10, 0x65, + 0xb8, 0x83, 0x02, 0x82, 0x23, 0x21, 0xdd, 0xd3, 0x5f, 0x29, 0xa0, 0x23, 0x01, 0x01, 0xe9, 0xf5, + 0x85, 0x16, 0xf3, 0x8e, 0xc0, 0x91, 0x8f, 0x59, 0x48, 0x34, 0xb8, 0x58, 0xa5, 0x06, 0xeb, 0x23, + 0x7a, 0xc4, 0x86, 0xb1, 0xa0, 0x9d, 0x33, 0x3c, 0xe4, 0xa9, 0xf6, 0x7f, 0x88, 0xf2, 0x90, 0xf2, + 0x0e, 0x96, 0x07, 0x8b, 0x10, 0xee, 0x24, 0x9b, 0x1e, 0x16, 0x70, 0x33, 0x17, 0x64, 0x7e, 0xa7, + 0x38, 0x0f, 0xf2, 0x02, 0x83, 0x28, 0x49, 0xfd, 0x6e, 0xfd, 0x38, 0x0d, 0xac, 0x2e, 0x8d, 0xf8, + 0x20, 0xc4, 0x6c, 0xc7, 0xf7, 0x89, 0x3c, 0xd2, 0x21, 0xa3, 0x31, 0xe5, 0x30, 0x30, 0x57, 0xc1, + 0x94, 0x20, 0x22, 0xc0, 0x96, 0xd1, 0x34, 0xda, 0x35, 0x47, 0x2f, 0xcc, 0x26, 0xa8, 0xfb, 0x98, + 0x23, 0x46, 0x62, 0x09, 0xb6, 0x26, 0x95, 0x6e, 0x54, 0x64, 0xae, 0x81, 0x59, 0x9d, 0x05, 0xe2, + 0x5b, 0x15, 0xa5, 0x9e, 0x51, 0xeb, 0x7d, 0xdf, 0x7c, 0x00, 0x16, 0x48, 0x44, 0x04, 0x81, 0x81, + 0xdb, 0xc7, 0x32, 0x1a, 0x56, 0xb5, 0x69, 0xb4, 0xeb, 0x5b, 0xd7, 0x6d, 0xe2, 0x21, 0x5b, 0x06, + 0xd0, 0x4e, 0xc3, 0x96, 0x6c, 0xda, 0x7b, 0x0a, 0xb1, 0x5b, 0x7d, 0xfd, 0x76, 0x63, 0xc2, 0x99, + 0x4f, 0xed, 0xb4, 0xd0, 0xbc, 0x01, 0xe6, 0x7a, 0x38, 0xc2, 0x9c, 0x70, 0xb7, 0x0f, 0x79, 0xdf, + 0x9a, 0x6a, 0x1a, 0xed, 0x39, 0xa7, 0x9e, 0xca, 0xf6, 0x20, 0xef, 0x9b, 0x1b, 0xa0, 0xee, 0x91, + 0x08, 0xb2, 0xa1, 0x46, 0x4c, 0x2b, 0x04, 0xd0, 0x22, 0x05, 0xe8, 0x02, 0xc0, 0x63, 0xf8, 0x2c, + 0x72, 0x65, 0xb6, 0xad, 0x99, 0xd4, 0x11, 0x9d, 0x69, 0x3b, 0xcb, 0xb4, 0x7d, 0x9c, 0x95, 0xc2, + 0xee, 0xac, 0x74, 0xe4, 0xc5, 0xaf, 0x1b, 0x86, 0x53, 0x53, 0x76, 0x52, 0x63, 0x3e, 0x02, 0x4b, + 0x83, 0xc8, 0xa3, 0x91, 0x4f, 0xa2, 0x9e, 0x1b, 0x63, 0x46, 0xa8, 0x6f, 0xcd, 0x2a, 0xaa, 0xb5, + 0xf7, 0xa8, 0xee, 0xa6, 0x45, 0xa3, 0x99, 0x5e, 0x4a, 0xa6, 0xc5, 0xdc, 0xf8, 0x50, 0xd9, 0x9a, + 0x4f, 0x80, 0x89, 0x50, 0xa2, 0x5c, 0xa2, 0x03, 0x91, 0x31, 0xd6, 0x2e, 0xcf, 0xb8, 0x84, 0x50, + 0x72, 0xac, 0xad, 0x53, 0xca, 0xef, 0xc0, 0x35, 0xc1, 0x60, 0xc4, 0x4f, 0x31, 0x1b, 0xe7, 0x05, + 0x97, 0xe7, 0xbd, 0x92, 0x71, 0x94, 0xc9, 0xf7, 0x40, 0x13, 0xa5, 0x05, 0xe4, 0x32, 0xec, 0x13, + 0x2e, 0x18, 0xf1, 0x06, 0xd2, 0xd6, 0x3d, 0x65, 0x10, 0xa9, 0x1a, 0xa9, 0xab, 0x22, 0x68, 0x64, + 0x38, 0xa7, 0x04, 0xbb, 0x9f, 0xa2, 0xcc, 0xc7, 0xe0, 0x3f, 0x5e, 0x40, 0xd1, 0x19, 0x97, 0xce, + 0xb9, 0x25, 0x26, 0xb5, 0x75, 0x48, 0x38, 0x97, 0x6c, 0x73, 0x4d, 0xa3, 0x5d, 0x71, 0x6e, 0x68, + 0xec, 0x21, 0x66, 0x77, 0x47, 0x90, 0xc7, 0x23, 0x40, 0xf3, 0x36, 0x30, 0xfb, 0x84, 0x0b, 0xca, + 0x08, 0x82, 0x81, 0x8b, 0x23, 0xc1, 0x08, 0xe6, 0xd6, 0xbc, 0x32, 0x5f, 0x2e, 0x34, 0xf7, 0xb4, + 0x62, 0x7b, 0xf6, 0xfb, 0x57, 0x1b, 0x13, 0x2f, 0x5f, 0x6d, 0x4c, 0xb4, 0x7e, 0x36, 0xc0, 0xb5, + 0x6e, 0xee, 0x6c, 0x48, 0x13, 0x18, 0xfc, 0x93, 0x4d, 0xb1, 0x03, 0x6a, 0x5c, 0xd0, 0x58, 0x97, + 0x61, 0xf5, 0x23, 0xca, 0x70, 0x56, 0x9a, 0x49, 0x45, 0xeb, 0x27, 0x03, 0xac, 0xde, 0x7b, 0x3a, + 0x20, 0x09, 0x45, 0xf0, 0x6f, 0xe9, 0xe1, 0x03, 0x30, 0x8f, 0x47, 0xf8, 0xb8, 0x55, 0x69, 0x56, + 0xda, 0xf5, 0xad, 0xff, 0xda, 0x7a, 0xa0, 0xd8, 0xf9, 0x9c, 0x49, 0x87, 0x8a, 0x3d, 0xba, 0xbb, + 0x53, 0xb6, 0x6d, 0xfd, 0x6e, 0x80, 0xa5, 0x07, 0x01, 0xf5, 0x60, 0x70, 0x14, 0x40, 0xde, 0x97, + 0x01, 0x1f, 0xca, 0x53, 0x33, 0x9c, 0x56, 0xba, 0xf2, 0xee, 0xd2, 0xa7, 0x96, 0x66, 0xaa, 0xf7, + 0x3e, 0x07, 0xcb, 0x79, 0xed, 0xe5, 0xc1, 0x55, 0x87, 0xd9, 0x5d, 0x39, 0x7f, 0xbb, 0xb1, 0x98, + 0xe5, 0xb0, 0xab, 0x02, 0x7d, 0xd7, 0x59, 0x44, 0x25, 0x81, 0x6f, 0x36, 0x40, 0x9d, 0x78, 0xc8, + 0xe5, 0xf8, 0xa9, 0x1b, 0x0d, 0x42, 0x95, 0x97, 0xaa, 0x53, 0x23, 0x1e, 0x3a, 0xc2, 0x4f, 0x1f, + 0x0d, 0x42, 0xf3, 0x0e, 0xb8, 0x9a, 0x5d, 0x1e, 0x6e, 0x02, 0x03, 0x57, 0xda, 0xbb, 0xd0, 0xf7, + 0x99, 0x4a, 0xd3, 0x9c, 0xb3, 0x92, 0x69, 0x4f, 0x60, 0x20, 0x37, 0xdb, 0xf1, 0x7d, 0xd6, 0xfa, + 0xa3, 0x0a, 0xa6, 0x0f, 0x21, 0x83, 0x21, 0x37, 0x8f, 0xc1, 0xa2, 0xc0, 0x61, 0x1c, 0x40, 0x81, + 0x5d, 0x3d, 0xd7, 0xd2, 0x93, 0xde, 0x52, 0xf3, 0x6e, 0xf4, 0x3e, 0xb0, 0x47, 0x6e, 0x80, 0x64, + 0xd3, 0xee, 0x2a, 0xe9, 0x91, 0x80, 0x02, 0x3b, 0x0b, 0x19, 0x87, 0x16, 0x9a, 0x9f, 0x00, 0x4b, + 0xb0, 0x01, 0x17, 0xc5, 0xc4, 0x29, 0x5a, 0x4d, 0xa7, 0xf2, 0x6a, 0xa6, 0xd7, 0x4d, 0x9a, 0xb7, + 0xd8, 0xc5, 0xc3, 0xa5, 0xf2, 0x57, 0x86, 0xcb, 0x11, 0x58, 0x91, 0x93, 0x79, 0x9c, 0xb3, 0x7a, + 0x79, 0xce, 0x65, 0x69, 0x5f, 0x26, 0x7d, 0x02, 0xcc, 0x84, 0xa3, 0x71, 0xce, 0xa9, 0x8f, 0xf0, + 0x33, 0xe1, 0xa8, 0x4c, 0xe9, 0x83, 0x75, 0x2e, 0x8b, 0xcf, 0x0d, 0xb1, 0x50, 0xa3, 0x2a, 0x0e, + 0x70, 0x44, 0x78, 0x3f, 0x23, 0x9f, 0xbe, 0x3c, 0xf9, 0x9a, 0x22, 0x7a, 0x28, 0x79, 0x9c, 0x8c, + 0x26, 0xdd, 0xa5, 0x0b, 0x1a, 0x17, 0xef, 0x92, 0x27, 0x68, 0x46, 0x25, 0xe8, 0x5f, 0x17, 0x50, + 0xe4, 0x59, 0xda, 0x02, 0x57, 0x42, 0xf8, 0xdc, 0x15, 0x7d, 0x46, 0x85, 0x08, 0xb0, 0xef, 0xc6, + 0x10, 0x9d, 0x61, 0xc1, 0xd5, 0xbd, 0x52, 0x71, 0x56, 0x42, 0xf8, 0xfc, 0x38, 0xd3, 0x1d, 0x6a, + 0x55, 0xcb, 0x03, 0xcb, 0x7b, 0x30, 0xf2, 0x79, 0x1f, 0x9e, 0xe1, 0x87, 0x58, 0x40, 0x1f, 0x0a, + 0x58, 0x2a, 0xdf, 0x53, 0x8c, 0xdd, 0x98, 0xd2, 0x40, 0x97, 0xaf, 0x9e, 0x06, 0x79, 0xf9, 0xde, + 0xc7, 0xf8, 0x90, 0xd2, 0x40, 0x96, 0xaf, 0x69, 0x81, 0x99, 0x04, 0x33, 0x5e, 0x14, 0x53, 0xb6, + 0x6c, 0xfd, 0x1f, 0xd4, 0x54, 0xff, 0xee, 0xa0, 0x33, 0x6e, 0xae, 0x83, 0x9a, 0x64, 0xc2, 0x9c, + 0x63, 0x6e, 0x19, 0xcd, 0x4a, 0xbb, 0xe6, 0x14, 0x82, 0x96, 0x00, 0x6b, 0x1f, 0x7a, 0x56, 0x70, + 0xf3, 0x6b, 0x30, 0x13, 0x63, 0x75, 0xe7, 0x29, 0xc3, 0xfa, 0xd6, 0x67, 0xf6, 0x25, 0x9e, 0x6e, + 0xf6, 0x87, 0x08, 0x9d, 0x8c, 0xad, 0xc5, 0x8a, 0xc7, 0xcc, 0xd8, 0xd8, 0xe6, 0xe6, 0xc9, 0xf8, + 0xa6, 0x9f, 0x7e, 0xd4, 0xa6, 0x63, 0x7c, 0xc5, 0x9e, 0xb7, 0x40, 0x7d, 0x47, 0x1f, 0xfb, 0x4b, + 0xc2, 0xc5, 0xfb, 0x61, 0x99, 0x1b, 0x0d, 0xcb, 0x17, 0x60, 0xa1, 0xdb, 0x87, 0x51, 0x84, 0x83, + 0x63, 0xaa, 0x66, 0x90, 0xf9, 0x6f, 0x00, 0x90, 0x96, 0xc8, 0xd9, 0xa5, 0xd3, 0x52, 0x4b, 0x25, + 0xfb, 0x7e, 0xe9, 0xd6, 0x98, 0x2c, 0xdd, 0x1a, 0x2d, 0x07, 0x2c, 0x9e, 0x70, 0xf4, 0x55, 0xf6, + 0x7c, 0x78, 0x1c, 0x73, 0xf3, 0x0a, 0x98, 0x96, 0x6d, 0x93, 0x12, 0x55, 0x9d, 0xa9, 0x84, 0xa3, + 0x7d, 0xdf, 0x6c, 0x8f, 0x3e, 0x51, 0x68, 0xec, 0x12, 0x9f, 0x5b, 0x93, 0xcd, 0x4a, 0xbb, 0xea, + 0x2c, 0x0c, 0x0a, 0xf3, 0x7d, 0x9f, 0xb7, 0xbe, 0x01, 0xf5, 0x11, 0x42, 0x73, 0x01, 0x4c, 0xe6, + 0x5c, 0x93, 0xc4, 0x37, 0xb7, 0xc1, 0x5a, 0x41, 0x54, 0x9e, 0xbc, 0x9a, 0xb1, 0xe6, 0x5c, 0xcb, + 0x01, 0xa5, 0xe1, 0xcb, 0x5b, 0x8f, 0xc1, 0xea, 0x7e, 0xd1, 0xe7, 0xf9, 0x5c, 0x2f, 0x9d, 0xd0, + 0x28, 0xdf, 0x8b, 0xeb, 0xa0, 0x96, 0xbf, 0xc3, 0xd5, 0xe9, 0xab, 0x4e, 0x21, 0x68, 0x85, 0x60, + 0xe9, 0x84, 0xa3, 0x23, 0x1c, 0xf9, 0x05, 0xd9, 0x07, 0x02, 0xb0, 0x3b, 0x4e, 0x74, 0xe9, 0x77, + 0x5e, 0xb1, 0xdd, 0x0f, 0x06, 0xb0, 0x0e, 0xf0, 0x70, 0x87, 0x73, 0xd2, 0x8b, 0x42, 0x1c, 0x09, + 0xd9, 0xb7, 0x10, 0x61, 0xf9, 0x69, 0xde, 0x04, 0xf3, 0x79, 0xa3, 0xe5, 0xfd, 0x35, 0xe7, 0xcc, + 0x65, 0x42, 0xd5, 0x58, 0xdb, 0x00, 0xc4, 0x0c, 0x27, 0x2e, 0x72, 0xcf, 0xf0, 0x30, 0x75, 0x63, + 0x7d, 0x74, 0xec, 0xeb, 0x67, 0xbe, 0x7d, 0x38, 0xf0, 0x02, 0x82, 0x0e, 0xf0, 0xd0, 0x99, 0x95, + 0xf8, 0xee, 0x01, 0x1e, 0xca, 0x6b, 0x3c, 0xa6, 0xcf, 0x30, 0x53, 0xb3, 0xba, 0xe2, 0xe8, 0xc5, + 0xee, 0xf1, 0xeb, 0xf3, 0x86, 0xf1, 0xe6, 0xbc, 0x61, 0xfc, 0x76, 0xde, 0x30, 0x5e, 0xbc, 0x6b, + 0x4c, 0xbc, 0x79, 0xd7, 0x98, 0xf8, 0xe5, 0x5d, 0x63, 0xe2, 0xdb, 0xed, 0x1e, 0x11, 0xfd, 0x81, + 0x67, 0x23, 0x1a, 0x76, 0xd2, 0x5f, 0x80, 0xa2, 0xda, 0x6f, 0xe7, 0x7f, 0x54, 0xcf, 0xcb, 0xff, + 0x54, 0x62, 0x18, 0x63, 0xee, 0x4d, 0xab, 0x90, 0xdc, 0xf9, 0x33, 0x00, 0x00, 0xff, 0xff, 0xee, + 0xbd, 0x04, 0x84, 0x84, 0x0d, 0x00, 0x00, } func (m *ConsumerAdditionProposal) Marshal() (dAtA []byte, err error) { diff --git a/x/ccv/provider/types/query.pb.go b/x/ccv/provider/types/query.pb.go index 26a533a8a8..51df34a76f 100644 --- a/x/ccv/provider/types/query.pb.go +++ b/x/ccv/provider/types/query.pb.go @@ -949,6 +949,94 @@ func (*ThrottledPacketDataWrapper) XXX_OneofWrappers() []interface{} { } } +type QueryRegisteredConsumerRewardDenomsRequest struct { +} + +func (m *QueryRegisteredConsumerRewardDenomsRequest) Reset() { + *m = QueryRegisteredConsumerRewardDenomsRequest{} +} +func (m *QueryRegisteredConsumerRewardDenomsRequest) String() string { + return proto.CompactTextString(m) +} +func (*QueryRegisteredConsumerRewardDenomsRequest) ProtoMessage() {} +func (*QueryRegisteredConsumerRewardDenomsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{19} +} +func (m *QueryRegisteredConsumerRewardDenomsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRegisteredConsumerRewardDenomsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRegisteredConsumerRewardDenomsRequest.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 *QueryRegisteredConsumerRewardDenomsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRegisteredConsumerRewardDenomsRequest.Merge(m, src) +} +func (m *QueryRegisteredConsumerRewardDenomsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryRegisteredConsumerRewardDenomsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRegisteredConsumerRewardDenomsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryRegisteredConsumerRewardDenomsRequest proto.InternalMessageInfo + +type QueryRegisteredConsumerRewardDenomsResponse struct { + Denoms []string `protobuf:"bytes,1,rep,name=denoms,proto3" json:"denoms,omitempty"` +} + +func (m *QueryRegisteredConsumerRewardDenomsResponse) Reset() { + *m = QueryRegisteredConsumerRewardDenomsResponse{} +} +func (m *QueryRegisteredConsumerRewardDenomsResponse) String() string { + return proto.CompactTextString(m) +} +func (*QueryRegisteredConsumerRewardDenomsResponse) ProtoMessage() {} +func (*QueryRegisteredConsumerRewardDenomsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{20} +} +func (m *QueryRegisteredConsumerRewardDenomsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRegisteredConsumerRewardDenomsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRegisteredConsumerRewardDenomsResponse.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 *QueryRegisteredConsumerRewardDenomsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRegisteredConsumerRewardDenomsResponse.Merge(m, src) +} +func (m *QueryRegisteredConsumerRewardDenomsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryRegisteredConsumerRewardDenomsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRegisteredConsumerRewardDenomsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryRegisteredConsumerRewardDenomsResponse proto.InternalMessageInfo + +func (m *QueryRegisteredConsumerRewardDenomsResponse) GetDenoms() []string { + if m != nil { + return m.Denoms + } + return nil +} + func init() { proto.RegisterType((*QueryConsumerGenesisRequest)(nil), "interchain_security.ccv.provider.v1.QueryConsumerGenesisRequest") proto.RegisterType((*QueryConsumerGenesisResponse)(nil), "interchain_security.ccv.provider.v1.QueryConsumerGenesisResponse") @@ -969,6 +1057,8 @@ func init() { proto.RegisterType((*QueryThrottledConsumerPacketDataResponse)(nil), "interchain_security.ccv.provider.v1.QueryThrottledConsumerPacketDataResponse") proto.RegisterType((*ThrottledSlashPacket)(nil), "interchain_security.ccv.provider.v1.ThrottledSlashPacket") proto.RegisterType((*ThrottledPacketDataWrapper)(nil), "interchain_security.ccv.provider.v1.ThrottledPacketDataWrapper") + proto.RegisterType((*QueryRegisteredConsumerRewardDenomsRequest)(nil), "interchain_security.ccv.provider.v1.QueryRegisteredConsumerRewardDenomsRequest") + proto.RegisterType((*QueryRegisteredConsumerRewardDenomsResponse)(nil), "interchain_security.ccv.provider.v1.QueryRegisteredConsumerRewardDenomsResponse") } func init() { @@ -976,85 +1066,90 @@ func init() { } var fileDescriptor_422512d7b7586cd7 = []byte{ - // 1236 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x6f, 0x1b, 0x45, - 0x1c, 0xf5, 0x26, 0x69, 0x9b, 0x4e, 0x0a, 0x89, 0x26, 0x01, 0xdc, 0x4d, 0x64, 0x87, 0x05, 0x41, - 0x0a, 0x62, 0xb7, 0x76, 0x85, 0xd4, 0x04, 0x52, 0xc7, 0x4e, 0x43, 0x1a, 0xd1, 0x88, 0xb0, 0x89, - 0x8a, 0x04, 0xa8, 0x66, 0xb2, 0x3b, 0x38, 0x2b, 0xd6, 0x3b, 0xdb, 0x9d, 0xf1, 0xb6, 0xe1, 0xe3, - 0xc0, 0x87, 0xa0, 0xc7, 0x4a, 0xfc, 0x03, 0x3d, 0xf1, 0x5f, 0x70, 0xef, 0x8d, 0x8a, 0x5e, 0x7a, - 0x2a, 0x28, 0xe1, 0xc0, 0x11, 0x71, 0x47, 0x42, 0x3b, 0x3b, 0xe3, 0x8f, 0x78, 0x6d, 0xaf, 0xdd, - 0xde, 0x9c, 0x99, 0xf9, 0xbd, 0xdf, 0x7b, 0x2f, 0xbf, 0x19, 0x3f, 0x03, 0xc3, 0xf1, 0x18, 0x0e, - 0xac, 0x03, 0xe4, 0x78, 0x55, 0x8a, 0xad, 0x46, 0xe0, 0xb0, 0x43, 0xc3, 0xb2, 0x42, 0xc3, 0x0f, - 0x48, 0xe8, 0xd8, 0x38, 0x30, 0xc2, 0x82, 0x71, 0xab, 0x81, 0x83, 0x43, 0xdd, 0x0f, 0x08, 0x23, - 0xf0, 0x95, 0x84, 0x02, 0xdd, 0xb2, 0x42, 0x5d, 0x16, 0xe8, 0x61, 0x41, 0x5d, 0xa8, 0x11, 0x52, - 0x73, 0xb1, 0x81, 0x7c, 0xc7, 0x40, 0x9e, 0x47, 0x18, 0x62, 0x0e, 0xf1, 0x68, 0x0c, 0xa1, 0xce, - 0xd5, 0x48, 0x8d, 0xf0, 0x8f, 0x46, 0xf4, 0x49, 0xac, 0xe6, 0x45, 0x0d, 0xff, 0x6b, 0xbf, 0xf1, - 0xb9, 0xc1, 0x9c, 0x3a, 0xa6, 0x0c, 0xd5, 0x7d, 0x71, 0xe0, 0xd5, 0x5e, 0x54, 0xc3, 0x82, 0x21, - 0x08, 0x30, 0xa2, 0x16, 0x7a, 0x9d, 0xb2, 0x88, 0x47, 0x1b, 0xf5, 0x58, 0x50, 0x0d, 0x7b, 0x98, - 0x3a, 0x92, 0x4f, 0x31, 0x8d, 0x07, 0x4d, 0x79, 0xbc, 0x46, 0xbb, 0x0c, 0xe6, 0x3f, 0x8c, 0x5c, - 0x59, 0x17, 0xa8, 0x9b, 0x31, 0xa2, 0x89, 0x6f, 0x35, 0x30, 0x65, 0xf0, 0x3c, 0x98, 0x8c, 0xf1, - 0x1c, 0x3b, 0xab, 0x2c, 0x2a, 0x4b, 0x67, 0xcd, 0x33, 0xfc, 0xef, 0x2d, 0x5b, 0xfb, 0x1a, 0x2c, - 0x24, 0x57, 0x52, 0x9f, 0x78, 0x14, 0xc3, 0x4f, 0xc1, 0x73, 0x82, 0x5e, 0x95, 0x32, 0xc4, 0x30, - 0xaf, 0x9f, 0x2a, 0x16, 0xf4, 0x5e, 0xc6, 0x4b, 0x61, 0x7a, 0x58, 0xd0, 0x05, 0xd8, 0x6e, 0x54, - 0x58, 0x99, 0x78, 0xf0, 0x24, 0x9f, 0x31, 0xcf, 0xd5, 0xda, 0xd6, 0xb4, 0x05, 0xa0, 0x76, 0x74, - 0x5f, 0x8f, 0xf0, 0x24, 0x6d, 0x0d, 0x9d, 0x50, 0x25, 0x77, 0x05, 0xb5, 0x0a, 0x38, 0xcd, 0xfb, - 0xd3, 0xac, 0xb2, 0x38, 0xbe, 0x34, 0x55, 0x7c, 0x43, 0x4f, 0x31, 0x0c, 0x3a, 0x07, 0x31, 0x45, - 0xa5, 0x76, 0x01, 0xbc, 0xde, 0xdd, 0x62, 0x97, 0xa1, 0x80, 0xed, 0x04, 0xc4, 0x27, 0x14, 0xb9, - 0x4d, 0x36, 0x77, 0x15, 0xb0, 0x34, 0xf8, 0x6c, 0xd3, 0xb6, 0xb3, 0xbe, 0x5c, 0x14, 0x96, 0x5d, - 0x49, 0x47, 0x4f, 0x80, 0x97, 0x6d, 0xdb, 0x89, 0xa6, 0xb4, 0x05, 0xdd, 0x02, 0xd4, 0x96, 0xc0, - 0x6b, 0x49, 0x4c, 0x88, 0xdf, 0x45, 0xfa, 0x47, 0x25, 0x59, 0x60, 0xc7, 0x51, 0xc1, 0xf9, 0x93, - 0x6e, 0xce, 0xab, 0x43, 0x71, 0x36, 0x71, 0x9d, 0x84, 0xc8, 0x4d, 0xa4, 0x5c, 0x02, 0xa7, 0x78, - 0xeb, 0x3e, 0xb3, 0x08, 0xe7, 0xc1, 0x59, 0xcb, 0x75, 0xb0, 0xc7, 0xa2, 0xbd, 0x31, 0xbe, 0x37, - 0x19, 0x2f, 0x6c, 0xd9, 0xda, 0x4f, 0x0a, 0x78, 0x99, 0x2b, 0xb9, 0x81, 0x5c, 0xc7, 0x46, 0x8c, - 0x04, 0x6d, 0x56, 0x05, 0x83, 0x27, 0x1d, 0xae, 0x82, 0x19, 0x49, 0xba, 0x8a, 0x6c, 0x3b, 0xc0, - 0x94, 0xc6, 0x4d, 0x2a, 0xf0, 0xdf, 0x27, 0xf9, 0xe7, 0x0f, 0x51, 0xdd, 0x5d, 0xd1, 0xc4, 0x86, - 0x66, 0x4e, 0xcb, 0xb3, 0xe5, 0x78, 0x65, 0x65, 0xf2, 0xee, 0xfd, 0x7c, 0xe6, 0xef, 0xfb, 0xf9, - 0x8c, 0xf6, 0x01, 0xd0, 0xfa, 0x11, 0x11, 0x6e, 0x5e, 0x00, 0x33, 0xf2, 0x2a, 0x34, 0xdb, 0xc5, - 0x8c, 0xa6, 0xad, 0xb6, 0xf3, 0x51, 0xb3, 0x6e, 0x69, 0x3b, 0x6d, 0xcd, 0xd3, 0x49, 0xeb, 0xea, - 0xd5, 0x47, 0xda, 0x89, 0xfe, 0xfd, 0xa4, 0x75, 0x12, 0x69, 0x49, 0xeb, 0x72, 0x52, 0x48, 0x3b, - 0xe1, 0x9a, 0x36, 0x0f, 0xce, 0x73, 0xc0, 0xbd, 0x83, 0x80, 0x30, 0xe6, 0x62, 0x7e, 0xed, 0xe5, - 0x70, 0xfe, 0x32, 0x26, 0xae, 0xff, 0x89, 0x5d, 0xd1, 0x26, 0x0f, 0xa6, 0xa8, 0x8b, 0xe8, 0x41, - 0xb5, 0x8e, 0x19, 0x0e, 0x78, 0x87, 0x71, 0x13, 0xf0, 0xa5, 0xed, 0x68, 0x05, 0x16, 0xc1, 0x0b, - 0x6d, 0x07, 0xaa, 0xc8, 0x75, 0xc9, 0x6d, 0xe4, 0x59, 0x98, 0x6b, 0x1f, 0x37, 0x67, 0x5b, 0x47, - 0xcb, 0x72, 0x0b, 0xde, 0x04, 0x59, 0x0f, 0xdf, 0x61, 0xd5, 0x00, 0xfb, 0x2e, 0xf6, 0x1c, 0x7a, - 0x50, 0xb5, 0x90, 0x67, 0x47, 0x62, 0x71, 0x76, 0x9c, 0xcf, 0xbc, 0xaa, 0xc7, 0x4f, 0xbf, 0x2e, - 0x9f, 0x7e, 0x7d, 0x4f, 0x3e, 0xfd, 0x95, 0xc9, 0xe8, 0x0d, 0xbb, 0xf7, 0x47, 0x5e, 0x31, 0x5f, - 0x8c, 0x50, 0x4c, 0x09, 0xb2, 0x2e, 0x31, 0xe0, 0x2e, 0x38, 0xe3, 0x23, 0xeb, 0x0b, 0xcc, 0x68, - 0x76, 0x82, 0xbf, 0x4a, 0xcb, 0xa9, 0xae, 0x90, 0x74, 0xc0, 0xde, 0x8d, 0x38, 0xef, 0x70, 0x04, - 0x53, 0x22, 0x69, 0x57, 0xc5, 0x25, 0x6e, 0x9e, 0x92, 0x13, 0x17, 0x1f, 0xbc, 0x8a, 0x18, 0x4a, - 0xf1, 0xd4, 0xff, 0x2e, 0x1f, 0xb0, 0xbe, 0x30, 0xc2, 0xfc, 0x3e, 0xd3, 0x06, 0xc1, 0x04, 0x75, - 0xbe, 0x8c, 0x5d, 0x9e, 0x30, 0xf9, 0x67, 0x78, 0x1b, 0xcc, 0xfa, 0x4d, 0x90, 0x2d, 0x8f, 0xb2, - 0xc8, 0x6c, 0x9a, 0x1d, 0xe7, 0x16, 0x94, 0x86, 0xb3, 0xa0, 0xc5, 0xe6, 0xa3, 0x00, 0xf9, 0x3e, - 0x0e, 0xc4, 0x57, 0x47, 0x52, 0x07, 0xed, 0x57, 0x05, 0xcc, 0x25, 0x99, 0x07, 0x6f, 0x82, 0x73, - 0x35, 0x97, 0xec, 0x23, 0xb7, 0x8a, 0x3d, 0x16, 0x1c, 0x8a, 0x07, 0xed, 0xed, 0x54, 0x54, 0x36, - 0x79, 0x21, 0x47, 0xdb, 0x88, 0x8a, 0x05, 0x81, 0xa9, 0x18, 0x90, 0x2f, 0xc1, 0x0d, 0x30, 0x61, - 0x23, 0x86, 0xb8, 0x0b, 0x53, 0xc5, 0x37, 0x7b, 0xe2, 0x86, 0x05, 0xbd, 0x8d, 0x56, 0x44, 0x5e, - 0xa0, 0xf1, 0x72, 0xed, 0xb1, 0x02, 0xd4, 0xde, 0xca, 0xe1, 0x0e, 0x38, 0x17, 0x8f, 0x78, 0xac, - 0x5d, 0xa8, 0x18, 0xa6, 0xdb, 0xb5, 0x8c, 0x19, 0x5f, 0x23, 0xe1, 0xcb, 0x67, 0x00, 0x86, 0xd4, - 0xaa, 0xd6, 0x11, 0x6b, 0x04, 0xd8, 0x96, 0xb8, 0xb1, 0x8a, 0x8b, 0xfd, 0x70, 0x6f, 0xec, 0xae, - 0x6f, 0xc7, 0x45, 0x1d, 0xe0, 0x33, 0x21, 0xb5, 0x3a, 0xd6, 0x2b, 0xa7, 0x63, 0x67, 0x8a, 0x3f, - 0x4c, 0x83, 0x53, 0x7c, 0xde, 0xe0, 0x91, 0x02, 0xe6, 0x92, 0x52, 0x06, 0x5c, 0x4b, 0xf5, 0xef, - 0xe8, 0x13, 0x6d, 0xd4, 0xf2, 0x53, 0x20, 0xc4, 0xa3, 0xae, 0x6d, 0x7c, 0xf7, 0xe8, 0xaf, 0x9f, - 0xc7, 0x4a, 0x70, 0x75, 0x70, 0xfa, 0x6c, 0xbe, 0xb2, 0x22, 0xc5, 0x18, 0x5f, 0xc9, 0x4b, 0xf2, - 0x0d, 0x7c, 0xa4, 0x80, 0xd9, 0x84, 0xb8, 0x02, 0x4b, 0xc3, 0x33, 0xec, 0x88, 0x41, 0xea, 0xda, - 0xe8, 0x00, 0x42, 0xe1, 0x32, 0x57, 0x78, 0x09, 0x16, 0x86, 0x50, 0x18, 0x07, 0x24, 0xf8, 0xed, - 0x18, 0xc8, 0xf6, 0x48, 0x3d, 0x14, 0x5e, 0x1f, 0x91, 0x59, 0x62, 0xc0, 0x52, 0xb7, 0x9f, 0x11, - 0x9a, 0x10, 0x7d, 0x8d, 0x8b, 0xae, 0xc0, 0xb5, 0x61, 0x45, 0x47, 0x41, 0x37, 0x60, 0xd5, 0x66, - 0x76, 0x81, 0xff, 0x29, 0xe0, 0xa5, 0xe4, 0x10, 0x45, 0xe1, 0xfb, 0x23, 0x93, 0xee, 0x4e, 0x6b, - 0xea, 0xf5, 0x67, 0x03, 0x26, 0x0c, 0xd8, 0xe4, 0x06, 0x94, 0x61, 0x69, 0x04, 0x03, 0x88, 0xdf, - 0xa6, 0xff, 0x1f, 0x45, 0x7c, 0x4f, 0x27, 0x26, 0x1e, 0xf8, 0x5e, 0x7a, 0xd6, 0xfd, 0xb2, 0x9b, - 0xba, 0xf9, 0xd4, 0x38, 0x42, 0x78, 0x99, 0x0b, 0x7f, 0x07, 0x2e, 0xa7, 0xf8, 0x39, 0x29, 0x81, - 0xaa, 0x1d, 0x01, 0x2a, 0x41, 0x72, 0x7b, 0x12, 0x1a, 0x49, 0x72, 0x42, 0xa6, 0x1b, 0x49, 0x72, - 0x52, 0x24, 0x1b, 0x4d, 0x72, 0x47, 0x88, 0x83, 0xbf, 0x29, 0x00, 0x76, 0xa7, 0x31, 0x78, 0x25, - 0x3d, 0xc5, 0xa4, 0x90, 0xa7, 0x96, 0x46, 0xae, 0x17, 0xd2, 0x2e, 0x73, 0x69, 0x45, 0x78, 0x71, - 0xb0, 0x34, 0x26, 0x00, 0xe2, 0x9f, 0xaa, 0xf0, 0xfb, 0x31, 0xb0, 0x38, 0x28, 0xf0, 0x0c, 0xf3, - 0x86, 0x0d, 0x8e, 0x5f, 0xc3, 0xbc, 0x61, 0x29, 0x52, 0x98, 0x56, 0xe1, 0xda, 0xdf, 0x85, 0x2b, - 0x83, 0xb5, 0xfb, 0xd8, 0xb3, 0x1d, 0xaf, 0xd6, 0x9a, 0x63, 0x11, 0x1e, 0x2b, 0x7b, 0x0f, 0x8e, - 0x72, 0xca, 0xc3, 0xa3, 0x9c, 0xf2, 0xe7, 0x51, 0x4e, 0xb9, 0x77, 0x9c, 0xcb, 0x3c, 0x3c, 0xce, - 0x65, 0x1e, 0x1f, 0xe7, 0x32, 0x1f, 0xaf, 0xd4, 0x1c, 0x76, 0xd0, 0xd8, 0xd7, 0x2d, 0x52, 0x37, - 0x2c, 0x42, 0xeb, 0x84, 0xb6, 0xb5, 0x79, 0xab, 0xd9, 0xe6, 0xce, 0x09, 0x93, 0x0f, 0x7d, 0x4c, - 0xf7, 0x4f, 0xf3, 0x74, 0x7c, 0xe9, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8c, 0xf5, 0x7d, 0x58, - 0xb2, 0x11, 0x00, 0x00, + // 1321 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xcf, 0x6f, 0x1b, 0xc5, + 0x1f, 0xf5, 0x3a, 0x69, 0x9a, 0x4c, 0xfa, 0xfd, 0xb6, 0x4c, 0x43, 0x71, 0x37, 0x91, 0x1d, 0xb6, + 0x08, 0xd2, 0x16, 0x76, 0x6b, 0x57, 0x48, 0x4d, 0x20, 0x75, 0xec, 0x24, 0xa4, 0x51, 0x1b, 0x35, + 0x6c, 0xa2, 0x22, 0x01, 0xea, 0x32, 0xd9, 0x1d, 0x9c, 0x15, 0xeb, 0x9d, 0xed, 0xce, 0xd8, 0x69, + 0xf8, 0x71, 0x00, 0x24, 0xe8, 0xb1, 0x12, 0xe2, 0xc6, 0xa1, 0x27, 0xfe, 0x0b, 0xee, 0xbd, 0x51, + 0xd1, 0x4b, 0x4f, 0x05, 0x25, 0x1c, 0x38, 0x22, 0xee, 0x48, 0x68, 0x67, 0x67, 0xfd, 0x23, 0x5e, + 0xdb, 0x6b, 0x37, 0x37, 0x7b, 0x76, 0x3e, 0xef, 0xf3, 0xde, 0xd3, 0x67, 0x66, 0xdf, 0x02, 0xcd, + 0x76, 0x19, 0xf6, 0xcd, 0x5d, 0x64, 0xbb, 0x06, 0xc5, 0x66, 0xcd, 0xb7, 0xd9, 0xbe, 0x66, 0x9a, + 0x75, 0xcd, 0xf3, 0x49, 0xdd, 0xb6, 0xb0, 0xaf, 0xd5, 0xf3, 0xda, 0xbd, 0x1a, 0xf6, 0xf7, 0x55, + 0xcf, 0x27, 0x8c, 0xc0, 0x0b, 0x31, 0x05, 0xaa, 0x69, 0xd6, 0xd5, 0xa8, 0x40, 0xad, 0xe7, 0xe5, + 0x99, 0x0a, 0x21, 0x15, 0x07, 0x6b, 0xc8, 0xb3, 0x35, 0xe4, 0xba, 0x84, 0x21, 0x66, 0x13, 0x97, + 0x86, 0x10, 0xf2, 0x54, 0x85, 0x54, 0x08, 0xff, 0xa9, 0x05, 0xbf, 0xc4, 0x6a, 0x4e, 0xd4, 0xf0, + 0x7f, 0x3b, 0xb5, 0x4f, 0x35, 0x66, 0x57, 0x31, 0x65, 0xa8, 0xea, 0x89, 0x0d, 0xaf, 0x75, 0xa3, + 0x5a, 0xcf, 0x6b, 0x82, 0x00, 0x23, 0x72, 0xbe, 0xdb, 0x2e, 0x93, 0xb8, 0xb4, 0x56, 0x0d, 0x05, + 0x55, 0xb0, 0x8b, 0xa9, 0x1d, 0xf1, 0x29, 0x24, 0xf1, 0xa0, 0x21, 0x8f, 0xd7, 0x28, 0xd7, 0xc0, + 0xf4, 0xfb, 0x81, 0x2b, 0xcb, 0x02, 0x75, 0x2d, 0x44, 0xd4, 0xf1, 0xbd, 0x1a, 0xa6, 0x0c, 0x9e, + 0x07, 0xe3, 0x21, 0x9e, 0x6d, 0x65, 0xa4, 0x59, 0x69, 0x6e, 0x42, 0x3f, 0xc9, 0xff, 0xaf, 0x5b, + 0xca, 0x97, 0x60, 0x26, 0xbe, 0x92, 0x7a, 0xc4, 0xa5, 0x18, 0x7e, 0x0c, 0xfe, 0x27, 0xe8, 0x19, + 0x94, 0x21, 0x86, 0x79, 0xfd, 0x64, 0x21, 0xaf, 0x76, 0x33, 0x3e, 0x12, 0xa6, 0xd6, 0xf3, 0xaa, + 0x00, 0xdb, 0x0a, 0x0a, 0xcb, 0xa3, 0x8f, 0x9f, 0xe7, 0x52, 0xfa, 0xa9, 0x4a, 0xcb, 0x9a, 0x32, + 0x03, 0xe4, 0xb6, 0xee, 0xcb, 0x01, 0x5e, 0x44, 0x5b, 0x41, 0x47, 0x54, 0x45, 0x4f, 0x05, 0xb5, + 0x32, 0x18, 0xe3, 0xfd, 0x69, 0x46, 0x9a, 0x1d, 0x99, 0x9b, 0x2c, 0x5c, 0x52, 0x13, 0x0c, 0x83, + 0xca, 0x41, 0x74, 0x51, 0xa9, 0x5c, 0x04, 0x6f, 0x74, 0xb6, 0xd8, 0x62, 0xc8, 0x67, 0x9b, 0x3e, + 0xf1, 0x08, 0x45, 0x4e, 0x83, 0xcd, 0x03, 0x09, 0xcc, 0xf5, 0xdf, 0xdb, 0xb0, 0x6d, 0xc2, 0x8b, + 0x16, 0x85, 0x65, 0xd7, 0x93, 0xd1, 0x13, 0xe0, 0x25, 0xcb, 0xb2, 0x83, 0x29, 0x6d, 0x42, 0x37, + 0x01, 0x95, 0x39, 0xf0, 0x7a, 0x1c, 0x13, 0xe2, 0x75, 0x90, 0xfe, 0x4e, 0x8a, 0x17, 0xd8, 0xb6, + 0x55, 0x70, 0xfe, 0xa8, 0x93, 0xf3, 0xe2, 0x40, 0x9c, 0x75, 0x5c, 0x25, 0x75, 0xe4, 0xc4, 0x52, + 0x2e, 0x82, 0x13, 0xbc, 0x75, 0x8f, 0x59, 0x84, 0xd3, 0x60, 0xc2, 0x74, 0x6c, 0xec, 0xb2, 0xe0, + 0x59, 0x9a, 0x3f, 0x1b, 0x0f, 0x17, 0xd6, 0x2d, 0xe5, 0x7b, 0x09, 0xbc, 0xca, 0x95, 0xdc, 0x41, + 0x8e, 0x6d, 0x21, 0x46, 0xfc, 0x16, 0xab, 0xfc, 0xfe, 0x93, 0x0e, 0x17, 0xc1, 0x99, 0x88, 0xb4, + 0x81, 0x2c, 0xcb, 0xc7, 0x94, 0x86, 0x4d, 0xca, 0xf0, 0x9f, 0xe7, 0xb9, 0xff, 0xef, 0xa3, 0xaa, + 0xb3, 0xa0, 0x88, 0x07, 0x8a, 0x7e, 0x3a, 0xda, 0x5b, 0x0a, 0x57, 0x16, 0xc6, 0x1f, 0x3c, 0xca, + 0xa5, 0xfe, 0x7a, 0x94, 0x4b, 0x29, 0xb7, 0x81, 0xd2, 0x8b, 0x88, 0x70, 0xf3, 0x22, 0x38, 0x13, + 0x1d, 0x85, 0x46, 0xbb, 0x90, 0xd1, 0x69, 0xb3, 0x65, 0x7f, 0xd0, 0xac, 0x53, 0xda, 0x66, 0x4b, + 0xf3, 0x64, 0xd2, 0x3a, 0x7a, 0xf5, 0x90, 0x76, 0xa4, 0x7f, 0x2f, 0x69, 0xed, 0x44, 0x9a, 0xd2, + 0x3a, 0x9c, 0x14, 0xd2, 0x8e, 0xb8, 0xa6, 0x4c, 0x83, 0xf3, 0x1c, 0x70, 0x7b, 0xd7, 0x27, 0x8c, + 0x39, 0x98, 0x1f, 0xfb, 0x68, 0x38, 0x7f, 0x4e, 0x8b, 0xe3, 0x7f, 0xe4, 0xa9, 0x68, 0x93, 0x03, + 0x93, 0xd4, 0x41, 0x74, 0xd7, 0xa8, 0x62, 0x86, 0x7d, 0xde, 0x61, 0x44, 0x07, 0x7c, 0x69, 0x23, + 0x58, 0x81, 0x05, 0xf0, 0x72, 0xcb, 0x06, 0x03, 0x39, 0x0e, 0xd9, 0x43, 0xae, 0x89, 0xb9, 0xf6, + 0x11, 0xfd, 0x6c, 0x73, 0x6b, 0x29, 0x7a, 0x04, 0xef, 0x82, 0x8c, 0x8b, 0xef, 0x33, 0xc3, 0xc7, + 0x9e, 0x83, 0x5d, 0x9b, 0xee, 0x1a, 0x26, 0x72, 0xad, 0x40, 0x2c, 0xce, 0x8c, 0xf0, 0x99, 0x97, + 0xd5, 0xf0, 0xea, 0x57, 0xa3, 0xab, 0x5f, 0xdd, 0x8e, 0xae, 0xfe, 0xf2, 0x78, 0x70, 0x87, 0x3d, + 0xfc, 0x3d, 0x27, 0xe9, 0xe7, 0x02, 0x14, 0x3d, 0x02, 0x59, 0x8e, 0x30, 0xe0, 0x16, 0x38, 0xe9, + 0x21, 0xf3, 0x33, 0xcc, 0x68, 0x66, 0x94, 0xdf, 0x4a, 0xf3, 0x89, 0x8e, 0x50, 0xe4, 0x80, 0xb5, + 0x15, 0x70, 0xde, 0xe4, 0x08, 0x7a, 0x84, 0xa4, 0xac, 0x88, 0x43, 0xdc, 0xd8, 0x15, 0x4d, 0x5c, + 0xb8, 0x71, 0x05, 0x31, 0x94, 0xe0, 0xaa, 0xff, 0x2d, 0xba, 0xc0, 0x7a, 0xc2, 0x08, 0xf3, 0x7b, + 0x4c, 0x1b, 0x04, 0xa3, 0xd4, 0xfe, 0x3c, 0x74, 0x79, 0x54, 0xe7, 0xbf, 0xe1, 0x1e, 0x38, 0xeb, + 0x35, 0x40, 0xd6, 0x5d, 0xca, 0x02, 0xb3, 0x69, 0x66, 0x84, 0x5b, 0x50, 0x1c, 0xcc, 0x82, 0x26, + 0x9b, 0x0f, 0x7c, 0xe4, 0x79, 0xd8, 0x17, 0xaf, 0x8e, 0xb8, 0x0e, 0xca, 0x2f, 0x12, 0x98, 0x8a, + 0x33, 0x0f, 0xde, 0x05, 0xa7, 0x2a, 0x0e, 0xd9, 0x41, 0x8e, 0x81, 0x5d, 0xe6, 0xef, 0x8b, 0x0b, + 0xed, 0xed, 0x44, 0x54, 0xd6, 0x78, 0x21, 0x47, 0x5b, 0x0d, 0x8a, 0x05, 0x81, 0xc9, 0x10, 0x90, + 0x2f, 0xc1, 0x55, 0x30, 0x6a, 0x21, 0x86, 0xb8, 0x0b, 0x93, 0x85, 0xcb, 0x5d, 0x71, 0xeb, 0x79, + 0xb5, 0x85, 0x56, 0x40, 0x5e, 0xa0, 0xf1, 0x72, 0xe5, 0x99, 0x04, 0xe4, 0xee, 0xca, 0xe1, 0x26, + 0x38, 0x15, 0x8e, 0x78, 0xa8, 0x5d, 0xa8, 0x18, 0xa4, 0xdb, 0x8d, 0x94, 0x1e, 0x1e, 0x23, 0xe1, + 0xcb, 0x27, 0x00, 0xd6, 0xa9, 0x69, 0x54, 0x11, 0xab, 0xf9, 0xd8, 0x8a, 0x70, 0x43, 0x15, 0x57, + 0x7a, 0xe1, 0xde, 0xd9, 0x5a, 0xde, 0x08, 0x8b, 0xda, 0xc0, 0xcf, 0xd4, 0xa9, 0xd9, 0xb6, 0x5e, + 0x1e, 0x0b, 0x9d, 0x51, 0xde, 0x04, 0x97, 0xf8, 0xb8, 0xe9, 0xb8, 0x62, 0x53, 0x86, 0xfd, 0xe6, + 0xbc, 0xe9, 0x78, 0x0f, 0xf9, 0xd6, 0x0a, 0x76, 0x49, 0xb5, 0xf1, 0xa6, 0x5a, 0x05, 0x97, 0x13, + 0xed, 0x16, 0xf3, 0x79, 0x0e, 0x8c, 0x59, 0x7c, 0x85, 0xbf, 0xfc, 0x27, 0x74, 0xf1, 0xaf, 0xf0, + 0xd3, 0x4b, 0xe0, 0x04, 0xc7, 0x81, 0x07, 0x12, 0x98, 0x8a, 0x8b, 0x36, 0x70, 0x29, 0xd1, 0x0c, + 0xf4, 0xc8, 0x53, 0x72, 0xe9, 0x05, 0x10, 0x42, 0xfe, 0xca, 0xea, 0x37, 0x4f, 0xff, 0xfc, 0x21, + 0x5d, 0x84, 0x8b, 0xfd, 0x23, 0x6f, 0xe3, 0x6a, 0x17, 0xd1, 0x49, 0xfb, 0x22, 0x3a, 0x99, 0x5f, + 0xc1, 0xa7, 0x12, 0x38, 0x1b, 0x93, 0x91, 0x60, 0x71, 0x70, 0x86, 0x6d, 0xd9, 0x4b, 0x5e, 0x1a, + 0x1e, 0x40, 0x28, 0x9c, 0xe7, 0x0a, 0xaf, 0xc2, 0xfc, 0x00, 0x0a, 0xc3, 0x54, 0x06, 0xbf, 0x4e, + 0x83, 0x4c, 0x97, 0xa8, 0x45, 0xe1, 0xad, 0x21, 0x99, 0xc5, 0xa6, 0x3a, 0x79, 0xe3, 0x98, 0xd0, + 0x84, 0xe8, 0x1b, 0x5c, 0x74, 0x19, 0x2e, 0x0d, 0x2a, 0x3a, 0x48, 0xd7, 0x3e, 0x33, 0x1a, 0x81, + 0x09, 0xfe, 0x2b, 0x81, 0x57, 0xe2, 0x93, 0x1b, 0x85, 0x37, 0x87, 0x26, 0xdd, 0x19, 0x11, 0xe5, + 0x5b, 0xc7, 0x03, 0x26, 0x0c, 0x58, 0xe3, 0x06, 0x94, 0x60, 0x71, 0x08, 0x03, 0x88, 0xd7, 0xa2, + 0xff, 0x6f, 0x49, 0x84, 0x83, 0xd8, 0x98, 0x05, 0xdf, 0x4b, 0xce, 0xba, 0x57, 0x60, 0x94, 0xd7, + 0x5e, 0x18, 0x47, 0x08, 0x2f, 0x71, 0xe1, 0xef, 0xc0, 0xf9, 0x04, 0xdf, 0xb0, 0x11, 0x90, 0xd1, + 0x96, 0xda, 0x62, 0x24, 0xb7, 0xc6, 0xaf, 0xa1, 0x24, 0xc7, 0x04, 0xc9, 0xa1, 0x24, 0xc7, 0xe5, + 0xc0, 0xe1, 0x24, 0xb7, 0x25, 0x47, 0xf8, 0xab, 0x04, 0x60, 0x67, 0x04, 0x84, 0xd7, 0x93, 0x53, + 0x8c, 0x4b, 0x96, 0x72, 0x71, 0xe8, 0x7a, 0x21, 0xed, 0x1a, 0x97, 0x56, 0x80, 0x57, 0xfa, 0x4b, + 0x63, 0x02, 0x20, 0xfc, 0x3e, 0x86, 0xdf, 0xa6, 0xc1, 0x6c, 0xbf, 0x94, 0x35, 0xc8, 0x1d, 0xd6, + 0x3f, 0xf3, 0x0d, 0x72, 0x87, 0x25, 0x88, 0x7e, 0x4a, 0x99, 0x6b, 0x7f, 0x17, 0x2e, 0xf4, 0xd7, + 0xee, 0x61, 0xd7, 0xb2, 0xdd, 0x4a, 0x73, 0x8e, 0x45, 0x62, 0x85, 0x3f, 0xa6, 0xc1, 0x85, 0x04, + 0xaf, 0x73, 0x78, 0x3b, 0x39, 0xf5, 0x44, 0x31, 0x42, 0xde, 0x3c, 0x3e, 0x40, 0x61, 0xc7, 0x4d, + 0x6e, 0xc7, 0x2a, 0x5c, 0xee, 0x6f, 0x87, 0xdf, 0x40, 0x6c, 0x3a, 0xe2, 0x73, 0x4c, 0x23, 0x8c, + 0x27, 0xe5, 0xed, 0xc7, 0x07, 0x59, 0xe9, 0xc9, 0x41, 0x56, 0xfa, 0xe3, 0x20, 0x2b, 0x3d, 0x3c, + 0xcc, 0xa6, 0x9e, 0x1c, 0x66, 0x53, 0xcf, 0x0e, 0xb3, 0xa9, 0x0f, 0x17, 0x2a, 0x36, 0xdb, 0xad, + 0xed, 0xa8, 0x26, 0xa9, 0x6a, 0x26, 0xa1, 0x55, 0x42, 0x5b, 0xfa, 0xbd, 0xd5, 0xe8, 0x77, 0xff, + 0xc8, 0xf0, 0xed, 0x7b, 0x98, 0xee, 0x8c, 0xf1, 0x4f, 0x95, 0xab, 0xff, 0x05, 0x00, 0x00, 0xff, + 0xff, 0x99, 0xe0, 0xf2, 0x45, 0x3f, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1090,6 +1185,8 @@ type QueryClient interface { // QueryThrottledConsumerPacketData returns a list of pending packet data instances // (slash packet and vsc matured) for a single consumer chain QueryThrottledConsumerPacketData(ctx context.Context, in *QueryThrottledConsumerPacketDataRequest, opts ...grpc.CallOption) (*QueryThrottledConsumerPacketDataResponse, error) + // QueryRegisteredConsumerRewardDenoms returns a list of consumer reward denoms that are registered + QueryRegisteredConsumerRewardDenoms(ctx context.Context, in *QueryRegisteredConsumerRewardDenomsRequest, opts ...grpc.CallOption) (*QueryRegisteredConsumerRewardDenomsResponse, error) } type queryClient struct { @@ -1172,6 +1269,15 @@ func (c *queryClient) QueryThrottledConsumerPacketData(ctx context.Context, in * return out, nil } +func (c *queryClient) QueryRegisteredConsumerRewardDenoms(ctx context.Context, in *QueryRegisteredConsumerRewardDenomsRequest, opts ...grpc.CallOption) (*QueryRegisteredConsumerRewardDenomsResponse, error) { + out := new(QueryRegisteredConsumerRewardDenomsResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryRegisteredConsumerRewardDenoms", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // ConsumerGenesis queries the genesis state needed to start a consumer chain @@ -1195,6 +1301,8 @@ type QueryServer interface { // QueryThrottledConsumerPacketData returns a list of pending packet data instances // (slash packet and vsc matured) for a single consumer chain QueryThrottledConsumerPacketData(context.Context, *QueryThrottledConsumerPacketDataRequest) (*QueryThrottledConsumerPacketDataResponse, error) + // QueryRegisteredConsumerRewardDenoms returns a list of consumer reward denoms that are registered + QueryRegisteredConsumerRewardDenoms(context.Context, *QueryRegisteredConsumerRewardDenomsRequest) (*QueryRegisteredConsumerRewardDenomsResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1225,6 +1333,9 @@ func (*UnimplementedQueryServer) QueryThrottleState(ctx context.Context, req *Qu func (*UnimplementedQueryServer) QueryThrottledConsumerPacketData(ctx context.Context, req *QueryThrottledConsumerPacketDataRequest) (*QueryThrottledConsumerPacketDataResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method QueryThrottledConsumerPacketData not implemented") } +func (*UnimplementedQueryServer) QueryRegisteredConsumerRewardDenoms(ctx context.Context, req *QueryRegisteredConsumerRewardDenomsRequest) (*QueryRegisteredConsumerRewardDenomsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryRegisteredConsumerRewardDenoms not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1374,6 +1485,24 @@ func _Query_QueryThrottledConsumerPacketData_Handler(srv interface{}, ctx contex return interceptor(ctx, in, info, handler) } +func _Query_QueryRegisteredConsumerRewardDenoms_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryRegisteredConsumerRewardDenomsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).QueryRegisteredConsumerRewardDenoms(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryRegisteredConsumerRewardDenoms", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).QueryRegisteredConsumerRewardDenoms(ctx, req.(*QueryRegisteredConsumerRewardDenomsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "interchain_security.ccv.provider.v1.Query", HandlerType: (*QueryServer)(nil), @@ -1410,6 +1539,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "QueryThrottledConsumerPacketData", Handler: _Query_QueryThrottledConsumerPacketData_Handler, }, + { + MethodName: "QueryRegisteredConsumerRewardDenoms", + Handler: _Query_QueryRegisteredConsumerRewardDenoms_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "interchain_security/ccv/provider/v1/query.proto", @@ -2099,6 +2232,61 @@ func (m *ThrottledPacketDataWrapper_VscMaturedPacket) MarshalToSizedBuffer(dAtA } return len(dAtA) - i, nil } +func (m *QueryRegisteredConsumerRewardDenomsRequest) 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 *QueryRegisteredConsumerRewardDenomsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRegisteredConsumerRewardDenomsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryRegisteredConsumerRewardDenomsResponse) 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 *QueryRegisteredConsumerRewardDenomsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRegisteredConsumerRewardDenomsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Denoms) > 0 { + for iNdEx := len(m.Denoms) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Denoms[iNdEx]) + copy(dAtA[i:], m.Denoms[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denoms[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -2395,6 +2583,29 @@ func (m *ThrottledPacketDataWrapper_VscMaturedPacket) Size() (n int) { } return n } +func (m *QueryRegisteredConsumerRewardDenomsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryRegisteredConsumerRewardDenomsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Denoms) > 0 { + for _, s := range m.Denoms { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 @@ -4137,6 +4348,138 @@ func (m *ThrottledPacketDataWrapper) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryRegisteredConsumerRewardDenomsRequest) 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: QueryRegisteredConsumerRewardDenomsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRegisteredConsumerRewardDenomsRequest: 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 *QueryRegisteredConsumerRewardDenomsResponse) 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: QueryRegisteredConsumerRewardDenomsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRegisteredConsumerRewardDenomsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denoms", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denoms = append(m.Denoms, string(dAtA[iNdEx:postIndex])) + 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/ccv/provider/types/query.pb.gw.go b/x/ccv/provider/types/query.pb.gw.go index cb5e2f2411..6a249ca2a2 100644 --- a/x/ccv/provider/types/query.pb.gw.go +++ b/x/ccv/provider/types/query.pb.gw.go @@ -267,6 +267,24 @@ func local_request_Query_QueryThrottledConsumerPacketData_0(ctx context.Context, } +func request_Query_QueryRegisteredConsumerRewardDenoms_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRegisteredConsumerRewardDenomsRequest + var metadata runtime.ServerMetadata + + msg, err := client.QueryRegisteredConsumerRewardDenoms(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_QueryRegisteredConsumerRewardDenoms_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRegisteredConsumerRewardDenomsRequest + var metadata runtime.ServerMetadata + + msg, err := server.QueryRegisteredConsumerRewardDenoms(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. @@ -457,6 +475,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_QueryRegisteredConsumerRewardDenoms_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_QueryRegisteredConsumerRewardDenoms_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_QueryRegisteredConsumerRewardDenoms_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -658,6 +699,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_QueryRegisteredConsumerRewardDenoms_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_QueryRegisteredConsumerRewardDenoms_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_QueryRegisteredConsumerRewardDenoms_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -677,6 +738,8 @@ var ( pattern_Query_QueryThrottleState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "provider", "throttle_state"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_QueryThrottledConsumerPacketData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "provider", "pending_consumer_packets"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_QueryRegisteredConsumerRewardDenoms_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "provider", "registered_consumer_reward_denoms"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -695,4 +758,6 @@ var ( forward_Query_QueryThrottleState_0 = runtime.ForwardResponseMessage forward_Query_QueryThrottledConsumerPacketData_0 = runtime.ForwardResponseMessage + + forward_Query_QueryRegisteredConsumerRewardDenoms_0 = runtime.ForwardResponseMessage ) diff --git a/x/ccv/provider/types/tx.pb.go b/x/ccv/provider/types/tx.pb.go index fcf29bb203..3bc162ceb2 100644 --- a/x/ccv/provider/types/tx.pb.go +++ b/x/ccv/provider/types/tx.pb.go @@ -6,7 +6,7 @@ package types import ( context "context" fmt "fmt" - types "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/cosmos/cosmos-sdk/codec/types" _ "github.com/gogo/protobuf/gogoproto" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" @@ -36,8 +36,10 @@ type MsgAssignConsumerKey struct { ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` // The validator address on the provider ProviderAddr string `protobuf:"bytes,2,opt,name=provider_addr,json=providerAddr,proto3" json:"provider_addr,omitempty" yaml:"address"` - // The consensus public key to use on the consumer - ConsumerKey *types.Any `protobuf:"bytes,3,opt,name=consumer_key,json=consumerKey,proto3" json:"consumer_key,omitempty"` + // The consensus public key to use on the consumer. + // in json string format corresponding to proto-any, ex: + // `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is="}` + ConsumerKey string `protobuf:"bytes,3,opt,name=consumer_key,json=consumerKey,proto3" json:"consumer_key,omitempty"` } func (m *MsgAssignConsumerKey) Reset() { *m = MsgAssignConsumerKey{} } @@ -109,9 +111,91 @@ func (m *MsgAssignConsumerKeyResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgAssignConsumerKeyResponse proto.InternalMessageInfo +// MsgRegisterConsumerRewardDenom allows an account to register +// a consumer reward denom, i.e., add it to the list of denoms +// accepted by the provider as rewards. +type MsgRegisterConsumerRewardDenom struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` + Depositor string `protobuf:"bytes,2,opt,name=depositor,proto3" json:"depositor,omitempty"` +} + +func (m *MsgRegisterConsumerRewardDenom) Reset() { *m = MsgRegisterConsumerRewardDenom{} } +func (m *MsgRegisterConsumerRewardDenom) String() string { return proto.CompactTextString(m) } +func (*MsgRegisterConsumerRewardDenom) ProtoMessage() {} +func (*MsgRegisterConsumerRewardDenom) Descriptor() ([]byte, []int) { + return fileDescriptor_43221a4391e9fbf4, []int{2} +} +func (m *MsgRegisterConsumerRewardDenom) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRegisterConsumerRewardDenom) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRegisterConsumerRewardDenom.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 *MsgRegisterConsumerRewardDenom) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRegisterConsumerRewardDenom.Merge(m, src) +} +func (m *MsgRegisterConsumerRewardDenom) XXX_Size() int { + return m.Size() +} +func (m *MsgRegisterConsumerRewardDenom) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRegisterConsumerRewardDenom.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRegisterConsumerRewardDenom proto.InternalMessageInfo + +// MsgRegisterConsumerRewardDenomResponse defines the Msg/RegisterConsumerRewardDenom response type. +type MsgRegisterConsumerRewardDenomResponse struct { +} + +func (m *MsgRegisterConsumerRewardDenomResponse) Reset() { + *m = MsgRegisterConsumerRewardDenomResponse{} +} +func (m *MsgRegisterConsumerRewardDenomResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRegisterConsumerRewardDenomResponse) ProtoMessage() {} +func (*MsgRegisterConsumerRewardDenomResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_43221a4391e9fbf4, []int{3} +} +func (m *MsgRegisterConsumerRewardDenomResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRegisterConsumerRewardDenomResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRegisterConsumerRewardDenomResponse.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 *MsgRegisterConsumerRewardDenomResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRegisterConsumerRewardDenomResponse.Merge(m, src) +} +func (m *MsgRegisterConsumerRewardDenomResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRegisterConsumerRewardDenomResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRegisterConsumerRewardDenomResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRegisterConsumerRewardDenomResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgAssignConsumerKey)(nil), "interchain_security.ccv.provider.v1.MsgAssignConsumerKey") proto.RegisterType((*MsgAssignConsumerKeyResponse)(nil), "interchain_security.ccv.provider.v1.MsgAssignConsumerKeyResponse") + proto.RegisterType((*MsgRegisterConsumerRewardDenom)(nil), "interchain_security.ccv.provider.v1.MsgRegisterConsumerRewardDenom") + proto.RegisterType((*MsgRegisterConsumerRewardDenomResponse)(nil), "interchain_security.ccv.provider.v1.MsgRegisterConsumerRewardDenomResponse") } func init() { @@ -119,33 +203,35 @@ func init() { } var fileDescriptor_43221a4391e9fbf4 = []byte{ - // 406 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0xbd, 0x8e, 0xd3, 0x40, - 0x10, 0xc7, 0xbd, 0x9c, 0x04, 0xc7, 0xde, 0x81, 0x84, 0xe5, 0xc2, 0x17, 0x9d, 0x9c, 0x93, 0x69, - 0xae, 0xe0, 0x76, 0x75, 0xa1, 0x40, 0xa4, 0x73, 0xa8, 0x50, 0x14, 0x09, 0x2c, 0x2a, 0x1a, 0xcb, - 0x5e, 0x2f, 0x9b, 0x15, 0xf1, 0xae, 0xb5, 0xbb, 0xb6, 0xb2, 0x6f, 0x40, 0x09, 0x25, 0x5d, 0x1e, - 0x82, 0x77, 0x00, 0x51, 0xa5, 0xa4, 0x42, 0x28, 0x69, 0xa8, 0x79, 0x02, 0x14, 0x7f, 0x10, 0x21, - 0x52, 0xa0, 0xeb, 0x66, 0xe6, 0x3f, 0x3b, 0xf3, 0x9b, 0x9d, 0x81, 0x8f, 0xb8, 0x30, 0x54, 0x91, - 0x79, 0xca, 0x45, 0xa2, 0x29, 0xa9, 0x14, 0x37, 0x16, 0x13, 0x52, 0xe3, 0x52, 0xc9, 0x9a, 0xe7, - 0x54, 0xe1, 0xfa, 0x1a, 0x9b, 0x25, 0x2a, 0x95, 0x34, 0xd2, 0x7d, 0x78, 0x20, 0x1b, 0x11, 0x52, - 0xa3, 0x3e, 0x1b, 0xd5, 0xd7, 0x83, 0x73, 0x26, 0x25, 0x5b, 0x50, 0x9c, 0x96, 0x1c, 0xa7, 0x42, - 0x48, 0x93, 0x1a, 0x2e, 0x85, 0x6e, 0x4b, 0x0c, 0x3c, 0x26, 0x99, 0x6c, 0x4c, 0xbc, 0xb3, 0xba, - 0xe8, 0x19, 0x91, 0xba, 0x90, 0x3a, 0x69, 0x85, 0xd6, 0xe9, 0xa5, 0xae, 0x5c, 0xe3, 0x65, 0xd5, - 0x1b, 0x9c, 0x0a, 0xdb, 0x4a, 0xe1, 0x67, 0x00, 0xbd, 0x99, 0x66, 0x91, 0xd6, 0x9c, 0x89, 0x67, - 0x52, 0xe8, 0xaa, 0xa0, 0x6a, 0x4a, 0xad, 0x7b, 0x06, 0x8f, 0x5b, 0x48, 0x9e, 0xfb, 0xe0, 0x02, - 0x5c, 0xde, 0x8d, 0xef, 0x34, 0xfe, 0xf3, 0xdc, 0x7d, 0x02, 0xef, 0xf5, 0xb0, 0x49, 0x9a, 0xe7, - 0xca, 0xbf, 0xb5, 0xd3, 0x27, 0xee, 0xaf, 0xef, 0xc3, 0xfb, 0x36, 0x2d, 0x16, 0xe3, 0x70, 0x17, - 0xa5, 0x5a, 0x87, 0xf1, 0x69, 0x9f, 0x18, 0xe5, 0xb9, 0x72, 0x5f, 0xc2, 0x53, 0xd2, 0xb5, 0x48, - 0xde, 0x52, 0xeb, 0x1f, 0x5d, 0x80, 0xcb, 0x93, 0x91, 0x87, 0x5a, 0x3c, 0xd4, 0xe3, 0xa1, 0x48, - 0xd8, 0x89, 0xff, 0xf5, 0xd3, 0x95, 0xd7, 0x4d, 0x41, 0x94, 0x2d, 0x8d, 0x44, 0x2f, 0xaa, 0x6c, - 0x4a, 0x6d, 0x7c, 0x42, 0xf6, 0x98, 0xe3, 0xe3, 0x77, 0xab, 0xa1, 0xf3, 0x73, 0x35, 0x74, 0xc2, - 0x00, 0x9e, 0x1f, 0x1a, 0x24, 0xa6, 0xba, 0x94, 0x42, 0xd3, 0xd1, 0x47, 0x00, 0x8f, 0x66, 0x9a, - 0xb9, 0x1f, 0x00, 0x7c, 0xf0, 0xef, 0xb8, 0x4f, 0xd1, 0x7f, 0xec, 0x05, 0x1d, 0x6a, 0x30, 0x88, - 0x6e, 0xfc, 0xb4, 0x67, 0x9b, 0xbc, 0xfa, 0xb2, 0x09, 0xc0, 0x7a, 0x13, 0x80, 0x1f, 0x9b, 0x00, - 0xbc, 0xdf, 0x06, 0xce, 0x7a, 0x1b, 0x38, 0xdf, 0xb6, 0x81, 0xf3, 0x7a, 0xcc, 0xb8, 0x99, 0x57, - 0x19, 0x22, 0xb2, 0xe8, 0x76, 0x8a, 0xf7, 0xdd, 0xae, 0xfe, 0x9c, 0xdb, 0xf2, 0xef, 0x83, 0x33, - 0xb6, 0xa4, 0x3a, 0xbb, 0xdd, 0x7c, 0xe8, 0xe3, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x78, 0xcb, - 0x05, 0x85, 0xa1, 0x02, 0x00, 0x00, + // 448 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x3d, 0x6f, 0xd3, 0x40, + 0x18, 0xc7, 0xed, 0x56, 0x40, 0x7b, 0x14, 0x24, 0x4e, 0x19, 0xd2, 0x10, 0x39, 0x60, 0x24, 0xd4, + 0x01, 0x7c, 0x2a, 0x0c, 0x88, 0x6c, 0x69, 0x59, 0x50, 0x95, 0xc5, 0x62, 0x62, 0x20, 0x72, 0xee, + 0x8e, 0xeb, 0x89, 0xfa, 0x1e, 0xeb, 0x9e, 0x8b, 0xa9, 0xbf, 0x01, 0x23, 0x4c, 0xac, 0xfd, 0x06, + 0x7c, 0x0d, 0x24, 0x96, 0x8e, 0x4c, 0x08, 0x25, 0x0b, 0x33, 0x9f, 0x00, 0xf9, 0x8d, 0x80, 0x88, + 0xa2, 0x0a, 0x75, 0x7b, 0xde, 0xfc, 0xff, 0xff, 0x7c, 0x77, 0x0f, 0x79, 0xa0, 0x8d, 0x93, 0x96, + 0x1f, 0x27, 0xda, 0x4c, 0x50, 0xf2, 0x99, 0xd5, 0xae, 0x60, 0x9c, 0xe7, 0x2c, 0xb3, 0x90, 0x6b, + 0x21, 0x2d, 0xcb, 0xf7, 0x99, 0x3b, 0x8d, 0x32, 0x0b, 0x0e, 0xe8, 0xbd, 0x15, 0xd3, 0x11, 0xe7, + 0x79, 0xd4, 0x4e, 0x47, 0xf9, 0x7e, 0xaf, 0xaf, 0x00, 0xd4, 0x89, 0x64, 0x49, 0xa6, 0x59, 0x62, + 0x0c, 0xb8, 0xc4, 0x69, 0x30, 0x58, 0x4b, 0xf4, 0x3a, 0x0a, 0x14, 0x54, 0x21, 0x2b, 0xa3, 0xa6, + 0xba, 0xcb, 0x01, 0x53, 0xc0, 0x49, 0xdd, 0xa8, 0x93, 0xb6, 0xd5, 0xc8, 0x55, 0xd9, 0x74, 0xf6, + 0x9a, 0x25, 0xa6, 0xa8, 0x5b, 0xe1, 0x47, 0x9f, 0x74, 0xc6, 0xa8, 0x46, 0x88, 0x5a, 0x99, 0x43, + 0x30, 0x38, 0x4b, 0xa5, 0x3d, 0x92, 0x05, 0xdd, 0x25, 0x5b, 0x35, 0xa4, 0x16, 0x5d, 0xff, 0x8e, + 0xbf, 0xb7, 0x1d, 0x5f, 0xab, 0xf2, 0xe7, 0x82, 0x3e, 0x21, 0x37, 0x5a, 0xd8, 0x49, 0x22, 0x84, + 0xed, 0x6e, 0x94, 0xfd, 0x03, 0xfa, 0xf3, 0xdb, 0xe0, 0x66, 0x91, 0xa4, 0x27, 0xc3, 0xb0, 0xac, + 0x4a, 0xc4, 0x30, 0xde, 0x69, 0x07, 0x47, 0x42, 0x58, 0x7a, 0x97, 0xec, 0xf0, 0xc6, 0x62, 0xf2, + 0x46, 0x16, 0xdd, 0xcd, 0x4a, 0xf7, 0x3a, 0x5f, 0xda, 0x0e, 0xb7, 0xde, 0x9d, 0x0d, 0xbc, 0x1f, + 0x67, 0x03, 0x2f, 0x0c, 0x48, 0x7f, 0x15, 0x58, 0x2c, 0x31, 0x03, 0x83, 0x32, 0x7c, 0x45, 0x82, + 0x31, 0xaa, 0x58, 0x2a, 0x8d, 0x4e, 0xda, 0x76, 0x22, 0x96, 0x6f, 0x13, 0x2b, 0x9e, 0x49, 0x03, + 0x29, 0xed, 0x90, 0x2b, 0xa2, 0x0c, 0x1a, 0xfe, 0x3a, 0xa1, 0x7d, 0xb2, 0x2d, 0x64, 0x06, 0xa8, + 0x1d, 0x34, 0xe4, 0xf1, 0xb2, 0xf0, 0x87, 0xff, 0x1e, 0xb9, 0xbf, 0x5e, 0xbf, 0x25, 0x79, 0xf4, + 0x65, 0x83, 0x6c, 0x8e, 0x51, 0xd1, 0x0f, 0x3e, 0xb9, 0xf5, 0xef, 0x41, 0x3e, 0x8d, 0x2e, 0x70, + 0xe3, 0xd1, 0xaa, 0x5f, 0xed, 0x8d, 0xfe, 0xfb, 0xd3, 0x96, 0x8d, 0x7e, 0xf2, 0xc9, 0xed, 0x75, + 0x67, 0x74, 0x78, 0x51, 0x8b, 0x35, 0x22, 0xbd, 0xa3, 0x4b, 0x10, 0x69, 0x89, 0x0f, 0x5e, 0x7c, + 0x9e, 0x07, 0xfe, 0xf9, 0x3c, 0xf0, 0xbf, 0xcf, 0x03, 0xff, 0xfd, 0x22, 0xf0, 0xce, 0x17, 0x81, + 0xf7, 0x75, 0x11, 0x78, 0x2f, 0x87, 0x4a, 0xbb, 0xe3, 0xd9, 0x34, 0xe2, 0x90, 0x36, 0xef, 0x9b, + 0x2d, 0x7d, 0x1f, 0xfe, 0x5e, 0xbd, 0xd3, 0xbf, 0x97, 0xcf, 0x15, 0x99, 0xc4, 0xe9, 0xd5, 0xea, + 0xb9, 0x3f, 0xfe, 0x15, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xbc, 0x30, 0xff, 0xad, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -161,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 MsgClient interface { AssignConsumerKey(ctx context.Context, in *MsgAssignConsumerKey, opts ...grpc.CallOption) (*MsgAssignConsumerKeyResponse, error) + RegisterConsumerRewardDenom(ctx context.Context, in *MsgRegisterConsumerRewardDenom, opts ...grpc.CallOption) (*MsgRegisterConsumerRewardDenomResponse, error) } type msgClient struct { @@ -180,9 +267,19 @@ func (c *msgClient) AssignConsumerKey(ctx context.Context, in *MsgAssignConsumer return out, nil } +func (c *msgClient) RegisterConsumerRewardDenom(ctx context.Context, in *MsgRegisterConsumerRewardDenom, opts ...grpc.CallOption) (*MsgRegisterConsumerRewardDenomResponse, error) { + out := new(MsgRegisterConsumerRewardDenomResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Msg/RegisterConsumerRewardDenom", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { AssignConsumerKey(context.Context, *MsgAssignConsumerKey) (*MsgAssignConsumerKeyResponse, error) + RegisterConsumerRewardDenom(context.Context, *MsgRegisterConsumerRewardDenom) (*MsgRegisterConsumerRewardDenomResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -192,6 +289,9 @@ type UnimplementedMsgServer struct { func (*UnimplementedMsgServer) AssignConsumerKey(ctx context.Context, req *MsgAssignConsumerKey) (*MsgAssignConsumerKeyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AssignConsumerKey not implemented") } +func (*UnimplementedMsgServer) RegisterConsumerRewardDenom(ctx context.Context, req *MsgRegisterConsumerRewardDenom) (*MsgRegisterConsumerRewardDenomResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterConsumerRewardDenom not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -215,6 +315,24 @@ func _Msg_AssignConsumerKey_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Msg_RegisterConsumerRewardDenom_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRegisterConsumerRewardDenom) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RegisterConsumerRewardDenom(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/interchain_security.ccv.provider.v1.Msg/RegisterConsumerRewardDenom", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RegisterConsumerRewardDenom(ctx, req.(*MsgRegisterConsumerRewardDenom)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "interchain_security.ccv.provider.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -223,6 +341,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "AssignConsumerKey", Handler: _Msg_AssignConsumerKey_Handler, }, + { + MethodName: "RegisterConsumerRewardDenom", + Handler: _Msg_RegisterConsumerRewardDenom_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "interchain_security/ccv/provider/v1/tx.proto", @@ -248,15 +370,10 @@ func (m *MsgAssignConsumerKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.ConsumerKey != nil { - { - size, err := m.ConsumerKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } + if len(m.ConsumerKey) > 0 { + i -= len(m.ConsumerKey) + copy(dAtA[i:], m.ConsumerKey) + i = encodeVarintTx(dAtA, i, uint64(len(m.ConsumerKey))) i-- dAtA[i] = 0x1a } @@ -300,6 +417,66 @@ func (m *MsgAssignConsumerKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } +func (m *MsgRegisterConsumerRewardDenom) 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 *MsgRegisterConsumerRewardDenom) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterConsumerRewardDenom) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Depositor) > 0 { + i -= len(m.Depositor) + copy(dAtA[i:], m.Depositor) + i = encodeVarintTx(dAtA, i, uint64(len(m.Depositor))) + i-- + dAtA[i] = 0x12 + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintTx(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRegisterConsumerRewardDenomResponse) 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 *MsgRegisterConsumerRewardDenomResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRegisterConsumerRewardDenomResponse) 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 @@ -325,8 +502,8 @@ func (m *MsgAssignConsumerKey) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if m.ConsumerKey != nil { - l = m.ConsumerKey.Size() + l = len(m.ConsumerKey) + if l > 0 { n += 1 + l + sovTx(uint64(l)) } return n @@ -341,6 +518,32 @@ func (m *MsgAssignConsumerKeyResponse) Size() (n int) { return n } +func (m *MsgRegisterConsumerRewardDenom) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Depositor) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRegisterConsumerRewardDenomResponse) 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 } @@ -444,7 +647,7 @@ func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error { if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ConsumerKey", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -454,27 +657,23 @@ func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - if m.ConsumerKey == nil { - m.ConsumerKey = &types.Any{} - } - if err := m.ConsumerKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.ConsumerKey = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -547,6 +746,170 @@ func (m *MsgAssignConsumerKeyResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgRegisterConsumerRewardDenom) 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: MsgRegisterConsumerRewardDenom: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterConsumerRewardDenom: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", 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.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Depositor", 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.Depositor = string(dAtA[iNdEx:postIndex]) + 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 *MsgRegisterConsumerRewardDenomResponse) 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: MsgRegisterConsumerRewardDenomResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRegisterConsumerRewardDenomResponse: 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 diff --git a/x/ccv/types/events.go b/x/ccv/types/events.go index 1cab3e8a15..ba71e063f3 100644 --- a/x/ccv/types/events.go +++ b/x/ccv/types/events.go @@ -2,12 +2,13 @@ package types // CCV events const ( - EventTypeTimeout = "timeout" - EventTypePacket = "ccv_packet" - EventTypeChannelEstablished = "channel_established" - EventTypeFeeTransferChannelOpened = "fee_transfer_channel_opened" - EventTypeConsumerClientCreated = "consumer_client_created" - EventTypeAssignConsumerKey = "assign_consumer_key" + EventTypeTimeout = "timeout" + EventTypePacket = "ccv_packet" + EventTypeChannelEstablished = "channel_established" + EventTypeFeeTransferChannelOpened = "fee_transfer_channel_opened" + EventTypeConsumerClientCreated = "consumer_client_created" + EventTypeAssignConsumerKey = "assign_consumer_key" + EventTypeRegisterConsumerRewardDenom = "register_consumer_reward_denom" EventTypeExecuteConsumerChainSlash = "execute_consumer_chain_slash" EventTypeFeeDistribution = "fee_distribution" @@ -38,4 +39,7 @@ const ( AttributeDistributionFraction = "distribution_fraction" AttributeDistributionTotal = "total" AttributeDistributionToProvider = "provider_amount" + + AttributeConsumerRewardDenom = "consumer_reward_denom" + AttributeConsumerRewardDepositor = "consumer_reward_depositor" ) diff --git a/x/ccv/types/expected_keepers.go b/x/ccv/types/expected_keepers.go index 6ce079f454..7a220111b1 100644 --- a/x/ccv/types/expected_keepers.go +++ b/x/ccv/types/expected_keepers.go @@ -35,6 +35,7 @@ type StakingKeeper interface { PowerReduction(ctx sdk.Context) sdk.Int PutUnbondingOnHold(ctx sdk.Context, id uint64) error GetLastTotalPower(ctx sdk.Context) sdk.Int + BondDenom(ctx sdk.Context) (res string) } type EvidenceKeeper interface { @@ -79,7 +80,10 @@ type ClientKeeper interface { GetSelfConsensusState(ctx sdk.Context, height ibcexported.Height) (ibcexported.ConsensusState, error) } -// TODO: Expected interfaces for distribution on provider and consumer chains +// DistributionKeeper defines the expected interface of the distribution keeper +type DistributionKeeper interface { + FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error +} // ConsumerHooks event hooks for newly bonded cross-chain validators type ConsumerHooks interface {