add custom errors

This commit is contained in:
rhuairahrighairigh 2020-03-29 20:43:25 +01:00
parent e228aa6659
commit 074bb246a8
10 changed files with 86 additions and 58 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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