From cba7fd7ee831ab1b690d2414fec91d6674e7c09d Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Tue, 10 Jul 2018 17:59:07 -0700 Subject: [PATCH] gov enums marshal to String --- CHANGELOG.md | 2 + client/lcd/lcd_test.go | 60 ++++---- cmd/gaia/cli_test/cli_test.go | 18 +-- x/gov/client/cli/tx.go | 12 +- x/gov/client/rest/rest.go | 75 +++------- x/gov/depositsvotes.go | 136 ++++++++++--------- x/gov/errors.go | 9 +- x/gov/keeper.go | 6 +- x/gov/msgs.go | 44 ++---- x/gov/msgs_test.go | 2 +- x/gov/proposals.go | 248 +++++++++++++++++++++++----------- 11 files changed, 323 insertions(+), 289 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a4c6acf7b43..f7a12d87fb98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,8 @@ BREAKING CHANGES * [lcd] Switch key creation output to return bech32 * [lcd] Removed shorthand CLI flags (`a`, `c`, `n`, `o`) * [gaiad] genesis transactions now use bech32 addresses / pubkeys +* [gov] VoteStatus renamed to ProposalStatus +* [gov] VoteOption, ProposalType, and ProposalStatus all marshal to string form in JSON DEPRECATED * [cli] Deprecated `--name` flag in commands that send txs, in favor of `--from` diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index b5800ca2920f..d4ca9d0d388e 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -443,7 +443,7 @@ func TestSubmitProposal(t *testing.T) { // query proposal proposal := getProposal(t, port, proposalID) - require.Equal(t, "Test", proposal.Title) + require.Equal(t, "Test", proposal.GetTitle()) } func TestDeposit(t *testing.T) { @@ -465,7 +465,7 @@ func TestDeposit(t *testing.T) { // query proposal proposal := getProposal(t, port, proposalID) - require.Equal(t, "Test", proposal.Title) + require.Equal(t, "Test", proposal.GetTitle()) // create SubmitProposal TX resultTx = doDeposit(t, port, seed, name, password, addr, proposalID) @@ -473,7 +473,7 @@ func TestDeposit(t *testing.T) { // query proposal proposal = getProposal(t, port, proposalID) - require.True(t, proposal.TotalDeposit.IsEqual(sdk.Coins{sdk.NewCoin("steak", 10)})) + require.True(t, proposal.GetTotalDeposit().IsEqual(sdk.Coins{sdk.NewCoin("steak", 10)})) // query deposit deposit := getDeposit(t, port, proposalID, addr) @@ -499,7 +499,7 @@ func TestVote(t *testing.T) { // query proposal proposal := getProposal(t, port, proposalID) - require.Equal(t, "Test", proposal.Title) + require.Equal(t, "Test", proposal.GetTitle()) // create SubmitProposal TX resultTx = doDeposit(t, port, seed, name, password, addr, proposalID) @@ -507,7 +507,7 @@ func TestVote(t *testing.T) { // query proposal proposal = getProposal(t, port, proposalID) - require.Equal(t, gov.StatusToString(gov.StatusVotingPeriod), proposal.Status) + require.Equal(t, gov.StatusVotingPeriod, proposal.GetStatus()) // create SubmitProposal TX resultTx = doVote(t, port, seed, name, password, addr, proposalID) @@ -515,7 +515,7 @@ func TestVote(t *testing.T) { vote := getVote(t, port, proposalID, addr) require.Equal(t, proposalID, vote.ProposalID) - require.Equal(t, gov.VoteOptionToString(gov.OptionYes), vote.Option) + require.Equal(t, gov.OptionYes, vote.Option) } func TestUnrevoke(t *testing.T) { @@ -576,31 +576,31 @@ func TestProposalsQuery(t *testing.T) { // Test query all proposals proposals := getProposalsAll(t, port) - require.Equal(t, proposalID1, (proposals[0]).ProposalID) - require.Equal(t, proposalID2, (proposals[1]).ProposalID) - require.Equal(t, proposalID3, (proposals[2]).ProposalID) + require.Equal(t, proposalID1, (proposals[0]).GetProposalID()) + require.Equal(t, proposalID2, (proposals[1]).GetProposalID()) + require.Equal(t, proposalID3, (proposals[2]).GetProposalID()) // Test query deposited by addr1 proposals = getProposalsFilterDepositer(t, port, addr) - require.Equal(t, proposalID1, (proposals[0]).ProposalID) + require.Equal(t, proposalID1, (proposals[0]).GetProposalID()) // Test query deposited by addr2 proposals = getProposalsFilterDepositer(t, port, addr2) - require.Equal(t, proposalID2, (proposals[0]).ProposalID) - require.Equal(t, proposalID3, (proposals[1]).ProposalID) + require.Equal(t, proposalID2, (proposals[0]).GetProposalID()) + require.Equal(t, proposalID3, (proposals[1]).GetProposalID()) // Test query voted by addr1 proposals = getProposalsFilterVoter(t, port, addr) - require.Equal(t, proposalID2, (proposals[0]).ProposalID) - require.Equal(t, proposalID3, (proposals[1]).ProposalID) + require.Equal(t, proposalID2, (proposals[0]).GetProposalID()) + require.Equal(t, proposalID3, (proposals[1]).GetProposalID()) // Test query voted by addr2 proposals = getProposalsFilterVoter(t, port, addr2) - require.Equal(t, proposalID3, (proposals[0]).ProposalID) + require.Equal(t, proposalID3, (proposals[0]).GetProposalID()) // Test query voted and deposited by addr1 proposals = getProposalsFilterVoterDepositer(t, port, addr, addr) - require.Equal(t, proposalID2, (proposals[0]).ProposalID) + require.Equal(t, proposalID2, (proposals[0]).GetProposalID()) } //_____________________________________________________________________________ @@ -838,68 +838,68 @@ func getValidators(t *testing.T, port string) []stakerest.StakeValidatorOutput { return validators } -func getProposal(t *testing.T, port string, proposalID int64) gov.ProposalRest { +func getProposal(t *testing.T, port string, proposalID int64) gov.Proposal { res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d", proposalID), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var proposal gov.ProposalRest + var proposal gov.Proposal err := cdc.UnmarshalJSON([]byte(body), &proposal) require.Nil(t, err) return proposal } -func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.AccAddress) gov.DepositRest { +func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.AccAddress) gov.Deposit { res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositerAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var deposit gov.DepositRest + var deposit gov.Deposit err := cdc.UnmarshalJSON([]byte(body), &deposit) require.Nil(t, err) return deposit } -func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.AccAddress) gov.VoteRest { +func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.AccAddress) gov.Vote { res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes/%s", proposalID, voterAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var vote gov.VoteRest + var vote gov.Vote err := cdc.UnmarshalJSON([]byte(body), &vote) require.Nil(t, err) return vote } -func getProposalsAll(t *testing.T, port string) []gov.ProposalRest { +func getProposalsAll(t *testing.T, port string) []gov.Proposal { res, body := Request(t, port, "GET", "/gov/proposals", nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var proposals []gov.ProposalRest + var proposals []gov.Proposal err := cdc.UnmarshalJSON([]byte(body), &proposals) require.Nil(t, err) return proposals } -func getProposalsFilterDepositer(t *testing.T, port string, depositerAddr sdk.AccAddress) []gov.ProposalRest { +func getProposalsFilterDepositer(t *testing.T, port string, depositerAddr sdk.AccAddress) []gov.Proposal { res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?depositer=%s", depositerAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var proposals []gov.ProposalRest + var proposals []gov.Proposal err := cdc.UnmarshalJSON([]byte(body), &proposals) require.Nil(t, err) return proposals } -func getProposalsFilterVoter(t *testing.T, port string, voterAddr sdk.AccAddress) []gov.ProposalRest { +func getProposalsFilterVoter(t *testing.T, port string, voterAddr sdk.AccAddress) []gov.Proposal { res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?voter=%s", voterAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var proposals []gov.ProposalRest + var proposals []gov.Proposal err := cdc.UnmarshalJSON([]byte(body), &proposals) require.Nil(t, err) return proposals } -func getProposalsFilterVoterDepositer(t *testing.T, port string, voterAddr, depositerAddr sdk.AccAddress) []gov.ProposalRest { +func getProposalsFilterVoterDepositer(t *testing.T, port string, voterAddr, depositerAddr sdk.AccAddress) []gov.Proposal { res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?depositer=%s&voter=%s", depositerAddr, voterAddr), nil) require.Equal(t, http.StatusOK, res.StatusCode, body) - var proposals []gov.ProposalRest + var proposals []gov.Proposal err := cdc.UnmarshalJSON([]byte(body), &proposals) require.Nil(t, err) return proposals diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 38a347b24121..645a6c276ab1 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -183,8 +183,8 @@ func TestGaiaCLISubmitProposal(t *testing.T) { require.Equal(t, int64(45), fooAcc.GetCoins().AmountOf("steak").Int64()) proposal1 := executeGetProposal(t, fmt.Sprintf("gaiacli gov query-proposal --proposalID=1 --output=json %v", flags)) - require.Equal(t, int64(1), proposal1.ProposalID) - require.Equal(t, gov.StatusToString(gov.StatusDepositPeriod), proposal1.Status) + require.Equal(t, int64(1), proposal1.GetProposalID()) + require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus()) executeWrite(t, fmt.Sprintf("gaiacli gov deposit %v --depositer=%s --deposit=10steak --proposalID=1 --from=foo", flags, fooAddr), pass) tests.WaitForNextHeightTM(port) @@ -192,15 +192,15 @@ func TestGaiaCLISubmitProposal(t *testing.T) { fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) require.Equal(t, int64(35), fooAcc.GetCoins().AmountOf("steak").Int64()) proposal1 = executeGetProposal(t, fmt.Sprintf("gaiacli gov query-proposal --proposalID=1 --output=json %v", flags)) - require.Equal(t, int64(1), proposal1.ProposalID) - require.Equal(t, gov.StatusToString(gov.StatusVotingPeriod), proposal1.Status) + require.Equal(t, int64(1), proposal1.GetProposalID()) + require.Equal(t, gov.StatusVotingPeriod, proposal1.GetStatus()) executeWrite(t, fmt.Sprintf("gaiacli gov vote %v --proposalID=1 --voter=%s --option=Yes --from=foo", flags, fooAddr), pass) tests.WaitForNextHeightTM(port) vote := executeGetVote(t, fmt.Sprintf("gaiacli gov query-vote --proposalID=1 --voter=%s --output=json %v", fooAddr, flags)) require.Equal(t, int64(1), vote.ProposalID) - require.Equal(t, gov.VoteOptionToString(gov.OptionYes), vote.Option) + require.Equal(t, gov.OptionYes, vote.Option) } //___________________________________________________________________________________ @@ -288,18 +288,18 @@ func executeGetValidator(t *testing.T, cmdStr string) stake.Validator { return validator } -func executeGetProposal(t *testing.T, cmdStr string) gov.ProposalRest { +func executeGetProposal(t *testing.T, cmdStr string) gov.Proposal { out := tests.ExecuteT(t, cmdStr) - var proposal gov.ProposalRest + var proposal gov.Proposal cdc := app.MakeCodec() err := cdc.UnmarshalJSON([]byte(out), &proposal) require.NoError(t, err, "out %v\n, err %v", out, err) return proposal } -func executeGetVote(t *testing.T, cmdStr string) gov.VoteRest { +func executeGetVote(t *testing.T, cmdStr string) gov.Vote { out := tests.ExecuteT(t, cmdStr) - var vote gov.VoteRest + var vote gov.Vote cdc := app.MakeCodec() err := cdc.UnmarshalJSON([]byte(out), &vote) require.NoError(t, err, "out %v\n, err %v", out, err) diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index 1c5c11b71e05..8369c9927394 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -48,7 +48,7 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { return err } - proposalType, err := gov.StringToProposalType(strProposalType) + proposalType, err := gov.ProposalTypeFromString(strProposalType) if err != nil { return err } @@ -145,7 +145,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { option := viper.GetString(flagOption) - byteVoteOption, err := gov.StringToVoteOption(option) + byteVoteOption, err := gov.VoteOptionFromString(option) if err != nil { return err } @@ -158,7 +158,7 @@ func GetCmdVote(cdc *wire.Codec) *cobra.Command { return err } - fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]", bechVoter, msg.ProposalID, gov.VoteOptionToString(msg.Option)) + fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]", bechVoter, msg.ProposalID, msg.Option) // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) @@ -195,8 +195,7 @@ func GetCmdQueryProposal(storeName string, cdc *wire.Codec) *cobra.Command { var proposal gov.Proposal cdc.MustUnmarshalBinary(res, &proposal) - proposalRest := gov.ProposalToRest(proposal) - output, err := wire.MarshalJSONIndent(cdc, proposalRest) + output, err := wire.MarshalJSONIndent(cdc, proposal) if err != nil { return err } @@ -232,8 +231,7 @@ func GetCmdQueryVote(storeName string, cdc *wire.Codec) *cobra.Command { var vote gov.Vote cdc.MustUnmarshalBinary(res, &vote) - voteRest := gov.VoteToRest(vote) - output, err := wire.MarshalJSONIndent(cdc, voteRest) + output, err := wire.MarshalJSONIndent(cdc, vote) if err != nil { return err } diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 3e121d4d419c..147304587126 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -36,24 +36,24 @@ func RegisterRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec) { } type postProposalReq struct { - BaseReq baseReq `json:"base_req"` - Title string `json:"title"` // Title of the proposal - Description string `json:"description"` // Description of the proposal - ProposalType string `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} - Proposer string `json:"proposer"` // Address of the proposer - InitialDeposit sdk.Coins `json:"initial_deposit"` // Coins to add to the proposal's deposit + BaseReq baseReq `json:"base_req"` + Title string `json:"title"` // Title of the proposal + Description string `json:"description"` // Description of the proposal + ProposalType gov.ProposalKind `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} + Proposer sdk.AccAddress `json:"proposer"` // Address of the proposer + InitialDeposit sdk.Coins `json:"initial_deposit"` // Coins to add to the proposal's deposit } type depositReq struct { - BaseReq baseReq `json:"base_req"` - Depositer string `json:"depositer"` // Address of the depositer - Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit + BaseReq baseReq `json:"base_req"` + Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer + Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit } type voteReq struct { - BaseReq baseReq `json:"base_req"` - Voter string `json:"voter"` // address of the voter - Option string `json:"option"` // option from OptionSet chosen by the voter + BaseReq baseReq `json:"base_req"` + Voter sdk.AccAddress `json:"voter"` // address of the voter + Option gov.VoteOption `json:"option"` // option from OptionSet chosen by the voter } func postProposalHandlerFn(cdc *wire.Codec, ctx context.CoreContext) http.HandlerFunc { @@ -68,20 +68,8 @@ func postProposalHandlerFn(cdc *wire.Codec, ctx context.CoreContext) http.Handle return } - proposer, err := sdk.AccAddressFromBech32(req.Proposer) - if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) - return - } - - proposalTypeByte, err := gov.StringToProposalType(req.ProposalType) - if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) - return - } - // create the message - msg := gov.NewMsgSubmitProposal(req.Title, req.Description, proposalTypeByte, proposer, req.InitialDeposit) + msg := gov.NewMsgSubmitProposal(req.Title, req.Description, req.ProposalType, req.Proposer, req.InitialDeposit) err = msg.ValidateBasic() if err != nil { writeErr(&w, http.StatusBadRequest, err.Error()) @@ -117,19 +105,12 @@ func depositHandlerFn(cdc *wire.Codec, ctx context.CoreContext) http.HandlerFunc if err != nil { return } - if !req.BaseReq.baseReqValidate(w) { return } - depositer, err := sdk.AccAddressFromBech32(req.Depositer) - if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) - return - } - // create the message - msg := gov.NewMsgDeposit(depositer, proposalID, req.Amount) + msg := gov.NewMsgDeposit(req.Depositer, proposalID, req.Amount) err = msg.ValidateBasic() if err != nil { writeErr(&w, http.StatusBadRequest, err.Error()) @@ -165,25 +146,12 @@ func voteHandlerFn(cdc *wire.Codec, ctx context.CoreContext) http.HandlerFunc { if err != nil { return } - if !req.BaseReq.baseReqValidate(w) { return } - voter, err := sdk.AccAddressFromBech32(req.Voter) - if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) - return - } - - voteOptionByte, err := gov.StringToVoteOption(req.Option) - if err != nil { - writeErr(&w, http.StatusBadRequest, err.Error()) - return - } - // create the message - msg := gov.NewMsgVote(voter, proposalID, voteOptionByte) + msg := gov.NewMsgVote(req.Voter, proposalID, req.Option) err = msg.ValidateBasic() if err != nil { writeErr(&w, http.StatusBadRequest, err.Error()) @@ -225,8 +193,7 @@ func queryProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { var proposal gov.Proposal cdc.MustUnmarshalBinary(res, &proposal) - proposalRest := gov.ProposalToRest(proposal) - output, err := wire.MarshalJSONIndent(cdc, proposalRest) + output, err := wire.MarshalJSONIndent(cdc, proposal) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) @@ -291,8 +258,7 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { var deposit gov.Deposit cdc.MustUnmarshalBinary(res, &deposit) - depositRest := gov.DepositToRest(deposit) - output, err := wire.MarshalJSONIndent(cdc, depositRest) + output, err := wire.MarshalJSONIndent(cdc, deposit) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) @@ -358,8 +324,7 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { var vote gov.Vote cdc.MustUnmarshalBinary(res, &vote) - voteRest := gov.VoteToRest(vote) - output, err := wire.MarshalJSONIndent(cdc, voteRest) + output, err := wire.MarshalJSONIndent(cdc, vote) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) @@ -411,7 +376,7 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { var maxProposalID int64 cdc.MustUnmarshalBinary(res, &maxProposalID) - matchingProposals := []gov.ProposalRest{} + matchingProposals := []gov.Proposal{} for proposalID := int64(0); proposalID < maxProposalID; proposalID++ { if voterAddr != nil { @@ -435,7 +400,7 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { var proposal gov.Proposal cdc.MustUnmarshalBinary(res, &proposal) - matchingProposals = append(matchingProposals, gov.ProposalToRest(proposal)) + matchingProposals = append(matchingProposals, proposal) } output, err := wire.MarshalJSONIndent(cdc, matchingProposals) diff --git a/x/gov/depositsvotes.go b/x/gov/depositsvotes.go index 5ec565189771..19ed97f69d28 100644 --- a/x/gov/depositsvotes.go +++ b/x/gov/depositsvotes.go @@ -1,19 +1,11 @@ package gov import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) + "encoding/json" + "fmt" -// Type that represents VoteOption as a byte -type VoteOption = byte - -//nolint -const ( - OptionEmpty VoteOption = 0x00 - OptionYes VoteOption = 0x01 - OptionAbstain VoteOption = 0x02 - OptionNo VoteOption = 0x03 - OptionNoWithVeto VoteOption = 0x04 + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" ) // Vote @@ -30,34 +22,20 @@ type Deposit struct { Amount sdk.Coins `json:"amount"` // Deposit amount } -// ProposalTypeToString for pretty prints of ProposalType -func VoteOptionToString(option VoteOption) string { - switch option { - case OptionYes: - return "Yes" - case OptionAbstain: - return "Abstain" - case OptionNo: - return "No" - case OptionNoWithVeto: - return "NoWithVeto" - default: - return "" - } -} +// Type that represents VoteOption as a byte +type VoteOption byte -func validVoteOption(option VoteOption) bool { - if option == OptionYes || - option == OptionAbstain || - option == OptionNo || - option == OptionNoWithVeto { - return true - } - return false -} +//nolint +const ( + OptionEmpty VoteOption = 0x00 + OptionYes VoteOption = 0x01 + OptionAbstain VoteOption = 0x02 + OptionNo VoteOption = 0x03 + OptionNoWithVeto VoteOption = 0x04 +) // String to proposalType byte. Returns ff if invalid. -func StringToVoteOption(str string) (VoteOption, sdk.Error) { +func VoteOptionFromString(str string) (VoteOption, error) { switch str { case "Yes": return OptionYes, nil @@ -68,41 +46,75 @@ func StringToVoteOption(str string) (VoteOption, sdk.Error) { case "NoWithVeto": return OptionNoWithVeto, nil default: - return VoteOption(0xff), ErrInvalidVote(DefaultCodespace, str) + return VoteOption(0xff), errors.Errorf("'%s' is not a valid vote option", str) + } +} + +// Is defined VoteOption +func validVoteOption(option VoteOption) bool { + if option == OptionYes || + option == OptionAbstain || + option == OptionNo || + option == OptionNoWithVeto { + return true } + return false } -//----------------------------------------------------------- -// REST +// Marshal needed for protobuf compatibility +func (vo VoteOption) Marshal() ([]byte, error) { + return []byte{byte(vo)}, nil +} -// Rest Deposits -type DepositRest struct { - Depositer sdk.AccAddress `json:"depositer"` // address of the depositer - ProposalID int64 `json:"proposal_id"` // proposalID of the proposal - Amount sdk.Coins `json:"option"` +// Unmarshal needed for protobuf compatibility +func (vo *VoteOption) Unmarshal(data []byte) error { + *vo = VoteOption(data[0]) + return nil } -// Turn any Deposit to a DepositRest -func DepositToRest(deposit Deposit) DepositRest { - return DepositRest{ - Depositer: deposit.Depositer, - ProposalID: deposit.ProposalID, - Amount: deposit.Amount, +// Marshals to JSON using string +func (vo VoteOption) MarshalJSON() ([]byte, error) { + return json.Marshal(vo.String()) +} + +// Unmarshals from JSON assuming Bech32 encoding +func (vo *VoteOption) UnmarshalJSON(data []byte) error { + var s string + err := json.Unmarshal(data, &s) + if err != nil { + return nil } + + bz2, err := VoteOptionFromString(s) + if err != nil { + return err + } + *vo = bz2 + return nil } -// Rest Votes -type VoteRest struct { - Voter sdk.AccAddress `json:"voter"` // address of the voter - ProposalID int64 `json:"proposal_id"` // proposalID of the proposal - Option string `json:"option"` +// Turns VoteOption byte to String +func (vo VoteOption) String() string { + switch vo { + case OptionYes: + return "Yes" + case OptionAbstain: + return "Abstain" + case OptionNo: + return "No" + case OptionNoWithVeto: + return "NoWithVeto" + default: + return "" + } } -// Turn any Vote to a VoteRest -func VoteToRest(vote Vote) VoteRest { - return VoteRest{ - Voter: vote.Voter, - ProposalID: vote.ProposalID, - Option: VoteOptionToString(vote.Option), +// For Printf / Sprintf, returns bech32 when using %s +func (vo VoteOption) Format(s fmt.State, verb rune) { + switch verb { + case 's': + s.Write([]byte(fmt.Sprintf("%s", vo.String()))) + default: + s.Write([]byte(fmt.Sprintf("%v", byte(vo)))) } } diff --git a/x/gov/errors.go b/x/gov/errors.go index e1f2f279376f..0825e00f8cc9 100644 --- a/x/gov/errors.go +++ b/x/gov/errors.go @@ -20,6 +20,7 @@ const ( CodeInvalidProposalType sdk.CodeType = 8 CodeInvalidVote sdk.CodeType = 9 CodeInvalidGenesis sdk.CodeType = 10 + CodeInvalidProposalStatus sdk.CodeType = 11 ) //---------------------------------------- @@ -53,12 +54,12 @@ func ErrInvalidDescription(codespace sdk.CodespaceType, description string) sdk. return sdk.NewError(codespace, CodeInvalidDescription, fmt.Sprintf("Proposal Desciption '%s' is not valid", description)) } -func ErrInvalidProposalType(codespace sdk.CodespaceType, strProposalType string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidProposalType, fmt.Sprintf("Proposal Type '%s' is not valid", strProposalType)) +func ErrInvalidProposalType(codespace sdk.CodespaceType, proposalType ProposalKind) sdk.Error { + return sdk.NewError(codespace, CodeInvalidProposalType, fmt.Sprintf("Proposal Type '%s' is not valid", proposalType)) } -func ErrInvalidVote(codespace sdk.CodespaceType, strOption string) sdk.Error { - return sdk.NewError(codespace, CodeInvalidVote, fmt.Sprintf("'%s' is not a valid voting option", strOption)) +func ErrInvalidVote(codespace sdk.CodespaceType, voteOption VoteOption) sdk.Error { + return sdk.NewError(codespace, CodeInvalidVote, fmt.Sprintf("'%v' is not a valid voting option", voteOption)) } func ErrInvalidGenesis(codespace sdk.CodespaceType, msg string) sdk.Error { diff --git a/x/gov/keeper.go b/x/gov/keeper.go index d966a78a2fff..b60404b8ce7b 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -48,7 +48,7 @@ func (keeper Keeper) WireCodec() *wire.Codec { // Proposals // Creates a NewProposal -func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description string, proposalType byte) Proposal { +func (keeper Keeper) NewTextProposal(ctx sdk.Context, title string, description string, proposalType ProposalKind) Proposal { proposalID, err := keeper.getNewProposalID(ctx) if err != nil { return nil @@ -165,8 +165,8 @@ func (keeper Keeper) AddVote(ctx sdk.Context, proposalID int64, voterAddr sdk.Ac return ErrInactiveProposal(keeper.codespace, proposalID) } - if option != OptionYes && option != OptionAbstain && option != OptionNo && option != OptionNoWithVeto { - return ErrInvalidVote(keeper.codespace, VoteOptionToString(option)) + if !validVoteOption(option) { + return ErrInvalidVote(keeper.codespace, option) } vote := Vote{ diff --git a/x/gov/msgs.go b/x/gov/msgs.go index 5b38861eef6e..5d85f689e58c 100644 --- a/x/gov/msgs.go +++ b/x/gov/msgs.go @@ -41,7 +41,7 @@ func (msg MsgSubmitProposal) ValidateBasic() sdk.Error { return ErrInvalidDescription(DefaultCodespace, msg.Description) // TODO: Proper Error } if !validProposalType(msg.ProposalType) { - return ErrInvalidProposalType(DefaultCodespace, ProposalTypeToString(msg.ProposalType)) + return ErrInvalidProposalType(DefaultCodespace, msg.ProposalType) } if len(msg.Proposer) == 0 { return sdk.ErrInvalidAddress(msg.Proposer.String()) @@ -56,7 +56,7 @@ func (msg MsgSubmitProposal) ValidateBasic() sdk.Error { } func (msg MsgSubmitProposal) String() string { - return fmt.Sprintf("MsgSubmitProposal{%v, %v, %v, %v}", msg.Title, msg.Description, ProposalTypeToString(msg.ProposalType), msg.InitialDeposit) + return fmt.Sprintf("MsgSubmitProposal{%s, %s, %s, %v}", msg.Title, msg.Description, msg.ProposalType, msg.InitialDeposit) } // Implements Msg. @@ -66,19 +66,7 @@ func (msg MsgSubmitProposal) Get(key interface{}) (value interface{}) { // Implements Msg. func (msg MsgSubmitProposal) GetSignBytes() []byte { - b, err := msgCdc.MarshalJSON(struct { - Title string `json:"title"` - Description string `json:"description"` - ProposalType string `json:"proposal_type"` - Proposer sdk.AccAddress `json:"proposer"` - InitialDeposit sdk.Coins `json:"deposit"` - }{ - Title: msg.Title, - Description: msg.Description, - ProposalType: ProposalTypeToString(msg.ProposalType), - Proposer: msg.Proposer, - InitialDeposit: msg.InitialDeposit, - }) + b, err := msgCdc.MarshalJSON(msg) if err != nil { panic(err) } @@ -127,7 +115,7 @@ func (msg MsgDeposit) ValidateBasic() sdk.Error { } func (msg MsgDeposit) String() string { - return fmt.Sprintf("MsgDeposit{%v=>%v: %v}", msg.Depositer, msg.ProposalID, msg.Amount) + return fmt.Sprintf("MsgDeposit{%s=>%v: %v}", msg.Depositer, msg.ProposalID, msg.Amount) } // Implements Msg. @@ -137,15 +125,7 @@ func (msg MsgDeposit) Get(key interface{}) (value interface{}) { // Implements Msg. func (msg MsgDeposit) GetSignBytes() []byte { - b, err := msgCdc.MarshalJSON(struct { - ProposalID int64 `json:"proposalID"` - Depositer sdk.AccAddress `json:"proposer"` - Amount sdk.Coins `json:"deposit"` - }{ - ProposalID: msg.ProposalID, - Depositer: msg.Depositer, - Amount: msg.Amount, - }) + b, err := msgCdc.MarshalJSON(msg) if err != nil { panic(err) } @@ -185,13 +165,13 @@ func (msg MsgVote) ValidateBasic() sdk.Error { return ErrUnknownProposal(DefaultCodespace, msg.ProposalID) } if !validVoteOption(msg.Option) { - return ErrInvalidVote(DefaultCodespace, VoteOptionToString(msg.Option)) + return ErrInvalidVote(DefaultCodespace, msg.Option) } return nil } func (msg MsgVote) String() string { - return fmt.Sprintf("MsgVote{%v - %v}", msg.ProposalID, msg.Option) + return fmt.Sprintf("MsgVote{%v - %s}", msg.ProposalID, msg.Option) } // Implements Msg. @@ -201,15 +181,7 @@ func (msg MsgVote) Get(key interface{}) (value interface{}) { // Implements Msg. func (msg MsgVote) GetSignBytes() []byte { - b, err := msgCdc.MarshalJSON(struct { - ProposalID int64 `json:"proposalID"` - Voter sdk.AccAddress `json:"voter"` - Option string `json:"option"` - }{ - ProposalID: msg.ProposalID, - Voter: msg.Voter, - Option: VoteOptionToString(msg.Option), - }) + b, err := msgCdc.MarshalJSON(msg) if err != nil { panic(err) } diff --git a/x/gov/msgs_test.go b/x/gov/msgs_test.go index fd526c7fa773..186b8365ba89 100644 --- a/x/gov/msgs_test.go +++ b/x/gov/msgs_test.go @@ -22,7 +22,7 @@ func TestMsgSubmitProposal(t *testing.T) { _, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{}) tests := []struct { title, description string - proposalType byte + proposalType ProposalKind proposerAddr sdk.AccAddress initialDeposit sdk.Coins expectPass bool diff --git a/x/gov/proposals.go b/x/gov/proposals.go index c81d61e21d58..64ffe6bfa2a7 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -1,25 +1,12 @@ package gov import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) + "encoding/json" + "fmt" -// Type that represents Status as a byte -type VoteStatus = byte - -// Type that represents Proposal Type as a byte -type ProposalKind = byte - -//nolint -const ( - StatusDepositPeriod VoteStatus = 0x01 - StatusVotingPeriod VoteStatus = 0x02 - StatusPassed VoteStatus = 0x03 - StatusRejected VoteStatus = 0x04 + "github.com/pkg/errors" - ProposalTypeText ProposalKind = 0x01 - ProposalTypeParameterChange ProposalKind = 0x02 - ProposalTypeSoftwareUpgrade ProposalKind = 0x03 + sdk "github.com/cosmos/cosmos-sdk/types" ) //----------------------------------------------------------- @@ -37,8 +24,8 @@ type Proposal interface { GetProposalType() ProposalKind SetProposalType(ProposalKind) - GetStatus() VoteStatus - SetStatus(VoteStatus) + GetStatus() ProposalStatus + SetStatus(ProposalStatus) GetSubmitBlock() int64 SetSubmitBlock(int64) @@ -73,7 +60,7 @@ type TextProposal struct { Description string `json:"description"` // Description of the proposal ProposalType ProposalKind `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} - Status VoteStatus `json:"string"` // Status of the Proposal {Pending, Active, Passed, Rejected} + Status ProposalStatus `json:"string"` // Status of the Proposal {Pending, Active, Passed, Rejected} SubmitBlock int64 `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit @@ -93,8 +80,8 @@ func (tp TextProposal) GetDescription() string { return tp.D func (tp *TextProposal) SetDescription(description string) { tp.Description = description } func (tp TextProposal) GetProposalType() ProposalKind { return tp.ProposalType } func (tp *TextProposal) SetProposalType(proposalType ProposalKind) { tp.ProposalType = proposalType } -func (tp TextProposal) GetStatus() VoteStatus { return tp.Status } -func (tp *TextProposal) SetStatus(status VoteStatus) { tp.Status = status } +func (tp TextProposal) GetStatus() ProposalStatus { return tp.Status } +func (tp *TextProposal) SetStatus(status ProposalStatus) { tp.Status = status } func (tp TextProposal) GetSubmitBlock() int64 { return tp.SubmitBlock } func (tp *TextProposal) SetSubmitBlock(submitBlock int64) { tp.SubmitBlock = submitBlock } func (tp TextProposal) GetTotalDeposit() sdk.Coins { return tp.TotalDeposit } @@ -104,12 +91,82 @@ func (tp *TextProposal) SetVotingStartBlock(votingStartBlock int64) { tp.VotingStartBlock = votingStartBlock } -// Current Active Proposals +//----------------------------------------------------------- +// ProposalQueue type ProposalQueue []int64 -// ProposalTypeToString for pretty prints of ProposalType -func ProposalTypeToString(proposalType ProposalKind) string { - switch proposalType { +//----------------------------------------------------------- +// ProposalKind + +// Type that represents Proposal Type as a byte +type ProposalKind byte + +//nolint +const ( + ProposalTypeText ProposalKind = 0x01 + ProposalTypeParameterChange ProposalKind = 0x02 + ProposalTypeSoftwareUpgrade ProposalKind = 0x03 +) + +// String to proposalType byte. Returns ff if invalid. +func ProposalTypeFromString(str string) (ProposalKind, error) { + switch str { + case "Text": + return ProposalTypeText, nil + case "ParameterChange": + return ProposalTypeParameterChange, nil + case "SoftwareUpgrade": + return ProposalTypeSoftwareUpgrade, nil + default: + return ProposalKind(0xff), errors.Errorf("'%s' is not a valid proposal type", str) + } +} + +// is defined ProposalType? +func validProposalType(pt ProposalKind) bool { + if pt == ProposalTypeText || + pt == ProposalTypeParameterChange || + pt == ProposalTypeSoftwareUpgrade { + return true + } + return false +} + +// Marshal needed for protobuf compatibility +func (pt ProposalKind) Marshal() ([]byte, error) { + return []byte{byte(pt)}, nil +} + +// Unmarshal needed for protobuf compatibility +func (pt *ProposalKind) Unmarshal(data []byte) error { + *pt = ProposalKind(data[0]) + return nil +} + +// Marshals to JSON using string +func (pt ProposalKind) MarshalJSON() ([]byte, error) { + return json.Marshal(pt.String()) +} + +// Unmarshals from JSON assuming Bech32 encoding +func (pt *ProposalKind) UnmarshalJSON(data []byte) error { + var s string + err := json.Unmarshal(data, &s) + if err != nil { + return nil + } + + bz2, err := ProposalTypeFromString(s) + if err != nil { + return err + } + *pt = bz2 + return nil +} + +// Turns VoteOption byte to String +func (pt ProposalKind) String() string { + switch pt { case 0x00: return "Text" case 0x01: @@ -121,31 +178,91 @@ func ProposalTypeToString(proposalType ProposalKind) string { } } -func validProposalType(proposalType ProposalKind) bool { - if proposalType == ProposalTypeText || - proposalType == ProposalTypeParameterChange || - proposalType == ProposalTypeSoftwareUpgrade { - return true +// For Printf / Sprintf, returns bech32 when using %s +func (pt ProposalKind) Format(s fmt.State, verb rune) { + switch verb { + case 's': + s.Write([]byte(fmt.Sprintf("%s", pt.String()))) + default: + s.Write([]byte(fmt.Sprintf("%v", pt))) } - return false } -// String to proposalType byte. Returns ff if invalid. -func StringToProposalType(str string) (ProposalKind, sdk.Error) { +//----------------------------------------------------------- +// ProposalStatus + +// Type that represents Proposal Status as a byte +type ProposalStatus byte + +//nolint +const ( + StatusDepositPeriod ProposalStatus = 0x01 + StatusVotingPeriod ProposalStatus = 0x02 + StatusPassed ProposalStatus = 0x03 + StatusRejected ProposalStatus = 0x04 +) + +// ProposalStatusToString turns a string into a ProposalStatus +func ProposalStatusFromString(str string) (ProposalStatus, error) { switch str { - case "Text": - return ProposalTypeText, nil - case "ParameterChange": - return ProposalTypeParameterChange, nil - case "SoftwareUpgrade": - return ProposalTypeSoftwareUpgrade, nil + case "DepositPeriod": + return StatusDepositPeriod, nil + case "VotingPeriod": + return StatusVotingPeriod, nil + case "Passed": + return StatusPassed, nil + case "Rejected": + return StatusRejected, nil default: - return ProposalKind(0xff), ErrInvalidProposalType(DefaultCodespace, str) + return ProposalStatus(0xff), errors.Errorf("'%s' is not a valid proposal status", str) + } +} + +// is defined ProposalType? +func validProposalStatus(status ProposalStatus) bool { + if status == StatusDepositPeriod || + status == StatusVotingPeriod || + status == StatusPassed || + status == StatusRejected { + return true + } + return false +} + +// Marshal needed for protobuf compatibility +func (status ProposalStatus) Marshal() ([]byte, error) { + return []byte{byte(status)}, nil +} + +// Unmarshal needed for protobuf compatibility +func (status *ProposalStatus) Unmarshal(data []byte) error { + *status = ProposalStatus(data[0]) + return nil +} + +// Marshals to JSON using string +func (status ProposalStatus) MarshalJSON() ([]byte, error) { + return json.Marshal(status.String()) +} + +// Unmarshals from JSON assuming Bech32 encoding +func (status *ProposalStatus) UnmarshalJSON(data []byte) error { + var s string + err := json.Unmarshal(data, &s) + if err != nil { + return nil + } + + bz2, err := ProposalStatusFromString(s) + if err != nil { + return err } + *status = bz2 + return nil } -// StatusToString for pretty prints of Status -func StatusToString(status VoteStatus) string { +// Turns VoteStatus byte to String +func (status ProposalStatus) String() string { switch status { case StatusDepositPeriod: return "DepositPeriod" @@ -160,45 +277,12 @@ func StatusToString(status VoteStatus) string { } } -// StatusToString for pretty prints of Status -func StringToStatus(status string) VoteStatus { - switch status { - case "DepositPeriod": - return StatusDepositPeriod - case "VotingPeriod": - return StatusVotingPeriod - case "Passed": - return StatusPassed - case "Rejected": - return StatusRejected +// For Printf / Sprintf, returns bech32 when using %s +func (status ProposalStatus) Format(s fmt.State, verb rune) { + switch verb { + case 's': + s.Write([]byte(fmt.Sprintf("%s", status.String()))) default: - return VoteStatus(0xff) - } -} - -//----------------------------------------------------------- -// Rest Proposals -type ProposalRest struct { - ProposalID int64 `json:"proposal_id"` // ID of the proposal - Title string `json:"title"` // Title of the proposal - Description string `json:"description"` // Description of the proposal - ProposalType string `json:"proposal_type"` // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal} - Status string `json:"string"` // Status of the Proposal {Pending, Active, Passed, Rejected} - SubmitBlock int64 `json:"submit_block"` // Height of the block where TxGovSubmitProposal was included - TotalDeposit sdk.Coins `json:"total_deposit"` // Current deposit on this proposal. Initial value is set at InitialDeposit - VotingStartBlock int64 `json:"voting_start_block"` // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached -} - -// Turn any Proposal to a ProposalRest -func ProposalToRest(proposal Proposal) ProposalRest { - return ProposalRest{ - ProposalID: proposal.GetProposalID(), - Title: proposal.GetTitle(), - Description: proposal.GetDescription(), - ProposalType: ProposalTypeToString(proposal.GetProposalType()), - Status: StatusToString(proposal.GetStatus()), - SubmitBlock: proposal.GetSubmitBlock(), - TotalDeposit: proposal.GetTotalDeposit(), - VotingStartBlock: proposal.GetVotingStartBlock(), + s.Write([]byte(fmt.Sprintf("%v", status))) } }