From 074bb246a8b490f136b81e61c5a63c00f1e69fd1 Mon Sep 17 00:00:00 2001 From: rhuairahrighairigh Date: Sun, 29 Mar 2020 20:43:25 +0100 Subject: [PATCH] add custom errors --- app/app.go | 3 ++- x/committee/alias.go | 13 ++++++++++ x/committee/handler.go | 2 +- x/committee/keeper/keeper.go | 16 ++++++------ x/committee/keeper/proposal.go | 24 +++++++++--------- x/committee/keeper/querier.go | 37 +++------------------------- x/committee/proposal_handler.go | 4 +-- x/committee/types/errors.go | 41 +++++++++++++++++++++++++++++++ x/committee/types/gov_proposal.go | 2 +- x/committee/types/msg.go | 2 +- 10 files changed, 86 insertions(+), 58 deletions(-) diff --git a/app/app.go b/app/app.go index c0ff9680..18ebdb7f 100644 --- a/app/app.go +++ b/app/app.go @@ -217,7 +217,8 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, app.committeeKeeper = committee.NewKeeper( app.cdc, keys[committee.StoreKey], - committeeGovRouter) // TODO blacklist module addresses?) + committeeGovRouter, + committee.DefaultCodespace) // TODO blacklist module addresses?) govRouter := gov.NewRouter() govRouter. AddRoute(gov.RouterKey, gov.ProposalHandler). diff --git a/x/committee/alias.go b/x/committee/alias.go index 01d8188f..baae2c18 100644 --- a/x/committee/alias.go +++ b/x/committee/alias.go @@ -16,6 +16,11 @@ const ( AttributeValueProposalFailed = types.AttributeValueProposalFailed AttributeValueProposalPassed = types.AttributeValueProposalPassed AttributeValueProposalTimeout = types.AttributeValueProposalTimeout + CodeInvalidCommittee = types.CodeInvalidCommittee + CodeInvalidGenesis = types.CodeInvalidGenesis + CodeInvalidProposal = types.CodeInvalidProposal + CodeProposalExpired = types.CodeProposalExpired + CodeUnknownItem = types.CodeUnknownItem DefaultCodespace = types.DefaultCodespace DefaultNextProposalID = types.DefaultNextProposalID DefaultParamspace = types.DefaultParamspace @@ -45,6 +50,14 @@ var ( NewKeeper = keeper.NewKeeper NewQuerier = keeper.NewQuerier DefaultGenesisState = types.DefaultGenesisState + ErrInvalidCommittee = types.ErrInvalidCommittee + ErrInvalidGenesis = types.ErrInvalidGenesis + ErrInvalidPubProposal = types.ErrInvalidPubProposal + ErrNoProposalHandlerExists = types.ErrNoProposalHandlerExists + ErrProposalExpired = types.ErrProposalExpired + ErrUnknownCommittee = types.ErrUnknownCommittee + ErrUnknownProposal = types.ErrUnknownProposal + ErrUnknownVote = types.ErrUnknownVote GetKeyFromID = types.GetKeyFromID GetVoteKey = types.GetVoteKey NewCommittee = types.NewCommittee diff --git a/x/committee/handler.go b/x/committee/handler.go index 7233dbca..23210d43 100644 --- a/x/committee/handler.go +++ b/x/committee/handler.go @@ -50,7 +50,7 @@ func handleMsgVote(ctx sdk.Context, k keeper.Keeper, msg types.MsgVote) sdk.Resu // get the proposal just to add fields to the event proposal, found := k.GetProposal(ctx, msg.ProposalID) if !found { - return sdk.ErrInternal("proposal not found").Result() + return ErrUnknownProposal(DefaultCodespace, msg.ProposalID).Result() } err := k.AddVote(ctx, msg.ProposalID, msg.Voter) diff --git a/x/committee/keeper/keeper.go b/x/committee/keeper/keeper.go index c1471fbb..327b653a 100644 --- a/x/committee/keeper/keeper.go +++ b/x/committee/keeper/keeper.go @@ -12,22 +12,24 @@ import ( ) type Keeper struct { - cdc *codec.Codec - storeKey sdk.StoreKey + cdc *codec.Codec + storeKey sdk.StoreKey + codespace sdk.CodespaceType // Proposal router router govtypes.Router } -func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, router govtypes.Router) Keeper { +func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, router govtypes.Router, codespace sdk.CodespaceType) Keeper { // Logic in the keeper methods assume the set of gov handlers is fixed. // So the gov router must be sealed so no handlers can be added or removed after the keeper is created. router.Seal() return Keeper{ - cdc: cdc, - storeKey: storeKey, - router: router, + cdc: cdc, + storeKey: storeKey, + codespace: codespace, + router: router, } } @@ -87,7 +89,7 @@ func (k Keeper) GetNextProposalID(ctx sdk.Context) (uint64, sdk.Error) { store := ctx.KVStore(k.storeKey) bz := store.Get(types.NextProposalIDKey) if bz == nil { - return 0, sdk.ErrInternal("proposal ID not set at genesis") + return 0, types.ErrInvalidGenesis(k.codespace, "next proposal ID not set at genesis") } return types.Uint64FromBytes(bz), nil } diff --git a/x/committee/keeper/proposal.go b/x/committee/keeper/proposal.go index d0218777..424bcc56 100644 --- a/x/committee/keeper/proposal.go +++ b/x/committee/keeper/proposal.go @@ -13,15 +13,15 @@ func (k Keeper) SubmitProposal(ctx sdk.Context, proposer sdk.AccAddress, committ // Limit proposals to only be submitted by committee members com, found := k.GetCommittee(ctx, committeeID) if !found { - return 0, sdk.ErrInternal("committee doesn't exist") + return 0, types.ErrUnknownCommittee(k.codespace, committeeID) } if !com.HasMember(proposer) { - return 0, sdk.ErrInternal("only member can propose proposals") + return 0, sdk.ErrUnauthorized("proposer not member of committee") } // Check committee has permissions to enact proposal. if !com.HasPermissionsFor(pubProposal) { - return 0, sdk.ErrInternal("committee does not have permissions to enact proposal") + return 0, sdk.ErrUnauthorized("committee does not have permissions to enact proposal") } // Check proposal is valid @@ -51,17 +51,17 @@ func (k Keeper) AddVote(ctx sdk.Context, proposalID uint64, voter sdk.AccAddress // Validate pr, found := k.GetProposal(ctx, proposalID) if !found { - return sdk.ErrInternal("proposal not found") + return types.ErrUnknownProposal(k.codespace, proposalID) } if pr.HasExpiredBy(ctx.BlockTime()) { - return sdk.ErrInternal("proposal expired") + return types.ErrProposalExpired(k.codespace, ctx.BlockTime(), pr.Deadline) } com, found := k.GetCommittee(ctx, pr.CommitteeID) if !found { - return sdk.ErrInternal("committee disbanded") + return types.ErrUnknownCommittee(k.codespace, pr.CommitteeID) } if !com.HasMember(voter) { - return sdk.ErrInternal("not authorized to vote on proposal") + return sdk.ErrUnauthorized("voter must be a member of committee") } // Store vote, overwriting any prior vote @@ -81,11 +81,11 @@ func (k Keeper) AddVote(ctx sdk.Context, proposalID uint64, voter sdk.AccAddress func (k Keeper) GetProposalResult(ctx sdk.Context, proposalID uint64) (bool, sdk.Error) { pr, found := k.GetProposal(ctx, proposalID) if !found { - return false, sdk.ErrInternal("proposal not found") + return false, types.ErrUnknownProposal(k.codespace, proposalID) } com, found := k.GetCommittee(ctx, pr.CommitteeID) if !found { - return false, sdk.ErrInternal("committee disbanded") + return false, types.ErrUnknownCommittee(k.codespace, pr.CommitteeID) } numVotes := k.TallyVotes(ctx, proposalID) @@ -111,7 +111,7 @@ func (k Keeper) TallyVotes(ctx sdk.Context, proposalID uint64) int64 { func (k Keeper) EnactProposal(ctx sdk.Context, proposalID uint64) sdk.Error { pr, found := k.GetProposal(ctx, proposalID) if !found { - return sdk.ErrInternal("proposal not found") + return types.ErrUnknownProposal(k.codespace, proposalID) } // Run the proposal's changes through the associated handler, but using a cached version of state to ensure changes are not permanent if an error occurs. @@ -128,14 +128,14 @@ func (k Keeper) EnactProposal(ctx sdk.Context, proposalID uint64) sdk.Error { // ValidatePubProposal checks if a pubproposal is valid. func (k Keeper) ValidatePubProposal(ctx sdk.Context, pubProposal types.PubProposal) sdk.Error { if pubProposal == nil { - return sdk.ErrInternal("proposal is empty") + return types.ErrInvalidPubProposal(k.codespace, "pub proposal cannot be nil") } if err := pubProposal.ValidateBasic(); err != nil { return err } if !k.router.HasRoute(pubProposal.ProposalRoute()) { - return sdk.ErrInternal("no handler found for proposal") + return types.ErrNoProposalHandlerExists(k.codespace, pubProposal) } // Run the proposal's changes through the associated handler using a cached version of state to ensure changes are not permanent. diff --git a/x/committee/keeper/querier.go b/x/committee/keeper/querier.go index c378d750..54ede8b6 100644 --- a/x/committee/keeper/querier.go +++ b/x/committee/keeper/querier.go @@ -29,8 +29,6 @@ func NewQuerier(keeper Keeper) sdk.Querier { return queryVote(ctx, path[1:], req, keeper) case types.QueryTally: return queryTally(ctx, path[1:], req, keeper) - // case types.QueryParams: - // return queryParams(ctx, path[1:], req, keeper) default: return nil, sdk.ErrUnknownRequest(fmt.Sprintf("unknown %s query endpoint", types.ModuleName)) @@ -64,7 +62,7 @@ func queryCommittee(ctx sdk.Context, path []string, req abci.RequestQuery, keepe committee, found := keeper.GetCommittee(ctx, params.CommitteeID) if !found { - return nil, sdk.ErrInternal("not found") ///types.ErrUnknownProposal(types.DefaultCodespace, params.ProposalID) + return nil, types.ErrUnknownCommittee(types.DefaultCodespace, params.CommitteeID) } bz, err := codec.MarshalJSONIndent(keeper.cdc, committee) @@ -107,7 +105,7 @@ func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper proposal, found := keeper.GetProposal(ctx, params.ProposalID) if !found { - return nil, sdk.ErrInternal("not found") // TODO types.ErrUnknownProposal(types.DefaultCodespace, params.ProposalID) + return nil, types.ErrUnknownProposal(types.DefaultCodespace, params.ProposalID) } bz, err := codec.MarshalJSONIndent(keeper.cdc, proposal) @@ -149,7 +147,7 @@ func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Kee vote, found := keeper.GetVote(ctx, params.ProposalID, params.Voter) if !found { - return nil, sdk.ErrInternal("not found") + return nil, types.ErrUnknownVote(types.DefaultCodespace, params.ProposalID, params.Voter) } bz, err := codec.MarshalJSONIndent(keeper.cdc, vote) @@ -170,7 +168,7 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke _, found := keeper.GetProposal(ctx, params.ProposalID) if !found { - return nil, sdk.ErrInternal("proposal not found") + return nil, types.ErrUnknownProposal(types.DefaultCodespace, params.ProposalID) } numVotes := keeper.TallyVotes(ctx, params.ProposalID) @@ -180,30 +178,3 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke } return bz, nil } - -// ---------- Params ---------- - -// func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) { -// switch path[0] { -// case types.ParamDeposit: -// bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetDepositParams(ctx)) -// if err != nil { -// return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) -// } -// return bz, nil -// case types.ParamVoting: -// bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetVotingParams(ctx)) -// if err != nil { -// return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) -// } -// return bz, nil -// case types.ParamTallying: -// bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetTallyParams(ctx)) -// if err != nil { -// return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error())) -// } -// return bz, nil -// default: -// return nil, sdk.ErrUnknownRequest(fmt.Sprintf("%s is not a valid query request path", req.Path)) -// } -// } diff --git a/x/committee/proposal_handler.go b/x/committee/proposal_handler.go index e9d1eef8..e48ada2c 100644 --- a/x/committee/proposal_handler.go +++ b/x/committee/proposal_handler.go @@ -24,7 +24,7 @@ func NewProposalHandler(k Keeper) govtypes.Handler { func handleCommitteeChangeProposal(ctx sdk.Context, k Keeper, committeeProposal CommitteeChangeProposal) sdk.Error { if err := committeeProposal.ValidateBasic(); err != nil { - return sdk.ErrInternal(err.Error()) + return ErrInvalidCommittee(DefaultCodespace, err.Error()) } // Remove all committee's ongoing proposals @@ -46,7 +46,7 @@ func handleCommitteeChangeProposal(ctx sdk.Context, k Keeper, committeeProposal func handleCommitteeDeleteProposal(ctx sdk.Context, k Keeper, committeeProposal CommitteeDeleteProposal) sdk.Error { if err := committeeProposal.ValidateBasic(); err != nil { - return sdk.ErrInternal(err.Error()) + return ErrInvalidPubProposal(DefaultCodespace, err.Error()) } // Remove all committee's ongoing proposals diff --git a/x/committee/types/errors.go b/x/committee/types/errors.go index 57ccf762..0fa66126 100644 --- a/x/committee/types/errors.go +++ b/x/committee/types/errors.go @@ -1,9 +1,50 @@ package types import ( + "fmt" + "time" + sdk "github.com/cosmos/cosmos-sdk/types" ) const ( DefaultCodespace sdk.CodespaceType = ModuleName + + CodeProposalExpired sdk.CodeType = 1 + CodeUnknownItem sdk.CodeType = 2 + CodeInvalidGenesis sdk.CodeType = 3 + CodeInvalidProposal sdk.CodeType = 4 + CodeInvalidCommittee sdk.CodeType = 5 ) + +func ErrUnknownCommittee(codespace sdk.CodespaceType, id uint64) sdk.Error { + return sdk.NewError(codespace, CodeUnknownItem, fmt.Sprintf("committee with id '%d' not found", id)) +} + +func ErrInvalidCommittee(codespace sdk.CodespaceType, msg string) sdk.Error { + return sdk.NewError(codespace, CodeInvalidCommittee, msg) +} + +func ErrUnknownProposal(codespace sdk.CodespaceType, id uint64) sdk.Error { + return sdk.NewError(codespace, CodeUnknownItem, fmt.Sprintf("proposal with id '%d' not found", id)) +} + +func ErrProposalExpired(codespace sdk.CodespaceType, blockTime, expiry time.Time) sdk.Error { + return sdk.NewError(codespace, CodeProposalExpired, fmt.Sprintf("proposal expired at %s, current blocktime %s", expiry, blockTime)) +} + +func ErrInvalidPubProposal(codespace sdk.CodespaceType, msg string) sdk.Error { + return sdk.NewError(codespace, CodeInvalidProposal, msg) +} + +func ErrUnknownVote(codespace sdk.CodespaceType, proposalID uint64, voter sdk.AccAddress) sdk.Error { + return sdk.NewError(codespace, CodeUnknownItem, fmt.Sprintf("vote with for proposal '%d' and voter %s not found", proposalID, voter)) +} + +func ErrInvalidGenesis(codespace sdk.CodespaceType, msg string) sdk.Error { + return sdk.NewError(codespace, CodeInvalidGenesis, msg) +} + +func ErrNoProposalHandlerExists(codespace sdk.CodespaceType, content interface{}) sdk.Error { + return sdk.NewError(codespace, CodeUnknownItem, fmt.Sprintf("'%T' does not have a corresponding handler", content)) +} diff --git a/x/committee/types/gov_proposal.go b/x/committee/types/gov_proposal.go index b5938ad3..3609b90a 100644 --- a/x/committee/types/gov_proposal.go +++ b/x/committee/types/gov_proposal.go @@ -53,7 +53,7 @@ func (ccp CommitteeChangeProposal) ValidateBasic() sdk.Error { return err } if err := ccp.NewCommittee.Validate(); err != nil { - return sdk.ErrInternal(err.Error()) + return ErrInvalidCommittee(DefaultCodespace, err.Error()) } return nil } diff --git a/x/committee/types/msg.go b/x/committee/types/msg.go index 273a4654..173d9564 100644 --- a/x/committee/types/msg.go +++ b/x/committee/types/msg.go @@ -36,7 +36,7 @@ func (msg MsgSubmitProposal) Type() string { return TypeMsgSubmitProposal } // ValidateBasic does a simple validation check that doesn't require access to any other information. func (msg MsgSubmitProposal) ValidateBasic() sdk.Error { if msg.PubProposal == nil { - return sdk.ErrInternal("no proposal") + return ErrInvalidPubProposal(DefaultCodespace, "pub proposal cannot be nil") } if msg.Proposer.Empty() { return sdk.ErrInvalidAddress(msg.Proposer.String())