Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Outstanding per-validator rewards; correctly handle same-BeginBlock redelegation-double-slash #3750

Merged
merged 58 commits into from
Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
da12165
Add altered random number generation
cwgoes Feb 22, 2019
b7d1d69
WIP Allow undelegation of more coins than delegated; Add more validit…
jaekwon Feb 22, 2019
2f9a0da
Fix tests
jaekwon Feb 22, 2019
c938039
Revert "Fix tests"
jaekwon Feb 22, 2019
066e11f
fix tests
jaekwon Feb 22, 2019
f7c3cc6
Add comment on new behavior
jaekwon Feb 22, 2019
637902d
Call AddCoins conditionally
jaekwon Feb 22, 2019
71774b8
Do not panic with unknown evidence
jaekwon Feb 23, 2019
d9b5071
update comments from bez's branch
jaekwon Feb 23, 2019
0c0b142
fixing more sim issues
jaekwon Feb 24, 2019
aca59ac
Ignore unknown proposer
jaekwon Feb 24, 2019
002e49f
Add bias to return 0 to RandomAmount
jaekwon Feb 25, 2019
89e84f5
Negative coins amount during fees distribution
hleb-albau Feb 24, 2019
d25f793
Truncate multiplication & division; add back old testcase
cwgoes Feb 25, 2019
c388d00
PENDING.md
cwgoes Feb 25, 2019
02b076f
Address @alexanderbez comments
cwgoes Feb 25, 2019
1861c97
Merge branch 'develop' into cwgoes/alternative-negative-coins-fix
cwgoes Feb 25, 2019
7972df8
Merge branch 'cwgoes/alternative-negative-coins-fix' into cwgoes/back…
cwgoes Feb 26, 2019
8ff6302
Debugging...
cwgoes Feb 26, 2019
4e15d33
More debugging...
cwgoes Feb 26, 2019
f29bbae
Moar debugging
cwgoes Feb 26, 2019
72a850e
...
cwgoes Feb 26, 2019
1c57f32
...
cwgoes Feb 26, 2019
ed989af
Outstanding per-validator
cwgoes Feb 26, 2019
4dd5f14
Naming; genesis fix, ...
cwgoes Feb 26, 2019
e8b83e2
Merge branch 'cwgoes/back-to-truncation' into cwgoes/outstanding-per-…
cwgoes Feb 26, 2019
f4e2c66
..
cwgoes Feb 27, 2019
f312638
..
cwgoes Feb 27, 2019
4b1a338
Merge branch 'develop' into cwgoes/outstanding-per-validator
cwgoes Feb 27, 2019
79809ee
Cleanup, separate out invariant changes
cwgoes Feb 27, 2019
e434724
Fixes
cwgoes Feb 27, 2019
9e1a4e4
Testcase fixes
cwgoes Feb 27, 2019
bf9c168
Fixup outstanding-rewards REST
cwgoes Feb 27, 2019
db5c799
Naming agreement; swagger.yaml update
cwgoes Feb 27, 2019
a9a72d1
Remove unused param
cwgoes Feb 27, 2019
bc26e22
Fix hook
cwgoes Feb 28, 2019
713e7b6
Fix linter
cwgoes Feb 28, 2019
38bb5e1
Add outstanding to community pool
cwgoes Feb 28, 2019
93f0556
...
cwgoes Feb 28, 2019
ea06e12
...
cwgoes Feb 28, 2019
7d02f1b
Correctly calculate effective slash fraction
cwgoes Feb 28, 2019
132b30f
Maximum of the slash fractions
cwgoes Feb 28, 2019
280d9f4
Sanity check
cwgoes Feb 28, 2019
0bc856e
Sanity check; on the right track
cwgoes Feb 28, 2019
77959f5
Fix it
cwgoes Feb 28, 2019
094ae45
Merge pull request #3766 from cosmos/cwgoes/debugging-contd
cwgoes Feb 28, 2019
66f44f9
Fix linter
cwgoes Feb 28, 2019
ead8a2f
Merge branch 'cwgoes/outstanding-per-validator' of github.com:cosmos/…
cwgoes Feb 28, 2019
1d47060
exapand decimal tests
rigelrozanski Feb 28, 2019
9360b08
Testcase fixes
cwgoes Feb 28, 2019
96bf7e9
Fix stake calculation ordering
cwgoes Feb 28, 2019
37311ca
Address @rigelrozanski comments
cwgoes Feb 28, 2019
4c1fd17
comment
rigelrozanski Feb 28, 2019
86763f8
Address @jaekwon comments
cwgoes Mar 1, 2019
56b2b04
Merge branch 'cwgoes/outstanding-per-validator' of github.com:cosmos/…
cwgoes Mar 1, 2019
afdac45
Merge PR #3788: F1 mechanism rounding fix
rigelrozanski Mar 6, 2019
31cd44d
Merge branch 'develop' into cwgoes/outstanding-per-validator
cwgoes Mar 6, 2019
1217373
Update PENDING.md
cwgoes Mar 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,17 @@

