Merge PR #2249: Staking Querier pt1

* Cherry picked commits from prev branch

* Added new keepers for querier functionalities

* Renaming

* Fixed gov errors and messages

* Added Querier to stake and app

* Update delegation keepers

* REST Queriers not working

* Fix marshalling error

* Querier tests working

* Pool and params working

* sdk.NewCoin for test handler

* Refactor and renaming

* Update LCD queries and added more tests for queriers

* use sdk.NewCoin

* Delegator summary query and tests

* Added more tests for keeper

* Update PENDING.md

* Update stake rest query

* Format and replaced panics for sdk.Error

* Refactor and addressed comments from Sunny and Aleks

* Fixed some of the errors produced by addr type change

* Fixed remaining errors

* Updated and fixed lite tests

* JSON Header and consistency on errors

* Increased cov for genesis

* Added comment for maxRetrieve param in keepers

* Comment on DelegationWithoutDec

* Bech32Validator Keepers

* Changed Bech validator

* Updated remaining tests and bech32 validator

* Addressed most of Rigel's comments

* Updated tests and types

* Make codec to be unexported from keeper

* Moved logic to query_utils and updated tests

* Fix linter err and PENDING

* Fix err

* Fix err

* Fixed tests

* Update PENDING description

* Update UpdateBondedValidatorsFull

* Update iterator

* defer iterator.Close()

* delete comment

* Address some of Aleks comments, need to fix tests

* export querier

* Fixed tests

* Address Rigel's comments

* More tests

* return error for GetDelegatorValidator

* Fixed conflicts

* Fix linter warnings

* Address @rigelrozanski comments

* Delete comments

* wire ––> codec
This commit is contained in:
Federico Kunze 2018-09-13 23:23:44 +02:00 committed by Rigel
parent 6b55093c75
commit d195cc15ed
21 changed files with 968 additions and 621 deletions

42
Gopkg.lock generated
View File

