Release v0.34.2

* Merge PR #4163: Fix v0.33.x export script to port gov data correctly

* Remove TOC

* Add missing changelog entry for v0.34.1

* Merge PR #4182: Cherry pick #4083 into v0.34.2

* Merge PR #4181: Cherry pick 4135 v0.34.2

* Merge PR #4183: Cherry pick 4181 into v0.34.2 

* Support pagination and status query params for /staking/validators

* Rename BondStatusToString to String

* Cherry pick 4181

* Remove pending log

* Fix CODEOWNERS
This commit is contained in:
Alexander Bezobchuk 2019-04-25 17:30:24 -04:00 committed by Jack Zampolin
parent bfb2b49b09
commit 13bd5b62cf
31 changed files with 251 additions and 100 deletions

7
.github/CODEOWNERS vendored
View File

@ -1,9 +1,4 @@
# CODEOWNERS: https://help.github.com/articles/about-codeowners/
# Primary repo maintainers
* @ebuchman @rigelrozanski @cwgoes
# Precious documentation
/docs/README.md @zramsay
/docs/DOCS_README.md @zramsay
/docs/.vuepress/ @zramsay
* @alessio @alexanderbez @cwgoes @jackzampolin

View File

@ -1,30 +1,31 @@
# Changelog
* [0.34.0](#0340)
* [Breaking Changes](#breaking-changes)
* [Gaia](#gaia)
* [Gaia CLI](#gaia-cli)
* [SDK](#sdk)
* [Tendermint](#tendermint)
* [New features](#new-features)
* [SDK](#sdk-1)
* [Gaia](#gaia-1)
* [Gaia CLI](#gaia-cli-1)
* [Gaia REST API](#gaia-rest-api)
* [Improvements](#improvements)
* [Gaia](#gaia-2)
* [Gaia CLI](#gaia-cli-2)
* [SDK](#sdk-2)
* [Bug Fixes](#bug-fixes)
* [Gaia](#gaia-3)
* [Gaia CLI](#gaia-cli-3)
* [SDK](#sdk-3)
* [0.33.2](#0332)
* [Improvements](#improvements-1)
* [Tendermint](#tendermint-1)
* [0.33.1](#0331)
* [Bug Fixes](#bug-fixes-1)
* [Gaia](#gaia-4)
## 0.34.2
### Improvements
#### SDK
* [\#4135](https://github.com/cosmos/cosmos-sdk/pull/4135) Add further clarification
to generate only usage.
### Bug Fixes
#### SDK
* [\#4135](https://github.com/cosmos/cosmos-sdk/pull/4135) Fix `NewResponseFormatBroadcastTxCommit`
* [\#4053](https://github.com/cosmos/cosmos-sdk/issues/4053) Add `--inv-check-period`
flag to gaiad to set period at which invariants checks will run.
* [\#4099](https://github.com/cosmos/cosmos-sdk/issues/4099) Update the /staking/validators endpoint to support
status and pagination query flags.
## 0.34.1
### Bug Fixes
#### Gaia
* [#4163](https://github.com/cosmos/cosmos-sdk/pull/4163) Fix v0.33.x export script to port gov data correctly.
## 0.34.0

View File

@ -9,7 +9,7 @@ import (
"github.com/tendermint/tendermint/libs/cli"
"github.com/pelletier/go-toml"
toml "github.com/pelletier/go-toml"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

View File

@ -7,6 +7,8 @@ import (
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/codec"
@ -292,7 +294,7 @@ func GetFromFields(from string, genOnly bool) (sdk.AccAddress, string, error) {
if genOnly {
addr, err := sdk.AccAddressFromBech32(from)
if err != nil {
return nil, "", err
return nil, "", errors.Wrap(err, "must provide a valid Bech32 address for generate-only")
}
return addr, "", nil

View File

@ -93,7 +93,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
c.Flags().Bool(FlagPrintResponse, true, "return tx response (only works with async = false)")
c.Flags().Bool(FlagTrustNode, true, "Trust connected full node (don't verify proofs for responses)")
c.Flags().Bool(FlagDryRun, false, "ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it")
c.Flags().Bool(FlagGenerateOnly, false, "build an unsigned transaction and write it to STDOUT")
c.Flags().Bool(FlagGenerateOnly, false, "Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase is not accessible)")
c.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation")
// --gas can accept integers and "simulate"

View File

@ -763,7 +763,23 @@ paths:
description: Internal Server Error
/staking/validators:
get:
summary: Get all validator candidates
summary: Get all validator candidates. By default it returns only the bonded validators.
parameters:
- in: query
name: status
type: string
description: The validator bond status. Must be either 'bonded', 'unbonded', or 'unbonding'.
x-example: bonded
- in: query
name: page
description: The gage number.
type: integer
x-example: 1
- in: query
name: limit
description: The maximum number of items per page.
type: integer
x-example: 1
tags:
- ICS21
produces:

View File

@ -221,7 +221,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress
privVal.Reset()
db := dbm.NewMemDB()
app := gapp.NewGaiaApp(logger, db, nil, true, false)
app := gapp.NewGaiaApp(logger, db, nil, true, 0)
cdc = gapp.MakeCodec()
genesisFile := config.GenesisFile()

View File

@ -1,7 +1,7 @@
package rpc
import (
"github.com/tendermint/go-amino"
amino "github.com/tendermint/go-amino"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
)

View File

@ -162,7 +162,6 @@ func QueryTxsByTagsRequestHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec)
}
tags, page, limit, err = rest.ParseHTTPArgs(r)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return

View File

@ -42,7 +42,7 @@ type GaiaApp struct {
*bam.BaseApp
cdc *codec.Codec
assertInvariantsBlockly bool
invCheckPeriod uint
// keys to access the substores
keyMain *sdk.KVStoreKey
@ -72,7 +72,8 @@ type GaiaApp struct {
}
// NewGaiaApp returns a reference to an initialized GaiaApp.
func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest, assertInvariantsBlockly bool,
func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
invCheckPeriod uint,
baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {
cdc := MakeCodec()
@ -83,6 +84,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest,
var app = &GaiaApp{
BaseApp: bApp,
cdc: cdc,
invCheckPeriod: invCheckPeriod,
keyMain: sdk.NewKVStoreKey(bam.MainStoreKey),
keyAccount: sdk.NewKVStoreKey(auth.StoreKey),
keyStaking: sdk.NewKVStoreKey(staking.StoreKey),
@ -244,7 +246,7 @@ func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.R
validatorUpdates, endBlockerTags := staking.EndBlocker(ctx, app.stakingKeeper)
tags = append(tags, endBlockerTags...)
if app.assertInvariantsBlockly {
if app.invCheckPeriod != 0 && ctx.BlockHeight()%int64(app.invCheckPeriod) == 0 {
app.assertRuntimeInvariants()
}

View File

@ -55,11 +55,11 @@ func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error {
func TestGaiadExport(t *testing.T) {
db := db.NewMemDB()
gapp := NewGaiaApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, false)
gapp := NewGaiaApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, 0)
setGenesis(gapp)
// Making a new app object with the db, so that initchain hasn't been called
newGapp := NewGaiaApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, false)
newGapp := NewGaiaApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, 0)
_, _, err := newGapp.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
}

View File

@ -26,5 +26,6 @@ func (app *GaiaApp) assertRuntimeInvariantsOnContext(ctx sdk.Context) {
}
end := time.Now()
diff := end.Sub(start)
app.BaseApp.Logger().With("module", "invariants").Info("Asserted all invariants", "duration", diff)
app.BaseApp.Logger().With("module", "invariants").Info(
"Asserted all invariants", "duration", diff, "height", app.LastBlockHeight())
}

View File

@ -319,7 +319,7 @@ func BenchmarkFullGaiaSimulation(b *testing.B) {
db.Close()
os.RemoveAll(dir)
}()
app := NewGaiaApp(logger, db, nil, true, false)
app := NewGaiaApp(logger, db, nil, true, 0)
// Run randomized simulation
// TODO parameterize numbers, save for a later PR
@ -354,7 +354,7 @@ func TestFullGaiaSimulation(t *testing.T) {
db.Close()
os.RemoveAll(dir)
}()
app := NewGaiaApp(logger, db, nil, true, false, fauxMerkleModeOpt)
app := NewGaiaApp(logger, db, nil, true, 0, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", app.Name())
// Run randomized simulation
@ -388,7 +388,7 @@ func TestGaiaImportExport(t *testing.T) {
db.Close()
os.RemoveAll(dir)
}()
app := NewGaiaApp(logger, db, nil, true, false, fauxMerkleModeOpt)
app := NewGaiaApp(logger, db, nil, true, 0, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", app.Name())
// Run randomized simulation
@ -415,7 +415,7 @@ func TestGaiaImportExport(t *testing.T) {
newDB.Close()
os.RemoveAll(newDir)
}()
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil, true, false, fauxMerkleModeOpt)
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", newApp.Name())
var genesisState GenesisState
err = app.cdc.UnmarshalJSON(appState, &genesisState)
@ -478,7 +478,7 @@ func TestGaiaSimulationAfterImport(t *testing.T) {
db.Close()
os.RemoveAll(dir)
}()
app := NewGaiaApp(logger, db, nil, true, false, fauxMerkleModeOpt)
app := NewGaiaApp(logger, db, nil, true, 0, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", app.Name())
// Run randomized simulation
@ -514,7 +514,7 @@ func TestGaiaSimulationAfterImport(t *testing.T) {
newDB.Close()
os.RemoveAll(newDir)
}()
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil, true, false, fauxMerkleModeOpt)
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", newApp.Name())
newApp.InitChain(abci.RequestInitChain{
AppStateBytes: appState,
@ -542,7 +542,7 @@ func TestAppStateDeterminism(t *testing.T) {
for j := 0; j < numTimesToRunPerSeed; j++ {
logger := log.NewNopLogger()
db := dbm.NewMemDB()
app := NewGaiaApp(logger, db, nil, true, false)
app := NewGaiaApp(logger, db, nil, true, 0)
// Run randomized simulation
simulation.SimulateFromSeed(

View File

@ -12,7 +12,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/go-amino"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/client"

View File

@ -23,9 +23,9 @@ import (
)
// gaiad custom flags
const flagAssertInvariantsBlockly = "assert-invariants-blockly"
const flagInvCheckPeriod = "inv-check-period"
var assertInvariantsBlockly bool
var invCheckPeriod uint
func main() {
cdc := app.MakeCodec()
@ -43,6 +43,7 @@ func main() {
Short: "Gaia Daemon (server)",
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
}
rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.CollectGenTxsCmd(ctx, cdc))
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc))
@ -55,8 +56,8 @@ func main() {
// prepare and add flags
executor := cli.PrepareBaseCmd(rootCmd, "GA", app.DefaultNodeHome)
rootCmd.PersistentFlags().BoolVar(&assertInvariantsBlockly, flagAssertInvariantsBlockly,
false, "Assert registered invariants on a blockly basis")
rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod,
1, "Assert registered invariants every N blocks")
err := executor.Execute()
if err != nil {
// handle with #870
@ -66,7 +67,7 @@ func main() {
func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application {
return app.NewGaiaApp(
logger, db, traceStore, true, assertInvariantsBlockly,
logger, db, traceStore, true, invCheckPeriod,
baseapp.SetPruning(store.NewPruningOptionsFromString(viper.GetString("pruning"))),
baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
)
@ -77,13 +78,13 @@ func exportAppStateAndTMValidators(
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
if height != -1 {
gApp := app.NewGaiaApp(logger, db, traceStore, false, false)
gApp := app.NewGaiaApp(logger, db, traceStore, false, uint(1))
err := gApp.LoadHeight(height)
if err != nil {
return nil, nil, err
}
return gApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
}
gApp := app.NewGaiaApp(logger, db, traceStore, true, false)
gApp := app.NewGaiaApp(logger, db, traceStore, true, uint(1))
return gApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
}

View File

@ -107,7 +107,7 @@ func run(rootDir string) {
// Application
fmt.Println("Creating application")
myapp := app.NewGaiaApp(
ctx.Logger, appDB, traceStoreWriter, true, true,
ctx.Logger, appDB, traceStoreWriter, true, uint(1),
baseapp.SetPruning(store.PruneEverything), // nothing
)

View File

@ -15,7 +15,10 @@ def process_raw_genesis(genesis, parsed_args):
},
}
# default tm value
# migrate governance state as the internal structure of proposals has changed
migrate_gov_data(genesis['app_state']['gov'])
# default Tendermint block time (ms)
genesis['consensus_params']['block']['time_iota_ms'] = '1000'
# proposal #1 updates
@ -36,6 +39,36 @@ def process_raw_genesis(genesis, parsed_args):
return genesis
def migrate_gov_data(gov_data):
for p in gov_data['proposals']:
# get Amino type and value
t = p['type']
v = p['value']
del p['type']
del p['value']
assert t == 'gov/TextProposal', 'invalid proposal type: {t}'
assert p == {}, 'expected proposal to be empty after deleting contents'
p['proposal_content'] = {
'type': t,
'value': {
'title': v['title'],
'description': v['description']
}
}
p['proposal_id'] = v['proposal_id']
p['proposal_status'] = v['proposal_status']
p['final_tally_result'] = v['final_tally_result']
p['submit_time'] = v['submit_time']
p['deposit_end_time'] = v['deposit_end_time']
p['total_deposit'] = v['total_deposit']
p['voting_start_time'] = v['voting_start_time']
p['voting_end_time'] = v['voting_end_time']
if __name__ == '__main__':
parser = lib.init_default_argument_parser(
prog_desc='Convert genesis.json from v0.33.x to v0.34.0',

View File

@ -1,8 +1,8 @@
package crypto
import (
"github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/crypto/encoding/amino"
amino "github.com/tendermint/go-amino"
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
)
var cdc = amino.NewCodec()

View File

@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/cosmos/go-bip39"
bip39 "github.com/cosmos/go-bip39"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/secp256k1"

View File

@ -5,7 +5,7 @@ import (
"fmt"
"testing"
"github.com/cosmos/go-bip39"
bip39 "github.com/cosmos/go-bip39"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

View File

@ -256,6 +256,10 @@ gaiacli tx sign \
unsignedSendTx.json > signedSendTx.json
```
::: tip Note
The `--generate-only` flag prevents `gaiacli` from accessing the local keybase.
:::
You can validate the transaction's signatures by typing the following:
```bash

View File

@ -107,6 +107,10 @@ func NewResponseResultTx(res *ctypes.ResultTx, tx Tx, timestamp string) TxRespon
// NewResponseFormatBroadcastTxCommit returns a TxResponse given a
// ResultBroadcastTxCommit from tendermint.
func NewResponseFormatBroadcastTxCommit(res *ctypes.ResultBroadcastTxCommit) TxResponse {
if res == nil {
return TxResponse{}
}
if !res.CheckTx.IsOK() {
return newTxResponseCheckTx(res)
}

View File

@ -25,19 +25,23 @@ const (
// Constant as this should not change without a hard fork.
// TODO: Link to some Tendermint docs, this is very unobvious.
ValidatorUpdateDelay int64 = 1
BondStatusUnbonded = "Unbonded"
BondStatusUnbonding = "Unbonding"
BondStatusBonded = "Bonded"
)
//BondStatusToString for pretty prints of Bond Status
func BondStatusToString(b BondStatus) string {
// String implements the Stringer interface for BondStatus.
func (b BondStatus) String() string {
switch b {
case 0x00:
return "Unbonded"
return BondStatusUnbonded
case 0x01:
return "Unbonding"
return BondStatusUnbonding
case 0x02:
return "Bonded"
return BondStatusBonded
default:
panic("improper use of BondStatusToString")
panic("invalid bond status")
}
}

View File

@ -248,6 +248,10 @@ func (bldr TxBuilder) BuildTxForSim(msgs []sdk.Msg) ([]byte, error) {
// SignStdTx appends a signature to a StdTx and returns a copy of it. If append
// is false, it replaces the signatures already attached with the new signature.
func (bldr TxBuilder) SignStdTx(name, passphrase string, stdTx auth.StdTx, appendSig bool) (signedStdTx auth.StdTx, err error) {
if bldr.chainID == "" {
return auth.StdTx{}, fmt.Errorf("chain ID required but not specified")
}
stdSignature, err := MakeSignature(bldr.keybase, name, passphrase, StdSignMsg{
ChainID: bldr.chainID,
AccountNumber: bldr.accountNumber,

View File

@ -4,6 +4,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/mint/client/cli"
"github.com/spf13/cobra"
"github.com/tendermint/go-amino"
)

View File

@ -36,6 +36,7 @@ type (
QueryValidatorParams = querier.QueryValidatorParams
QueryBondsParams = querier.QueryBondsParams
QueryRedelegationParams = querier.QueryRedelegationParams
QueryValidatorsParams = querier.QueryValidatorsParams
)
var (
@ -97,10 +98,11 @@ var (
NewMsgUndelegate = types.NewMsgUndelegate
NewMsgBeginRedelegate = types.NewMsgBeginRedelegate
NewQuerier = querier.NewQuerier
NewQueryDelegatorParams = querier.NewQueryDelegatorParams
NewQueryValidatorParams = querier.NewQueryValidatorParams
NewQueryBondsParams = querier.NewQueryBondsParams
NewQuerier = querier.NewQuerier
NewQueryDelegatorParams = querier.NewQueryDelegatorParams
NewQueryValidatorParams = querier.NewQueryValidatorParams
NewQueryBondsParams = querier.NewQueryBondsParams
NewQueryValidatorsParams = querier.NewQueryValidatorsParams
)
const (

View File

@ -1,6 +1,7 @@
package rest
import (
"fmt"
"net/http"
"strings"
@ -15,7 +16,6 @@ import (
)
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) {
// Get all delegations from a delegator
r.HandleFunc(
"/staking/delegators/{delegatorAddr}/delegations",
@ -249,7 +249,31 @@ func delegatorValidatorHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) ht
// HTTP request handler to query list of validators
func validatorsHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
res, err := cliCtx.QueryWithData("custom/staking/validators", nil)
_, page, limit, err := rest.ParseHTTPArgs(r)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
// override default limit if it wasn't provided
if l := r.FormValue("limit"); l == "" {
limit = 0
}
status := r.FormValue("status")
if status == "" {
status = sdk.BondStatusBonded
}
params := staking.NewQueryValidatorsParams(page, limit, status)
bz, err := cdc.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
route := fmt.Sprintf("custom/%s/%s", staking.QuerierRoute, staking.QueryValidators)
res, err := cliCtx.QueryWithData(route, bz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return

View File

@ -162,9 +162,8 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) {
assert.Equal(
t, status, val.GetStatus(),
fmt.Sprintf("expected validator at index %v to have status: %s",
valIdx,
sdk.BondStatusToString(status)))
fmt.Sprintf("expected validator at index %v to have status: %s", valIdx, status),
)
}
}

View File

@ -2,6 +2,7 @@ package querier
import (
"fmt"
"strings"
abci "github.com/tendermint/tendermint/abci/types"
@ -35,7 +36,7 @@ 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)
return queryValidators(ctx, cdc, req, k)
case QueryValidator:
return queryValidator(ctx, cdc, req, k)
case QueryValidatorDelegations:
@ -128,14 +129,47 @@ func NewQueryRedelegationParams(delegatorAddr sdk.AccAddress, srcValidatorAddr s
}
}
func queryValidators(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []byte, err sdk.Error) {
stakingParams := k.GetParams(ctx)
validators := k.GetValidators(ctx, stakingParams.MaxValidators)
func queryValidators(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) ([]byte, sdk.Error) {
var params QueryValidatorsParams
res, errRes := codec.MarshalJSONIndent(cdc, validators)
err := cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error()))
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
}
stakingParams := k.GetParams(ctx)
if params.Limit == 0 {
params.Limit = int(stakingParams.MaxValidators)
}
validators := k.GetAllValidators(ctx)
filteredVals := make([]types.Validator, 0, len(validators))
for _, val := range validators {
if strings.ToLower(val.GetStatus().String()) == strings.ToLower(params.Status) {
filteredVals = append(filteredVals, val)
}
}
// get pagination bounds
start := (params.Page - 1) * params.Limit
end := params.Limit + start
if end >= len(filteredVals) {
end = len(filteredVals)
}
if start >= len(filteredVals) {
// page is out of bounds
filteredVals = []types.Validator{}
} else {
filteredVals = filteredVals[start:end]
}
res, err := codec.MarshalJSONIndent(cdc, filteredVals)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error()))
}
return res, nil
}
@ -354,3 +388,14 @@ func queryParameters(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []by
}
return res, nil
}
// QueryValidatorsParams defines the params for the following queries:
// - 'custom/staking/validators'
type QueryValidatorsParams struct {
Page, Limit int
Status string
}
func NewQueryValidatorsParams(page, limit int, status string) QueryValidatorsParams {
return QueryValidatorsParams{page, limit, status}
}

View File

@ -1,6 +1,7 @@
package querier
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
@ -44,9 +45,6 @@ func TestNewQuerier(t *testing.T) {
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)
@ -121,28 +119,44 @@ func TestQueryValidators(t *testing.T) {
params := keeper.GetParams(ctx)
// Create Validators
amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8)}
var validators [2]types.Validator
amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8), sdk.NewInt(7)}
status := []sdk.BondStatus{sdk.Bonded, sdk.Unbonded, sdk.Unbonding}
var validators [3]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)
validators[i], pool = validators[i].UpdateStatus(pool, status[i])
}
keeper.SetPool(ctx, pool)
keeper.SetValidator(ctx, validators[0])
keeper.SetValidator(ctx, validators[1])
keeper.SetValidator(ctx, validators[2])
// Query Validators
queriedValidators := keeper.GetValidators(ctx, params.MaxValidators)
res, err := queryValidators(ctx, cdc, keeper)
require.Nil(t, err)
for i, s := range status {
queryValsParams := NewQueryValidatorsParams(1, int(params.MaxValidators), s.String())
bz, errRes := cdc.MarshalJSON(queryValsParams)
require.Nil(t, errRes)
var validatorsResp []types.Validator
errRes := cdc.UnmarshalJSON(res, &validatorsResp)
require.Nil(t, errRes)
req := abci.RequestQuery{
Path: fmt.Sprintf("/custom/%s/%s", types.QuerierRoute, QueryValidators),
Data: bz,
}
require.Equal(t, len(queriedValidators), len(validatorsResp))
require.ElementsMatch(t, queriedValidators, validatorsResp)
res, err := queryValidators(ctx, cdc, req, keeper)
require.Nil(t, err)
var validatorsResp []types.Validator
errRes = cdc.UnmarshalJSON(res, &validatorsResp)
require.Nil(t, errRes)
require.Equal(t, 1, len(validatorsResp))
require.ElementsMatch(t, validators[i].OperatorAddress, validatorsResp[0].OperatorAddress)
}
// Query each validator
queryParams := NewQueryValidatorParams(addrVal1)
@ -153,7 +167,7 @@ func TestQueryValidators(t *testing.T) {
Path: "/custom/staking/validator",
Data: bz,
}
res, err = queryValidator(ctx, cdc, query, keeper)
res, err := queryValidator(ctx, cdc, query, keeper)
require.Nil(t, err)
var validator types.Validator

View File

@ -117,7 +117,7 @@ func (v Validator) String() string {
Unbonding Completion Time: %v
Minimum Self Delegation: %v
Commission: %s`, v.OperatorAddress, bechConsPubKey,
v.Jailed, sdk.BondStatusToString(v.Status), v.Tokens,
v.Jailed, v.Status, v.Tokens,
v.DelegatorShares, v.Description,
v.UnbondingHeight, v.UnbondingCompletionTime, v.MinSelfDelegation, v.Commission)
}