Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error improvements #238

Merged
merged 12 commits into from
Jul 17, 2020
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Version 0.10.0
## Changes
- Changed the returned error to make them more clear (#237)

## Bug fixes
- Fixed a bug that caused valid URIs to be considered invalid (#233)

Expand Down
10 changes: 10 additions & 0 deletions x/commons/types/errors/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package errors

import sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

// RootCodespace is the codespace for all errors defined in this package
const RootCodespace = "desmos"

var (
ErrInvalidURI = sdkerrors.Register(RootCodespace, 1, "invalid uri")
)
7 changes: 4 additions & 3 deletions x/magpie/keeper/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/desmos-labs/desmos/x/magpie/types"
"github.com/tendermint/tendermint/crypto/secp256k1"

"github.com/desmos-labs/desmos/x/magpie/types"
)

// NewHandler returns a handler for "magpie" type messages.
Expand All @@ -21,8 +22,8 @@ func NewHandler(keeper Keeper) sdk.Handler {
case types.MsgCreateSession:
return handleMsgCreateSession(ctx, keeper, msg)
default:
errMsg := fmt.Sprintf("Unrecognized Magpie message type: %v", msg.Type())
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest,
fmt.Sprintf("unrecognized magpie message type: %v", msg.Type()))
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions x/magpie/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,24 @@ func (msg MsgCreateSession) Type() string { return ActionCreationSession }
// ValidateBasic runs stateless checks on the message
func (msg MsgCreateSession) ValidateBasic() error {
if msg.Owner.Empty() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("Invalid session owner: %s", msg.Owner))
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid session owner: %s", msg.Owner))
}

if len(strings.TrimSpace(msg.Namespace)) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Session namespace cannot be empty")
return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "session namespace cannot be empty")
}

if len(strings.TrimSpace(msg.PubKey)) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Signer public key cannot be empty")
return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "signer's public key cannot be empty")
}

// The external signer address doesn't have to exist on Desmos
if len(strings.TrimSpace(msg.ExternalOwner)) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Session external owner cannot be empty")
return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "session external owner cannot be empty")
}

if len(strings.TrimSpace(msg.Signature)) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Session signature cannot be empty")
return sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "session signature cannot be empty")
}

return nil
Expand Down
13 changes: 7 additions & 6 deletions x/magpie/types/msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/desmos-labs/desmos/x/magpie/types"
"github.com/stretchr/testify/require"

"github.com/desmos-labs/desmos/x/magpie/types"
)

// ----------------------
Expand Down Expand Up @@ -47,7 +48,7 @@ func TestMsgCreateSession_ValidateBasic(t *testing.T) {
"cosmospub1addwnpepqf06gxm8tf4u9af99zsuphr2jmqvr2t956me5rcx9kywmrtg6jewy8gjtcs",
"QmZh...===",
),
expErr: sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "Invalid session owner: "),
expErr: sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid session owner: "),
},
{
name: "Invalid namespace",
Expand All @@ -58,7 +59,7 @@ func TestMsgCreateSession_ValidateBasic(t *testing.T) {
"cosmospub1addwnpepqf06gxm8tf4u9af99zsuphr2jmqvr2t956me5rcx9kywmrtg6jewy8gjtcs",
"QmZh...===",
),
expErr: sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Session namespace cannot be empty"),
expErr: sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "session namespace cannot be empty"),
},
{
name: "Invalid external owner",
Expand All @@ -69,7 +70,7 @@ func TestMsgCreateSession_ValidateBasic(t *testing.T) {
"cosmospub1addwnpepqf06gxm8tf4u9af99zsuphr2jmqvr2t956me5rcx9kywmrtg6jewy8gjtcs",
"QmZh...===",
),
expErr: sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Session external owner cannot be empty"),
expErr: sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "session external owner cannot be empty"),
},
{
name: "Invalid public key",
Expand All @@ -80,7 +81,7 @@ func TestMsgCreateSession_ValidateBasic(t *testing.T) {
" ",
"QmZh...===",
),
expErr: sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Signer public key cannot be empty"),
expErr: sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "signer's public key cannot be empty"),
},
{
name: "Invalid signature",
Expand All @@ -91,7 +92,7 @@ func TestMsgCreateSession_ValidateBasic(t *testing.T) {
"cosmospub1addwnpepqf06gxm8tf4u9af99zsuphr2jmqvr2t956me5rcx9kywmrtg6jewy8gjtcs",
" ",
),
expErr: sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "Session signature cannot be empty"),
expErr: sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "session signature cannot be empty"),
},
}

Expand Down
18 changes: 18 additions & 0 deletions x/posts/types/errors/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package errors

import sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

// RootCodespace is the codespace for all errors defined in this package
const RootCodespace = "posts"

