Gov Get Vote(s)/Deposit(s) Updates (#3091)

This commit is contained in:
Alexander Bezobchuk 2018-12-14 14:13:43 -05:00 committed by Jack Zampolin
parent 110fd63e22
commit ff6c2f2bad
9 changed files with 372 additions and 86 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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
}

View File

@ -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
View 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
}

View File

@ -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

View File

@ -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 {

View File

@ -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"