Wrote gnarly query to get outstanding rewards for delegator

This commit is contained in:
Ethan Frey
2020-10-06 20:57:18 +02:00
parent 0b290cbab4
commit 2a92028b29
5 changed files with 68 additions and 20 deletions

View File

@@ -6,6 +6,7 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/x/distribution"
"io/ioutil"
"math/rand"
"os"
@@ -496,7 +497,7 @@ func setupKeeper(t *testing.T) (Keeper, sdk.Context, []sdk.StoreKey, func()) {
cdc := MakeTestCodec()
pk := params.NewKeeper(cdc, keyParams, tkeyParams)
wasmConfig := wasmTypes.DefaultWasmConfig()
srcKeeper := NewKeeper(cdc, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), auth.AccountKeeper{}, nil, staking.Keeper{}, nil, tempDir, wasmConfig, "", nil, nil)
srcKeeper := NewKeeper(cdc, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), auth.AccountKeeper{}, nil, staking.Keeper{}, distribution.Keeper{}, nil, tempDir, wasmConfig, "", nil, nil)
srcKeeper.setParams(ctx, wasmTypes.DefaultParams())
return srcKeeper, ctx, []sdk.StoreKey{keyWasm, keyParams}, cleanup

View File

@@ -3,6 +3,7 @@ package keeper
import (
"bytes"
"encoding/binary"
"github.com/cosmos/cosmos-sdk/x/distribution"
"path/filepath"
"github.com/cosmos/cosmos-sdk/x/params/subspace"
@@ -61,7 +62,7 @@ type Keeper struct {
// NewKeeper creates a new contract Keeper instance
// If customEncoders is non-nil, we can use this to override some of the message handler, especially custom
func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace, accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper,
stakingKeeper staking.Keeper,
stakingKeeper staking.Keeper, distKeeper distribution.Keeper,
router sdk.Router, homeDir string, wasmConfig types.WasmConfig, supportedFeatures string, customEncoders *MessageEncoders, customPlugins *QueryPlugins) Keeper {
wasmer, err := wasm.NewWasmer(filepath.Join(homeDir, "wasm"), supportedFeatures)
if err != nil {
@@ -84,7 +85,7 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspa
authZPolicy: DefaultAuthorizationPolicy{},
paramSpace: paramSpace,
}
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, stakingKeeper, &keeper).Merge(customPlugins)
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, stakingKeeper, distKeeper, &keeper).Merge(customPlugins)
return keeper
}

View File

