Skip to content

Commit

Permalink
feat!: deposit to validator rewards pool (#14322)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored Dec 20, 2022
1 parent 3aa16ed commit 11f1e8d
Show file tree
Hide file tree
Showing 11 changed files with 2,025 additions and 162 deletions.
11 changes: 6 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,20 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* (x/slashing, x/staking) [#14363](https://github.com/cosmos/cosmos-sdk/pull/14363) Add the infraction a validator commited type as an argument to a `SlashWithInfractionReason` keeper method.
* (x/distribution) [#14322](https://github.com/cosmos/cosmos-sdk/pull/14322) Introduce a new gRPC message handler, `DepositValidatorRewardsPool`, that allows explicit funding of a validator's reward pool.
* (x/slashing, x/staking) [#14363](https://github.com/cosmos/cosmos-sdk/pull/14363) Add the infraction a validator committed type as an argument to a `SlashWithInfractionReason` keeper method.
* (x/evidence) [#13740](https://github.com/cosmos/cosmos-sdk/pull/13740) Add new proto field `hash` of type `string` to `QueryEvidenceRequest` which helps to decode the hash properly while using query API.
* (core) [#13306](https://github.com/cosmos/cosmos-sdk/pull/13306) Add a `FormatCoins` function to in `core/coins` to format sdk Coins following the Value Renderers spec.
* (math) [#13306](https://github.com/cosmos/cosmos-sdk/pull/13306) Add `FormatInt` and `FormatDec` functiosn in `math` to format integers and decimals following the Value Renderers spec.
* (math) [#13306](https://github.com/cosmos/cosmos-sdk/pull/13306) Add `FormatInt` and `FormatDec` functions in `math` to format integers and decimals following the Value Renderers spec.
* (x/staking) [#13122](https://github.com/cosmos/cosmos-sdk/pull/13122) Add `UnbondingCanComplete` and `PutUnbondingOnHold` to `x/staking` module.
* [#13437](https://github.com/cosmos/cosmos-sdk/pull/13437) Add new flag `--modules-to-export` in `simd export` command to export only selected modules.
* [#13298](https://github.com/cosmos/cosmos-sdk/pull/13298) Add `AddGenesisAccount` helper func in x/auth module which helps adding accounts to genesis state.
* (x/authz) [#12648](https://github.com/cosmos/cosmos-sdk/pull/12648) Add an allow list, an optional list of addresses allowed to receive bank assets via authz MsgSend grant.
* (sdk.Coins) [#12627](https://github.com/cosmos/cosmos-sdk/pull/12627) Make a Denoms method on sdk.Coins.
* (sdk.Coins) [#12627](https://github.com/cosmos/cosmos-sdk/pull/12627) Make a `Denoms` method on sdk.Coins.
* (testutil) [#12973](https://github.com/cosmos/cosmos-sdk/pull/12973) Add generic `testutil.RandSliceElem` function which selects a random element from the list.
* (client) [#12936](https://github.com/cosmos/cosmos-sdk/pull/12936) Add capability to preprocess transactions before broadcasting from a higher level chain.
* (client) [#12936](https://github.com/cosmos/cosmos-sdk/pull/12936) Add capability to pre-process transactions before broadcasting from a higher level chain.
* (cli) [#13064](https://github.com/cosmos/cosmos-sdk/pull/13064) Add `debug prefixes` to list supported HRP prefixes via .
* (ledger) [#12935](https://github.com/cosmos/cosmos-sdk/pull/12935) Generalize Ledger integration to allow for different apps or keytypes that use SECP256k1.
* (ledger) [#12935](https://github.com/cosmos/cosmos-sdk/pull/12935) Generalize Ledger integration to allow for different apps or key types that use SECP256k1.
* (x/bank) [#11981](https://github.com/cosmos/cosmos-sdk/pull/11981) Create the `SetSendEnabled` endpoint for managing the bank's SendEnabled settings.
* (x/auth) [#13210](https://github.com/cosmos/cosmos-sdk/pull/13210) Add `Query/AccountInfo` endpoint for simplified access to basic account info.
* (x/consensus) [#12905](https://github.com/cosmos/cosmos-sdk/pull/12905) Create a new `x/consensus` module that is now responsible for maintaining Tendermint consensus parameters instead of `x/param`. Legacy types remain in order to facilitate parameter migration from the deprecated `x/params`. App developers should ensure that they execute `baseapp.MigrateParams` during their chain upgrade. These legacy types will be removed in a future release.
Expand Down
1,301 changes: 1,212 additions & 89 deletions api/cosmos/distribution/v1beta1/tx.pulsar.go

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions api/cosmos/distribution/v1beta1/tx_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 46 additions & 9 deletions proto/cosmos/distribution/v1beta1/tx.proto
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
syntax = "proto3";
package cosmos.distribution.v1beta1;

option go_package = "github.com/cosmos/cosmos-sdk/x/distribution/types";
option go_package = "github.com/cosmos/cosmos-sdk/x/distribution/types";
option (gogoproto.equal_all) = true;

import "gogoproto/gogo.proto";
Expand All @@ -17,19 +17,23 @@ service Msg {

// SetWithdrawAddress defines a method to change the withdraw address
// for a delegator (or validator self-delegation).
rpc SetWithdrawAddress(MsgSetWithdrawAddress) returns (MsgSetWithdrawAddressResponse);
rpc SetWithdrawAddress(MsgSetWithdrawAddress)
returns (MsgSetWithdrawAddressResponse);

// WithdrawDelegatorReward defines a method to withdraw rewards of delegator
// from a single validator.
rpc WithdrawDelegatorReward(MsgWithdrawDelegatorReward) returns (MsgWithdrawDelegatorRewardResponse);
rpc WithdrawDelegatorReward(MsgWithdrawDelegatorReward)
returns (MsgWithdrawDelegatorRewardResponse);

// WithdrawValidatorCommission defines a method to withdraw the
// full commission to the validator address.
rpc WithdrawValidatorCommission(MsgWithdrawValidatorCommission) returns (MsgWithdrawValidatorCommissionResponse);
rpc WithdrawValidatorCommission(MsgWithdrawValidatorCommission)
returns (MsgWithdrawValidatorCommissionResponse);

// FundCommunityPool defines a method to allow an account to directly
// fund the community pool.
rpc FundCommunityPool(MsgFundCommunityPool) returns (MsgFundCommunityPoolResponse);
rpc FundCommunityPool(MsgFundCommunityPool)
returns (MsgFundCommunityPoolResponse);

// UpdateParams defines a governance operation for updating the x/distribution
// module parameters. The authority is defined in the keeper.
Expand All @@ -43,7 +47,15 @@ service Msg {
// keeper.
//
// Since: cosmos-sdk 0.47
rpc CommunityPoolSpend(MsgCommunityPoolSpend) returns (MsgCommunityPoolSpendResponse);
rpc CommunityPoolSpend(MsgCommunityPoolSpend)
returns (MsgCommunityPoolSpendResponse);

// DepositValidatorRewardsPool defines a method to provide additional rewards
// to delegators to a specific validator.
//
// Since: cosmos-sdk 0.48
rpc DepositValidatorRewardsPool(MsgDepositValidatorRewardsPool)
returns (MsgDepositValidatorRewardsPoolResponse);
}

// MsgSetWithdrawAddress sets the withdraw address for
Expand Down Expand Up @@ -143,7 +155,8 @@ message MsgUpdateParams {
// params defines the x/distribution parameters to update.
//
// NOTE: All parameters must be supplied.
Params params = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
Params params = 2
[(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
}

// MsgUpdateParamsResponse defines the response structure for executing a
Expand All @@ -162,8 +175,8 @@ message MsgCommunityPoolSpend {
option (amino.name) = "cosmos-sdk/distr/MsgCommunityPoolSpend";

// authority is the address of the governance account.
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string recipient = 2;
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string recipient = 2;
repeated cosmos.base.v1beta1.Coin amount = 3 [
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true,
Expand All @@ -176,3 +189,27 @@ message MsgCommunityPoolSpend {
//
// Since: cosmos-sdk 0.47
message MsgCommunityPoolSpendResponse {}

// DepositValidatorRewardsPool defines the request structure to provide
// additional rewards to delegators from a specific validator.
//
// Since: cosmos-sdk 0.48
message MsgDepositValidatorRewardsPool {
option (cosmos.msg.v1.signer) = "authority";

option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string validator_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
repeated cosmos.base.v1beta1.Coin amount = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}

// MsgDepositValidatorRewardsPoolResponse defines the response to executing a
// MsgDepositValidatorRewardsPool message.
//
// Since: cosmos-sdk 0.48
message MsgDepositValidatorRewardsPoolResponse {}
11 changes: 6 additions & 5 deletions tests/integration/distribution/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ type KeeperTestSuite struct {
msgServer types.MsgServer
}

func TestDistributionTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}

func (suite *KeeperTestSuite) SetupTest() {
app, err := simtestutil.Setup(testutil.AppConfig,
app, err := simtestutil.Setup(
testutil.AppConfig,
&suite.interfaceRegistry,
&suite.bankKeeper,
&suite.distrKeeper,
Expand Down Expand Up @@ -672,7 +677,3 @@ func (suite *KeeperTestSuite) TestGRPCCommunityPool() {
})
}
}

func TestDistributionTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
74 changes: 74 additions & 0 deletions tests/integration/distribution/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package keeper_test

import (
"cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

func (s *KeeperTestSuite) TestMsgUpdateParams() {
Expand Down Expand Up @@ -206,3 +211,72 @@ func (s *KeeperTestSuite) TestCommunityPoolSpend() {
})
}
}

func (s *KeeperTestSuite) TestMsgDepositValidatorRewardsPool() {
tstaking := stakingtestutil.NewHelper(s.T(), s.ctx, s.stakingKeeper)
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
tstaking.CreateValidator(s.valAddrs[1], valConsPk0, sdk.NewInt(100), true)

// mint a non-staking token and send to an account
amt := sdk.NewCoins(sdk.NewInt64Coin("foo", 500))
s.bankKeeper.MintCoins(s.ctx, minttypes.ModuleName, amt)
s.bankKeeper.SendCoinsFromModuleToAccount(s.ctx, minttypes.ModuleName, s.addrs[0], amt)

testCases := []struct {
name string
input *types.MsgDepositValidatorRewardsPool
expErr bool
expErrMsg string
}{
{
name: "happy path (staking token)",
input: &types.MsgDepositValidatorRewardsPool{
Authority: s.addrs[0].String(),
ValidatorAddress: s.valAddrs[1].String(),
Amount: sdk.NewCoins(sdk.NewCoin(s.stakingKeeper.BondDenom(s.ctx), sdk.NewInt(100))),
},
},
{
name: "happy path (non-staking token)",
input: &types.MsgDepositValidatorRewardsPool{
Authority: s.addrs[0].String(),
ValidatorAddress: s.valAddrs[1].String(),
Amount: amt,
},
},
{
name: "invalid validator",
input: &types.MsgDepositValidatorRewardsPool{
Authority: s.addrs[0].String(),
ValidatorAddress: sdk.ValAddress([]byte("addr1_______________")).String(),
Amount: sdk.NewCoins(sdk.NewCoin(s.stakingKeeper.BondDenom(s.ctx), sdk.NewInt(100))),
},
expErr: true,
expErrMsg: "validator does not exist",
},
}

for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
_, err := s.msgServer.DepositValidatorRewardsPool(s.ctx, tc.input)

if tc.expErr {
s.Require().Error(err)
s.Require().Contains(err.Error(), tc.expErrMsg)
} else {
s.Require().NoError(err)

valAddr, err := sdk.ValAddressFromBech32(tc.input.ValidatorAddress)
s.Require().NoError(err)

// check validator outstanding rewards
outstandingRewards := s.distrKeeper.GetValidatorOutstandingRewards(s.ctx, valAddr)
for _, c := range tc.input.Amount {
x := outstandingRewards.Rewards.AmountOf(c.Denom)
s.Require().Equal(x, sdk.NewDecFromInt(c.Amount))
}
}
})
}
}
40 changes: 40 additions & 0 deletions x/distribution/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func NewTxCmd() *cobra.Command {
NewWithdrawAllRewardsCmd(),
NewSetWithdrawAddrCmd(),
NewFundCommunityPoolCmd(),
NewDepositValidatorRewardsPoolCmd(),
)

return distTxCmd
Expand Down Expand Up @@ -254,3 +255,42 @@ $ %s tx distribution fund-community-pool 100uatom --from mykey

return cmd
}

// NewDepositValidatorRewardsPoolCmd returns a CLI command handler for creating
// a MsgDepositValidatorRewardsPool transaction.
func NewDepositValidatorRewardsPoolCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "fund-validator-rewards-pool [val_addr] [amount]",
Args: cobra.ExactArgs(2),
Short: "Fund the validator rewards pool with the specified amount",
Example: fmt.Sprintf(
"%s tx distribution fund-validator-rewards-pool cosmosvaloper1x20lytyf6zkcrv5edpkfkn8sz578qg5sqfyqnp 100uatom --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()

valAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}

amount, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return err
}

msg := types.NewMsgDepositValidatorRewardsPool(depositorAddr, valAddr, amount)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
Loading

0 comments on commit 11f1e8d

Please sign in to comment.