### SDK

* \#3750 Track outstanding rewards per-validator instead of globally,
and fix the main simulation issue, which was that slashes of
re-delegations to a validator were not correctly accounted for
in fee distribution when the redelegation in question had itself
been slashed (from a fault committed by a different validator)
in the same BeginBlock. Outstanding rewards are now available
on a per-validator basis in REST.
* [\#3669] Ensure consistency in message naming, codec registration, and JSON
tags.
* #3788 Change order of operations for greater accuracy when calculating delegation share token value
* #3788 DecCoins.Cap -> DecCoins.Intersect
* [\#3666] Improve coins denom validation.
* [\#3751] Disable (temporarily) support for ED25519 account key pairs.

Expand Down
6 changes: 3 additions & 3 deletions client/lcd/lcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ func TestBonding(t *testing.T) {
// hence we utilize the exchange rate in the following test

validator2 := getValidator(t, port, operAddrs[1])
delTokensAfterRedelegation := delegatorDels[0].GetShares().Mul(validator2.DelegatorShareExRate())
delTokensAfterRedelegation := validator2.ShareTokens(delegatorDels[0].GetShares())
require.Equal(t, rdTokens.ToDec(), delTokensAfterRedelegation)

redelegation := getRedelegations(t, port, addr, operAddrs[0], operAddrs[1])
Expand Down Expand Up @@ -945,7 +945,7 @@ func TestDistributionFlow(t *testing.T) {
operAddr := sdk.AccAddress(valAddr)

var rewards sdk.DecCoins
res, body := Request(t, port, "GET", fmt.Sprintf("/distribution/outstanding_rewards"), nil)
res, body := Request(t, port, "GET", fmt.Sprintf("/distribution/validators/%s/outstanding_rewards", valAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
require.NoError(t, cdc.UnmarshalJSON([]byte(body), &rewards))

Expand All @@ -967,7 +967,7 @@ func TestDistributionFlow(t *testing.T) {
require.Equal(t, uint32(0), resultTx.Code)

// Query outstanding rewards changed
res, body = Request(t, port, "GET", fmt.Sprintf("/distribution/outstanding_rewards"), nil)
res, body = Request(t, port, "GET", fmt.Sprintf("/distribution/validators/%s/outstanding_rewards", valAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
require.NoError(t, cdc.UnmarshalJSON([]byte(body), &rewards))

Expand Down
42 changes: 24 additions & 18 deletions client/lcd/swagger-ui/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,28 @@ paths:
description: Invalid validator address
500:
description: Internal Server Error
/distribution/validators/{validatorAddr}/outstanding_rewards:
parameters:
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
get:
summary: Fee distribution outstanding rewards of a single validator
tags:
- ICS24
produces:
- application/json
responses:
200:
description: OK
schema:
type: array
items:
$ref: "#/definitions/Coin"
500:
description: Internal Server Error
/distribution/validators/{validatorAddr}/rewards:
parameters:
- in: path
Expand All @@ -1566,8 +1588,8 @@ paths:
required: true
type: string
get:
summary: Commission and self-delegation rewards of a single a validator
description: Query the commission and self-delegation rewards of a validator.
summary: Commission and self-delegation rewards of a single validator
description: Query the commission and self-delegation rewards of validator.
tags:
- ICS24
produces:
Expand Down Expand Up @@ -1630,22 +1652,6 @@ paths:
type: string
500:
description: Internal Server Error
/distribution/outstanding_rewards:
get:
summary: Fee distribution outstanding rewards
tags:
- ICS24
produces:
- application/json
responses:
200:
description: OK
schema:
type: array
items:
$ref: "#/definitions/Coin"
500:
description: Internal Server Error
definitions:
CheckTxResult:
type: object
Expand Down
7 changes: 7 additions & 0 deletions cmd/gaia/app/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ func (app *GaiaApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st

// reinitialize all validators
app.stakingKeeper.IterateValidators(ctx, func(_ int64, val sdk.Validator) (stop bool) {

// donate any unwithdrawn outstanding reward fraction tokens to the community pool
scraps := app.distrKeeper.GetValidatorOutstandingRewards(ctx, val.GetOperator())
feePool := app.distrKeeper.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(scraps)
app.distrKeeper.SetFeePool(ctx, feePool)

app.distrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator())
return false
})
Expand Down
9 changes: 6 additions & 3 deletions types/dec_coin.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,12 @@ func (coins DecCoins) SafeSub(coinsB DecCoins) (DecCoins, bool) {
return diff, diff.IsAnyNegative()
}

// Trims any denom amount from coin which exceeds that of coinB,
// such that (coin.Cap(coinB)).IsLTE(coinB).
func (coins DecCoins) Cap(coinsB DecCoins) DecCoins {
// Intersect will return a new set of coins which contains the minimum DecCoin
// for common denoms found in both `coins` and `coinsB`. For denoms not common
// to both `coins` and `coinsB` the minimum is considered to be 0, thus they
// are not added to the final set.In other words, trim any denom amount from
// coin which exceeds that of coinB, such that (coin.Intersect(coinB)).IsLTE(coinB).
func (coins DecCoins) Intersect(coinsB DecCoins) DecCoins {
res := make([]DecCoin, len(coins))
for i, coin := range coins {
minCoin := DecCoin{
Expand Down
6 changes: 3 additions & 3 deletions types/dec_coin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func TestDecCoinsString(t *testing.T) {
}
}

func TestDecCoinsCap(t *testing.T) {
func TestDecCoinsIntersect(t *testing.T) {
testCases := []struct {
input1 string
input2 string
Expand All @@ -252,7 +252,7 @@ func TestDecCoinsCap(t *testing.T) {
exr, err := ParseDecCoins(tc.expectedResult)
require.NoError(t, err, "unexpected parse error in %v", i)

require.True(t, in1.Cap(in2).IsEqual(exr), "in1.cap(in2) != exr in %v", i)
// require.Equal(t, tc.expectedResult, in1.Cap(in2).String(), "in1.cap(in2) != exr in %v", i)
require.True(t, in1.Intersect(in2).IsEqual(exr), "in1.cap(in2) != exr in %v", i)
// require.Equal(t, tc.expectedResult, in1.Intersect(in2).String(), "in1.cap(in2) != exr in %v", i)
}
}
38 changes: 38 additions & 0 deletions types/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,21 @@ func (d Dec) QuoTruncate(d2 Dec) Dec {
return Dec{chopped}
}

// quotient, round up
func (d Dec) QuoRoundUp(d2 Dec) Dec {
// multiply precision twice
mul := new(big.Int).Mul(d.Int, precisionReuse)
mul.Mul(mul, precisionReuse)

quo := new(big.Int).Quo(mul, d2.Int)
chopped := chopPrecisionAndRoundUp(quo)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of doing this, since multiplication/division is expensive, i think we can do:

((d.Int + (precisionReuse-1)) * precisionReuse) / d2.Int

then we wouldn't need chopPrecisionAndRoundUp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's do that, but in a separate PR - #3812


if chopped.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{chopped}
}

// quotient
func (d Dec) QuoInt(i Int) Dec {
mul := new(big.Int).Quo(d.Int, i.i)
Expand Down Expand Up @@ -412,6 +427,29 @@ func chopPrecisionAndRound(d *big.Int) *big.Int {
}
}

func chopPrecisionAndRoundUp(d *big.Int) *big.Int {

// remove the negative and add it back when returning
if d.Sign() == -1 {
// make d positive, compute chopped value, and then un-mutate d
d = d.Neg(d)
// truncate since d is negative...
d = chopPrecisionAndTruncate(d)
d = d.Neg(d)
return d
}

// get the truncated quotient and remainder
quo, rem := d, big.NewInt(0)
quo, rem = quo.QuoRem(d, precisionReuse, rem)

if rem.Sign() == 0 { // remainder is zero
return quo
}

return quo.Add(quo, oneInt)
}

func chopPrecisionAndRoundNonMutative(d *big.Int) *big.Int {
tmp := new(big.Int).Set(d)
return chopPrecisionAndRound(tmp)
Expand Down
61 changes: 39 additions & 22 deletions types/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,44 +156,61 @@ func TestDecsEqual(t *testing.T) {

func TestArithmetic(t *testing.T) {
tests := []struct {
d1, d2 Dec
expMul, expQuo, expAdd, expSub Dec
d1, d2 Dec
expMul, expMulTruncate Dec
expQuo, expQuoRoundUp, expQuoTruncate Dec
expAdd, expSub Dec
}{
// d1 d2 MUL DIV ADD SUB
{NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0)},
{NewDec(1), NewDec(0), NewDec(0), NewDec(0), NewDec(1), NewDec(1)},
{NewDec(0), NewDec(1), NewDec(0), NewDec(0), NewDec(1), NewDec(-1)},
{NewDec(0), NewDec(-1), NewDec(0), NewDec(0), NewDec(-1), NewDec(1)},
{NewDec(-1), NewDec(0), NewDec(0), NewDec(0), NewDec(-1), NewDec(-1)},

{NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(2), NewDec(0)},
{NewDec(-1), NewDec(-1), NewDec(1), NewDec(1), NewDec(-2), NewDec(0)},
{NewDec(1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(2)},
{NewDec(-1), NewDec(1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(-2)},

{NewDec(3), NewDec(7), NewDec(21), NewDecWithPrec(428571428571428571, 18), NewDec(10), NewDec(-4)},
{NewDec(2), NewDec(4), NewDec(8), NewDecWithPrec(5, 1), NewDec(6), NewDec(-2)},
{NewDec(100), NewDec(100), NewDec(10000), NewDec(1), NewDec(200), NewDec(0)},

{NewDecWithPrec(15, 1), NewDecWithPrec(15, 1), NewDecWithPrec(225, 2),
NewDec(1), NewDec(3), NewDec(0)},
{NewDecWithPrec(3333, 4), NewDecWithPrec(333, 4), NewDecWithPrec(1109889, 8),
MustNewDecFromStr("10.009009009009009009"), NewDecWithPrec(3666, 4), NewDecWithPrec(3, 1)},
// d1 d2 MUL MulTruncate QUO QUORoundUp QUOTrunctate ADD SUB
{NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0)},
{NewDec(1), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(1), NewDec(1)},
{NewDec(0), NewDec(1), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(1), NewDec(-1)},
{NewDec(0), NewDec(-1), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(-1), NewDec(1)},
{NewDec(-1), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(-1), NewDec(-1)},

{NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(2), NewDec(0)},
{NewDec(-1), NewDec(-1), NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(-2), NewDec(0)},
{NewDec(1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(2)},
{NewDec(-1), NewDec(1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(-2)},

{NewDec(3), NewDec(7), NewDec(21), NewDec(21),
NewDecWithPrec(428571428571428571, 18), NewDecWithPrec(428571428571428572, 18), NewDecWithPrec(428571428571428571, 18),
NewDec(10), NewDec(-4)},
{NewDec(2), NewDec(4), NewDec(8), NewDec(8), NewDecWithPrec(5, 1), NewDecWithPrec(5, 1), NewDecWithPrec(5, 1),
NewDec(6), NewDec(-2)},

{NewDec(100), NewDec(100), NewDec(10000), NewDec(10000), NewDec(1), NewDec(1), NewDec(1), NewDec(200), NewDec(0)},

{NewDecWithPrec(15, 1), NewDecWithPrec(15, 1), NewDecWithPrec(225, 2), NewDecWithPrec(225, 2),
NewDec(1), NewDec(1), NewDec(1), NewDec(3), NewDec(0)},
{NewDecWithPrec(3333, 4), NewDecWithPrec(333, 4), NewDecWithPrec(1109889, 8), NewDecWithPrec(1109889, 8),
MustNewDecFromStr("10.009009009009009009"), MustNewDecFromStr("10.009009009009009010"), MustNewDecFromStr("10.009009009009009009"),
NewDecWithPrec(3666, 4), NewDecWithPrec(3, 1)},
}

for tcIndex, tc := range tests {
resAdd := tc.d1.Add(tc.d2)
resSub := tc.d1.Sub(tc.d2)
resMul := tc.d1.Mul(tc.d2)
resMulTruncate := tc.d1.MulTruncate(tc.d2)
require.True(t, tc.expAdd.Equal(resAdd), "exp %v, res %v, tc %d", tc.expAdd, resAdd, tcIndex)
require.True(t, tc.expSub.Equal(resSub), "exp %v, res %v, tc %d", tc.expSub, resSub, tcIndex)
require.True(t, tc.expMul.Equal(resMul), "exp %v, res %v, tc %d", tc.expMul, resMul, tcIndex)
require.True(t, tc.expMulTruncate.Equal(resMulTruncate), "exp %v, res %v, tc %d", tc.expMulTruncate, resMulTruncate, tcIndex)

if tc.d2.IsZero() { // panic for divide by zero
require.Panics(t, func() { tc.d1.Quo(tc.d2) })
} else {
resQuo := tc.d1.Quo(tc.d2)
require.True(t, tc.expQuo.Equal(resQuo), "exp %v, res %v, tc %d", tc.expQuo.String(), resQuo.String(), tcIndex)

resQuoRoundUp := tc.d1.QuoRoundUp(tc.d2)
require.True(t, tc.expQuoRoundUp.Equal(resQuoRoundUp), "exp %v, res %v, tc %d",
tc.expQuoRoundUp.String(), resQuoRoundUp.String(), tcIndex)

resQuoTruncate := tc.d1.QuoTruncate(tc.d2)
require.True(t, tc.expQuoTruncate.Equal(resQuoTruncate), "exp %v, res %v, tc %d",
tc.expQuoTruncate.String(), resQuoTruncate.String(), tcIndex)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion types/staking.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ type Validator interface {
GetCommission() Dec // validator commission rate
GetMinSelfDelegation() Int // validator minimum self delegation
GetDelegatorShares() Dec // total outstanding delegator shares
GetDelegatorShareExRate() Dec // tokens per delegator share exchange rate
ShareTokens(Dec) Dec // token worth of provided delegator shares
ShareTokensTruncated(Dec) Dec // token worth of provided delegator shares, truncated
}

// validator which fulfills abci validator interface for use in Tendermint
Expand Down
17 changes: 9 additions & 8 deletions x/distribution/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@ var (
NewMsgWithdrawDelegatorReward = types.NewMsgWithdrawDelegatorReward
NewMsgWithdrawValidatorCommission = types.NewMsgWithdrawValidatorCommission

NewKeeper = keeper.NewKeeper
NewQuerier = keeper.NewQuerier
NewQueryValidatorCommissionParams = keeper.NewQueryValidatorCommissionParams
NewQueryValidatorSlashesParams = keeper.NewQueryValidatorSlashesParams
NewQueryDelegationRewardsParams = keeper.NewQueryDelegationRewardsParams
NewQueryDelegatorParams = keeper.NewQueryDelegatorParams
NewQueryDelegatorWithdrawAddrParams = keeper.NewQueryDelegatorWithdrawAddrParams
DefaultParamspace = keeper.DefaultParamspace
NewKeeper = keeper.NewKeeper
NewQuerier = keeper.NewQuerier
NewQueryValidatorOutstandingRewardsParams = keeper.NewQueryValidatorOutstandingRewardsParams
NewQueryValidatorCommissionParams = keeper.NewQueryValidatorCommissionParams
NewQueryValidatorSlashesParams = keeper.NewQueryValidatorSlashesParams
NewQueryDelegationRewardsParams = keeper.NewQueryDelegationRewardsParams
NewQueryDelegatorParams = keeper.NewQueryDelegatorParams
NewQueryDelegatorWithdrawAddrParams = keeper.NewQueryDelegatorWithdrawAddrParams
DefaultParamspace = keeper.DefaultParamspace

RegisterCodec = types.RegisterCodec
DefaultGenesisState = types.DefaultGenesisState
Expand Down
12 changes: 6 additions & 6 deletions x/distribution/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,22 @@ func GetCmdQueryParams(queryRoute string, cdc *codec.Codec) *cobra.Command {
}
}

// GetCmdQueryOutstandingRewards implements the query outstanding rewards command.
func GetCmdQueryOutstandingRewards(queryRoute string, cdc *codec.Codec) *cobra.Command {
// GetCmdQueryValidatorOutstandingRewards implements the query validator outstanding rewards command.
func GetCmdQueryValidatorOutstandingRewards(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "outstanding-rewards",
Use: "validator-outstanding-rewards",
Args: cobra.NoArgs,
Short: "Query distribution outstanding (un-withdrawn) rewards",
Short: "Query distribution outstanding (un-withdrawn) rewards for a validator and all their delegations",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)

route := fmt.Sprintf("custom/%s/outstanding_rewards", queryRoute)
route := fmt.Sprintf("custom/%s/validator_outstanding_rewards", queryRoute)
res, err := cliCtx.QueryWithData(route, []byte{})
if err != nil {
return err
}

var outstandingRewards types.OutstandingRewards
var outstandingRewards types.ValidatorOutstandingRewards
cdc.MustUnmarshalJSON(res, &outstandingRewards)
return cliCtx.PrintOutput(outstandingRewards)
},
Expand Down
2 changes: 1 addition & 1 deletion x/distribution/client/module_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (mc ModuleClient) GetQueryCmd() *cobra.Command {

distQueryCmd.AddCommand(client.GetCommands(
distCmds.GetCmdQueryParams(mc.storeKey, mc.cdc),
distCmds.GetCmdQueryOutstandingRewards(mc.storeKey, mc.cdc),
distCmds.GetCmdQueryValidatorOutstandingRewards(mc.storeKey, mc.cdc),
distCmds.GetCmdQueryValidatorCommission(mc.storeKey, mc.cdc),
distCmds.GetCmdQueryValidatorSlashes(mc.storeKey, mc.cdc),
distCmds.GetCmdQueryDelegatorRewards(mc.storeKey, mc.cdc),
Expand Down
Loading