diff --git a/PENDING.md b/PENDING.md index d773e4645261..8c08d2b8f31f 100644 --- a/PENDING.md +++ b/PENDING.md @@ -5,6 +5,7 @@ BREAKING CHANGES * Gaia REST API (`gaiacli advanced rest-server`) * [x/stake] Validator.Owner renamed to Validator.Operator * [\#595](https://github.com/cosmos/cosmos-sdk/issues/595) Connections to the REST server are now secured using Transport Layer Security by default. The --insecure flag is provided to switch back to insecure HTTP. + * [gaia-lite] [\#2258](https://github.com/cosmos/cosmos-sdk/issues/2258) Split `GET stake/delegators/{delegatorAddr}` into `GET stake/delegators/{delegatorAddr}/delegations`, `GET stake/delegators/{delegatorAddr}/unbonding_delegations` and `GET stake/delegators/{delegatorAddr}/redelegations` * Gaia CLI (`gaiacli`) * [x/stake] Validator.Owner renamed to Validator.Operator diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index a173ac0e271d..d25dedee7742 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -542,11 +542,9 @@ func TestBonding(t *testing.T) { bond := getDelegation(t, port, addr, operAddrs[0]) require.Equal(t, amt, bond.Shares) - summary := getDelegationSummary(t, port, addr) - - require.Len(t, summary.Delegations, 1, "Delegation summary holds all delegations") - require.Equal(t, amt, summary.Delegations[0].Shares) - require.Len(t, summary.UnbondingDelegations, 0, "Delegation summary holds all unbonding-delegations") + delegatorDels := getDelegatorDelegations(t, port, addr) + require.Len(t, delegatorDels, 1) + require.Equal(t, amt, delegatorDels[0].Shares) bondedValidators := getDelegatorValidators(t, port, addr) require.Len(t, bondedValidators, 1) @@ -557,8 +555,6 @@ func TestBonding(t *testing.T) { require.Equal(t, operAddrs[0], bondedValidator.OperatorAddr) // testing unbonding - - // create unbond TX resultTx = doBeginUnbonding(t, port, seed, name, password, addr, operAddrs[0], 30) tests.WaitForHeight(resultTx.Height+1, port) @@ -580,15 +576,18 @@ func TestBonding(t *testing.T) { require.Equal(t, uint32(0), resultTx.CheckTx.Code) require.Equal(t, uint32(0), resultTx.DeliverTx.Code) - summary = getDelegationSummary(t, port, addr) + // query delegations, unbondings and redelegations from validator and delegator + delegatorDels = getDelegatorDelegations(t, port, addr) + require.Len(t, delegatorDels, 1) + require.Equal(t, "30.0000000000", delegatorDels[0].GetShares().String()) - require.Len(t, summary.Delegations, 1, "Delegation summary holds all delegations") - require.Len(t, summary.UnbondingDelegations, 1, "Delegation summary holds all unbonding-delegations") - require.Len(t, summary.Redelegations, 1, "Delegation summary holds all redelegations") + delegatorUbds := getDelegatorUnbondingDelegations(t, port, addr) + require.Len(t, delegatorUbds, 1) + require.Equal(t, "30", delegatorUbds[0].Balance.Amount.String()) - require.Equal(t, "30.0000000000", summary.Delegations[0].GetShares().String()) - require.Equal(t, "30", summary.UnbondingDelegations[0].Balance.Amount.String()) - require.Equal(t, "30", summary.Redelegations[0].Balance.Amount.String()) + delegatorReds := getDelegatorRedelegations(t, port, addr) + require.Len(t, delegatorReds, 1) + require.Equal(t, "30", delegatorReds[0].Balance.Amount.String()) validatorUbds := getValidatorUnbondingDelegations(t, port, operAddrs[0]) require.Len(t, validatorUbds, 1) @@ -598,9 +597,6 @@ func TestBonding(t *testing.T) { require.Len(t, validatorReds, 1) require.Equal(t, "30", validatorReds[0].Balance.Amount.String()) - bondedValidators = getDelegatorValidators(t, port, addr) - require.Len(t, bondedValidators, 1, "There's a delegation as the user only withdraw half of the funds") - // TODO Undonding status not currently implemented // require.Equal(t, sdk.Unbonding, bondedValidators[0].Status) @@ -997,16 +993,40 @@ func getUndelegation(t *testing.T, port string, delegatorAddr sdk.AccAddress, va return unbond } -func getDelegationSummary(t *testing.T, port string, delegatorAddr sdk.AccAddress) stake.DelegationSummary { - res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s", delegatorAddr), nil) +func getDelegatorDelegations(t *testing.T, port string, delegatorAddr sdk.AccAddress) []stake.Delegation { + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), nil) + require.Equal(t, http.StatusOK, res.StatusCode, body) + + var dels []stake.Delegation + + err := cdc.UnmarshalJSON([]byte(body), &dels) + require.Nil(t, err) + + return dels +} + +func getDelegatorUnbondingDelegations(t *testing.T, port string, delegatorAddr sdk.AccAddress) []stake.UnbondingDelegation { + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/unbonding_delegations", delegatorAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var summary stake.DelegationSummary + var ubds []stake.UnbondingDelegation - err := cdc.UnmarshalJSON([]byte(body), &summary) + err := cdc.UnmarshalJSON([]byte(body), &ubds) require.Nil(t, err) - return summary + return ubds +} + +func getDelegatorRedelegations(t *testing.T, port string, delegatorAddr sdk.AccAddress) []stake.Redelegation { + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/redelegations", delegatorAddr), nil) + require.Equal(t, http.StatusOK, res.StatusCode, body) + + var reds []stake.Redelegation + + err := cdc.UnmarshalJSON([]byte(body), &reds) + require.Nil(t, err) + + return reds } func getBondingTxs(t *testing.T, port string, delegatorAddr sdk.AccAddress, query string) []tx.Info { diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 14de0b8e814d..935c0229f67d 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -18,10 +18,22 @@ const storeName = "stake" func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) { - // Get all delegations (delegation, undelegation and redelegation) from a delegator + // Get all delegations from a delegator r.HandleFunc( - "/stake/delegators/{delegatorAddr}", - delegatorHandlerFn(cliCtx, cdc), + "/stake/delegators/{delegatorAddr}/delegations", + delegatorDelegationsHandlerFn(cliCtx, cdc), + ).Methods("GET") + + // Get all unbonding delegations from a delegator + r.HandleFunc( + "/stake/delegators/{delegatorAddr}/unbonding_delegations", + delegatorUnbondingDelegationsHandlerFn(cliCtx, cdc), + ).Methods("GET") + + // Get all redelegations from a delegator + r.HandleFunc( + "/stake/delegators/{delegatorAddr}/redelegations", + delegatorRedelegationsHandlerFn(cliCtx, cdc), ).Methods("GET") // Get all staking txs (i.e msgs) from a delegator @@ -93,8 +105,18 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Co } // HTTP request handler to query a delegator delegations -func delegatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return queryDelegator(cliCtx, cdc, "custom/stake/delegator") +func delegatorDelegationsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { + return queryDelegator(cliCtx, cdc, "custom/stake/delegatorDelegations") +} + +// HTTP request handler to query a delegator unbonding delegations +func delegatorUnbondingDelegationsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { + return queryDelegator(cliCtx, cdc, "custom/stake/delegatorUnbondingDelegations") +} + +// HTTP request handler to query a delegator redelegations +func delegatorRedelegationsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { + return queryDelegator(cliCtx, cdc, "custom/stake/delegatorRedelegations") } // HTTP request handler to query all staking txs (msgs) from a delegator diff --git a/x/stake/querier/queryable.go b/x/stake/querier/queryable.go index ace001fce862..bacc8d6aecc4 100644 --- a/x/stake/querier/queryable.go +++ b/x/stake/querier/queryable.go @@ -12,6 +12,9 @@ import ( const ( QueryValidators = "validators" QueryValidator = "validator" + QueryDelegatorDelegations = "delegatorDelegations" + QueryDelegatorUnbondingDelegations = "delegatorUnbondingDelegations" + QueryDelegatorRedelegations = "delegatorRedelegations" QueryValidatorUnbondingDelegations = "validatorUnbondingDelegations" QueryValidatorRedelegations = "validatorRedelegations" QueryDelegator = "delegator" @@ -35,12 +38,16 @@ func NewQuerier(k keep.Keeper, cdc *codec.Codec) sdk.Querier { return queryValidatorUnbondingDelegations(ctx, cdc, req, k) case QueryValidatorRedelegations: return queryValidatorRedelegations(ctx, cdc, req, k) - case QueryDelegator: - return queryDelegator(ctx, cdc, req, k) case QueryDelegation: return queryDelegation(ctx, cdc, req, k) case QueryUnbondingDelegation: return queryUnbondingDelegation(ctx, cdc, req, k) + case QueryDelegatorDelegations: + return queryDelegatorDelegations(ctx, cdc, req, k) + case QueryDelegatorUnbondingDelegations: + return queryDelegatorUnbondingDelegations(ctx, cdc, req, k) + case QueryDelegatorRedelegations: + return queryDelegatorRedelegations(ctx, cdc, req, k) case QueryDelegatorValidators: return queryDelegatorValidators(ctx, cdc, req, k) case QueryDelegatorValidator: @@ -56,7 +63,9 @@ func NewQuerier(k keep.Keeper, cdc *codec.Codec) sdk.Querier { } // defines the params for the following queries: -// - 'custom/stake/delegator' +// - 'custom/stake/delegatorDelegations' +// - 'custom/stake/delegatorUnbondingDelegations' +// - 'custom/stake/delegatorRedelegations' // - 'custom/stake/delegatorValidators' type QueryDelegatorParams struct { DelegatorAddr sdk.AccAddress @@ -144,23 +153,51 @@ func queryValidatorRedelegations(ctx sdk.Context, cdc *codec.Codec, req abci.Req return res, nil } -func queryDelegator(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryDelegatorDelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryDelegatorParams + errRes := cdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrUnknownAddress("") } + delegations := k.GetAllDelegatorDelegations(ctx, params.DelegatorAddr) + + 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 queryDelegatorUnbondingDelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { + var params QueryDelegatorParams + + errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + if errRes != nil { + return []byte{}, sdk.ErrUnknownAddress("") + } + unbondingDelegations := k.GetAllUnbondingDelegations(ctx, params.DelegatorAddr) - redelegations := k.GetAllRedelegations(ctx, params.DelegatorAddr) - summary := types.DelegationSummary{ - Delegations: delegations, - UnbondingDelegations: unbondingDelegations, - Redelegations: redelegations, + res, errRes = codec.MarshalJSONIndent(cdc, unbondingDelegations) + if errRes != nil { + return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } + return res, nil +} + +func queryDelegatorRedelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { + var params QueryDelegatorParams - res, errRes = codec.MarshalJSONIndent(cdc, summary) + errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + if errRes != nil { + return []byte{}, sdk.ErrUnknownAddress("") + } + + redelegations := k.GetAllRedelegations(ctx, params.DelegatorAddr) + + res, errRes = codec.MarshalJSONIndent(cdc, redelegations) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } diff --git a/x/stake/querier/queryable_test.go b/x/stake/querier/queryable_test.go index 2a8608417520..973e2376ff9c 100644 --- a/x/stake/querier/queryable_test.go +++ b/x/stake/querier/queryable_test.go @@ -72,8 +72,8 @@ func TestNewQuerier(t *testing.T) { _, err = querier(ctx, []string{"parameters"}, query) require.Nil(t, err) - queryParams := newTestValidatorQuery(addrVal1) - bz, errRes := cdc.MarshalJSON(queryParams) + queryValParams := newTestValidatorQuery(addrVal1) + bz, errRes := cdc.MarshalJSON(queryValParams) require.Nil(t, errRes) query.Path = "/custom/stake/validator" @@ -87,6 +87,25 @@ func TestNewQuerier(t *testing.T) { _, err = querier(ctx, []string{"validatorRedelegations"}, query) require.Nil(t, err) + + queryDelParams := newTestDelegatorQuery(addrAcc2) + bz, errRes = cdc.MarshalJSON(queryDelParams) + require.Nil(t, errRes) + + query.Path = "/custom/stake/validator" + query.Data = bz + + _, err = querier(ctx, []string{"delegatorDelegations"}, query) + require.Nil(t, err) + + _, err = querier(ctx, []string{"delegatorUnbondingDelegations"}, query) + require.Nil(t, err) + + _, err = querier(ctx, []string{"delegatorRedelegations"}, query) + require.Nil(t, err) + + _, err = querier(ctx, []string{"delegatorValidators"}, query) + require.Nil(t, err) } func TestQueryParametersPool(t *testing.T) { @@ -247,6 +266,22 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, delegation, delegationRes) + // Query Delegator Delegations + + query = abci.RequestQuery{ + Path: "/custom/stake/delegatorDelegations", + Data: bz, + } + + res, err = queryDelegatorDelegations(ctx, cdc, query, keeper) + require.Nil(t, err) + + var delegatorDelegations []types.Delegation + errRes = cdc.UnmarshalJSON(res, &delegatorDelegations) + require.Nil(t, errRes) + require.Len(t, delegatorDelegations, 1) + require.Equal(t, delegation, delegatorDelegations[0]) + // error unknown request query.Data = bz[:len(bz)-1] @@ -279,25 +314,81 @@ func TestQueryDelegation(t *testing.T) { _, err = queryUnbondingDelegation(ctx, cdc, query, keeper) require.NotNil(t, err) - // Query Delegator Summary + // Query Delegator Delegations query = abci.RequestQuery{ - Path: "/custom/stake/delegator", + Path: "/custom/stake/delegatorUnbondingDelegations", Data: bz, } - res, err = queryDelegator(ctx, cdc, query, keeper) + res, err = queryDelegatorUnbondingDelegations(ctx, cdc, query, keeper) require.Nil(t, err) - var summary types.DelegationSummary - errRes = cdc.UnmarshalJSON(res, &summary) + var delegatorUbds []types.UnbondingDelegation + errRes = cdc.UnmarshalJSON(res, &delegatorUbds) require.Nil(t, errRes) - - require.Equal(t, unbond, summary.UnbondingDelegations[0]) + require.Equal(t, unbond, delegatorUbds[0]) // error unknown request query.Data = bz[:len(bz)-1] - _, err = queryDelegator(ctx, cdc, query, keeper) + _, err = queryDelegatorUnbondingDelegations(ctx, cdc, query, keeper) require.NotNil(t, err) } + +func TestQueryRedelegations(t *testing.T) { + cdc := codec.New() + ctx, _, keeper := keep.CreateTestInput(t, false, 10000) + + // Create Validators and Delegation + val1 := types.NewValidator(addrVal1, pk1, types.Description{}) + val2 := types.NewValidator(addrVal2, pk2, types.Description{}) + keeper.SetValidator(ctx, val1) + keeper.SetValidator(ctx, val2) + + keeper.Delegate(ctx, addrAcc2, sdk.NewCoin("steak", sdk.NewInt(100)), val1, true) + keeper.ApplyAndReturnValidatorSetUpdates(ctx) + + keeper.BeginRedelegation(ctx, addrAcc2, val1.GetOperator(), val2.GetOperator(), sdk.NewDec(20)) + keeper.ApplyAndReturnValidatorSetUpdates(ctx) + + redelegation, found := keeper.GetRedelegation(ctx, addrAcc2, val1.OperatorAddr, val2.OperatorAddr) + require.True(t, found) + + // delegator redelegations + queryDelegatorParams := newTestDelegatorQuery(addrAcc2) + bz, errRes := cdc.MarshalJSON(queryDelegatorParams) + require.Nil(t, errRes) + + query := abci.RequestQuery{ + Path: "/custom/stake/delegatorRedelegations", + Data: bz, + } + + res, err := queryDelegatorRedelegations(ctx, cdc, query, keeper) + require.Nil(t, err) + + var redsRes []types.Redelegation + errRes = cdc.UnmarshalJSON(res, &redsRes) + require.Nil(t, errRes) + + require.Equal(t, redelegation, redsRes[0]) + + // validator redelegations + queryValidatorParams := newTestValidatorQuery(val1.GetOperator()) + bz, errRes = cdc.MarshalJSON(queryValidatorParams) + require.Nil(t, errRes) + + query = abci.RequestQuery{ + Path: "/custom/stake/validatorRedelegations", + Data: bz, + } + + res, err = queryValidatorRedelegations(ctx, cdc, query, keeper) + require.Nil(t, err) + + errRes = cdc.UnmarshalJSON(res, &redsRes) + require.Nil(t, errRes) + + require.Equal(t, redelegation, redsRes[0]) +} diff --git a/x/stake/stake.go b/x/stake/stake.go index c4aa547022d8..179f8b72119f 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -14,7 +14,6 @@ type ( Description = types.Description Commission = types.Commission Delegation = types.Delegation - DelegationSummary = types.DelegationSummary UnbondingDelegation = types.UnbondingDelegation Redelegation = types.Redelegation Params = types.Params @@ -85,15 +84,19 @@ var ( ) const ( - QueryValidators = querier.QueryValidators - QueryValidator = querier.QueryValidator - QueryDelegator = querier.QueryDelegator - QueryDelegation = querier.QueryDelegation - QueryUnbondingDelegation = querier.QueryUnbondingDelegation - QueryDelegatorValidators = querier.QueryDelegatorValidators - QueryDelegatorValidator = querier.QueryDelegatorValidator - QueryPool = querier.QueryPool - QueryParameters = querier.QueryParameters + QueryValidators = querier.QueryValidators + QueryValidator = querier.QueryValidator + QueryValidatorUnbondingDelegations = querier.QueryValidatorUnbondingDelegations + QueryValidatorRedelegations = querier.QueryValidatorRedelegations + QueryDelegation = querier.QueryDelegation + QueryUnbondingDelegation = querier.QueryUnbondingDelegation + QueryDelegatorDelegations = querier.QueryDelegatorDelegations + QueryDelegatorUnbondingDelegations = querier.QueryDelegatorUnbondingDelegations + QueryDelegatorRedelegations = querier.QueryDelegatorRedelegations + QueryDelegatorValidators = querier.QueryDelegatorValidators + QueryDelegatorValidator = querier.QueryDelegatorValidator + QueryPool = querier.QueryPool + QueryParameters = querier.QueryParameters ) const ( diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 1b51e00acf19..3158b89fa54b 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -41,13 +41,6 @@ type delegationValue struct { Height int64 } -// aggregates of all delegations, unbondings and redelegations -type DelegationSummary struct { - Delegations []Delegation `json:"delegations"` - UnbondingDelegations []UnbondingDelegation `json:"unbonding_delegations"` - Redelegations []Redelegation `json:"redelegations"` -} - // return the delegation without fields contained within the key for the store func MustMarshalDelegation(cdc *codec.Codec, delegation Delegation) []byte { val := delegationValue{