var (
// ErrInvalidPostID is returned if we cannot parse a post id
ErrInvalidPostID = sdkerrors.Register(RootCodespace, 1, "invalid post id")

// ErrInvalidSubspace is returned if a post subspace is not valid
ErrInvalidSubspace = sdkerrors.Register(RootCodespace, 2, "invalid subspace")

// ErrInvalidReactionCode is returned if we cannot validate a reaction short code
ErrInvalidReactionCode = sdkerrors.Register(RootCodespace, 3,
"invalid reaction shortcode (it must only contains a-z, 0-9, - and _ and must start and end with a ':')")
)
20 changes: 11 additions & 9 deletions x/posts/types/msgs/msg_reactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

postsModels "github.com/desmos-labs/desmos/x/posts/types/models"
commonerrors "github.com/desmos-labs/desmos/x/commons/types/errors"
postserrors "github.com/desmos-labs/desmos/x/posts/types/errors"
postsmodels "github.com/desmos-labs/desmos/x/posts/types/models"
)

// MsgRegisterReaction represents the message that must be used when wanting
Expand All @@ -31,27 +33,27 @@ func NewMsgRegisterReaction(creator sdk.AccAddress, shortCode, value, subspace s
}

// Route should return the name of the module
func (msg MsgRegisterReaction) Route() string { return postsModels.RouterKey }
func (msg MsgRegisterReaction) Route() string { return postsmodels.RouterKey }

// Type should return the action
func (msg MsgRegisterReaction) Type() string { return postsModels.ActionRegisterReaction }
func (msg MsgRegisterReaction) Type() string { return postsmodels.ActionRegisterReaction }

// ValidateBasic runs stateless checks on the message
func (msg MsgRegisterReaction) ValidateBasic() error {
if msg.Creator.Empty() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("Invalid creator address: %s", msg.Creator))
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid creator address: %s", msg.Creator))
}

if !postsModels.ShortCodeRegEx.MatchString(msg.ShortCode) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "The specified shortcode is not valid. To be valid it must only contains a-z, 0-9, - and _ and must start and end with a :")
if !postsmodels.ShortCodeRegEx.MatchString(msg.ShortCode) {
return sdkerrors.Wrap(postserrors.ErrInvalidReactionCode, msg.ShortCode)
}

if !commons.IsURIValid(msg.Value) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reaction value should be a valid URL")
return sdkerrors.Wrap(commonerrors.ErrInvalidURI, "reaction value should be a valid uri")
}

if !postsModels.Sha256RegEx.MatchString(msg.Subspace) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reaction subspace must be a valid sha-256 hash")
if !postsmodels.Sha256RegEx.MatchString(msg.Subspace) {
return sdkerrors.Wrap(postserrors.ErrInvalidSubspace, "reaction subspace must be a valid sha-256 hash")
}

return nil
Expand Down
20 changes: 11 additions & 9 deletions x/posts/types/msgs/msg_reactions_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package msgs_test

import (
"fmt"
"testing"

commonerrors "github.com/desmos-labs/desmos/x/commons/types/errors"
postserrors "github.com/desmos-labs/desmos/x/posts/types/errors"

sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -33,48 +35,48 @@ func TestMsgRegisterReaction_ValidateBasic(t *testing.T) {
name: "Invalid creator returns error",
msg: msgs.NewMsgRegisterReaction(nil, ":smile:", "https://smile.jpg",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("Invalid creator address: %s", "")),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid creator address: "),
},
{
name: "Empty short code returns error",
msg: msgs.NewMsgRegisterReaction(testOwner, "", "https://smile.jpg",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "The specified shortcode is not valid. To be valid it must only contains a-z, 0-9, - and _ and must start and end with a :"),
error: sdkerrors.Wrap(postserrors.ErrInvalidReactionCode, ""),
},
{
name: "Invalid short code returns error",
msg: msgs.NewMsgRegisterReaction(testOwner, ":smile", "https://smile.jpg",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "The specified shortcode is not valid. To be valid it must only contains a-z, 0-9, - and _ and must start and end with a :"),
error: sdkerrors.Wrap(postserrors.ErrInvalidReactionCode, ":smile"),
},
{
name: "Empty value returns error",
msg: msgs.NewMsgRegisterReaction(testOwner, ":smile:", "",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reaction value should be a valid URL"),
error: sdkerrors.Wrap(commonerrors.ErrInvalidURI, "reaction value should be a valid uri"),
},
{
name: "Invalid value returns error (url)",
msg: msgs.NewMsgRegisterReaction(testOwner, ":smile:", "htp://smile.jpg",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reaction value should be a valid URL"),
error: sdkerrors.Wrap(commonerrors.ErrInvalidURI, "reaction value should be a valid uri"),
},
{
name: "Invalid value returns error (unicode)",
msg: msgs.NewMsgRegisterReaction(testOwner, ":smile:", "U+1",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reaction value should be a valid URL"),
error: sdkerrors.Wrap(commonerrors.ErrInvalidURI, "reaction value should be a valid uri"),
},
{
name: "Valid emoji value returns no error",
msg: msgs.NewMsgRegisterReaction(testOwner, ":smile:", "💙", "4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reaction value should be a valid URL"),
error: sdkerrors.Wrap(commonerrors.ErrInvalidURI, "reaction value should be a valid uri"),
},
{
name: "Invalid subspace returns error",
msg: msgs.NewMsgRegisterReaction(testOwner, ":smile:", "https://smile.jpg",
"1234"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "reaction subspace must be a valid sha-256 hash"),
error: sdkerrors.Wrap(postserrors.ErrInvalidSubspace, "reaction subspace must be a valid sha-256 hash"),
},
}

Expand Down
16 changes: 10 additions & 6 deletions x/posts/types/msgs/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import (
"strings"
"time"

postserrors "github.com/desmos-labs/desmos/x/posts/types/errors"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/desmos-labs/desmos/x/posts/types/models"
)

Expand Down Expand Up @@ -54,23 +57,24 @@ func (msg MsgCreatePost) Type() string { return models.ActionCreatePost }
// ValidateBasic runs stateless checks on the message
func (msg MsgCreatePost) ValidateBasic() error {
if msg.Creator.Empty() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("Invalid creator address: %s", msg.Creator))
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid creator address: %s", msg.Creator))
}

if len(strings.TrimSpace(msg.Message)) == 0 && len(msg.Medias) == 0 && msg.PollData == nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Post message, medias or poll are required and cannot be all blank or empty")
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
"post message, medias or poll are required and cannot be all blank or empty")
}