@ -34,7 +34,7 @@
[[projects]]
branch = "master"
digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79"
digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8"
name = "github.com/btcsuite/btcd"
packages = ["btcec"]
pruneopts = "UT"
@ -71,7 +71,7 @@
version = "v1.4.7"
[[projects]]
digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe"
digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11"
name = "github.com/go-kit/kit"
packages = [
"log",
@ -103,7 +103,7 @@
version = "v1.7.0"
[[projects]]
digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45"
digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e"
name = "github.com/gogo/protobuf"
packages = [
"gogoproto",
@ -118,7 +118,7 @@
version = "v1.1.1"
[[projects]]
digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888"
digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260"
name = "github.com/golang/protobuf"
packages = [
"proto",
@ -165,7 +165,7 @@
[[projects]]
branch = "master"
digest = "1:8951fe6e358876736d8fa1f3992624fdbb2dec6bc49401c1381d1ef8abbb544f"
digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240"
name = "github.com/hashicorp/hcl"
packages = [
".",
@ -262,7 +262,7 @@
version = "v1.0.0"
[[projects]]
digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e"
digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0"
name = "github.com/prometheus/client_golang"
packages = [
"prometheus",
@ -273,7 +273,7 @@
[[projects]]
branch = "master"
digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a"
digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4"
name = "github.com/prometheus/client_model"
packages = ["go"]
pruneopts = "UT"
@ -281,7 +281,7 @@
[[projects]]
branch = "master"
digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3"
digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5"
name = "github.com/prometheus/common"
packages = [
"expfmt",
@ -293,7 +293,7 @@
[[projects]]
branch = "master"
digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd"
digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290"
name = "github.com/prometheus/procfs"
packages = [
".",
@ -312,7 +312,7 @@
revision = "e2704e165165ec55d062f5919b4b29494e9fa790"
[[projects]]
digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c"
digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84"
name = "github.com/spf13/afero"
packages = [
".",
@ -331,7 +331,7 @@
version = "v1.2.0"
[[projects]]
digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26"
digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e"
name = "github.com/spf13/cobra"
packages = ["."]
pruneopts = "UT"
@ -363,7 +363,7 @@
version = "v1.0.0"
[[projects]]
digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d"
digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6"
name = "github.com/stretchr/testify"
packages = [
"assert",
@ -375,7 +375,7 @@
[[projects]]
branch = "master"
digest = "1:442d2ffa75ffae302ce8800bf4144696b92bef02917923ea132ce2d39efe7d65"
digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5"
name = "github.com/syndtr/goleveldb"
packages = [
"leveldb",
@ -396,7 +396,7 @@
[[projects]]
branch = "master"
digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232"
digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722"
name = "github.com/tendermint/ed25519"
packages = [
".",
@ -423,7 +423,7 @@
version = "v0.11.0"
[[projects]]
digest = "1:963f6c04345ce36f900c1d6367200eebc3cc2db6ee632ff865ea8dcf64b748a0"
digest = "1:4f15e95fe3888cc75dd34f407d6394cbc7fd3ff24920851b92b295f6a8b556e6"
name = "github.com/tendermint/tendermint"
packages = [
"abci/client",
@ -490,7 +490,7 @@
version = "v0.23.1-rc0"
[[projects]]
digest = "1:ad879bb8c71020a3f92f0c61f414d93eae1d5dc2f37023b6abaa3cc84b00165e"
digest = "1:bf6d9a827ea3cad964c2f863302e4f6823170d0b5ed16f72cf1184a7c615067e"
name = "github.com/tendermint/tmlibs"
packages = ["cli"]
pruneopts = "UT"
@ -507,7 +507,7 @@
[[projects]]
branch = "master"
digest = "1:2a3ce1f08dcae8bac666deb6e4c88b5d7170c510da38fd746231144cac351704"
digest = "1:27507554c6d4f060d8d700c31c624a43d3a92baa634e178ddc044bdf7d13b44a"
name = "golang.org/x/crypto"
packages = [
"blowfish",
@ -529,7 +529,7 @@
revision = "614d502a4dac94afa3a6ce146bd1736da82514c6"
[[projects]]
digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9"
digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1"
name = "golang.org/x/net"
packages = [
"context",
@ -546,7 +546,7 @@
[[projects]]
branch = "master"
digest = "1:9d9e5fc87553258c36ee18d38023587edd61e4b2521f4473da34b47a83a492e5"
digest = "1:ead82e3e398388679f3ad77633a087ac31a47a6be59ae20841e1d1b3a3fbbd22"
name = "golang.org/x/sys"
packages = [
"cpu",
@ -556,7 +556,7 @@
revision = "4ea2f632f6e912459fe60b26b1749377f0d889d5"
[[projects]]
digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca"
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
name = "golang.org/x/text"
packages = [
"collate",
@ -587,7 +587,7 @@
revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4"
[[projects]]
digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac"
digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74"
name = "google.golang.org/grpc"
packages = [
".",

View File

@ -160,8 +160,8 @@ test_sim_gaia_fast:
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=400 -SimulationBlockSize=200 -SimulationCommit=true -v -timeout 24h
test_sim_gaia_slow:
@echo "Running full Gaia simulation. This may take awhile!"
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -SimulationCommit=true -v -timeout 24h
@echo "Running full Gaia simulation. This may take a while!"
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -SimulationCommit=true -v -timeout 24h
SIM_NUM_BLOCKS ?= 210
SIM_BLOCK_SIZE ?= 200

View File

@ -101,7 +101,7 @@ IMPROVEMENTS
* [x/stake] Improve speed of GetValidator, which was shown to be a performance bottleneck. [#2046](https://github.com/tendermint/tendermint/pull/2200)
* [genesis] \#2229 Ensure that there are no duplicate accounts or validators in the genesis state.
* Add SDK validation to `config.toml` (namely disabling `create_empty_blocks`) \#1571
* SDK
* [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present.
* [spec] Added simple piggy bank distribution spec
@ -113,6 +113,7 @@ IMPROVEMENTS
* [simulation] Add a concept of weighting the operations \#2303
* [simulation] Logs get written to file if large, and also get printed on panics \#2285
* [gaiad] \#1992 Add optional flag to `gaiad testnet` to make config directory of daemon (default `gaiad`) and cli (default `gaiacli`) configurable
* [x/stake] Add stake `Queriers` for Gaia-lite endpoints. This increases the staking endpoints performance by reusing the staking `keeper` logic for queries. [#2249](https://github.com/cosmos/cosmos-sdk/pull/2149)
* Tendermint

View File

@ -30,7 +30,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/x/stake/client/rest"
)
func init() {
@ -510,6 +509,7 @@ func TestBonding(t *testing.T) {
cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
defer cleanup()
amt := sdk.NewDec(60)
validator1Operator := sdk.ValAddress(pks[0].Address())
validator := getValidator(t, port, validator1Operator)
@ -527,18 +527,18 @@ func TestBonding(t *testing.T) {
// query validator
bond := getDelegation(t, port, addr, validator1Operator)
require.Equal(t, "60.0000000000", bond.Shares)
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, "60.0000000000", summary.Delegations[0].Shares)
require.Equal(t, amt, summary.Delegations[0].Shares)
require.Len(t, summary.UnbondingDelegations, 0, "Delegation summary holds all unbonding-delegations")
bondedValidators := getDelegatorValidators(t, port, addr)
require.Len(t, bondedValidators, 1)
require.Equal(t, validator1Operator, bondedValidators[0].OperatorAddr)
require.Equal(t, validator.DelegatorShares.Add(sdk.NewDec(60)).String(), bondedValidators[0].DelegatorShares.String())
require.Equal(t, validator.DelegatorShares.Add(amt).String(), bondedValidators[0].DelegatorShares.String())
bondedValidator := getDelegatorValidator(t, port, addr, validator1Operator)
require.Equal(t, validator1Operator, bondedValidator.OperatorAddr)
@ -558,9 +558,8 @@ func TestBonding(t *testing.T) {
coins = acc.GetCoins()
require.Equal(t, int64(40), coins.AmountOf("steak").Int64())
unbondings := getUndelegations(t, port, addr, validator1Operator)
require.Len(t, unbondings, 1, "Unbondings holds all unbonding-delegations")
require.Equal(t, "60", unbondings[0].Balance.Amount.String())
unbonding := getUndelegation(t, port, addr, validator1Operator)
require.Equal(t, "60", unbonding.Balance.Amount.String())
summary = getDelegationSummary(t, port, addr)
@ -895,43 +894,43 @@ func doIBCTransfer(t *testing.T, port, seed, name, password string, addr sdk.Acc
func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing.ValidatorSigningInfo {
res, body := Request(t, port, "GET", fmt.Sprintf("/slashing/signing_info/%s", validatorPubKey), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var signingInfo slashing.ValidatorSigningInfo
err := cdc.UnmarshalJSON([]byte(body), &signingInfo)
require.Nil(t, err)
return signingInfo
}
// ============= Stake Module ================
func getDelegation(t *testing.T, port string, delAddr sdk.AccAddress, valAddr sdk.ValAddress) rest.DelegationWithoutRat {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/delegations/%s", delAddr, valAddr), nil)
func getDelegation(t *testing.T, port string, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) stake.Delegation {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/delegations/%s", delegatorAddr, validatorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var bond rest.DelegationWithoutRat
var bond stake.Delegation
err := cdc.UnmarshalJSON([]byte(body), &bond)
require.Nil(t, err)
return bond
}
func getUndelegations(t *testing.T, port string, delAddr sdk.AccAddress, valAddr sdk.ValAddress) []stake.UnbondingDelegation {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/unbonding_delegations/%s", delAddr, valAddr), nil)
func getUndelegation(t *testing.T, port string, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) stake.UnbondingDelegation {
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
var unbondings stake.UnbondingDelegation
err := cdc.UnmarshalJSON([]byte(body), &unbondings)
require.Nil(t, err)
return unbondings
}
func getDelegationSummary(t *testing.T, port string, delegatorAddr sdk.AccAddress) rest.DelegationSummary {
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)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var summary rest.DelegationSummary
var summary stake.DelegationSummary
err := cdc.UnmarshalJSON([]byte(body), &summary)
require.Nil(t, err)
@ -970,8 +969,8 @@ func getDelegatorValidators(t *testing.T, port string, delegatorAddr sdk.AccAddr
return bondedValidators
}
func getDelegatorValidator(t *testing.T, port string, delAddr sdk.AccAddress, valAddr sdk.ValAddress) stake.Validator {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/validators/%s", delAddr, valAddr), nil)
func getDelegatorValidator(t *testing.T, port string, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) stake.Validator {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/validators/%s", delegatorAddr, validatorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var bondedValidator stake.Validator
@ -1097,18 +1096,22 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string,
func getValidators(t *testing.T, port string) []stake.Validator {
res, body := Request(t, port, "GET", "/stake/validators", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var validators []stake.Validator
err := cdc.UnmarshalJSON([]byte(body), &validators)
require.Nil(t, err)
return validators
}
func getValidator(t *testing.T, port string, valAddr sdk.ValAddress) stake.Validator {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s", valAddr.String()), nil)
func getValidator(t *testing.T, port string, validatorAddr sdk.ValAddress) stake.Validator {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s", validatorAddr.String()), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var validator stake.Validator
err := cdc.UnmarshalJSON([]byte(body), &validator)
require.Nil(t, err)
return validator
}
@ -1284,7 +1287,6 @@ func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.Ac
}
}`, proposerAddr, name, password, chainID, accnum, sequence))
res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/votes", proposalID), jsonStr)
fmt.Println(res)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var results ctypes.ResultBroadcastTxCommit

View File

@ -133,6 +133,7 @@ func SignStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string,
return txBldr.SignStdTx(name, passphrase, stdTx, appendSig)
}
// nolint
// SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value.
func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (estimated, adjusted int64, err error) {
txBytes, err := txBldr.BuildWithPubKey(name, msgs)

View File

@ -109,7 +109,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
AddRoute("gov", gov.NewHandler(app.govKeeper))
app.QueryRouter().
AddRoute("gov", gov.NewQuerier(app.govKeeper))
AddRoute("gov", gov.NewQuerier(app.govKeeper)).
AddRoute("stake", stake.NewQuerier(app.stakeKeeper, app.cdc))
// initialize BaseApp
app.SetInitChainer(app.initChainer)

View File

@ -22,6 +22,7 @@ type SignBody struct {
AppendSig bool `json:"append_sig"`
}
// nolint: unparam
// sign tx REST handler
func SignTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {

View File

@ -20,9 +20,9 @@ var (
addr3 = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())
priv4 = ed25519.GenPrivKey()
addr4 = sdk.AccAddress(priv4.PubKey().Address())
coins = sdk.Coins{{"foocoin", sdk.NewInt(10)}}
coins = sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(10))}
fee = auth.StdFee{
sdk.Coins{{"foocoin", sdk.NewInt(0)}},
sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(0))},
100000,
}
)

View File

@ -11,7 +11,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/x/stake/tags"
"github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/gorilla/mux"
)
@ -50,16 +49,16 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Co
delegationHandlerFn(cliCtx, cdc),
).Methods("GET")
// Query all unbonding_delegations between a delegator and a validator
// Query all unbonding delegations between a delegator and a validator
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr}",
unbondingDelegationsHandlerFn(cliCtx, cdc),
unbondingDelegationHandlerFn(cliCtx, cdc),
).Methods("GET")
// Get all validators
r.HandleFunc(
"/stake/validators",
validatorsHandlerFn(cliCtx, cdc),
validatorsHandlerFn(cliCtx),
).Methods("GET")
// Get a single validator info
@ -71,107 +70,53 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Co
// Get the current state of the staking pool
r.HandleFunc(
"/stake/pool",
poolHandlerFn(cliCtx, cdc),
poolHandlerFn(cliCtx),
).Methods("GET")
// Get the current staking parameter values
r.HandleFunc(
"/stake/parameters",
paramsHandlerFn(cliCtx, cdc),
paramsHandlerFn(cliCtx),
).Methods("GET")
}
// already resolve the rational shares to not handle this in the client
// defines a delegation without type Rat for shares
type DelegationWithoutRat struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
ValidatorAddr sdk.ValAddress `json:"validator_addr"`
Shares string `json:"shares"`
Height int64 `json:"height"`
}
// aggregation of all delegations, unbondings and redelegations
type DelegationSummary struct {
Delegations []DelegationWithoutRat `json:"delegations"`
UnbondingDelegations []stake.UnbondingDelegation `json:"unbonding_delegations"`
Redelegations []stake.Redelegation `json:"redelegations"`
}
// 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) {
var valAddr sdk.ValAddress
var delegationSummary = DelegationSummary{}
// read parameters
vars := mux.Vars(r)
bech32delegator := vars["delegatorAddr"]
delAddr, err := sdk.AccAddressFromBech32(bech32delegator)
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
}
// Get all validators using key
validators, statusCode, errMsg, err := getBech32Validators(storeName, cliCtx, cdc)
if err != nil {
w.WriteHeader(statusCode)
w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error())))
return
params := stake.QueryDelegatorParams{
DelegatorAddr: delegatorAddr,
}
for _, validator := range validators {
valAddr = validator.OperatorAddr
// Delegations
delegations, statusCode, errMsg, err := getDelegatorDelegations(cliCtx, cdc, delAddr, valAddr)
if err != nil {
w.WriteHeader(statusCode)
w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error())))
return
}
if statusCode != http.StatusNoContent {
delegationSummary.Delegations = append(delegationSummary.Delegations, delegations)
}
// Undelegations
unbondingDelegation, statusCode, errMsg, err := getDelegatorUndelegations(cliCtx, cdc, delAddr, valAddr)
if err != nil {
w.WriteHeader(statusCode)
w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error())))
return
}
if statusCode != http.StatusNoContent {
delegationSummary.UnbondingDelegations = append(delegationSummary.UnbondingDelegations, unbondingDelegation)
}
// Redelegations
// only querying redelegations to a validator as this should give us already all relegations
// if we also would put in redelegations from, we would have every redelegation double
redelegations, statusCode, errMsg, err := getDelegatorRedelegations(cliCtx, cdc, delAddr, valAddr)
if err != nil {
w.WriteHeader(statusCode)
w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error())))
return
}
if statusCode != http.StatusNoContent {
delegationSummary.Redelegations = append(delegationSummary.Redelegations, redelegations)
}
}
output, err := cdc.MarshalJSON(delegationSummary)
bz, err := cdc.MarshalJSON(params)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
res, err := cliCtx.QueryWithData("custom/stake/delegator", bz)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(res)
}
}
@ -184,6 +129,8 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han
vars := mux.Vars(r)
delegatorAddr := vars["delegatorAddr"]
w.Header().Set("Content-Type", "application/json")
_, err := sdk.AccAddressFromBech32(delegatorAddr)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
@ -237,7 +184,7 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han
foundTxs, errQuery := queryTxs(node, cdc, action, delegatorAddr)
if errQuery != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("error querying transactions. Error: %s", errQuery.Error())))
w.Write([]byte(errQuery.Error()))
}
txs = append(txs, foundTxs...)
}
@ -253,59 +200,49 @@ func delegatorTxsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Han
}
// HTTP request handler to query an unbonding-delegation
func unbondingDelegationsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
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"]
delAddr, err := sdk.AccAddressFromBech32(bech32delegator)
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
}
valAddr, err := sdk.ValAddressFromBech32(bech32validator)
validatorAddr, err := sdk.ValAddressFromBech32(bech32validator)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
key := stake.GetUBDKey(delAddr, valAddr)
params := stake.QueryBondsParams{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
}
res, err := cliCtx.QueryStore(key, storeName)
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(fmt.Sprintf("couldn't query unbonding-delegation. Error: %s", err.Error())))
w.Write([]byte(err.Error()))
return
}
// the query will return empty if there is no data for this record
if len(res) == 0 {
w.WriteHeader(http.StatusNoContent)
return
}
ubd, err := types.UnmarshalUBD(cdc, key, res)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't unmarshall unbonding-delegation. Error: %s", err.Error())))
return
}
// unbondings will be a list in the future but is not yet, but we want to keep the API consistent
ubdArray := []stake.UnbondingDelegation{ubd}
output, err := cdc.MarshalJSON(ubdArray)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't marshall unbonding-delegation. Error: %s", err.Error())))
return
}
w.Write(output)
w.Write(res)
}
}
@ -317,70 +254,7 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handl
bech32delegator := vars["delegatorAddr"]
bech32validator := vars["validatorAddr"]
delAddr, err := sdk.AccAddressFromBech32(bech32delegator)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
valAddr, err := sdk.ValAddressFromBech32(bech32validator)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
key := stake.GetDelegationKey(delAddr, valAddr)
res, err := cliCtx.QueryStore(key, storeName)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't query delegation. Error: %s", err.Error())))
return
}
// the query will return empty if there is no data for this record
if len(res) == 0 {
w.WriteHeader(http.StatusNoContent)
return
}
delegation, err := types.UnmarshalDelegation(cdc, key, res)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
outputDelegation := DelegationWithoutRat{
DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr,
Height: delegation.Height,
Shares: delegation.Shares.String(),
}
output, err := cdc.MarshalJSON(outputDelegation)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
}
}
// 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) {
var valAddr sdk.ValAddress
var bondedValidators []types.Validator
// read parameters
vars := mux.Vars(r)
bech32delegator := vars["delegatorAddr"]
w.Header().Set("Content-Type", "application/json")
delegatorAddr, err := sdk.AccAddressFromBech32(bech32delegator)
if err != nil {
@ -389,120 +263,134 @@ func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) h
return
}
// Get all validators using key
kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName)
validatorAddr, err := sdk.ValAddressFromBech32(bech32validator)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't query validators. Error: %s", err.Error())))
return
} else if len(kvs) == 0 {
// the query will return empty if there are no validators
w.WriteHeader(http.StatusNoContent)
return
}
validators, err := getValidators(kvs, cdc)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Error: %s", err.Error())))
return
}
for _, validator := range validators {
// get all transactions from the delegator to val and append
valAddr = validator.OperatorAddr
validator, statusCode, errMsg, errRes := getDelegatorValidator(cliCtx, cdc, delegatorAddr, valAddr)
if errRes != nil {
w.WriteHeader(statusCode)
w.Write([]byte(fmt.Sprintf("%s%s", errMsg, errRes.Error())))
return
} else if statusCode == http.StatusNoContent {
continue
}
bondedValidators = append(bondedValidators, validator)
}
output, err := cdc.MarshalJSON(bondedValidators)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
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/delegation", bz)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(res)
}
}
// 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)
}
}
// 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) {
// read parameters
var output []byte
vars := mux.Vars(r)
bech32delegator := vars["delegatorAddr"]
bech32validator := vars["validatorAddr"]
delAddr, err := sdk.AccAddressFromBech32(bech32delegator)
valAddr, err := sdk.ValAddressFromBech32(bech32validator)
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(fmt.Sprintf("Error: %s", err.Error())))
return
}
// Check if there if the delegator is bonded or redelegated to the validator
validator, statusCode, errMsg, err := getDelegatorValidator(cliCtx, cdc, delAddr, valAddr)
if err != nil {
w.WriteHeader(statusCode)
w.Write([]byte(fmt.Sprintf("%s%s", errMsg, err.Error())))
return
} else if statusCode == http.StatusNoContent {
w.WriteHeader(statusCode)
return
}
output, err = cdc.MarshalJSON(validator)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
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)
}
}
// TODO bech32
// http request handler to query list of validators
func validatorsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
// HTTP request handler to query list of validators
func validatorsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't query validators. Error: %s", err.Error())))
return
}
// the query will return empty if there are no validators
if len(kvs) == 0 {
w.WriteHeader(http.StatusNoContent)
return
}
w.Header().Set("Content-Type", "application/json")
validators, err := getValidators(kvs, cdc)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Error: %s", err.Error())))
return
}
output, err := cdc.MarshalJSON(validators)
res, err := cliCtx.QueryWithData("custom/stake/validators", nil)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
w.Header().Set("Content-Type", "application/json")
w.Write(res)
}
}
@ -510,111 +398,73 @@ func validatorsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.Handl
func validatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var output []byte
// read parameters
vars := mux.Vars(r)
bech32validatorAddr := vars["addr"]
valAddr, err := sdk.ValAddressFromBech32(bech32validatorAddr)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("error: %s", err.Error())))
return
}
w.Header().Set("Content-Type", "application/json")
key := stake.GetValidatorKey(valAddr)
res, err := cliCtx.QueryStore(key, storeName)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't query validator, error: %s", err.Error())))
return
}
// the query will return empty if there is no data for this record
if len(res) == 0 {
w.WriteHeader(http.StatusNoContent)
return
}
validator, err := types.UnmarshalValidator(cdc, valAddr, res)
validatorAddr, err := sdk.ValAddressFromBech32(bech32validatorAddr)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
output, err = cdc.MarshalJSON(validator)
params := stake.QueryValidatorParams{
ValidatorAddr: validatorAddr,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Error: %s", err.Error())))
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
if output == nil {
w.WriteHeader(http.StatusNoContent)
res, err := cliCtx.QueryWithData("custom/stake/validator", bz)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
w.Write(res)
}
}
// HTTP request handler to query the pool information
func poolHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
func poolHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
key := stake.PoolKey
res, err := cliCtx.QueryStore(key, storeName)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't query pool. Error: %s", err.Error())))
return
}
w.Header().Set("Content-Type", "application/json")
pool, err := types.UnmarshalPool(cdc, res)
res, err := cliCtx.QueryWithData("custom/stake/pool", nil)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
output, err := cdc.MarshalJSON(pool)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
w.Write(res)
}
}
// HTTP request handler to query the staking params values
func paramsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
func paramsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
key := stake.ParamKey
res, err := cliCtx.QueryStore(key, storeName)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't query parameters. Error: %s", err.Error())))
return
}
w.Header().Set("Content-Type", "application/json")
params, err := types.UnmarshalParams(cdc, res)
res, err := cliCtx.QueryWithData("custom/stake/parameters", nil)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
output, err := cdc.MarshalJSON(params)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
w.Write(res)
}
}

View File

@ -2,15 +2,10 @@ 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/cosmos/cosmos-sdk/x/stake/types"
rpcclient "github.com/tendermint/tendermint/rpc/client"
)
@ -24,106 +19,6 @@ func contains(stringSlice []string, txType string) bool {
return false
}
func getDelegatorValidator(cliCtx context.CLIContext, cdc *codec.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (
validator types.Validator, httpStatusCode int, errMsg string, err error) {
key := stake.GetDelegationKey(delAddr, valAddr)
res, err := cliCtx.QueryStore(key, storeName)
if err != nil {
return types.Validator{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err
}
if len(res) == 0 {
return types.Validator{}, http.StatusNoContent, "", nil
}
key = stake.GetValidatorKey(valAddr)
res, err = cliCtx.QueryStore(key, storeName)
if err != nil {
return types.Validator{}, http.StatusInternalServerError, "couldn't query validator. Error: ", err
}
if len(res) == 0 {
return types.Validator{}, http.StatusNoContent, "", nil
}
validator, err = types.UnmarshalValidator(cdc, valAddr, res)
if err != nil {
return types.Validator{}, http.StatusBadRequest, "", err
}
return validator, http.StatusOK, "", nil
}
func getDelegatorDelegations(
cliCtx context.CLIContext, cdc *codec.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (
outputDelegation DelegationWithoutRat, httpStatusCode int, errMsg string, err error) {
delegationKey := stake.GetDelegationKey(delAddr, valAddr)
marshalledDelegation, err := cliCtx.QueryStore(delegationKey, storeName)
if err != nil {
return DelegationWithoutRat{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err
}
if len(marshalledDelegation) == 0 {
return DelegationWithoutRat{}, http.StatusNoContent, "", nil
}
delegation, err := types.UnmarshalDelegation(cdc, delegationKey, marshalledDelegation)
if err != nil {
return DelegationWithoutRat{}, http.StatusInternalServerError, "couldn't unmarshall delegation. Error: ", err
}
outputDelegation = DelegationWithoutRat{
DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr,
Height: delegation.Height,
Shares: delegation.Shares.String(),
}
return outputDelegation, http.StatusOK, "", nil
}
func getDelegatorUndelegations(
cliCtx context.CLIContext, cdc *codec.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (
unbonds types.UnbondingDelegation, httpStatusCode int, errMsg string, err error) {
undelegationKey := stake.GetUBDKey(delAddr, valAddr)
marshalledUnbondingDelegation, err := cliCtx.QueryStore(undelegationKey, storeName)
if err != nil {
return types.UnbondingDelegation{}, http.StatusInternalServerError, "couldn't query unbonding-delegation. Error: ", err
}
if len(marshalledUnbondingDelegation) == 0 {
return types.UnbondingDelegation{}, http.StatusNoContent, "", nil
}
unbondingDelegation, err := types.UnmarshalUBD(cdc, undelegationKey, marshalledUnbondingDelegation)
if err != nil {
return types.UnbondingDelegation{}, http.StatusInternalServerError, "couldn't unmarshall unbonding-delegation. Error: ", err
}
return unbondingDelegation, http.StatusOK, "", nil
}
func getDelegatorRedelegations(
cliCtx context.CLIContext, cdc *codec.Codec, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (
regelegations types.Redelegation, httpStatusCode int, errMsg string, err error) {
key := stake.GetREDsByDelToValDstIndexKey(delAddr, valAddr)
marshalledRedelegations, err := cliCtx.QueryStore(key, storeName)
if err != nil {
return types.Redelegation{}, http.StatusInternalServerError, "couldn't query redelegation. Error: ", err
}
if len(marshalledRedelegations) == 0 {
return types.Redelegation{}, http.StatusNoContent, "", nil
}
redelegations, err := types.UnmarshalRED(cdc, key, marshalledRedelegations)
if err != nil {
return types.Redelegation{}, http.StatusInternalServerError, "couldn't unmarshall redelegations. Error: ", err
}
return redelegations, http.StatusOK, "", nil
}
// queries staking txs
func queryTxs(node rpcclient.Client, cdc *codec.Codec, tag string, delegatorAddr string) ([]tx.Info, error) {
page := 0
@ -137,42 +32,3 @@ func queryTxs(node rpcclient.Client, cdc *codec.Codec, tag string, delegatorAddr
return tx.FormatTxResults(cdc, res.Txs)
}
// gets all validators
func getValidators(validatorKVs []sdk.KVPair, cdc *codec.Codec) ([]types.Validator, error) {
validators := make([]types.Validator, len(validatorKVs))
for i, kv := range validatorKVs {
addr := kv.Key[1:]
validator, err := types.UnmarshalValidator(cdc, addr, kv.Value)
if err != nil {
return nil, err
}
validators[i] = validator
}
return validators, nil
}
// gets all Bech32 validators from a key
// nolint: unparam
func getBech32Validators(storeName string, cliCtx context.CLIContext, cdc *codec.Codec) (
validators []types.Validator, httpStatusCode int, errMsg string, err error) {
// Get all validators using key
kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName)
if err != nil {
return nil, http.StatusInternalServerError, "couldn't query validators. Error: ", err
}
// the query will return empty if there are no validators
if len(kvs) == 0 {
return nil, http.StatusNoContent, "", nil
}
validators, err = getValidators(kvs, cdc)
if err != nil {
return nil, http.StatusInternalServerError, "Error: ", err
}
return validators, http.StatusOK, "", nil
}

View File

@ -42,6 +42,12 @@ func TestInitGenesis(t *testing.T) {
vals, err := InitGenesis(ctx, keeper, genesisState)
require.NoError(t, err)
actualGenesis := WriteGenesis(ctx, keeper)
require.Equal(t, genesisState.Pool, actualGenesis.Pool)
require.Equal(t, genesisState.Params, actualGenesis.Params)
require.Equal(t, genesisState.Bonds, actualGenesis.Bonds)
require.EqualValues(t, keeper.GetAllValidators(ctx), actualGenesis.Validators)
// now make sure the validators are bonded and intra-tx counters are correct
resVal, found := keeper.GetValidator(ctx, sdk.ValAddress(keep.Addrs[0]))
require.True(t, found)

View File

@ -17,14 +17,14 @@ import (
//______________________________________________________________________
func newTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator {
return types.NewMsgCreateValidator(address, pubKey, sdk.Coin{"steak", sdk.NewInt(amt)}, Description{})
return types.NewMsgCreateValidator(address, pubKey, sdk.NewCoin("steak", sdk.NewInt(amt)), Description{})
}
func newTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt int64) MsgDelegate {
return MsgDelegate{
DelegatorAddr: delAddr,
ValidatorAddr: valAddr,
Delegation: sdk.Coin{"steak", sdk.NewInt(amt)},
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
}
}
@ -34,7 +34,7 @@ func newTestMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.Val
DelegatorAddr: delAddr,
ValidatorAddr: valAddr,
PubKey: valPubKey,
Delegation: sdk.Coin{"steak", sdk.NewInt(amt)},
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
}
}

View File

@ -8,7 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
// load a delegation
// return a specific delegation
func (k Keeper) GetDelegation(ctx sdk.Context,
delAddr sdk.AccAddress, valAddr sdk.ValAddress) (
delegation types.Delegation, found bool) {
@ -24,44 +24,37 @@ func (k Keeper) GetDelegation(ctx sdk.Context,
return delegation, true
}
// load all delegations used during genesis dump
// return all delegations used during genesis dump
func (k Keeper) GetAllDelegations(ctx sdk.Context) (delegations []types.Delegation) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, DelegationKey)
defer iterator.Close()
i := 0
for ; ; i++ {
if !iterator.Valid() {
break
}
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value())
delegations = append(delegations, delegation)
iterator.Next()
}
iterator.Close()
return delegations
}
// load all delegations for a delegator
func (k Keeper) GetDelegations(ctx sdk.Context, delegator sdk.AccAddress,
maxRetrieve int16) (delegations []types.Delegation) {
// 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) {
delegations = make([]types.Delegation, maxRetrieve)
store := ctx.KVStore(k.storeKey)
delegatorPrefixKey := GetDelegationsKey(delegator)
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey)
defer iterator.Close()
delegations = make([]types.Delegation, maxRetrieve)
i := 0
for ; ; i++ {
if !iterator.Valid() || i > int(maxRetrieve-1) {
break
}
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value())
delegations[i] = delegation
iterator.Next()
i++
}
iterator.Close()
return delegations[:i] // trim
return delegations[:i] // trim if the array length < maxRetrieve
}
// set the delegation
@ -71,7 +64,7 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) {
store.Set(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr), b)
}
// remove the delegation
// remove a delegation from store
func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) {
store := ctx.KVStore(k.storeKey)
store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr))
@ -79,7 +72,27 @@ func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) {
//_____________________________________________________________________________________
// load a unbonding delegation
// return a given amount of all the delegator unbonding-delegations
func (k Keeper) GetUnbondingDelegations(ctx sdk.Context, delegator sdk.AccAddress,
maxRetrieve uint16) (unbondingDelegations []types.UnbondingDelegation) {
unbondingDelegations = make([]types.UnbondingDelegation, maxRetrieve)
store := ctx.KVStore(k.storeKey)
delegatorPrefixKey := GetUBDsKey(delegator)
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey)
defer iterator.Close()
i := 0
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
unbondingDelegation := types.MustUnmarshalUBD(k.cdc, iterator.Key(), iterator.Value())
unbondingDelegations[i] = unbondingDelegation
i++
}
return unbondingDelegations[:i] // trim if the array length < maxRetrieve
}
// return a unbonding delegation
func (k Keeper) GetUnbondingDelegation(ctx sdk.Context,
delAddr sdk.AccAddress, valAddr sdk.ValAddress) (ubd types.UnbondingDelegation, found bool) {
@ -94,21 +107,18 @@ func (k Keeper) GetUnbondingDelegation(ctx sdk.Context,
return ubd, true
}
// load all unbonding delegations from a particular validator
// return all unbonding delegations from a particular validator
func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sdk.ValAddress) (ubds []types.UnbondingDelegation) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, GetUBDsByValIndexKey(valAddr))
for {
if !iterator.Valid() {
break
}
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
key := GetUBDKeyFromValIndexKey(iterator.Key())
value := store.Get(key)
ubd := types.MustUnmarshalUBD(k.cdc, key, value)
ubds = append(ubds, ubd)
iterator.Next()
}
iterator.Close()
return ubds
}
@ -116,16 +126,15 @@ func (k Keeper) GetUnbondingDelegationsFromValidator(ctx sdk.Context, valAddr sd
func (k Keeper) IterateUnbondingDelegations(ctx sdk.Context, fn func(index int64, ubd types.UnbondingDelegation) (stop bool)) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, UnbondingDelegationKey)
i := int64(0)
for ; iterator.Valid(); iterator.Next() {
defer iterator.Close()
for i := int64(0); iterator.Valid(); iterator.Next() {
ubd := types.MustUnmarshalUBD(k.cdc, iterator.Key(), iterator.Value())
stop := fn(i, ubd)
if stop {
if stop := fn(i, ubd); stop {
break
}
i++
}
iterator.Close()
}
// set the unbonding delegation and associated index
@ -147,7 +156,26 @@ func (k Keeper) RemoveUnbondingDelegation(ctx sdk.Context, ubd types.UnbondingDe
//_____________________________________________________________________________________
// load a redelegation
// return a given amount of all the delegator redelegations
func (k Keeper) GetRedelegations(ctx sdk.Context, delegator sdk.AccAddress,
maxRetrieve uint16) (redelegations []types.Redelegation) {
redelegations = make([]types.Redelegation, maxRetrieve)
store := ctx.KVStore(k.storeKey)
delegatorPrefixKey := GetREDsKey(delegator)
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey)
defer iterator.Close()
i := 0
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
redelegation := types.MustUnmarshalRED(k.cdc, iterator.Key(), iterator.Value())
redelegations[i] = redelegation
i++
}
return redelegations[:i] // trim if the array length < maxRetrieve
}
// return a redelegation
func (k Keeper) GetRedelegation(ctx sdk.Context,
delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) (red types.Redelegation, found bool) {
@ -162,38 +190,34 @@ func (k Keeper) GetRedelegation(ctx sdk.Context,
return red, true
}
// load all redelegations from a particular validator
// return all redelegations from a particular validator
func (k Keeper) GetRedelegationsFromValidator(ctx sdk.Context, valAddr sdk.ValAddress) (reds []types.Redelegation) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, GetREDsFromValSrcIndexKey(valAddr))
for {
if !iterator.Valid() {
break
}
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
key := GetREDKeyFromValSrcIndexKey(iterator.Key())
value := store.Get(key)
red := types.MustUnmarshalRED(k.cdc, key, value)
reds = append(reds, red)
iterator.Next()
}
iterator.Close()
return reds
}
// has a redelegation
// check if validator is receiving a redelegation
func (k Keeper) HasReceivingRedelegation(ctx sdk.Context,
delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) bool {
store := ctx.KVStore(k.storeKey)
prefix := GetREDsByDelToValDstIndexKey(delAddr, valDstAddr)
iterator := sdk.KVStorePrefixIterator(store, prefix) //smallest to largest
iterator := sdk.KVStorePrefixIterator(store, prefix)
defer iterator.Close()
found := false
if iterator.Valid() {
//record found
found = true
}
iterator.Close()
return found
}
@ -358,7 +382,7 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context,
// create the unbonding delegation
params := k.GetParams(ctx)
minTime, height, completeNow := k.getBeginInfo(ctx, params, valAddr)
balance := sdk.Coin{params.BondDenom, returnAmount.RoundInt()}
balance := sdk.NewCoin(params.BondDenom, returnAmount.RoundInt())
// no need to create the ubd object just complete now
if completeNow {
@ -418,7 +442,7 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress,
}
params := k.GetParams(ctx)
returnCoin := sdk.Coin{params.BondDenom, returnAmount.RoundInt()}
returnCoin := sdk.NewCoin(params.BondDenom, returnAmount.RoundInt())
dstValidator, found := k.GetValidator(ctx, valDstAddr)
if !found {
return types.ErrBadRedelegationDst(k.Codespace())

View File

@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
)
// tests GetDelegation, GetDelegations, SetDelegation, RemoveDelegation, GetDelegations
// tests GetDelegation, GetDelegatorDelegations, SetDelegation, RemoveDelegation, GetDelegatorDelegations
func TestDelegation(t *testing.T) {
ctx, _, keeper := CreateTestInput(t, false, 10)
pool := keeper.GetPool(ctx)
@ -30,6 +30,7 @@ func TestDelegation(t *testing.T) {
validators[2] = keeper.UpdateValidator(ctx, validators[2])
// first add a validators[0] to delegate too
bond1to1 := types.Delegation{
DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[0],
@ -66,16 +67,16 @@ func TestDelegation(t *testing.T) {
keeper.SetDelegation(ctx, bond2to3)
// test all bond retrieve capabilities
resBonds := keeper.GetDelegations(ctx, addrDels[0], 5)
resBonds := keeper.GetDelegatorDelegations(ctx, addrDels[0], 5)
require.Equal(t, 3, len(resBonds))
require.True(t, bond1to1.Equal(resBonds[0]))
require.True(t, bond1to2.Equal(resBonds[1]))
require.True(t, bond1to3.Equal(resBonds[2]))
resBonds = keeper.GetDelegations(ctx, addrDels[0], 3)
resBonds = keeper.GetAllDelegatorDelegations(ctx, addrDels[0])
require.Equal(t, 3, len(resBonds))
resBonds = keeper.GetDelegations(ctx, addrDels[0], 2)
resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[0], 2)
require.Equal(t, 2, len(resBonds))
resBonds = keeper.GetDelegations(ctx, addrDels[1], 5)
resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
require.Equal(t, 3, len(resBonds))
require.True(t, bond2to1.Equal(resBonds[0]))
require.True(t, bond2to2.Equal(resBonds[1]))
@ -89,15 +90,34 @@ func TestDelegation(t *testing.T) {
require.True(t, bond2to2.Equal(allBonds[4]))
require.True(t, bond2to3.Equal(allBonds[5]))
resVals := keeper.GetDelegatorValidators(ctx, addrDels[0], 3)
require.Equal(t, 3, len(resVals))
resVals = keeper.GetDelegatorValidators(ctx, addrDels[1], 4)
require.Equal(t, 3, len(resVals))
for i := 0; i < 3; i++ {
resVal, err := keeper.GetDelegatorValidator(ctx, addrDels[0], addrVals[i])
require.Nil(t, err)
require.Equal(t, addrVals[i], resVal.GetOperator())
resVal, err = keeper.GetDelegatorValidator(ctx, addrDels[1], addrVals[i])
require.Nil(t, err)
require.Equal(t, addrVals[i], resVal.GetOperator())
}
// delete a record
keeper.RemoveDelegation(ctx, bond2to3)
_, found = keeper.GetDelegation(ctx, addrDels[1], addrVals[2])
require.False(t, found)
resBonds = keeper.GetDelegations(ctx, addrDels[1], 5)
resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
require.Equal(t, 2, len(resBonds))
require.True(t, bond2to1.Equal(resBonds[0]))
require.True(t, bond2to2.Equal(resBonds[1]))
resBonds = keeper.GetAllDelegatorDelegations(ctx, addrDels[1])
require.Equal(t, 2, len(resBonds))
// delete all the records from delegator 2
keeper.RemoveDelegation(ctx, bond2to1)
keeper.RemoveDelegation(ctx, bond2to2)
@ -105,7 +125,7 @@ func TestDelegation(t *testing.T) {
require.False(t, found)
_, found = keeper.GetDelegation(ctx, addrDels[1], addrVals[1])
require.False(t, found)
resBonds = keeper.GetDelegations(ctx, addrDels[1], 5)
resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
require.Equal(t, 0, len(resBonds))
}
@ -123,21 +143,35 @@ func TestUnbondingDelegation(t *testing.T) {
// set and retrieve a record
keeper.SetUnbondingDelegation(ctx, ubd)
resBond, found := keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
resUnbond, found := keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
require.True(t, found)
require.True(t, ubd.Equal(resBond))
require.True(t, ubd.Equal(resUnbond))
// modify a records, save, and retrieve
ubd.Balance = sdk.NewInt64Coin("steak", 21)
keeper.SetUnbondingDelegation(ctx, ubd)
resBond, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
resUnbonds := keeper.GetUnbondingDelegations(ctx, addrDels[0], 5)
require.Equal(t, 1, len(resUnbonds))
resUnbonds = keeper.GetAllUnbondingDelegations(ctx, addrDels[0])
require.Equal(t, 1, len(resUnbonds))
resUnbond, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
require.True(t, found)
require.True(t, ubd.Equal(resBond))
require.True(t, ubd.Equal(resUnbond))
// delete a record
keeper.RemoveUnbondingDelegation(ctx, ubd)
_, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
require.False(t, found)
resUnbonds = keeper.GetUnbondingDelegations(ctx, addrDels[0], 5)
require.Equal(t, 0, len(resUnbonds))
resUnbonds = keeper.GetAllUnbondingDelegations(ctx, addrDels[0])
require.Equal(t, 0, len(resUnbonds))
}
func TestUnbondDelegation(t *testing.T) {
@ -413,12 +447,20 @@ func TestRedelegation(t *testing.T) {
// set and retrieve a record
keeper.SetRedelegation(ctx, rd)
resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
resRed, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.True(t, found)
redelegations := keeper.GetRedelegationsFromValidator(ctx, addrVals[0])
require.Equal(t, 1, len(redelegations))
require.True(t, redelegations[0].Equal(resBond))
require.True(t, redelegations[0].Equal(resRed))
redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5)
require.Equal(t, 1, len(redelegations))
require.True(t, redelegations[0].Equal(resRed))
redelegations = keeper.GetAllRedelegations(ctx, addrDels[0])
require.Equal(t, 1, len(redelegations))
require.True(t, redelegations[0].Equal(resRed))
// check if has the redelegation
has = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1])
@ -429,18 +471,28 @@ func TestRedelegation(t *testing.T) {
rd.SharesDst = sdk.NewDec(21)
keeper.SetRedelegation(ctx, rd)
resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
resRed, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.True(t, found)
require.True(t, rd.Equal(resBond))
require.True(t, rd.Equal(resRed))
redelegations = keeper.GetRedelegationsFromValidator(ctx, addrVals[0])
require.Equal(t, 1, len(redelegations))
require.True(t, redelegations[0].Equal(resBond))
require.True(t, redelegations[0].Equal(resRed))
redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5)
require.Equal(t, 1, len(redelegations))
require.True(t, redelegations[0].Equal(resRed))
// delete a record
keeper.RemoveRedelegation(ctx, rd)
_, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
require.False(t, found)
redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5)
require.Equal(t, 0, len(redelegations))
redelegations = keeper.GetAllRedelegations(ctx, addrDels[0])
require.Equal(t, 0, len(redelegations))
}
func TestRedelegateSelfDelegation(t *testing.T) {

View File

@ -0,0 +1,101 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
// Return all validators that a delegator is bonded to. If maxRetrieve is supplied, the respective amount will be returned.
func (k Keeper) GetDelegatorValidators(ctx sdk.Context, delegatorAddr sdk.AccAddress,
maxRetrieve uint16) (validators []types.Validator) {
validators = make([]types.Validator, maxRetrieve)
store := ctx.KVStore(k.storeKey)
delegatorPrefixKey := GetDelegationsKey(delegatorAddr)
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest
defer iterator.Close()
i := 0
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
addr := iterator.Key()
delegation := types.MustUnmarshalDelegation(k.cdc, addr, iterator.Value())
validator, found := k.GetValidator(ctx, delegation.ValidatorAddr)
if !found {
panic(types.ErrNoValidatorFound(types.DefaultCodespace))
}
validators[i] = validator
i++
}
return validators[:i] // trim
}
// return a validator that a delegator is bonded to
func (k Keeper) GetDelegatorValidator(ctx sdk.Context, delegatorAddr sdk.AccAddress,
validatorAddr sdk.ValAddress) (validator types.Validator, err sdk.Error) {
delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr)
if !found {
return validator, types.ErrNoDelegation(types.DefaultCodespace)
}
validator, found = k.GetValidator(ctx, delegation.ValidatorAddr)
if !found {
panic(types.ErrNoValidatorFound(types.DefaultCodespace))
}
return
}
//_____________________________________________________________________________________
// return all delegations for a delegator
func (k Keeper) GetAllDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress) (
delegations []types.Delegation) {
store := ctx.KVStore(k.storeKey)
delegatorPrefixKey := GetDelegationsKey(delegator)
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest
defer iterator.Close()
i := 0
for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value())
delegations = append(delegations, delegation)
i++
}
return delegations
}
// return all unbonding-delegations for a delegator
func (k Keeper) GetAllUnbondingDelegations(ctx sdk.Context, delegator sdk.AccAddress) (
unbondingDelegations []types.UnbondingDelegation) {
store := ctx.KVStore(k.storeKey)
delegatorPrefixKey := GetUBDsKey(delegator)
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest
defer iterator.Close()
i := 0
for ; iterator.Valid(); iterator.Next() {
unbondingDelegation := types.MustUnmarshalUBD(k.cdc, iterator.Key(), iterator.Value())
unbondingDelegations = append(unbondingDelegations, unbondingDelegation)
i++
}
return unbondingDelegations
}
// return all redelegations for a delegator
func (k Keeper) GetAllRedelegations(ctx sdk.Context, delegator sdk.AccAddress) (redelegations []types.Redelegation) {
store := ctx.KVStore(k.storeKey)
delegatorPrefixKey := GetREDsKey(delegator)
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest
defer iterator.Close()
i := 0
for ; iterator.Valid(); iterator.Next() {
redelegation := types.MustUnmarshalRED(k.cdc, iterator.Key(), iterator.Value())
redelegations = append(redelegations, redelegation)
i++
}
return redelegations
}

View File

@ -103,39 +103,32 @@ func (k Keeper) validatorByPowerIndexExists(ctx sdk.Context, power []byte) bool
func (k Keeper) GetAllValidators(ctx sdk.Context) (validators []types.Validator) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, ValidatorsKey)
defer iterator.Close()
i := 0
for ; ; i++ {
if !iterator.Valid() {
break
}
for ; iterator.Valid(); iterator.Next() {
addr := iterator.Key()[1:]
validator := types.MustUnmarshalValidator(k.cdc, addr, iterator.Value())
validators = append(validators, validator)
iterator.Next()
}
iterator.Close()
return validators
}
// Get the set of all validators, retrieve a maxRetrieve number of records
func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve int16) (validators []types.Validator) {
// return a given amount of all the validators
func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve uint16) (validators []types.Validator) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, ValidatorsKey)
validators = make([]types.Validator, maxRetrieve)
iterator := sdk.KVStorePrefixIterator(store, ValidatorsKey)
defer iterator.Close()
i := 0
for ; ; i++ {
if !iterator.Valid() || i > int(maxRetrieve-1) {
break
}
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
addr := iterator.Key()[1:]
validator := types.MustUnmarshalValidator(k.cdc, addr, iterator.Value())
validators[i] = validator
iterator.Next()
i++
}
iterator.Close()
return validators[:i] // trim
return validators[:i] // trim if the array length < maxRetrieve
}
//___________________________________________________________________________
@ -149,6 +142,8 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat
validators = make([]types.Validator, maxValidators)
iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey)
defer iterator.Close()
i := 0
for ; iterator.Valid(); iterator.Next() {
@ -163,7 +158,6 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat
validators[i] = validator
i++
}
iterator.Close()
return validators[:i] // trim
}
@ -174,12 +168,12 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator {
store := ctx.KVStore(k.storeKey)
maxValidators := k.GetParams(ctx).MaxValidators
validators := make([]types.Validator, maxValidators)
iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey) // largest to smallest
iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
defer iterator.Close()
i := 0
for {
if !iterator.Valid() || i > int(maxValidators-1) {
break
}
for ; iterator.Valid() && i < int(maxValidators); iterator.Next() {
address := iterator.Value()
validator, found := k.GetValidator(ctx, address)
ensureValidatorFound(found, address)
@ -188,9 +182,7 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator {
validators[i] = validator
i++
}
iterator.Next()
}
iterator.Close()
return validators[:i] // trim
}
@ -206,6 +198,8 @@ func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Valid
tstore := ctx.TransientStore(k.storeTKey)
iterator := sdk.KVStorePrefixIterator(tstore, TendermintUpdatesTKey)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var abciVal abci.Validator
@ -228,8 +222,6 @@ func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Valid
updates = append(updates, abciVal)
}
}
iterator.Close()
return
}
@ -447,10 +439,7 @@ func (k Keeper) UpdateBondedValidators(
// create a validator iterator ranging from largest to smallest by power
iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
for {
if !iterator.Valid() || bondedValidatorsCount > int(maxValidators-1) {
break
}
for ; iterator.Valid() && bondedValidatorsCount < int(maxValidators); iterator.Next() {
// either retrieve the original validator from the store, or under the
// situation that this is the "affected validator" just use the
@ -484,7 +473,6 @@ func (k Keeper) UpdateBondedValidators(
}
bondedValidatorsCount++
iterator.Next()
}
iterator.Close()
@ -551,11 +539,7 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
bondedValidatorsCount := 0
iterator = sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
for {
if !iterator.Valid() || bondedValidatorsCount > int(maxValidators-1) {
break
}
for ; iterator.Valid() && bondedValidatorsCount < int(maxValidators); iterator.Next() {
var found bool
ownerAddr := iterator.Value()
@ -578,12 +562,10 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
if validator.Status == sdk.Bonded {
panic(fmt.Sprintf("jailed validator cannot be bonded for address: %s\n", ownerAddr))
}
break
}
bondedValidatorsCount++
iterator.Next()
}
iterator.Close()

View File

@ -59,11 +59,22 @@ func TestSetValidator(t *testing.T) {
resVals = keeper.GetValidatorsByPower(ctx)
require.Equal(t, 1, len(resVals))
assert.True(ValEq(t, validator, resVals[0]))
require.True(ValEq(t, validator, resVals[0]))
resVals = keeper.GetValidators(ctx, 1)
require.Equal(t, 1, len(resVals))
require.True(ValEq(t, validator, resVals[0]))
resVals = keeper.GetValidators(ctx, 10)
require.Equal(t, 1, len(resVals))
require.True(ValEq(t, validator, resVals[0]))
updates := keeper.GetValidTendermintUpdates(ctx)
require.Equal(t, 1, len(updates))
require.Equal(t, validator.ABCIValidator(), updates[0])
allVals := keeper.GetAllValidators(ctx)
require.Equal(t, 1, len(allVals))
}
func TestUpdateValidatorByPowerIndex(t *testing.T) {
@ -283,7 +294,10 @@ func TestValidatorBasics(t *testing.T) {
_, found := keeper.GetValidator(ctx, addrVals[0])
require.False(t, found)
resVals := keeper.GetValidatorsBonded(ctx)
assert.Zero(t, len(resVals))
require.Zero(t, len(resVals))
resVals = keeper.GetValidators(ctx, 2)
require.Zero(t, len(resVals))
pool = keeper.GetPool(ctx)
assert.True(sdk.DecEq(t, sdk.ZeroDec(), pool.BondedTokens))

View File

@ -0,0 +1,227 @@
package querier
import (
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
keep "github.com/cosmos/cosmos-sdk/x/stake/keeper"
"github.com/cosmos/cosmos-sdk/x/stake/types"
abci "github.com/tendermint/tendermint/abci/types"
)
// query endpoints supported by the staking Querier
const (
QueryValidators = "validators"
QueryValidator = "validator"
QueryDelegator = "delegator"
QueryDelegation = "delegation"
QueryUnbondingDelegation = "unbondingDelegation"
QueryDelegatorValidators = "delegatorValidators"
QueryDelegatorValidator = "delegatorValidator"
QueryPool = "pool"
QueryParameters = "parameters"
)
// creates a querier for staking REST endpoints
func NewQuerier(k keep.Keeper, cdc *codec.Codec) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
switch path[0] {
case QueryValidators:
return queryValidators(ctx, cdc, k)
case QueryValidator:
return queryValidator(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 QueryDelegatorValidators:
return queryDelegatorValidators(ctx, cdc, req, k)
case QueryDelegatorValidator:
return queryDelegatorValidator(ctx, cdc, req, k)
case QueryPool:
return queryPool(ctx, cdc, k)
case QueryParameters:
return queryParameters(ctx, cdc, k)
default:
return nil, sdk.ErrUnknownRequest("unknown stake query endpoint")
}
}
}
// defines the params for the following queries:
// - 'custom/stake/delegator'
// - 'custom/stake/delegatorValidators'
type QueryDelegatorParams struct {
DelegatorAddr sdk.AccAddress
}
// defines the params for the following queries:
// - 'custom/stake/validator'
type QueryValidatorParams struct {
ValidatorAddr sdk.ValAddress
}
// defines the params for the following queries:
// - 'custom/stake/delegation'
// - 'custom/stake/unbondingDelegation'
// - 'custom/stake/delegatorValidator'
type QueryBondsParams struct {
DelegatorAddr sdk.AccAddress
ValidatorAddr 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)
res, errRes := codec.MarshalJSONIndent(cdc, validators)
if err != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error()))
}
return res, nil
}
func queryValidator(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(fmt.Sprintf("incorrectly formatted request address: %s", err.Error()))
}
validator, found := k.GetValidator(ctx, params.ValidatorAddr)
if !found {
return []byte{}, types.ErrNoValidatorFound(types.DefaultCodespace)
}
res, errRes = codec.MarshalJSONIndent(cdc, validator)
if errRes != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error()))
}
return res, nil
}
func queryDelegator(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, &params)
if errRes != nil {
return []byte{}, sdk.ErrUnknownAddress(fmt.Sprintf("incorrectly formatted request address: %s", errRes.Error()))
}
delegations := k.GetAllDelegatorDelegations(ctx, params.DelegatorAddr)
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, summary)
if errRes != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error()))
}
return res, nil
}
func queryDelegatorValidators(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) {
var params QueryDelegatorParams
stakeParams := k.GetParams(ctx)
errRes := cdc.UnmarshalJSON(req.Data, &params)
if errRes != nil {
return []byte{}, sdk.ErrUnknownAddress(fmt.Sprintf("incorrectly formatted request address: %s", errRes.Error()))
}
validators := k.GetDelegatorValidators(ctx, params.DelegatorAddr, stakeParams.MaxValidators)
res, errRes = codec.MarshalJSONIndent(cdc, validators)
if errRes != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error()))
}
return res, nil
}
func queryDelegatorValidator(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) {
var params QueryBondsParams
errRes := cdc.UnmarshalJSON(req.Data, &params)
if errRes != nil {
return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request address: %s", errRes.Error()))
}
validator, err := k.GetDelegatorValidator(ctx, params.DelegatorAddr, params.ValidatorAddr)
if err != nil {
return
}
res, errRes = codec.MarshalJSONIndent(cdc, validator)
if errRes != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error()))
}
return res, nil
}
func queryDelegation(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) {
var params QueryBondsParams
errRes := cdc.UnmarshalJSON(req.Data, &params)
if errRes != nil {
return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request address: %s", errRes.Error()))
}
delegation, found := k.GetDelegation(ctx, params.DelegatorAddr, params.ValidatorAddr)
if !found {
return []byte{}, types.ErrNoDelegation(types.DefaultCodespace)
}
res, errRes = codec.MarshalJSONIndent(cdc, delegation)
if errRes != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error()))
}
return res, nil
}
func queryUnbondingDelegation(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) {
var params QueryBondsParams
errRes := cdc.UnmarshalJSON(req.Data, &params)
if errRes != nil {
return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request address: %s", errRes.Error()))
}
unbond, found := k.GetUnbondingDelegation(ctx, params.DelegatorAddr, params.ValidatorAddr)
if !found {
return []byte{}, types.ErrNoUnbondingDelegation(types.DefaultCodespace)
}
res, errRes = codec.MarshalJSONIndent(cdc, unbond)
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)
res, errRes := codec.MarshalJSONIndent(cdc, pool)
if errRes != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error()))
}
return res, nil
}
func queryParameters(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []byte, err sdk.Error) {
params := k.GetParams(ctx)
res, errRes := codec.MarshalJSONIndent(cdc, params)
if errRes != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", errRes.Error()))
}
return res, nil
}

View File

@ -0,0 +1,215 @@
package querier
import (
"testing"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
keep "github.com/cosmos/cosmos-sdk/x/stake/keeper"
"github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
)
var (
addrAcc1, addrAcc2 = keep.Addrs[0], keep.Addrs[1]
addrVal1, addrVal2 = sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1])
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 TestQueryParametersPool(t *testing.T) {
cdc := codec.New()
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
res, err := queryParameters(ctx, cdc, keeper)
require.Nil(t, err)
var params types.Params
errRes := cdc.UnmarshalJSON(res, &params)
require.Nil(t, errRes)
require.Equal(t, keeper.GetParams(ctx), params)
res, err = queryPool(ctx, cdc, keeper)
require.Nil(t, err)
var pool types.Pool
errRes = cdc.UnmarshalJSON(res, &pool)
require.Nil(t, errRes)
require.Equal(t, keeper.GetPool(ctx), pool)
}
func TestQueryValidators(t *testing.T) {
cdc := codec.New()
ctx, _, keeper := keep.CreateTestInput(t, false, 10000)
pool := keeper.GetPool(ctx)
params := keeper.GetParams(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 Validators
queriedValidators := keeper.GetValidators(ctx, params.MaxValidators)
res, err := queryValidators(ctx, cdc, keeper)
require.Nil(t, err)
var validatorsResp []types.Validator
errRes := cdc.UnmarshalJSON(res, &validatorsResp)
require.Nil(t, errRes)
require.Equal(t, len(queriedValidators), len(validatorsResp))
require.ElementsMatch(t, queriedValidators, validatorsResp)
// Query each validator
queryParams := newTestValidatorQuery(addrVal1)
bz, errRes := cdc.MarshalJSON(queryParams)
require.Nil(t, errRes)
query := abci.RequestQuery{
Path: "/custom/stake/validator",
Data: bz,
}
res, err = queryValidator(ctx, cdc, query, keeper)
require.Nil(t, err)
var validator types.Validator
errRes = cdc.UnmarshalJSON(res, &validator)
require.Nil(t, errRes)
require.Equal(t, queriedValidators[0], validator)
}
func TestQueryDelegation(t *testing.T) {
cdc := codec.New()
ctx, _, keeper := keep.CreateTestInput(t, false, 10000)
params := keeper.GetParams(ctx)
// Create Validators and Delegation
val1 := types.NewValidator(addrVal1, pk1, types.Description{})
keeper.SetValidator(ctx, val1)
keeper.Delegate(ctx, addrAcc2, sdk.NewCoin("steak", sdk.NewInt(20)), val1, true)
// Query Delegator bonded validators
queryParams := newTestDelegatorQuery(addrAcc2)
bz, errRes := cdc.MarshalJSON(queryParams)
require.Nil(t, errRes)
query := abci.RequestQuery{
Path: "/custom/stake/delegatorValidators",
Data: bz,
}
delValidators := keeper.GetDelegatorValidators(ctx, addrAcc2, params.MaxValidators)
res, err := queryDelegatorValidators(ctx, cdc, query, keeper)
require.Nil(t, err)
var validatorsResp []types.Validator
errRes = cdc.UnmarshalJSON(res, &validatorsResp)
require.Nil(t, errRes)
require.Equal(t, len(delValidators), len(validatorsResp))
require.ElementsMatch(t, delValidators, validatorsResp)
// Query bonded validator
queryBondParams := newTestBondQuery(addrAcc2, addrVal1)
bz, errRes = cdc.MarshalJSON(queryBondParams)
require.Nil(t, errRes)
query = abci.RequestQuery{
Path: "/custom/stake/delegatorValidator",
Data: bz,
}
res, err = queryDelegatorValidator(ctx, cdc, query, keeper)
require.Nil(t, err)
var validator types.Validator
errRes = cdc.UnmarshalJSON(res, &validator)
require.Nil(t, errRes)
require.Equal(t, delValidators[0], validator)
// Query delegation
query = abci.RequestQuery{
Path: "/custom/stake/delegation",
Data: bz,
}
delegation, found := keeper.GetDelegation(ctx, addrAcc2, addrVal1)
require.True(t, found)
res, err = queryDelegation(ctx, cdc, query, keeper)
require.Nil(t, err)
var delegationRes types.Delegation
errRes = cdc.UnmarshalJSON(res, &delegationRes)
require.Nil(t, errRes)
require.Equal(t, delegation, delegationRes)
// Query unbonging delegation
keeper.BeginUnbonding(ctx, addrAcc2, val1.OperatorAddr, sdk.NewDec(10))
query = abci.RequestQuery{
Path: "/custom/stake/unbondingDelegation",
Data: bz,
}
unbond, found := keeper.GetUnbondingDelegation(ctx, addrAcc2, addrVal1)
require.True(t, found)
res, err = queryUnbondingDelegation(ctx, cdc, query, keeper)
require.Nil(t, err)
var unbondRes types.UnbondingDelegation
errRes = cdc.UnmarshalJSON(res, &unbondRes)
require.Nil(t, errRes)
require.Equal(t, unbond, unbondRes)
// Query Delegator Summary
query = abci.RequestQuery{
Path: "/custom/stake/delegator",
Data: bz,
}
res, err = queryDelegator(ctx, cdc, query, keeper)
require.Nil(t, err)
var summary types.DelegationSummary
errRes = cdc.UnmarshalJSON(res, &summary)
require.Nil(t, errRes)
require.Equal(t, unbond, summary.UnbondingDelegations[0])
}

View File

@ -3,6 +3,7 @@ package stake
import (
"github.com/cosmos/cosmos-sdk/x/stake/keeper"
"github.com/cosmos/cosmos-sdk/x/stake/querier"
"github.com/cosmos/cosmos-sdk/x/stake/tags"
"github.com/cosmos/cosmos-sdk/x/stake/types"
)
@ -12,6 +13,7 @@ type (
Validator = types.Validator
Description = types.Description
Delegation = types.Delegation
DelegationSummary = types.DelegationSummary
UnbondingDelegation = types.UnbondingDelegation
Redelegation = types.Redelegation
Params = types.Params
@ -24,6 +26,9 @@ type (
MsgBeginRedelegate = types.MsgBeginRedelegate
MsgCompleteRedelegate = types.MsgCompleteRedelegate
GenesisState = types.GenesisState
QueryDelegatorParams = querier.QueryDelegatorParams
QueryValidatorParams = querier.QueryValidatorParams
QueryBondsParams = querier.QueryBondsParams
)
var (
@ -75,6 +80,8 @@ var (
NewMsgCompleteUnbonding = types.NewMsgCompleteUnbonding
NewMsgBeginRedelegate = types.NewMsgBeginRedelegate
NewMsgCompleteRedelegate = types.NewMsgCompleteRedelegate
NewQuerier = querier.NewQuerier
)
const (

View File

@ -24,6 +24,13 @@ 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{