R4R: Querier - Get all delegations to validator (#2565)

* added querier redelegation and CLI/LCD calls
This commit is contained in:
Jack Zampolin 2018-11-13 11:41:58 -08:00 committed by GitHub
commit 23e841585f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 217 additions and 45 deletions

View File

@ -22,7 +22,8 @@ FEATURES
* Gaia REST API (`gaiacli advanced rest-server`)
* Gaia CLI (`gaiacli`)
* [stake][cli] [\#2027] Add CLI query command for getting all delegations to a specific validator.
* Gaia
* SDK

View File

@ -539,7 +539,7 @@ func TestBonding(t *testing.T) {
require.Equal(t, int64(40), coins.AmountOf(denom).Int64())
// query validator
// query delegation
bond := getDelegation(t, port, addr, operAddrs[0])
require.Equal(t, amt, bond.Shares)
@ -547,6 +547,10 @@ func TestBonding(t *testing.T) {
require.Len(t, delegatorDels, 1)
require.Equal(t, amt, delegatorDels[0].Shares)
// query all delegations to validator
bonds := getValidatorDelegations(t, port, operAddrs[0])
require.Len(t, bonds, 2)
bondedValidators := getDelegatorValidators(t, port, addr)
require.Len(t, bondedValidators, 1)
require.Equal(t, operAddrs[0], bondedValidators[0].OperatorAddr)
@ -1207,6 +1211,17 @@ func getValidator(t *testing.T, port string, validatorAddr sdk.ValAddress) stake
return validator
}
func getValidatorDelegations(t *testing.T, port string, validatorAddr sdk.ValAddress) []stake.Delegation {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s/delegations", validatorAddr.String()), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var delegations []stake.Delegation
err := cdc.UnmarshalJSON([]byte(body), &delegations)
require.Nil(t, err)
return delegations
}
func getValidatorUnbondingDelegations(t *testing.T, port string, validatorAddr sdk.ValAddress) []stake.UnbondingDelegation {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s/unbonding_delegations", validatorAddr.String()), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)

View File

@ -950,6 +950,30 @@ paths:
description: Invalid validator address
500:
description: Internal Server Error
/stake/validators/{validatorAddr}/delegations:
parameters:
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
get:
summary: Get all delegations from a validator
tags:
- ICS21
produces:
- application/json
responses:
200:
description: OK
schema:
type: array
items:
$ref: "#/definitions/Delegation"
400:
description: Invalid validator address
500:
description: Internal Server Error
/stake/validators/{validatorAddr}/unbonding_delegations:
parameters:
- in: path

View File

@ -272,6 +272,10 @@ func TestGaiaCLICreateValidator(t *testing.T) {
require.Equal(t, validator.OperatorAddr, sdk.ValAddress(barAddr))
require.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens))
validatorDelegations := executeGetValidatorDelegations(t, fmt.Sprintf("gaiacli query stake delegations-to %s --output=json %v", sdk.ValAddress(barAddr), flags))
require.Len(t, validatorDelegations, 1)
require.NotZero(t, validatorDelegations[0].Shares)
// unbond a single share
unbondStr := fmt.Sprintf("gaiacli tx stake unbond begin %v", flags)
unbondStr += fmt.Sprintf(" --from=%s", "bar")
@ -750,6 +754,15 @@ func executeGetValidatorRedelegations(t *testing.T, cmdStr string) []stake.Redel
return reds
}
func executeGetValidatorDelegations(t *testing.T, cmdStr string) []stake.Delegation {
out, _ := tests.ExecuteT(t, cmdStr, "")
var delegations []stake.Delegation
cdc := app.MakeCodec()
err := cdc.UnmarshalJSON([]byte(out), &delegations)
require.NoError(t, err, "out %v\n, err %v", out, err)
return delegations
}
func executeGetPool(t *testing.T, cmdStr string) stake.Pool {
out, _ := tests.ExecuteT(t, cmdStr, "")
var pool stake.Pool

View File

@ -36,6 +36,7 @@ func queryCmd(cdc *amino.Codec) *cobra.Command {
stakecmd.GetCmdQueryRedelegations(storeStake, cdc),
stakecmd.GetCmdQueryValidator(storeStake, cdc),
stakecmd.GetCmdQueryValidators(storeStake, cdc),
stakecmd.GetCmdQueryValidatorDelegations(storeStake, cdc),
stakecmd.GetCmdQueryValidatorUnbondingDelegations(queryRouteStake, cdc),
stakecmd.GetCmdQueryValidatorRedelegations(queryRouteStake, cdc),
stakecmd.GetCmdQueryParams(storeStake, cdc),

View File

@ -341,6 +341,13 @@ Additionally, as you can get all the outgoing redelegations from a particular va
To get previous redelegation(s) status on past blocks, try adding the `--height` flag.
##### Query Delegations To Validator
You can also query all of the delegations to a particular validator:
```bash
gaiacli query delegations-to <account_cosmosval>
```
### Governance
Governance is the process from which users in the Cosmos Hub can come to consensus on software upgrades, parameters of the mainnet or on custom text proposals. This is done through voting on proposals, which will be submitted by `Atom` holders on the mainnet.

View File

@ -127,9 +127,7 @@ func GetCmdQueryValidatorUnbondingDelegations(queryRoute string, cdc *codec.Code
}
cliCtx := context.NewCLIContext().WithCodec(cdc)
params := stake.QueryValidatorParams{
ValidatorAddr: valAddr,
}
params := stake.NewQueryValidatorParams(valAddr)
bz, err := cdc.MarshalJSON(params)
if err != nil {
@ -164,9 +162,7 @@ func GetCmdQueryValidatorRedelegations(queryRoute string, cdc *codec.Codec) *cob
}
cliCtx := context.NewCLIContext().WithCodec(cdc)
params := stake.QueryValidatorParams{
ValidatorAddr: valAddr,
}
params := stake.NewQueryValidatorParams(valAddr)
bz, err := cdc.MarshalJSON(params)
if err != nil {
@ -290,6 +286,41 @@ func GetCmdQueryDelegations(storeName string, cdc *codec.Codec) *cobra.Command {
return cmd
}
// GetCmdQueryValidatorDelegations implements the command to query all the
// delegations to a specific validator.
func GetCmdQueryValidatorDelegations(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "delegations-to [validator-addr]",
Short: "Query all delegations made to one validator",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
validatorAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
params := stake.NewQueryValidatorParams(validatorAddr)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/validatorDelegations", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
return cmd
}
// GetCmdQueryUnbondingDelegation implements the command to query a single
// unbonding-delegation record.
func GetCmdQueryUnbondingDelegation(storeName string, cdc *codec.Codec) *cobra.Command {

View File

@ -78,6 +78,12 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Co
validatorHandlerFn(cliCtx, cdc),
).Methods("GET")
// Get all delegations to a validator
r.HandleFunc(
"/stake/validators/{validatorAddr}/delegations",
validatorDelegationsHandlerFn(cliCtx, cdc),
).Methods("GET")
// Get all unbonding delegations from a validator
r.HandleFunc(
"/stake/validators/{validatorAddr}/unbonding_delegations",
@ -227,6 +233,11 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handle
return queryValidator(cliCtx, cdc, "custom/stake/validator")
}
// HTTP request handler to query all unbonding delegations from a validator
func validatorDelegationsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
return queryValidator(cliCtx, cdc, "custom/stake/validatorDelegations")
}
// HTTP request handler to query all unbonding delegations from a validator
func validatorUnbondingDelegationsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
return queryValidator(cliCtx, cdc, "custom/stake/validatorUnbondingDelegations")

View File

@ -62,10 +62,7 @@ func queryBonds(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string) ht
return
}
params := stake.QueryBondsParams{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
}
params := stake.NewQueryBondsParams(delegatorAddr, validatorAddr)
bz, err := cdc.MarshalJSON(params)
if err != nil {
@ -93,9 +90,7 @@ func queryDelegator(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string
return
}
params := stake.QueryDelegatorParams{
DelegatorAddr: delegatorAddr,
}
params := stake.NewQueryDelegatorParams(delegatorAddr)
bz, err := cdc.MarshalJSON(params)
if err != nil {
@ -123,9 +118,7 @@ func queryValidator(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string
return
}
params := stake.QueryValidatorParams{
ValidatorAddr: validatorAddr,
}
params := stake.NewQueryValidatorParams(validatorAddr)
bz, err := cdc.MarshalJSON(params)
if err != nil {

View File

@ -37,6 +37,21 @@ func (k Keeper) GetAllDelegations(ctx sdk.Context) (delegations []types.Delegati
return delegations
}
// return all delegations to a specific validator. Useful for querier.
func (k Keeper) GetValidatorDelegations(ctx sdk.Context, valAddr sdk.ValAddress) (delegations []types.Delegation) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, DelegationKey)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value())
if delegation.GetValidatorAddr().Equals(valAddr) {
delegations = append(delegations, delegation)
}
}
return delegations
}
// return a given amount of all the delegations from a delegator
func (k Keeper) GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress,
maxRetrieve uint16) (delegations []types.Delegation) {

View File

@ -105,6 +105,9 @@ func TestDelegation(t *testing.T) {
resVal, err = keeper.GetDelegatorValidator(ctx, addrDels[1], addrVals[i])
require.Nil(t, err)
require.Equal(t, addrVals[i], resVal.GetOperator())
resDels := keeper.GetValidatorDelegations(ctx, addrVals[i])
require.Len(t, resDels, 2)
}
// delete a record

View File

@ -15,6 +15,7 @@ const (
QueryDelegatorDelegations = "delegatorDelegations"
QueryDelegatorUnbondingDelegations = "delegatorUnbondingDelegations"
QueryDelegatorRedelegations = "delegatorRedelegations"
QueryValidatorDelegations = "validatorDelegations"
QueryValidatorUnbondingDelegations = "validatorUnbondingDelegations"
QueryValidatorRedelegations = "validatorRedelegations"
QueryDelegator = "delegator"
@ -34,6 +35,8 @@ func NewQuerier(k keep.Keeper, cdc *codec.Codec) sdk.Querier {
return queryValidators(ctx, cdc, k)
case QueryValidator:
return queryValidator(ctx, cdc, req, k)
case QueryValidatorDelegations:
return queryValidatorDelegations(ctx, cdc, req, k)
case QueryValidatorUnbondingDelegations:
return queryValidatorUnbondingDelegations(ctx, cdc, req, k)
case QueryValidatorRedelegations:
@ -73,6 +76,7 @@ type QueryDelegatorParams struct {
// defines the params for the following queries:
// - 'custom/stake/validator'
// - 'custom/stake/validatorDelegations'
// - 'custom/stake/validatorUnbondingDelegations'
// - 'custom/stake/validatorRedelegations'
type QueryValidatorParams struct {
@ -88,6 +92,28 @@ type QueryBondsParams struct {
ValidatorAddr sdk.ValAddress
}
// creates a new QueryDelegatorParams
func NewQueryDelegatorParams(delegatorAddr sdk.AccAddress) QueryDelegatorParams {
return QueryDelegatorParams{
DelegatorAddr: delegatorAddr,
}
}
// creates a new QueryValidatorParams
func NewQueryValidatorParams(validatorAddr sdk.ValAddress) QueryValidatorParams {
return QueryValidatorParams{
ValidatorAddr: validatorAddr,
}
}
// creates a new QueryBondsParams
func NewQueryBondsParams(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) QueryBondsParams {
return QueryBondsParams{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
}
}
func queryValidators(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []byte, err sdk.Error) {
stakeParams := k.GetParams(ctx)
validators := k.GetValidators(ctx, stakeParams.MaxValidators)
@ -119,6 +145,23 @@ func queryValidator(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k
return res, nil
}
func queryValidatorDelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) {
var params QueryValidatorParams
errRes := cdc.UnmarshalJSON(req.Data, &params)
if errRes != nil {
return []byte{}, sdk.ErrUnknownAddress("")
}
delegations := k.GetValidatorDelegations(ctx, params.ValidatorAddr)
res, errRes = codec.MarshalJSONIndent(cdc, delegations)
if errRes != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error()))
}
return res, nil
}
func queryValidatorUnbondingDelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) {
var params QueryValidatorParams

View File

@ -17,25 +17,6 @@ var (
pk1, pk2 = keep.PKs[0], keep.PKs[1]
)
func newTestDelegatorQuery(delegatorAddr sdk.AccAddress) QueryDelegatorParams {
return QueryDelegatorParams{
DelegatorAddr: delegatorAddr,
}
}
func newTestValidatorQuery(validatorAddr sdk.ValAddress) QueryValidatorParams {
return QueryValidatorParams{
ValidatorAddr: validatorAddr,
}
}
func newTestBondQuery(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) QueryBondsParams {
return QueryBondsParams{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
}
}
func TestNewQuerier(t *testing.T) {
cdc := codec.New()
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
@ -72,7 +53,7 @@ func TestNewQuerier(t *testing.T) {
_, err = querier(ctx, []string{"parameters"}, query)
require.Nil(t, err)
queryValParams := newTestValidatorQuery(addrVal1)
queryValParams := NewQueryValidatorParams(addrVal1)
bz, errRes := cdc.MarshalJSON(queryValParams)
require.Nil(t, errRes)
@ -82,13 +63,16 @@ func TestNewQuerier(t *testing.T) {
_, err = querier(ctx, []string{"validator"}, query)
require.Nil(t, err)
_, err = querier(ctx, []string{"validatorDelegations"}, query)
require.Nil(t, err)
_, err = querier(ctx, []string{"validatorUnbondingDelegations"}, query)
require.Nil(t, err)
_, err = querier(ctx, []string{"validatorRedelegations"}, query)
require.Nil(t, err)
queryDelParams := newTestDelegatorQuery(addrAcc2)
queryDelParams := NewQueryDelegatorParams(addrAcc2)
bz, errRes = cdc.MarshalJSON(queryDelParams)
require.Nil(t, errRes)
@ -160,7 +144,7 @@ func TestQueryValidators(t *testing.T) {
require.ElementsMatch(t, queriedValidators, validatorsResp)
// Query each validator
queryParams := newTestValidatorQuery(addrVal1)
queryParams := NewQueryValidatorParams(addrVal1)
bz, errRes := cdc.MarshalJSON(queryParams)
require.Nil(t, errRes)
@ -189,13 +173,18 @@ func TestQueryDelegation(t *testing.T) {
pool := keeper.GetPool(ctx)
keeper.SetValidatorByPowerIndex(ctx, val1, pool)
val2 := types.NewValidator(addrVal2, pk2, types.Description{})
keeper.SetValidator(ctx, val2)
pool = keeper.GetPool(ctx)
keeper.SetValidatorByPowerIndex(ctx, val2, pool)
keeper.Delegate(ctx, addrAcc2, sdk.NewCoin(types.DefaultBondDenom, sdk.NewInt(20)), val1, true)
// apply TM updates
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
// Query Delegator bonded validators
queryParams := newTestDelegatorQuery(addrAcc2)
queryParams := NewQueryDelegatorParams(addrAcc2)
bz, errRes := cdc.MarshalJSON(queryParams)
require.Nil(t, errRes)
@ -223,7 +212,7 @@ func TestQueryDelegation(t *testing.T) {
require.NotNil(t, err)
// Query bonded validator
queryBondParams := newTestBondQuery(addrAcc2, addrVal1)
queryBondParams := NewQueryBondsParams(addrAcc2, addrVal1)
bz, errRes = cdc.MarshalJSON(queryBondParams)
require.Nil(t, errRes)
@ -288,9 +277,32 @@ func TestQueryDelegation(t *testing.T) {
_, err = queryDelegation(ctx, cdc, query, keeper)
require.NotNil(t, err)
// Query validator delegations
bz, errRes = cdc.MarshalJSON(NewQueryValidatorParams(addrVal1))
require.Nil(t, errRes)
query = abci.RequestQuery{
Path: "custom/stake/validatorDelegations",
Data: bz,
}
res, err = queryValidatorDelegations(ctx, cdc, query, keeper)
require.Nil(t, err)
var delegationsRes []types.Delegation
errRes = cdc.UnmarshalJSON(res, &delegationsRes)
require.Nil(t, errRes)
require.Equal(t, delegationsRes[0], delegation)
// Query unbonging delegation
keeper.BeginUnbonding(ctx, addrAcc2, val1.OperatorAddr, sdk.NewDec(10))
queryBondParams = NewQueryBondsParams(addrAcc2, addrVal1)
bz, errRes = cdc.MarshalJSON(queryBondParams)
require.Nil(t, errRes)
query = abci.RequestQuery{
Path: "/custom/stake/unbondingDelegation",
Data: bz,
@ -356,7 +368,7 @@ func TestQueryRedelegations(t *testing.T) {
require.True(t, found)
// delegator redelegations
queryDelegatorParams := newTestDelegatorQuery(addrAcc2)
queryDelegatorParams := NewQueryDelegatorParams(addrAcc2)
bz, errRes := cdc.MarshalJSON(queryDelegatorParams)
require.Nil(t, errRes)
@ -375,7 +387,7 @@ func TestQueryRedelegations(t *testing.T) {
require.Equal(t, redelegation, redsRes[0])
// validator redelegations
queryValidatorParams := newTestValidatorQuery(val1.GetOperator())
queryValidatorParams := NewQueryValidatorParams(val1.GetOperator())
bz, errRes = cdc.MarshalJSON(queryValidatorParams)
require.Nil(t, errRes)

View File

@ -84,7 +84,10 @@ var (
NewMsgBeginUnbonding = types.NewMsgBeginUnbonding
NewMsgBeginRedelegate = types.NewMsgBeginRedelegate
NewQuerier = querier.NewQuerier
NewQuerier = querier.NewQuerier
NewQueryDelegatorParams = querier.NewQueryDelegatorParams
NewQueryValidatorParams = querier.NewQueryValidatorParams
NewQueryBondsParams = querier.NewQueryBondsParams
)
const (