@@ -6,7 +6,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/staking"
abci "github.com/tendermint/tendermint/abci/types"
)
type QueryHandler struct {
@@ -55,11 +57,11 @@ type QueryPlugins struct {
Wasm func(ctx sdk.Context, request *wasmTypes.WasmQuery) ([]byte, error)
}
func DefaultQueryPlugins(bank bank.ViewKeeper, staking staking.Keeper, wasm *Keeper) QueryPlugins {
func DefaultQueryPlugins(bank bank.ViewKeeper, staking staking.Keeper, distKeeper distribution.Keeper, wasm *Keeper) QueryPlugins {
return QueryPlugins{
Bank: BankQuerier(bank),
Custom: NoCustomQuerier,
Staking: StakingQuerier(staking),
Staking: StakingQuerier(staking, distKeeper),
Wasm: WasmQuerier(wasm),
}
}
@@ -120,7 +122,7 @@ func NoCustomQuerier(sdk.Context, json.RawMessage) ([]byte, error) {
return nil, wasmTypes.UnsupportedRequest{Kind: "custom"}
}
func StakingQuerier(keeper staking.Keeper) func(ctx sdk.Context, request *wasmTypes.StakingQuery) ([]byte, error) {
func StakingQuerier(keeper staking.Keeper, distKeeper distribution.Keeper) func(ctx sdk.Context, request *wasmTypes.StakingQuery) ([]byte, error) {
return func(ctx sdk.Context, request *wasmTypes.StakingQuery) ([]byte, error) {
if request.BondedDenom != nil {
denom := keeper.BondDenom(ctx)
@@ -174,7 +176,7 @@ func StakingQuerier(keeper staking.Keeper) func(ctx sdk.Context, request *wasmTy
var res wasmTypes.DelegationResponse
d, found := keeper.GetDelegation(ctx, delegator, validator)
if found {
res.Delegation, err = sdkToFullDelegation(ctx, keeper, d)
res.Delegation, err = sdkToFullDelegation(ctx, keeper, distKeeper, d)
if err != nil {
return nil, err
}
@@ -198,11 +200,6 @@ func sdkToDelegations(ctx sdk.Context, keeper staking.Keeper, delegations []stak
}
amount := sdk.NewCoin(bondDenom, val.TokensFromShares(d.Shares).TruncateInt())
// Accumulated Rewards???
// can relegate? other query for redelegations?
// keeper.GetRedelegation
result[i] = wasmTypes.Delegation{
Delegator: d.DelegatorAddress.String(),
Validator: d.ValidatorAddress.String(),
@@ -212,7 +209,7 @@ func sdkToDelegations(ctx sdk.Context, keeper staking.Keeper, delegations []stak
return result, nil
}
func sdkToFullDelegation(ctx sdk.Context, keeper staking.Keeper, delegation staking.Delegation) (*wasmTypes.FullDelegation, error) {
func sdkToFullDelegation(ctx sdk.Context, keeper staking.Keeper, distKeeper distribution.Keeper, delegation staking.Delegation) (*wasmTypes.FullDelegation, error) {
val, found := keeper.GetValidator(ctx, delegation.ValidatorAddress)
if !found {
return nil, sdkerrors.Wrap(staking.ErrNoValidatorFound, "can't load validator for delegation")
@@ -231,17 +228,63 @@ func sdkToFullDelegation(ctx sdk.Context, keeper staking.Keeper, delegation stak
redelegateCoins = delegationCoins
}
// FIXME: make a cleaner way to do this (modify the sdk)
// we need the info from `distKeeper.calculateDelegationRewards()`, but it is not public
// neither is `queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper)`
// so we go through the front door of the querier....
accRewards, err := getAccumulatedRewards(ctx, distKeeper, delegation)
if err != nil {
return nil, err
}
return &wasmTypes.FullDelegation{
Delegator: delegation.DelegatorAddress.String(),
Validator: delegation.ValidatorAddress.String(),
Amount: delegationCoins,
// TODO: AccumulatedRewards
AccumulatedRewards: wasmTypes.Coins{},
AccumulatedRewards: accRewards,
// TODO: Determine redelegate
CanRedelegate: redelegateCoins,
}, nil
}
// FIXME: simplify this enormously when
// https://github.com/cosmos/cosmos-sdk/issues/7466 is merged
func getAccumulatedRewards(ctx sdk.Context, distKeeper distribution.Keeper, delegation staking.Delegation) ([]wasmTypes.Coin, error) {
// Try to get *delegator* reward info!
params := distribution.QueryDelegationRewardsParams{
DelegatorAddress: delegation.DelegatorAddress,
ValidatorAddress: delegation.ValidatorAddress,
}
data, err := json.Marshal(params)
if err != nil {
return nil, err
}
req := abci.RequestQuery{Data: data}
qres, err := distribution.NewQuerier(distKeeper)(ctx, []string{distribution.QueryDelegationRewards}, req)
if err != nil {
return nil, err
}
var decRewards sdk.DecCoins
err = json.Unmarshal(qres, &decRewards)
if err != nil {
return nil, err
}
// **** all this above should be ONE method call
// now we have it, convert it into wasmTypes
var rewards []wasmTypes.Coin
for _, r := range decRewards {
c := wasmTypes.Coin{
Denom: r.Denom,
Amount: r.Amount.TruncateInt().String(),
}
rewards = append(rewards, c)
}
return rewards, nil
}
func WasmQuerier(wasm *Keeper) func(ctx sdk.Context, request *wasmTypes.WasmQuery) ([]byte, error) {
return func(ctx sdk.Context, request *wasmTypes.WasmQuery) ([]byte, error) {
if request.Smart != nil {

View File

@@ -369,7 +369,7 @@ func TestReinvest(t *testing.T) {
// we get 1/6, our share should be 40k minus 10% commission = 36k
setValidatorRewards(ctx, stakingKeeper, distKeeper, valAddr, "240000")
// this should withdraw our outstanding 40k of rewards and reinvest them in the same delegation
// this should withdraw our outstanding 36k of rewards and reinvest them in the same delegation
reinvest := StakingHandleMsg{
Reinvest: &struct{}{},
}
@@ -536,8 +536,10 @@ func TestQueryStakingInfo(t *testing.T) {
require.Equal(t, funds[0].Amount.String(), delInfo2.Amount.Amount)
// TODO: fix this - these should return real values!!! Issue #263
require.Len(t, delInfo2.AccumulatedRewards, 0)
require.Equal(t, wasmTypes.NewCoin(200000, "stake"), delInfo2.CanRedelegate)
require.Len(t, delInfo2.AccumulatedRewards, 1)
// see bonding above to see how we calculate 36000 (240000 / 6 - 10% commission)
require.Equal(t, wasmTypes.NewCoin(36000, "stake"), delInfo2.AccumulatedRewards[0])
}
func TestQueryStakingPlugin(t *testing.T) {
@@ -580,7 +582,7 @@ func TestQueryStakingPlugin(t *testing.T) {
Validator: valAddr.String(),
},
}
raw, err := StakingQuerier(stakingKeeper)(ctx, &query)
raw, err := StakingQuerier(stakingKeeper, distKeeper)(ctx, &query)
require.NoError(t, err)
var res wasmTypes.DelegationResponse
mustParse(t, raw, &res)
@@ -594,9 +596,10 @@ func TestQueryStakingPlugin(t *testing.T) {
require.Equal(t, funds[0].Denom, delInfo.Amount.Denom)
require.Equal(t, funds[0].Amount.String(), delInfo.Amount.Amount)
// TODO: fix this - these should return real values!!! Issue #263
require.Equal(t, wasmTypes.NewCoin(200000, "stake"), delInfo.CanRedelegate)
require.Len(t, delInfo.AccumulatedRewards, 0)
require.Len(t, delInfo.AccumulatedRewards, 1)
// see bonding above to see how we calculate 36000 (240000 / 6 - 10% commission)
require.Equal(t, wasmTypes.NewCoin(36000, "stake"), delInfo.AccumulatedRewards[0])
}
// adds a few validators and returns a list of validators that are registered

View File

@@ -171,7 +171,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, tempDir string, supportedFeat
// Load default wasm config
wasmConfig := wasmtypes.DefaultWasmConfig()
keeper := NewKeeper(cdc, keyContract, paramsKeeper.Subspace(wasmtypes.DefaultParamspace),
accountKeeper, bankKeeper, stakingKeeper, router, tempDir, wasmConfig,
accountKeeper, bankKeeper, stakingKeeper, distKeeper, router, tempDir, wasmConfig,
supportedFeatures, encoders, queriers,
)
keeper.setParams(ctx, wasmtypes.DefaultParams())