if !models.Sha256RegEx.MatchString(msg.Subspace) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Post subspace must be a valid sha-256 hash")
return sdkerrors.Wrap(postserrors.ErrInvalidSubspace, "post subspace must be a valid sha-256 hash")
}

if msg.CreationDate.IsZero() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid post creation date")
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid post creation date")
}

if msg.CreationDate.After(time.Now().UTC()) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Creation date cannot be in the future")
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "creation date cannot be in the future")
}

if msg.Medias != nil {
Expand All @@ -81,7 +85,7 @@ func (msg MsgCreatePost) ValidateBasic() error {

if msg.PollData != nil {
if !msg.PollData.Open {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Poll Post cannot be created closed")
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "poll cannot be created closed")
}
if err := msg.PollData.Validate(); err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())
Expand Down
9 changes: 6 additions & 3 deletions x/posts/types/msgs/msgs_polls.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package msgs
import (
"fmt"

postserrors "github.com/desmos-labs/desmos/x/posts/types/errors"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/desmos-labs/desmos/x/posts/types/models"
)

Expand Down Expand Up @@ -37,15 +40,15 @@ func (msg MsgAnswerPoll) Type() string { return models.ActionAnswerPoll }
// ValidateBasic runs stateless checks on the message
func (msg MsgAnswerPoll) ValidateBasic() error {
if !msg.PostID.Valid() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("Invalid post id: %s", msg.PostID))
return sdkerrors.Wrap(postserrors.ErrInvalidPostID, msg.PostID.String())
}

if msg.Answerer.Empty() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("Invalid answerer address: %s", msg.Answerer))
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, fmt.Sprintf("invalid answerer address: %s", msg.Answerer))
}

if len(msg.UserAnswers) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Provided answers must contains at least one answer")
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "provided answers must contains at least one answer")
}

return nil
Expand Down
11 changes: 7 additions & 4 deletions x/posts/types/msgs/msgs_polls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package msgs_test
import (
"testing"

postserrors "github.com/desmos-labs/desmos/x/posts/types/errors"

sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/stretchr/testify/require"

"github.com/desmos-labs/desmos/x/posts/types/models"
"github.com/desmos-labs/desmos/x/posts/types/msgs"
"github.com/stretchr/testify/require"
)

// ----------------------
Expand Down Expand Up @@ -34,17 +37,17 @@ func TestMsgAnswerPollPost_ValidateBasic(t *testing.T) {
{
name: "Invalid post id",
msg: msgs.NewMsgAnswerPoll("", []models.AnswerID{1, 2}, msgAnswerPollPost.Answerer),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Invalid post id: "),
error: sdkerrors.Wrap(postserrors.ErrInvalidPostID, ""),
},
{
name: "Invalid answerer address",
msg: msgs.NewMsgAnswerPoll(id, []models.AnswerID{1, 2}, nil),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "Invalid answerer address: "),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid answerer address: "),
},
{
name: "Returns error when no answer is provided",
msg: msgs.NewMsgAnswerPoll(id, []models.AnswerID{}, msgAnswerPollPost.Answerer),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Provided answers must contains at least one answer"),
error: sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "provided answers must contains at least one answer"),
},
{
name: "Valid message returns no error",
Expand Down
Loading