Gov Get Vote(s)/Deposit(s) Updates (#3091)
This commit is contained in:
parent
110fd63e22
commit
ff6c2f2bad
@ -35,8 +35,14 @@ FEATURES
|
||||
IMPROVEMENTS
|
||||
|
||||
* Gaia REST API (`gaiacli advanced rest-server`)
|
||||
* \#2879, \#2880 Update deposit and vote endpoints to perform a direct txs query
|
||||
when a given proposal is inactive and thus having votes and deposits removed
|
||||
from state.
|
||||
|
||||
* Gaia CLI (`gaiacli`)
|
||||
* \#2879, \#2880 Update deposit and vote CLI commands to perform a direct txs query
|
||||
when a given proposal is inactive and thus having votes and deposits removed
|
||||
from state.
|
||||
|
||||
* Gaia
|
||||
* [\#3021](https://github.com/cosmos/cosmos-sdk/pull/3021) Add `--gentx-dir` to `gaiad collect-gentxs` to specify a directory from which collect and load gentxs.
|
||||
|
||||
@ -687,6 +687,7 @@ func TestProposalsQuery(t *testing.T) {
|
||||
proposals := getProposalsFilterStatus(t, port, gov.StatusDepositPeriod)
|
||||
require.Len(t, proposals, 1)
|
||||
require.Equal(t, proposalID1, proposals[0].GetProposalID())
|
||||
|
||||
// Only proposals #2 and #3 should be in Voting Period
|
||||
proposals = getProposalsFilterStatus(t, port, gov.StatusVotingPeriod)
|
||||
require.Len(t, proposals, 2)
|
||||
|
||||
@ -58,7 +58,7 @@ $ gaiacli query txs --tags '<tag1>:<value1>&<tag2>:<value2>'
|
||||
}
|
||||
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
txs, err := searchTxs(cliCtx, cdc, tmTags)
|
||||
txs, err := SearchTxs(cliCtx, cdc, tmTags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -89,7 +89,10 @@ $ gaiacli query txs --tags '<tag1>:<value1>&<tag2>:<value2>'
|
||||
return cmd
|
||||
}
|
||||
|
||||
func searchTxs(cliCtx context.CLIContext, cdc *codec.Codec, tags []string) ([]Info, error) {
|
||||
// SearchTxs performs a search for transactions for a given set of tags via
|
||||
// Tendermint RPC. It returns a slice of Info object containing txs and metadata.
|
||||
// An error is returned if the query fails.
|
||||
func SearchTxs(cliCtx context.CLIContext, cdc *codec.Codec, tags []string) ([]Info, error) {
|
||||
if len(tags) == 0 {
|
||||
return nil, errors.New("must declare at least one tag to search")
|
||||
}
|
||||
@ -172,7 +175,7 @@ func SearchTxRequestHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
|
||||
txs, err = searchTxs(cliCtx, cdc, tags)
|
||||
txs, err = SearchTxs(cliCtx, cdc, tags)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
|
||||
@ -12,7 +12,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
govClientUtils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
|
||||
gcutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
|
||||
)
|
||||
|
||||
// GetCmdQueryProposal implements the query proposal command.
|
||||
@ -106,7 +106,7 @@ $ gaiacli query gov proposals --status (DepositPeriod|VotingPeriod|Passed|Reject
|
||||
}
|
||||
|
||||
if len(strProposalStatus) != 0 {
|
||||
proposalStatus, err := gov.ProposalStatusFromString(govClientUtils.NormalizeProposalStatus(strProposalStatus))
|
||||
proposalStatus, err := gov.ProposalStatusFromString(gcutils.NormalizeProposalStatus(strProposalStatus))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -160,8 +160,9 @@ func GetCmdQueryVote(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Query details of a single vote",
|
||||
Long: strings.TrimSpace(`
|
||||
Query details for a single vote on a proposal. You can find the proposal-id by running gaiacli query gov proposals:
|
||||
Query details for a single vote on a proposal given its identifier.
|
||||
|
||||
Example:
|
||||
$ gaiacli query gov vote 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk
|
||||
`),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
@ -179,25 +180,32 @@ $ gaiacli query gov vote 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk
|
||||
return fmt.Errorf("Failed to fetch proposal-id %d: %s", proposalID, err)
|
||||
}
|
||||
|
||||
// get voter address
|
||||
voterAddr, err := sdk.AccAddressFromBech32(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Construct query
|
||||
params := gov.NewQueryVoteParams(proposalID, voterAddr)
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Query store
|
||||
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/vote", queryRoute), bz)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var vote gov.Vote
|
||||
cdc.UnmarshalJSON(res, &vote)
|
||||
|
||||
if vote.Empty() {
|
||||
res, err = gcutils.QueryVoteByTxQuery(cdc, cliCtx, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(string(res))
|
||||
return nil
|
||||
},
|
||||
@ -213,8 +221,9 @@ func GetCmdQueryVotes(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Query votes on a proposal",
|
||||
Long: strings.TrimSpace(`
|
||||
Query vote details for a single proposal. You can find the proposal-id by running gaiacli query gov proposals:
|
||||
Query vote details for a single proposal by its identifier.
|
||||
|
||||
Example:
|
||||
$ gaiacli query gov votes 1
|
||||
`),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
@ -226,21 +235,30 @@ $ gaiacli query gov votes 1
|
||||
return fmt.Errorf("proposal-id %s not a valid int, please input a valid proposal-id", args[0])
|
||||
}
|
||||
|
||||
// check to see if the proposal is in the store
|
||||
_, err = queryProposal(proposalID, cliCtx, cdc, queryRoute)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to fetch proposal-id %d: %s", proposalID, err)
|
||||
}
|
||||
|
||||
// Construct query
|
||||
params := gov.NewQueryProposalParams(proposalID)
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Query store
|
||||
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/votes", queryRoute), bz)
|
||||
// check to see if the proposal is in the store
|
||||
res, err := queryProposal(proposalID, cliCtx, cdc, queryRoute)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to fetch proposal-id %d: %s", proposalID, err)
|
||||
}
|
||||
|
||||
var proposal gov.Proposal
|
||||
if err := cdc.UnmarshalJSON(res, &proposal); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
propStatus := proposal.GetStatus()
|
||||
if !(propStatus == gov.StatusVotingPeriod || propStatus == gov.StatusDepositPeriod) {
|
||||
res, err = gcutils.QueryVotesByTxQuery(cdc, cliCtx, params)
|
||||
} else {
|
||||
res, err = cliCtx.QueryWithData(fmt.Sprintf("custom/%s/votes", queryRoute), bz)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -261,8 +279,9 @@ func GetCmdQueryDeposit(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||
Args: cobra.ExactArgs(2),
|
||||
Short: "Query details of a deposit",
|
||||
Long: strings.TrimSpace(`
|
||||
Query details for a single proposal deposit on a proposal. You can find the proposal-id by running gaiacli query gov proposals:
|
||||
Query details for a single proposal deposit on a proposal by its identifier.
|
||||
|
||||
Example:
|
||||
$ gaiacli query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk
|
||||
`),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
@ -280,25 +299,32 @@ $ gaiacli query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk
|
||||
return fmt.Errorf("Failed to fetch proposal-id %d: %s", proposalID, err)
|
||||
}
|
||||
|
||||
// Get the depositer address
|
||||
depositorAddr, err := sdk.AccAddressFromBech32(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Construct query
|
||||
params := gov.NewQueryDepositParams(proposalID, depositorAddr)
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Query store
|
||||
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposit", queryRoute), bz)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var deposit gov.Deposit
|
||||
cdc.UnmarshalJSON(res, &deposit)
|
||||
|
||||
if deposit.Empty() {
|
||||
res, err = gcutils.QueryDepositByTxQuery(cdc, cliCtx, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(string(res))
|
||||
return nil
|
||||
},
|
||||
@ -327,21 +353,30 @@ $ gaiacli query gov deposits 1
|
||||
return fmt.Errorf("proposal-id %s not a valid uint, please input a valid proposal-id", args[0])
|
||||
}
|
||||
|
||||
// check to see if the proposal is in the store
|
||||
_, err = queryProposal(proposalID, cliCtx, cdc, queryRoute)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to fetch proposal-id %d: %s", proposalID, err)
|
||||
}
|
||||
|
||||
// Construct query
|
||||
params := gov.NewQueryProposalParams(proposalID)
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Query store
|
||||
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposits", queryRoute), bz)
|
||||
// check to see if the proposal is in the store
|
||||
res, err := queryProposal(proposalID, cliCtx, cdc, queryRoute)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to fetch proposal-id %d: %s", proposalID, err)
|
||||
}
|
||||
|
||||
var proposal gov.Proposal
|
||||
if err := cdc.UnmarshalJSON(res, &proposal); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
propStatus := proposal.GetStatus()
|
||||
if !(propStatus == gov.StatusVotingPeriod || propStatus == gov.StatusDepositPeriod) {
|
||||
res, err = gcutils.QueryDepositsByTxQuery(cdc, cliCtx, params)
|
||||
} else {
|
||||
res, err = cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposits", queryRoute), bz)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
gcutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
@ -225,9 +226,7 @@ func queryProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
|
||||
return
|
||||
}
|
||||
|
||||
params := gov.QueryProposalParams{
|
||||
ProposalID: proposalID,
|
||||
}
|
||||
params := gov.NewQueryProposalParams(proposalID)
|
||||
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
@ -263,7 +262,27 @@ func queryDepositsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
|
||||
return
|
||||
}
|
||||
|
||||
res, err := cliCtx.QueryWithData("custom/gov/deposits", bz)
|
||||
res, err := cliCtx.QueryWithData("custom/gov/proposal", bz)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var proposal gov.Proposal
|
||||
if err := cdc.UnmarshalJSON(res, &proposal); err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// For inactive proposals we must query the txs directly to get the deposits
|
||||
// as they're no longer in state.
|
||||
propStatus := proposal.GetStatus()
|
||||
if !(propStatus == gov.StatusVotingPeriod || propStatus == gov.StatusDepositPeriod) {
|
||||
res, err = gcutils.QueryDepositsByTxQuery(cdc, cliCtx, params)
|
||||
} else {
|
||||
res, err = cliCtx.QueryWithData("custom/gov/deposits", bz)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
@ -302,10 +321,7 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
|
||||
return
|
||||
}
|
||||
|
||||
params := gov.QueryDepositParams{
|
||||
ProposalID: proposalID,
|
||||
Depositor: depositorAddr,
|
||||
}
|
||||
params := gov.NewQueryDepositParams(proposalID, depositorAddr)
|
||||
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
@ -321,16 +337,29 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
|
||||
|
||||
var deposit gov.Deposit
|
||||
cdc.UnmarshalJSON(res, &deposit)
|
||||
|
||||
// For an empty deposit, either the proposal does not exist or is inactive in
|
||||
// which case the deposit would be removed from state and should be queried
|
||||
// for directly via a txs query.
|
||||
if deposit.Empty() {
|
||||
res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinaryLengthPrefixed(gov.QueryProposalParams{params.ProposalID}))
|
||||
bz, err := cdc.MarshalJSON(gov.NewQueryProposalParams(proposalID))
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res, err = cliCtx.QueryWithData("custom/gov/proposal", bz)
|
||||
if err != nil || len(res) == 0 {
|
||||
err := errors.Errorf("proposalID [%d] does not exist", proposalID)
|
||||
err := fmt.Errorf("proposalID %d does not exist", proposalID)
|
||||
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
err = errors.Errorf("depositor [%s] did not deposit on proposalID [%d]", bechDepositorAddr, proposalID)
|
||||
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
|
||||
res, err = gcutils.QueryDepositByTxQuery(cdc, cliCtx, params)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
@ -366,10 +395,8 @@ func queryVoteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Handle
|
||||
return
|
||||
}
|
||||
|
||||
params := gov.QueryVoteParams{
|
||||
Voter: voterAddr,
|
||||
ProposalID: proposalID,
|
||||
}
|
||||
params := gov.NewQueryVoteParams(proposalID, voterAddr)
|
||||
|
||||
bz, err := cdc.MarshalJSON(params)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
@ -384,22 +411,31 @@ func queryVoteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Handle
|
||||
|
||||
var vote gov.Vote
|
||||
cdc.UnmarshalJSON(res, &vote)
|
||||
|
||||
// For an empty vote, either the proposal does not exist or is inactive in
|
||||
// which case the vote would be removed from state and should be queried for
|
||||
// directly via a txs query.
|
||||
if vote.Empty() {
|
||||
bz, err := cdc.MarshalJSON(gov.QueryProposalParams{params.ProposalID})
|
||||
bz, err := cdc.MarshalJSON(gov.NewQueryProposalParams(proposalID))
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
res, err := cliCtx.QueryWithData("custom/gov/proposal", bz)
|
||||
|
||||
res, err = cliCtx.QueryWithData("custom/gov/proposal", bz)
|
||||
if err != nil || len(res) == 0 {
|
||||
err := errors.Errorf("proposalID [%d] does not exist", proposalID)
|
||||
err := fmt.Errorf("proposalID %d does not exist", proposalID)
|
||||
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
err = errors.Errorf("voter [%s] did not deposit on proposalID [%d]", bechVoterAddr, proposalID)
|
||||
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
|
||||
res, err = gcutils.QueryVoteByTxQuery(cdc, cliCtx, params)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
@ -429,7 +465,27 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := cliCtx.QueryWithData("custom/gov/votes", bz)
|
||||
res, err := cliCtx.QueryWithData("custom/gov/proposal", bz)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var proposal gov.Proposal
|
||||
if err := cdc.UnmarshalJSON(res, &proposal); err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// For inactive proposals we must query the txs directly to get the votes
|
||||
// as they're no longer in state.
|
||||
propStatus := proposal.GetStatus()
|
||||
if !(propStatus == gov.StatusVotingPeriod || propStatus == gov.StatusDepositPeriod) {
|
||||
res, err = gcutils.QueryVotesByTxQuery(cdc, cliCtx, params)
|
||||
} else {
|
||||
res, err = cliCtx.QueryWithData("custom/gov/votes", bz)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
|
||||
180
x/gov/client/utils/query.go
Normal file
180
x/gov/client/utils/query.go
Normal file
@ -0,0 +1,180 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/tags"
|
||||
)
|
||||
|
||||
// QueryDepositsByTxQuery will query for deposits via a direct txs tags query. It
|
||||
// will fetch and build deposits directly from the returned txs and return a
|
||||
// JSON marshalled result or any error that occurred.
|
||||
//
|
||||
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
|
||||
// support configurable pagination.
|
||||
func QueryDepositsByTxQuery(
|
||||
cdc *codec.Codec, cliCtx context.CLIContext, params gov.QueryProposalParams,
|
||||
) ([]byte, error) {
|
||||
|
||||
tags := []string{
|
||||
fmt.Sprintf("%s='%s'", tags.Action, tags.ActionProposalDeposit),
|
||||
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
}
|
||||
|
||||
infos, err := tx.SearchTxs(cliCtx, cdc, tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var deposits []gov.Deposit
|
||||
|
||||
for _, info := range infos {
|
||||
for _, msg := range info.Tx.GetMsgs() {
|
||||
if msg.Type() == gov.TypeMsgDeposit {
|
||||
depMsg := msg.(gov.MsgDeposit)
|
||||
|
||||
deposits = append(deposits, gov.Deposit{
|
||||
Depositor: depMsg.Depositor,
|
||||
ProposalID: params.ProposalID,
|
||||
Amount: depMsg.Amount,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cliCtx.Indent {
|
||||
return cdc.MarshalJSONIndent(deposits, "", " ")
|
||||
}
|
||||
|
||||
return cdc.MarshalJSON(deposits)
|
||||
}
|
||||
|
||||
// QueryVotesByTxQuery will query for votes via a direct txs tags query. It
|
||||
// will fetch and build votes directly from the returned txs and return a JSON
|
||||
// marshalled result or any error that occurred.
|
||||
//
|
||||
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
|
||||
// support configurable pagination.
|
||||
func QueryVotesByTxQuery(
|
||||
cdc *codec.Codec, cliCtx context.CLIContext, params gov.QueryProposalParams,
|
||||
) ([]byte, error) {
|
||||
|
||||
tags := []string{
|
||||
fmt.Sprintf("%s='%s'", tags.Action, tags.ActionProposalVote),
|
||||
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
}
|
||||
|
||||
infos, err := tx.SearchTxs(cliCtx, cdc, tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var votes []gov.Vote
|
||||
|
||||
for _, info := range infos {
|
||||
for _, msg := range info.Tx.GetMsgs() {
|
||||
if msg.Type() == gov.TypeMsgVote {
|
||||
voteMsg := msg.(gov.MsgVote)
|
||||
|
||||
votes = append(votes, gov.Vote{
|
||||
Voter: voteMsg.Voter,
|
||||
ProposalID: params.ProposalID,
|
||||
Option: voteMsg.Option,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cliCtx.Indent {
|
||||
return cdc.MarshalJSONIndent(votes, "", " ")
|
||||
}
|
||||
|
||||
return cdc.MarshalJSON(votes)
|
||||
}
|
||||
|
||||
// QueryVoteByTxQuery will query for a single vote via a direct txs tags query.
|
||||
func QueryVoteByTxQuery(
|
||||
cdc *codec.Codec, cliCtx context.CLIContext, params gov.QueryVoteParams,
|
||||
) ([]byte, error) {
|
||||
|
||||
tags := []string{
|
||||
fmt.Sprintf("%s='%s'", tags.Action, tags.ActionProposalVote),
|
||||
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
fmt.Sprintf("%s='%s'", tags.Voter, []byte(params.Voter.String())),
|
||||
}
|
||||
|
||||
infos, err := tx.SearchTxs(cliCtx, cdc, tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
for _, msg := range info.Tx.GetMsgs() {
|
||||
// there should only be a single vote under the given conditions
|
||||
if msg.Type() == gov.TypeMsgVote {
|
||||
voteMsg := msg.(gov.MsgVote)
|
||||
|
||||
vote := gov.Vote{
|
||||
Voter: voteMsg.Voter,
|
||||
ProposalID: params.ProposalID,
|
||||
Option: voteMsg.Option,
|
||||
}
|
||||
|
||||
if cliCtx.Indent {
|
||||
return cdc.MarshalJSONIndent(vote, "", " ")
|
||||
}
|
||||
|
||||
return cdc.MarshalJSON(vote)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = fmt.Errorf("address '%s' did not vote on proposalID %d", params.Voter, params.ProposalID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// QueryDepositByTxQuery will query for a single deposit via a direct txs tags
|
||||
// query.
|
||||
func QueryDepositByTxQuery(
|
||||
cdc *codec.Codec, cliCtx context.CLIContext, params gov.QueryDepositParams,
|
||||
) ([]byte, error) {
|
||||
|
||||
tags := []string{
|
||||
fmt.Sprintf("%s='%s'", tags.Action, tags.ActionProposalDeposit),
|
||||
fmt.Sprintf("%s='%s'", tags.ProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
|
||||
fmt.Sprintf("%s='%s'", tags.Depositor, []byte(params.Depositor.String())),
|
||||
}
|
||||
|
||||
infos, err := tx.SearchTxs(cliCtx, cdc, tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
for _, msg := range info.Tx.GetMsgs() {
|
||||
// there should only be a single deposit under the given conditions
|
||||
if msg.Type() == gov.TypeMsgDeposit {
|
||||
depMsg := msg.(gov.MsgDeposit)
|
||||
|
||||
deposit := gov.Deposit{
|
||||
Depositor: depMsg.Depositor,
|
||||
ProposalID: params.ProposalID,
|
||||
Amount: depMsg.Amount,
|
||||
}
|
||||
|
||||
if cliCtx.Indent {
|
||||
return cdc.MarshalJSONIndent(deposit, "", " ")
|
||||
}
|
||||
|
||||
return cdc.MarshalJSON(deposit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = fmt.Errorf("address '%s' did not deposit to proposalID %d", params.Depositor, params.ProposalID)
|
||||
return nil, err
|
||||
}
|
||||
@ -18,24 +18,24 @@ func NewHandler(keeper Keeper) sdk.Handler {
|
||||
case MsgVote:
|
||||
return handleMsgVote(ctx, keeper, msg)
|
||||
default:
|
||||
errMsg := "Unrecognized gov msg type"
|
||||
errMsg := fmt.Sprintf("Unrecognized gov msg type: %T", msg)
|
||||
return sdk.ErrUnknownRequest(errMsg).Result()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitProposal) sdk.Result {
|
||||
|
||||
proposal := keeper.NewTextProposal(ctx, msg.Title, msg.Description, msg.ProposalType)
|
||||
proposalID := proposal.GetProposalID()
|
||||
proposalIDBytes := []byte(fmt.Sprintf("%d", proposalID))
|
||||
|
||||
err, votingStarted := keeper.AddDeposit(ctx, proposal.GetProposalID(), msg.Proposer, msg.InitialDeposit)
|
||||
err, votingStarted := keeper.AddDeposit(ctx, proposalID, msg.Proposer, msg.InitialDeposit)
|
||||
if err != nil {
|
||||
return err.Result()
|
||||
}
|
||||
|
||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal.GetProposalID())
|
||||
|
||||
resTags := sdk.NewTags(
|
||||
tags.Action, tags.ActionProposalSubmitted,
|
||||
tags.Proposer, []byte(msg.Proposer.String()),
|
||||
tags.ProposalID, proposalIDBytes,
|
||||
)
|
||||
@ -45,22 +45,20 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos
|
||||
}
|
||||
|
||||
return sdk.Result{
|
||||
Data: proposalIDBytes,
|
||||
Data: keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID),
|
||||
Tags: resTags,
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result {
|
||||
|
||||
err, votingStarted := keeper.AddDeposit(ctx, msg.ProposalID, msg.Depositor, msg.Amount)
|
||||
if err != nil {
|
||||
return err.Result()
|
||||
}
|
||||
|
||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(msg.ProposalID)
|
||||
|
||||
// TODO: Add tag for if voting period started
|
||||
proposalIDBytes := []byte(fmt.Sprintf("%d", msg.ProposalID))
|
||||
resTags := sdk.NewTags(
|
||||
tags.Action, tags.ActionProposalDeposit,
|
||||
tags.Depositor, []byte(msg.Depositor.String()),
|
||||
tags.ProposalID, proposalIDBytes,
|
||||
)
|
||||
@ -75,33 +73,29 @@ func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result
|
||||
}
|
||||
|
||||
func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result {
|
||||
|
||||
err := keeper.AddVote(ctx, msg.ProposalID, msg.Voter, msg.Option)
|
||||
if err != nil {
|
||||
return err.Result()
|
||||
}
|
||||
|
||||
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(msg.ProposalID)
|
||||
|
||||
resTags := sdk.NewTags(
|
||||
tags.Voter, []byte(msg.Voter.String()),
|
||||
tags.ProposalID, proposalIDBytes,
|
||||
)
|
||||
return sdk.Result{
|
||||
Tags: resTags,
|
||||
Tags: sdk.NewTags(
|
||||
tags.Action, tags.ActionProposalVote,
|
||||
tags.Voter, []byte(msg.Voter.String()),
|
||||
tags.ProposalID, []byte(fmt.Sprintf("%d", msg.ProposalID)),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Called every block, process inflation, update validator set
|
||||
func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||
|
||||
logger := ctx.Logger().With("module", "x/gov")
|
||||
|
||||
resTags = sdk.NewTags()
|
||||
|
||||
inactiveIterator := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||
for ; inactiveIterator.Valid(); inactiveIterator.Next() {
|
||||
var proposalID uint64
|
||||
|
||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(inactiveIterator.Value(), &proposalID)
|
||||
inactiveProposal := keeper.GetProposal(ctx, proposalID)
|
||||
keeper.DeleteProposal(ctx, proposalID)
|
||||
@ -119,11 +113,13 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
inactiveIterator.Close()
|
||||
|
||||
activeIterator := keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||
for ; activeIterator.Valid(); activeIterator.Next() {
|
||||
var proposalID uint64
|
||||
|
||||
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID)
|
||||
activeProposal := keeper.GetProposal(ctx, proposalID)
|
||||
passes, tallyResults := tally(ctx, keeper, activeProposal)
|
||||
@ -138,9 +134,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||
activeProposal.SetStatus(StatusRejected)
|
||||
action = tags.ActionProposalRejected
|
||||
}
|
||||
|
||||
activeProposal.SetTallyResult(tallyResults)
|
||||
keeper.SetProposal(ctx, activeProposal)
|
||||
|
||||
keeper.RemoveFromActiveProposalQueue(ctx, activeProposal.GetVotingEndTime(), activeProposal.GetProposalID())
|
||||
|
||||
logger.Info(fmt.Sprintf("proposal %d (%s) tallied; passed: %v",
|
||||
@ -149,6 +145,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||
resTags = resTags.AppendTag(tags.Action, action)
|
||||
resTags = resTags.AppendTag(tags.ProposalID, []byte(string(proposalID)))
|
||||
}
|
||||
|
||||
activeIterator.Close()
|
||||
|
||||
return resTags
|
||||
|
||||
@ -6,8 +6,13 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// name to idetify transaction types
|
||||
const MsgRoute = "gov"
|
||||
// Governance message types and routes
|
||||
const (
|
||||
MsgRoute = "gov"
|
||||
TypeMsgDeposit = "deposit"
|
||||
TypeMsgVote = "vote"
|
||||
TypeMsgSubmitProposal = "submit_proposal"
|
||||
)
|
||||
|
||||
var _, _, _ sdk.Msg = MsgSubmitProposal{}, MsgDeposit{}, MsgVote{}
|
||||
|
||||
@ -33,7 +38,7 @@ func NewMsgSubmitProposal(title string, description string, proposalType Proposa
|
||||
|
||||
//nolint
|
||||
func (msg MsgSubmitProposal) Route() string { return MsgRoute }
|
||||
func (msg MsgSubmitProposal) Type() string { return "submit_proposal" }
|
||||
func (msg MsgSubmitProposal) Type() string { return TypeMsgSubmitProposal }
|
||||
|
||||
// Implements Msg.
|
||||
func (msg MsgSubmitProposal) ValidateBasic() sdk.Error {
|
||||
@ -100,7 +105,7 @@ func NewMsgDeposit(depositor sdk.AccAddress, proposalID uint64, amount sdk.Coins
|
||||
// Implements Msg.
|
||||
// nolint
|
||||
func (msg MsgDeposit) Route() string { return MsgRoute }
|
||||
func (msg MsgDeposit) Type() string { return "deposit" }
|
||||
func (msg MsgDeposit) Type() string { return TypeMsgDeposit }
|
||||
|
||||
// Implements Msg.
|
||||
func (msg MsgDeposit) ValidateBasic() sdk.Error {
|
||||
@ -161,7 +166,7 @@ func NewMsgVote(voter sdk.AccAddress, proposalID uint64, option VoteOption) MsgV
|
||||
// Implements Msg.
|
||||
// nolint
|
||||
func (msg MsgVote) Route() string { return MsgRoute }
|
||||
func (msg MsgVote) Type() string { return "vote" }
|
||||
func (msg MsgVote) Type() string { return TypeMsgVote }
|
||||
|
||||
// Implements Msg.
|
||||
func (msg MsgVote) ValidateBasic() sdk.Error {
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
// nolint
|
||||
package tags
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Governance tags
|
||||
var (
|
||||
ActionProposalDropped = []byte("proposal-dropped")
|
||||
ActionProposalPassed = []byte("proposal-passed")
|
||||
ActionProposalRejected = []byte("proposal-rejected")
|
||||
ActionProposalDropped = []byte("proposal-dropped")
|
||||
ActionProposalPassed = []byte("proposal-passed")
|
||||
ActionProposalRejected = []byte("proposal-rejected")
|
||||
ActionProposalSubmitted = []byte("proposal-submitted")
|
||||
ActionProposalVote = []byte("proposal-vote")
|
||||
ActionProposalDeposit = []byte("proposal-deposit")
|
||||
|
||||
Action = sdk.TagAction
|
||||
Proposer = "proposer"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user