From 52817994fd0c1a312c8ea7c057558592ee0ec049 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Fri, 14 Sep 2018 00:58:53 +0200 Subject: [PATCH 01/12] Add redelegation REST endpoint --- x/stake/client/rest/query.go | 193 +++++------------------------------ x/stake/client/rest/utils.go | 84 +++++++++++++++ x/stake/querier/queryable.go | 32 ++++++ x/stake/stake.go | 41 ++++---- 4 files changed, 164 insertions(+), 186 deletions(-) diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index c6e39ebd278d..2423f1bba843 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -55,6 +55,12 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Co unbondingDelegationHandlerFn(cliCtx, cdc), ).Methods("GET") + // Query a redelegation of a delegator's tokens from a validator to another + r.HandleFunc( + "/stake/redelegations/delegator/{delegatorAddr}/validator_from/{validatorSrcAddr}/validator_to/{validatorDestAddr}", + redelegationHandlerFn(cliCtx, cdc), + ).Methods("GET") + // Get all validators r.HandleFunc( "/stake/validators", @@ -63,7 +69,7 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Co // Get a single validator info r.HandleFunc( - "/stake/validators/{addr}", + "/stake/validators/{validatorAddr}", validatorHandlerFn(cliCtx, cdc), ).Methods("GET") @@ -83,41 +89,7 @@ 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 func(w http.ResponseWriter, r *http.Request) { - - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - params := stake.QueryDelegatorParams{ - DelegatorAddr: delegatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/delegator", bz) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - - return - } - - w.Write(res) - } + return queryDelegator(cliCtx, cdc, "custom/stake/delegator") } // nolint gocyclo @@ -201,78 +173,38 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han // HTTP request handler to query an unbonding-delegation func unbondingDelegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - bech32validator := vars["validatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - params := stake.QueryBondsParams{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/unbondingDelegation", bz) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - - return - } - - w.Write(res) - } + return queryBonds(cliCtx, cdc, "custom/stake/unbondingDelegation") } -// HTTP request handler to query a bonded validator +// HTTP request handler to query a delegation func delegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { + return queryBonds(cliCtx, cdc, "custom/stake/delegation") +} + +// HTTP request handler to query a redelegation +func redelegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // read parameters vars := mux.Vars(r) bech32delegator := vars["delegatorAddr"] - bech32validator := vars["validatorAddr"] + bech32ValidatorSrc := vars["validatorSrcAddr"] + bech32ValidatorDst := vars["validatorDstAddr"] w.Header().Set("Content-Type", "application/json") delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) + validatorSrcAddr, err := sdk.ValAddressFromBech32(bech32ValidatorSrc) + validatorDstAddr, err := sdk.ValAddressFromBech32(bech32ValidatorDst) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } - validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - params := stake.QueryBondsParams{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, + params := stake.QueryRedelegationParams{ + DelegatorAddr: delegatorAddr, + ValidatorSrcAddr: validatorSrcAddr, + ValidatorDstAddr: validatorDstAddr, } bz, err := cdc.MarshalJSON(params) @@ -282,7 +214,7 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handl return } - res, err := cliCtx.QueryWithData("custom/stake/delegation", bz) + res, err := cliCtx.QueryWithData("custom/stake/redelegation", bz) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) @@ -296,83 +228,12 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handl // HTTP request handler to query all delegator bonded validators func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - // read parameters - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - params := stake.QueryDelegatorParams{ - DelegatorAddr: delegatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/delegatorValidators", bz) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - - return - } - - w.Write(res) - } + return queryDelegator(cliCtx, cdc, "custom/stake/delegatorValidators") } // HTTP request handler to get information from a currently bonded validator func delegatorValidatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - - vars := mux.Vars(r) - bech32delegator := vars["delegatorAddr"] - bech32validator := vars["validatorAddr"] - - w.Header().Set("Content-Type", "application/json") - - delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) - validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - params := stake.QueryBondsParams{ - DelegatorAddr: delegatorAddr, - ValidatorAddr: validatorAddr, - } - - bz, err := cdc.MarshalJSON(params) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - return - } - - res, err := cliCtx.QueryWithData("custom/stake/delegatorValidator", bz) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - - return - } - - w.Write(res) - } + return queryBonds(cliCtx, cdc, "custom/stake/delegatorValidator") } // HTTP request handler to query list of validators @@ -399,7 +260,7 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handle return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - bech32validatorAddr := vars["addr"] + bech32validatorAddr := vars["validatorAddr"] w.Header().Set("Content-Type", "application/json") diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index afe672840c18..9ae312aab98c 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -2,10 +2,15 @@ package rest import ( "fmt" + "net/http" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake/tags" + "github.com/gorilla/mux" rpcclient "github.com/tendermint/tendermint/rpc/client" ) @@ -32,3 +37,82 @@ func queryTxs(node rpcclient.Client, cdc *codec.Codec, tag string, delegatorAddr return tx.FormatTxResults(cdc, res.Txs) } + +func queryBonds(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // read parameters + vars := mux.Vars(r) + bech32delegator := vars["delegatorAddr"] + bech32validator := vars["validatorAddr"] + + w.Header().Set("Content-Type", "application/json") + + delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) + validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + params := stake.QueryBondsParams{ + DelegatorAddr: delegatorAddr, + ValidatorAddr: validatorAddr, + } + + bz, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + res, err := cliCtx.QueryWithData(endpoint, bz) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + + return + } + + w.Write(res) + } +} + +func queryDelegator(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + + vars := mux.Vars(r) + bech32delegator := vars["validatorAddr"] + + w.Header().Set("Content-Type", "application/json") + + delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + params := stake.QueryDelegatorParams{ + DelegatorAddr: delegatorAddr, + } + + bz, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + res, err := cliCtx.QueryWithData(endpoint, bz) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + + return + } + + w.Write(res) + } +} diff --git a/x/stake/querier/queryable.go b/x/stake/querier/queryable.go index 8537f2bd49e7..c72c75df44d3 100644 --- a/x/stake/querier/queryable.go +++ b/x/stake/querier/queryable.go @@ -17,6 +17,7 @@ const ( QueryDelegator = "delegator" QueryDelegation = "delegation" QueryUnbondingDelegation = "unbondingDelegation" + QueryRedelegation = "redelegation" QueryDelegatorValidators = "delegatorValidators" QueryDelegatorValidator = "delegatorValidator" QueryPool = "pool" @@ -37,6 +38,8 @@ func NewQuerier(k keep.Keeper, cdc *codec.Codec) sdk.Querier { return queryDelegation(ctx, cdc, req, k) case QueryUnbondingDelegation: return queryUnbondingDelegation(ctx, cdc, req, k) + case QueryRedelegation: + return queryRedelegation(ctx, cdc, req, k) case QueryDelegatorValidators: return queryDelegatorValidators(ctx, cdc, req, k) case QueryDelegatorValidator: @@ -67,12 +70,21 @@ type QueryValidatorParams struct { // defines the params for the following queries: // - 'custom/stake/delegation' // - 'custom/stake/unbondingDelegation' +// - 'custom/stake/redelegation' // - 'custom/stake/delegatorValidator' type QueryBondsParams struct { DelegatorAddr sdk.AccAddress ValidatorAddr sdk.ValAddress } +// defines the params for the following query: +// - 'custom/stake/redelegation' +type QueryRedelegationParams struct { + DelegatorAddr sdk.AccAddress + ValidatorSrcAddr sdk.ValAddress + ValidatorDstAddr sdk.ValAddress +} + 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) @@ -206,6 +218,26 @@ func queryUnbondingDelegation(ctx sdk.Context, cdc *codec.Codec, req abci.Reques return res, nil } +func queryRedelegation(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { + var params QueryRedelegationParams + + errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + if errRes != nil { + return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request address: %s", errRes.Error())) + } + + redelegation, found := k.GetRedelegation(ctx, params.DelegatorAddr, params.ValidatorSrcAddr, params.ValidatorDstAddr) + if !found { + return []byte{}, types.ErrNoRedelegation(types.DefaultCodespace) + } + + res, errRes = codec.MarshalJSONIndent(cdc, redelegation) + if errRes != nil { + return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error())) + } + return res, nil +} + func queryPool(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []byte, err sdk.Error) { pool := k.GetPool(ctx) diff --git a/x/stake/stake.go b/x/stake/stake.go index 18b99fd4a0ba..c6e8fbe42008 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -9,26 +9,27 @@ import ( ) type ( - Keeper = keeper.Keeper - Validator = types.Validator - Description = types.Description - Delegation = types.Delegation - DelegationSummary = types.DelegationSummary - UnbondingDelegation = types.UnbondingDelegation - Redelegation = types.Redelegation - Params = types.Params - Pool = types.Pool - MsgCreateValidator = types.MsgCreateValidator - MsgEditValidator = types.MsgEditValidator - MsgDelegate = types.MsgDelegate - MsgBeginUnbonding = types.MsgBeginUnbonding - MsgCompleteUnbonding = types.MsgCompleteUnbonding - MsgBeginRedelegate = types.MsgBeginRedelegate - MsgCompleteRedelegate = types.MsgCompleteRedelegate - GenesisState = types.GenesisState - QueryDelegatorParams = querier.QueryDelegatorParams - QueryValidatorParams = querier.QueryValidatorParams - QueryBondsParams = querier.QueryBondsParams + Keeper = keeper.Keeper + Validator = types.Validator + Description = types.Description + Delegation = types.Delegation + DelegationSummary = types.DelegationSummary + UnbondingDelegation = types.UnbondingDelegation + Redelegation = types.Redelegation + Params = types.Params + Pool = types.Pool + MsgCreateValidator = types.MsgCreateValidator + MsgEditValidator = types.MsgEditValidator + MsgDelegate = types.MsgDelegate + MsgBeginUnbonding = types.MsgBeginUnbonding + MsgCompleteUnbonding = types.MsgCompleteUnbonding + MsgBeginRedelegate = types.MsgBeginRedelegate + MsgCompleteRedelegate = types.MsgCompleteRedelegate + GenesisState = types.GenesisState + QueryDelegatorParams = querier.QueryDelegatorParams + QueryValidatorParams = querier.QueryValidatorParams + QueryBondsParams = querier.QueryBondsParams + QueryRedelegationParams = querier.QueryRedelegationParams ) var ( From b8a547d48408e0add76b08b9b88461f7cbfc6f57 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Fri, 14 Sep 2018 01:22:31 +0200 Subject: [PATCH 02/12] Fixed utils and added tests --- client/lcd/lcd_test.go | 34 +++++++++++++++++++++++++++++----- x/stake/client/rest/utils.go | 2 +- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 3d51ca6db2de..db25b45e9c69 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -543,8 +543,7 @@ func TestBonding(t *testing.T) { bondedValidator := getDelegatorValidator(t, port, addr, validator1Operator) require.Equal(t, validator1Operator, bondedValidator.OperatorAddr) - ////////////////////// - // testing unbonding + // test unbonding // create unbond TX resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Operator, 60) @@ -561,6 +560,16 @@ func TestBonding(t *testing.T) { unbonding := getUndelegation(t, port, addr, validator1Operator) require.Equal(t, "60", unbonding.Balance.Amount.String()) + // test redelegation + + // resultTx = doBeginRedelegation(t, port, seed, name, password, addr, valSrcAddr, valDstAddr) + // tests.WaitForHeight(resultTx.Height+1, port) + // + // require.Equal(t, uint32(0), resultTx.CheckTx.Code) + // require.Equal(t, uint32(0), resultTx.DeliverTx.Code) + + // test delegator summary + summary = getDelegationSummary(t, port, addr) require.Len(t, summary.Delegations, 0, "Delegation summary holds all delegations") @@ -575,6 +584,7 @@ func TestBonding(t *testing.T) { // TODO add redelegation, need more complex capabilities such to mock context and // TODO check summary for redelegation + // assert.Len(t, summary.Redelegations, 1, "Delegation summary holds all redelegations") // query txs @@ -586,6 +596,9 @@ func TestBonding(t *testing.T) { txs = getBondingTxs(t, port, addr, "unbond") assert.Len(t, txs, 1, "All unbonding txs found") + + // txs = getBondingTxs(t, port, addr, "redelegate") + // assert.Len(t, txs, 1, "All unbonding txs found") } func TestSubmitProposal(t *testing.T) { @@ -919,11 +932,22 @@ func getUndelegation(t *testing.T, port string, delegatorAddr sdk.AccAddress, va res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/unbonding_delegations/%s", delegatorAddr, validatorAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var unbondings stake.UnbondingDelegation - err := cdc.UnmarshalJSON([]byte(body), &unbondings) + var unbond stake.UnbondingDelegation + err := cdc.UnmarshalJSON([]byte(body), &unbond) + require.Nil(t, err) + + return unbond +} + +func getRedelegation(t *testing.T, port string, delegatorAddr sdk.AccAddress, validatorSrcAddr, validatorDstAddr sdk.ValAddress) stake.Redelegation { + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/redelegations/delegator/%s/validator_from/%s/validator_to/%s", delegatorAddr, validatorSrcAddr, validatorDstAddr), nil) + require.Equal(t, http.StatusOK, res.StatusCode, body) + + var red stake.Redelegation + err := cdc.UnmarshalJSON([]byte(body), &red) require.Nil(t, err) - return unbondings + return red } func getDelegationSummary(t *testing.T, port string, delegatorAddr sdk.AccAddress) stake.DelegationSummary { diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index 9ae312aab98c..75dc59769d62 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -83,7 +83,7 @@ func queryDelegator(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - bech32delegator := vars["validatorAddr"] + bech32delegator := vars["delegatorAddr"] w.Header().Set("Content-Type", "application/json") From 80427f098cd098f0df21f14211ad680c2bc808f0 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Fri, 14 Sep 2018 12:33:51 +0200 Subject: [PATCH 03/12] Redelegation Querier tests --- x/stake/querier/queryable.go | 1 - x/stake/querier/queryable_test.go | 47 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/x/stake/querier/queryable.go b/x/stake/querier/queryable.go index c72c75df44d3..fbe587c48fbd 100644 --- a/x/stake/querier/queryable.go +++ b/x/stake/querier/queryable.go @@ -70,7 +70,6 @@ type QueryValidatorParams struct { // defines the params for the following queries: // - 'custom/stake/delegation' // - 'custom/stake/unbondingDelegation' -// - 'custom/stake/redelegation' // - 'custom/stake/delegatorValidator' type QueryBondsParams struct { DelegatorAddr sdk.AccAddress diff --git a/x/stake/querier/queryable_test.go b/x/stake/querier/queryable_test.go index ee52773c6e4c..1d345705b25d 100644 --- a/x/stake/querier/queryable_test.go +++ b/x/stake/querier/queryable_test.go @@ -36,6 +36,16 @@ func newTestBondQuery(delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress } } +func newTestRedelegationQuery( + delegatorAddr sdk.AccAddress, + validatorSrcAddr, validatorDstAddr sdk.ValAddress) QueryRedelegationParams { + return QueryRedelegationParams{ + DelegatorAddr: delegatorAddr, + ValidatorSrcAddr: validatorSrcAddr, + ValidatorDstAddr: validatorDstAddr, + } +} + func TestQueryParametersPool(t *testing.T) { cdc := codec.New() ctx, _, keeper := keep.CreateTestInput(t, false, 1000) @@ -213,3 +223,40 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, unbond, summary.UnbondingDelegations[0]) } + +func TestQueryRedelegation(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) + + // Query redelegation + keeper.BeginRedelegation(ctx, addrAcc2, val1.OperatorAddr, val2.OperatorAddr, sdk.NewDec(20)) + + queryRedParams := newTestRedelegationQuery(addrAcc2, val1.OperatorAddr, val2.OperatorAddr) + bz, errRes := cdc.MarshalJSON(queryRedParams) + require.Nil(t, errRes) + + query := abci.RequestQuery{ + Path: "/custom/stake/redelegation", + Data: bz, + } + + redelegation, found := keeper.GetRedelegation(ctx, addrAcc2, val1.OperatorAddr, val2.OperatorAddr) + require.True(t, found) + + res, err := queryRedelegation(ctx, cdc, query, keeper) + require.Nil(t, err) + + var redelegationRes types.Redelegation + errRes = cdc.UnmarshalJSON(res, &redelegationRes) + require.Nil(t, errRes) + + require.Equal(t, redelegation, redelegationRes) +} From 4f1a4ff5f0710b519dca5f2f594c57b9e764b9ac Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Fri, 14 Sep 2018 13:02:04 +0200 Subject: [PATCH 04/12] Fix HumanReadableString --- x/stake/types/delegation.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 38a94c369521..1703bd97c5d5 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -98,7 +98,7 @@ func (d Delegation) HumanReadableString() (string, error) { resp := "Delegation \n" resp += fmt.Sprintf("Delegator: %s\n", d.DelegatorAddr) resp += fmt.Sprintf("Validator: %s\n", d.ValidatorAddr) - resp += fmt.Sprintf("Shares: %s", d.Shares.String()) + resp += fmt.Sprintf("Shares: %s\n", d.Shares.String()) resp += fmt.Sprintf("Height: %d", d.Height) return resp, nil @@ -280,7 +280,7 @@ func (d Redelegation) HumanReadableString() (string, error) { resp += fmt.Sprintf("Destination Validator: %s\n", d.ValidatorDstAddr) resp += fmt.Sprintf("Creation height: %v\n", d.CreationHeight) resp += fmt.Sprintf("Min time to unbond (unix): %v\n", d.MinTime) - resp += fmt.Sprintf("Source shares: %s", d.SharesSrc.String()) + resp += fmt.Sprintf("Source shares: %s\n", d.SharesSrc.String()) resp += fmt.Sprintf("Destination shares: %s", d.SharesDst.String()) return resp, nil From 39169ff8e892d6a5751994e45e231a9ed6074e42 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Fri, 14 Sep 2018 15:35:10 +0200 Subject: [PATCH 05/12] Gaia-lite tests --- client/lcd/lcd_test.go | 45 ++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index db25b45e9c69..8b96bdb1c629 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -498,9 +498,9 @@ func TestValidatorQuery(t *testing.T) { defer cleanup() require.Equal(t, 1, len(pks)) - validator1Operator := sdk.ValAddress(pks[0].Address()) - validator := getValidator(t, port, validator1Operator) - assert.Equal(t, validator.OperatorAddr, validator1Operator, "The returned validator does not hold the correct data") + validatorOperator1 := sdk.ValAddress(pks[0].Address()) + validator := getValidator(t, port, validatorOperator1) + assert.Equal(t, validator.OperatorAddr, validatorOperator1, "The returned validator does not hold the correct data") } func TestBonding(t *testing.T) { @@ -510,11 +510,11 @@ func TestBonding(t *testing.T) { defer cleanup() amt := sdk.NewDec(60) - validator1Operator := sdk.ValAddress(pks[0].Address()) - validator := getValidator(t, port, validator1Operator) + validatorOperator1 := sdk.ValAddress(pks[0].Address()) + validator := getValidator(t, port, validatorOperator1) // create bond TX - resultTx := doDelegate(t, port, seed, name, password, addr, validator1Operator, 60) + resultTx := doDelegate(t, port, seed, name, password, addr, validatorOperator1, 60) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -526,7 +526,7 @@ func TestBonding(t *testing.T) { require.Equal(t, int64(40), coins.AmountOf(denom).Int64()) // query validator - bond := getDelegation(t, port, addr, validator1Operator) + bond := getDelegation(t, port, addr, validatorOperator1) require.Equal(t, amt, bond.Shares) summary := getDelegationSummary(t, port, addr) @@ -537,16 +537,16 @@ func TestBonding(t *testing.T) { bondedValidators := getDelegatorValidators(t, port, addr) require.Len(t, bondedValidators, 1) - require.Equal(t, validator1Operator, bondedValidators[0].OperatorAddr) + require.Equal(t, validatorOperator1, bondedValidators[0].OperatorAddr) require.Equal(t, validator.DelegatorShares.Add(amt).String(), bondedValidators[0].DelegatorShares.String()) - bondedValidator := getDelegatorValidator(t, port, addr, validator1Operator) - require.Equal(t, validator1Operator, bondedValidator.OperatorAddr) + bondedValidator := getDelegatorValidator(t, port, addr, validatorOperator1) + require.Equal(t, validatorOperator1, bondedValidator.OperatorAddr) // test unbonding // create unbond TX - resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Operator, 60) + resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validatorOperator1, 60) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -557,24 +557,33 @@ func TestBonding(t *testing.T) { coins = acc.GetCoins() require.Equal(t, int64(40), coins.AmountOf("steak").Int64()) - unbonding := getUndelegation(t, port, addr, validator1Operator) + unbonding := getUndelegation(t, port, addr, validatorOperator1) require.Equal(t, "60", unbonding.Balance.Amount.String()) // test redelegation - // resultTx = doBeginRedelegation(t, port, seed, name, password, addr, valSrcAddr, valDstAddr) + // resultTx = doBeginRedelegation(t, port, seed, name, password, addr, validatorOperator1, validatorOperator2, 30) // tests.WaitForHeight(resultTx.Height+1, port) // // require.Equal(t, uint32(0), resultTx.CheckTx.Code) // require.Equal(t, uint32(0), resultTx.DeliverTx.Code) + // redelegation := getRedelegation(t, port, addr, validatorOperator1, validatorOperator2) + // require.Equal(t, validatorOperator1.String(), redelegation.ValidatorSrcAddr.String()) + // require.Equal(t, validatorOperator2.String(), redelegation.ValidatorDstAddr.String()) + // require.Equal(t, "30", redelegation.Balance.Amount.String()) + + // TODO test that the bond to the validatorSrc has decreased + + // TODO test that the bond to the validatorDst has increased + // test delegator summary summary = getDelegationSummary(t, port, addr) require.Len(t, summary.Delegations, 0, "Delegation summary holds all delegations") require.Len(t, summary.UnbondingDelegations, 1, "Delegation summary holds all unbonding-delegations") - require.Equal(t, "60", summary.UnbondingDelegations[0].Balance.Amount.String()) + // assert.Len(t, summary.Redelegations, 1, "Delegation summary holds all redelegations") bondedValidators = getDelegatorValidators(t, port, addr) require.Len(t, bondedValidators, 0, "There's no delegation as the user withdraw all funds") @@ -585,8 +594,6 @@ func TestBonding(t *testing.T) { // TODO add redelegation, need more complex capabilities such to mock context and // TODO check summary for redelegation - // assert.Len(t, summary.Redelegations, 1, "Delegation summary holds all redelegations") - // query txs txs := getBondingTxs(t, port, addr, "") assert.Len(t, txs, 2, "All Txs found") @@ -1079,7 +1086,7 @@ func doBeginUnbonding(t *testing.T, port, seed, name, password string, } func doBeginRedelegation(t *testing.T, port, seed, name, password string, - delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) (resultTx ctypes.ResultBroadcastTxCommit) { + delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { acc := getAccount(t, port, delAddr) accnum := acc.GetAccountNumber() @@ -1101,11 +1108,11 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string, "delegator_addr": "%s", "validator_src_addr": "%s", "validator_dst_addr": "%s", - "shares": "30" + "shares": "%d" } ], "complete_redelegates": [] - }`, name, password, accnum, sequence, chainID, delAddr, valSrcAddr, valDstAddr)) + }`, name, password, accnum, sequence, chainID, delAddr, valSrcAddr, valDstAddr, amount)) res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delAddr), jsonStr) require.Equal(t, http.StatusOK, res.StatusCode, body) From 6dddbb0c82d64d94204fe422c0dd4fd803e5acb0 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 2 Oct 2018 16:20:44 +0200 Subject: [PATCH 06/12] add NewQuerier tests --- x/stake/querier/queryable_test.go | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/x/stake/querier/queryable_test.go b/x/stake/querier/queryable_test.go index 1d345705b25d..263e06f3513e 100644 --- a/x/stake/querier/queryable_test.go +++ b/x/stake/querier/queryable_test.go @@ -46,6 +46,52 @@ func newTestRedelegationQuery( } } +func TestNewQuerier(t *testing.T) { + cdc := codec.New() + ctx, _, keeper := keep.CreateTestInput(t, false, 1000) + pool := keeper.GetPool(ctx) + // Create Validators + amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8)} + var validators [2]types.Validator + for i, amt := range amts { + validators[i] = types.NewValidator(sdk.ValAddress(keep.Addrs[i]), keep.PKs[i], types.Description{}) + validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) + } + keeper.SetPool(ctx, pool) + validators[0] = keeper.UpdateValidator(ctx, validators[0]) + validators[1] = keeper.UpdateValidator(ctx, validators[1]) + + query := abci.RequestQuery{ + Path: "", + Data: []byte{}, + } + + querier := NewQuerier(keeper, cdc) + + bz, err := querier(ctx, []string{"other"}, query) + require.NotNil(t, err) + require.Nil(t, bz) + + _, err = querier(ctx, []string{"validators"}, query) + require.Nil(t, err) + + _, err = querier(ctx, []string{"pool"}, query) + require.Nil(t, err) + + _, err = querier(ctx, []string{"parameters"}, query) + require.Nil(t, err) + + queryParams := newTestValidatorQuery(addrVal1) + bz, errRes := cdc.MarshalJSON(queryParams) + require.Nil(t, errRes) + + query.Path = "/custom/stake/validator" + query.Data = bz + + _, err = querier(ctx, []string{"validator"}, query) + require.Nil(t, err) +} + func TestQueryParametersPool(t *testing.T) { cdc := codec.New() ctx, _, keeper := keep.CreateTestInput(t, false, 1000) From 96b997fd334142c0d1b0799dbbe91b3403d0363c Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 2 Oct 2018 16:44:06 +0200 Subject: [PATCH 07/12] Fixed error in rest redelegation endpoint --- x/stake/client/rest/query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index cbf07a0fb2a1..8bd98f03ef8b 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -57,7 +57,7 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Co // Query a redelegation of a delegator's tokens from a validator to another r.HandleFunc( - "/stake/delegators/{delegatorAddr}/redelegations/validator_from/{validatorSrcAddr}/validator_to/{validatorDestAddr}", + "/stake/delegators/{delegatorAddr}/redelegations/validator_from/{validatorSrcAddr}/validator_to/{validatorDstAddr}", redelegationHandlerFn(cliCtx, cdc), ).Methods("GET") From e0c681177688453e27ff47149f69191380119e7c Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 3 Oct 2018 20:58:34 +0200 Subject: [PATCH 08/12] Increased coverage --- x/stake/querier/queryable_test.go | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/x/stake/querier/queryable_test.go b/x/stake/querier/queryable_test.go index 263e06f3513e..be3c1409a137 100644 --- a/x/stake/querier/queryable_test.go +++ b/x/stake/querier/queryable_test.go @@ -195,6 +195,12 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, len(delValidators), len(validatorsResp)) require.ElementsMatch(t, delValidators, validatorsResp) + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryDelegatorValidators(ctx, cdc, query, keeper) + require.NotNil(t, err) + // Query bonded validator queryBondParams := newTestBondQuery(addrAcc2, addrVal1) bz, errRes = cdc.MarshalJSON(queryBondParams) @@ -214,6 +220,12 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, delValidators[0], validator) + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryDelegatorValidator(ctx, cdc, query, keeper) + require.NotNil(t, err) + // Query delegation query = abci.RequestQuery{ @@ -233,6 +245,12 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, delegation, delegationRes) + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryDelegation(ctx, cdc, query, keeper) + require.NotNil(t, err) + // Query unbonging delegation keeper.BeginUnbonding(ctx, addrAcc2, val1.OperatorAddr, sdk.NewDec(10)) @@ -253,6 +271,12 @@ func TestQueryDelegation(t *testing.T) { require.Equal(t, unbond, unbondRes) + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryUnbondingDelegation(ctx, cdc, query, keeper) + require.NotNil(t, err) + // Query Delegator Summary query = abci.RequestQuery{ @@ -268,6 +292,12 @@ func TestQueryDelegation(t *testing.T) { require.Nil(t, errRes) require.Equal(t, unbond, summary.UnbondingDelegations[0]) + + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryDelegator(ctx, cdc, query, keeper) + require.NotNil(t, err) } func TestQueryRedelegation(t *testing.T) { @@ -305,4 +335,20 @@ func TestQueryRedelegation(t *testing.T) { require.Nil(t, errRes) require.Equal(t, redelegation, redelegationRes) + + // error unknown request + query.Data = bz[:len(bz)-1] + + _, err = queryRedelegation(ctx, cdc, query, keeper) + require.NotNil(t, err) + + // error no redelegation + queryBondParams := newTestBondQuery(addrAcc2, val1.OperatorAddr) + bz, errRes = cdc.MarshalJSON(queryBondParams) + require.Nil(t, errRes) + + query.Data = bz + + _, err = queryRedelegation(ctx, cdc, query, keeper) + require.NotNil(t, err) } From 35cd97cc4a24170d460e1e15bd424fc697c4046c Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 9 Oct 2018 14:08:13 -0700 Subject: [PATCH 09/12] Update stake rest --- x/stake/client/rest/query.go | 46 +++++++++++------------------------- x/stake/client/rest/utils.go | 21 ++++++---------- 2 files changed, 21 insertions(+), 46 deletions(-) diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 8bd98f03ef8b..fe88315e3cdb 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -1,12 +1,12 @@ package rest import ( - "fmt" "net/http" "strings" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake" @@ -102,15 +102,13 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han _, err := sdk.AccAddressFromBech32(delegatorAddr) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } node, err := cliCtx.GetNode() if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Couldn't get current Node information. Error: %s", err.Error()))) + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } @@ -152,16 +150,14 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han for _, action := range actions { foundTxs, errQuery := queryTxs(node, cliCtx, cdc, action, delegatorAddr) if errQuery != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(errQuery.Error())) + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) } txs = append(txs, foundTxs...) } output, err = cdc.MarshalJSON(txs) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } @@ -192,8 +188,7 @@ func redelegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han validatorSrcAddr, err := sdk.ValAddressFromBech32(bech32ValidatorSrc) validatorDstAddr, err := sdk.ValAddressFromBech32(bech32ValidatorDst) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } @@ -205,16 +200,13 @@ func redelegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData("custom/stake/redelegation", bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } @@ -238,9 +230,7 @@ func validatorsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { res, err := cliCtx.QueryWithData("custom/stake/validators", nil) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } @@ -257,8 +247,7 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handle validatorAddr, err := sdk.ValAddressFromBech32(bech32validatorAddr) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } @@ -268,16 +257,13 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handle bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData("custom/stake/validator", bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } @@ -291,9 +277,7 @@ func poolHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { res, err := cliCtx.QueryWithData("custom/stake/pool", nil) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } @@ -307,9 +291,7 @@ func paramsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { res, err := cliCtx.QueryWithData("custom/stake/parameters", nil) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index b2996fdaa5b8..22cc7d18b32a 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake" @@ -57,8 +58,7 @@ func queryBonds(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string) ht delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) validatorAddr, err := sdk.ValAddressFromBech32(bech32validator) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } @@ -69,16 +69,13 @@ func queryBonds(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string) ht bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData(endpoint, bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } @@ -94,8 +91,7 @@ func queryDelegator(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } @@ -105,16 +101,13 @@ func queryDelegator(cliCtx context.CLIContext, cdc *codec.Codec, endpoint string bz, err := cdc.MarshalJSON(params) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) + utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } res, err := cliCtx.QueryWithData(endpoint, bz) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) - + utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } From 7c7dc55e2d149b006c4e20b86b5be2c3b7511759 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 9 Oct 2018 14:52:21 -0700 Subject: [PATCH 10/12] Add final unit tests --- client/lcd/lcd_test.go | 60 +++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index de178216ec93..517b9ba2a608 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -10,19 +10,19 @@ import ( "testing" "time" + "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/ethereum/go-ethereum/p2p" "github.com/spf13/viper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" cryptoKeys "github.com/cosmos/cosmos-sdk/crypto/keys" - p2p "github.com/tendermint/tendermint/p2p" ctypes "github.com/tendermint/tendermint/rpc/core/types" client "github.com/cosmos/cosmos-sdk/client" keys "github.com/cosmos/cosmos-sdk/client/keys" - rpc "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/codec" tests "github.com/cosmos/cosmos-sdk/tests" sdk "github.com/cosmos/cosmos-sdk/types" @@ -565,7 +565,7 @@ func TestBonding(t *testing.T) { // test unbonding // create unbond TX - resultTx = doBeginUnbonding(t, port, seed, name, password, addr, operAddrs[0], 60) + resultTx = doBeginUnbonding(t, port, seed, name, password, addr, operAddrs[0], 30) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -577,55 +577,49 @@ func TestBonding(t *testing.T) { require.Equal(t, int64(40), coins.AmountOf("steak").Int64()) unbonding := getUndelegation(t, port, addr, operAddrs[0]) - require.Equal(t, "60", unbonding.Balance.Amount.String()) + require.Equal(t, "30", unbonding.Balance.Amount.String()) - // TODO can't test functionality with less than 2 validators. See https://github.com/cosmos/cosmos-sdk/issues/2339 // test redelegation + resultTx = doBeginRedelegation(t, port, seed, name, password, addr, operAddrs[0], operAddrs[1], 30) + tests.WaitForHeight(resultTx.Height+1, port) - // resultTx = doBeginRedelegation(t, port, seed, name, password, addr, validatorOperator1, validatorOperator2, 30) - // tests.WaitForHeight(resultTx.Height+1, port) - // - // require.Equal(t, uint32(0), resultTx.CheckTx.Code) - // require.Equal(t, uint32(0), resultTx.DeliverTx.Code) - // - // redelegation := getRedelegation(t, port, addr, validatorOperator1, validatorOperator2) - // require.Equal(t, validatorOperator1.String(), redelegation.ValidatorSrcAddr.String()) - // require.Equal(t, validatorOperator2.String(), redelegation.ValidatorDstAddr.String()) - // require.Equal(t, "30", redelegation.Balance.Amount.String()) + require.Equal(t, uint32(0), resultTx.CheckTx.Code) + require.Equal(t, uint32(0), resultTx.DeliverTx.Code) - // TODO test that the bond to the validatorSrc has decreased + redelegation := getRedelegation(t, port, addr, operAddrs[0], operAddrs[1]) + require.Equal(t, operAddrs[0].String(), redelegation.ValidatorSrcAddr.String()) + require.Equal(t, operAddrs[1].String(), redelegation.ValidatorDstAddr.String()) + require.Equal(t, "30", redelegation.Balance.Amount.String()) - // TODO test that the bond to the validatorDst has increased + // test that the bond to the validatorDst has increased + delTo := getDelegation(t, port, addr, operAddrs[1]) + require.Equal(t, sdk.NewDec(30), delTo.GetShares()) // test delegator summary - summary = getDelegationSummary(t, port, addr) - require.Len(t, summary.Delegations, 0, "Delegation summary holds all delegations") + require.Len(t, summary.Delegations, 1, "Delegation summary holds all delegations") require.Len(t, summary.UnbondingDelegations, 1, "Delegation summary holds all unbonding-delegations") - // assert.Len(t, summary.Redelegations, 1, "Delegation summary holds all redelegations") + assert.Len(t, summary.Redelegations, 1, "Delegation summary holds all redelegations") bondedValidators = getDelegatorValidators(t, port, addr) - require.Len(t, bondedValidators, 0, "There's no delegation as the user withdraw all funds") + 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) - // TODO add redelegation, need more complex capabilities such to mock context and - // TODO check summary for redelegation - // query txs txs := getBondingTxs(t, port, addr, "") - assert.Len(t, txs, 2, "All Txs found") + require.Len(t, txs, 3, "All Txs found") txs = getBondingTxs(t, port, addr, "bond") - assert.Len(t, txs, 1, "All bonding txs found") + require.Len(t, txs, 1, "All bonding txs found") txs = getBondingTxs(t, port, addr, "unbond") - assert.Len(t, txs, 1, "All unbonding txs found") + require.Len(t, txs, 1, "All unbonding txs found") - // txs = getBondingTxs(t, port, addr, "redelegate") - // assert.Len(t, txs, 1, "All unbonding txs found") + txs = getBondingTxs(t, port, addr, "redelegate") + require.Len(t, txs, 1, "All redelegation txs found") } func TestSubmitProposal(t *testing.T) { @@ -985,7 +979,7 @@ func getUndelegation(t *testing.T, port string, delegatorAddr sdk.AccAddress, va } func getRedelegation(t *testing.T, port string, delegatorAddr sdk.AccAddress, validatorSrcAddr, validatorDstAddr sdk.ValAddress) stake.Redelegation { - res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegator/%s/redelegations/validator_from/%s/validator_to/%s", delegatorAddr, validatorSrcAddr, validatorDstAddr), nil) + res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/redelegations/validator_from/%s/validator_to/%s", delegatorAddr, validatorSrcAddr, validatorDstAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) var red stake.Redelegation @@ -1066,9 +1060,7 @@ func doDelegate(t *testing.T, port, seed, name, password string, } ], "begin_unbondings": [], - "complete_unbondings": [], "begin_redelegates": [], - "complete_redelegates": [], "base_req": { "name": "%s", "password": "%s", @@ -1105,9 +1097,7 @@ func doBeginUnbonding(t *testing.T, port, seed, name, password string, "shares": "%d" } ], - "complete_unbondings": [], "begin_redelegates": [], - "complete_redelegates": [], "base_req": { "name": "%s", "password": "%s", @@ -1139,7 +1129,6 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string, jsonStr := []byte(fmt.Sprintf(`{ "delegations": [], "begin_unbondings": [], - "complete_unbondings": [], "begin_redelegates": [ { "delegator_addr": "%s", @@ -1148,7 +1137,6 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string, "shares": "%d" } ], - "complete_redelegates": [], "base_req": { "name": "%s", "password": "%s", From a5d84b9816ce1fa1aa58402a02b9645107ca8ab6 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 9 Oct 2018 15:02:57 -0700 Subject: [PATCH 11/12] Fix error import --- client/lcd/lcd_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 517b9ba2a608..c3e325c5f8e4 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -10,9 +10,8 @@ import ( "testing" "time" - "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/ethereum/go-ethereum/p2p" + p2p "github.com/tendermint/tendermint/p2p" "github.com/spf13/viper" "github.com/stretchr/testify/assert" @@ -23,6 +22,7 @@ import ( client "github.com/cosmos/cosmos-sdk/client" keys "github.com/cosmos/cosmos-sdk/client/keys" + rpc "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/codec" tests "github.com/cosmos/cosmos-sdk/tests" sdk "github.com/cosmos/cosmos-sdk/types" From 0129010db65160586c71645bd113e8cf5f08d4c7 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 9 Oct 2018 15:10:04 -0700 Subject: [PATCH 12/12] Update PENDING --- CHANGELOG.md | 1 - PENDING.md | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da5a54d8fda8..d72440bae02c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,7 +71,6 @@ FEATURES * Gaia REST API (`gaiacli advanced rest-server`) - [x/gov] Can now query governance proposals by ProposalStatus - - [x/stake] \#2336 Added redelegation endpoint * Gaia CLI (`gaiacli`) - [x/gov] added `query-proposals` command. Can filter by `depositer`, `voter`, and `status` diff --git a/PENDING.md b/PENDING.md index dbae0cc2cd87..e5ee5ad480fd 100644 --- a/PENDING.md +++ b/PENDING.md @@ -44,7 +44,7 @@ BREAKING CHANGES * [simulation] \#2162 Added back correct supply invariants * [x/slashing] \#2430 Simulate more slashes, check if validator is jailed before jailing * [x/stake] \#2393 Removed `CompleteUnbonding` and `CompleteRedelegation` Msg types, and instead added unbonding/redelegation queues to endblocker - + * SDK * [core] \#2219 Update to Tendermint 0.24.0 * Validator set updates delayed by one block @@ -75,7 +75,7 @@ BREAKING CHANGES * Mempool now won't build too large blocks, or too computationally expensive blocks * Maximum tx sizes and gas are now removed, and are implicitly the blocks maximums * ABCI validators no longer send the pubkey. The pubkey is only sent in validator updates - * Validator set changes are now delayed by one block + * Validator set changes are now delayed by one block * Block header now includes the next validator sets hash * BFT time is implemented * Secp256k1 signature format has changed @@ -85,6 +85,7 @@ BREAKING CHANGES FEATURES * Gaia REST API (`gaiacli advanced rest-server`) + * [gaia-lite] [\#2182](https://github.com/cosmos/cosmos-sdk/issues/2182) Added redelegation endpoint * [gaia-lite] Endpoints to query staking pool and params * [gaia-lite] [\#2110](https://github.com/cosmos/cosmos-sdk/issues/2110) Add support for `simulate=true` requests query argument to endpoints that send txs to run simulations of transactions * [gaia-lite] [\#966](https://github.com/cosmos/cosmos-sdk/issues/966) Add support for `generate_only=true` query argument to generate offline unsigned transactions