diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 4d32b92f5..e2159aa29 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -87,7 +87,6 @@ func NewBaseApp(name string, cdc *wire.Codec, logger log.Logger, db dbm.DB) *Bas txDecoder: defaultTxDecoder(cdc), } // Register the undefined & root codespaces, which should not be used by any modules - app.codespacer.RegisterOrPanic(sdk.CodespaceUndefined) app.codespacer.RegisterOrPanic(sdk.CodespaceRoot) return app } @@ -137,7 +136,7 @@ func defaultTxDecoder(cdc *wire.Codec) sdk.TxDecoder { // are registered by MakeTxCodec err := cdc.UnmarshalBinary(txBytes, &tx) if err != nil { - return nil, sdk.ErrTxDecode("").Trace(err.Error()) + return nil, sdk.ErrTxDecode("").TraceSDK(err.Error()) } return tx, nil } @@ -486,7 +485,6 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk // Validate the Msg. err := msg.ValidateBasic() if err != nil { - err = err.WithDefaultCodespace(sdk.CodespaceRoot) return err.Result() } diff --git a/examples/democoin/x/cool/types.go b/examples/democoin/x/cool/types.go index b8640b211..77f49a0ba 100644 --- a/examples/democoin/x/cool/types.go +++ b/examples/democoin/x/cool/types.go @@ -41,13 +41,13 @@ func (msg MsgSetTrend) String() string { // Validate Basic is used to quickly disqualify obviously invalid messages quickly func (msg MsgSetTrend) ValidateBasic() sdk.Error { if len(msg.Sender) == 0 { - return sdk.ErrUnknownAddress(msg.Sender.String()).Trace("") + return sdk.ErrUnknownAddress(msg.Sender.String()).TraceSDK("") } if strings.Contains(msg.Cool, "hot") { - return sdk.ErrUnauthorized("").Trace("hot is not cool") + return sdk.ErrUnauthorized("").TraceSDK("hot is not cool") } if strings.Contains(msg.Cool, "warm") { - return sdk.ErrUnauthorized("").Trace("warm is not very cool") + return sdk.ErrUnauthorized("").TraceSDK("warm is not very cool") } return nil } @@ -91,7 +91,7 @@ func (msg MsgQuiz) String() string { // Validate Basic is used to quickly disqualify obviously invalid messages quickly func (msg MsgQuiz) ValidateBasic() sdk.Error { if len(msg.Sender) == 0 { - return sdk.ErrUnknownAddress(msg.Sender.String()).Trace("") + return sdk.ErrUnknownAddress(msg.Sender.String()).TraceSDK("") } return nil } diff --git a/types/errors.go b/types/errors.go index 20d452464..65c258b0c 100644 --- a/types/errors.go +++ b/types/errors.go @@ -55,10 +55,7 @@ const ( CodeOutOfGas CodeType = 12 // CodespaceRoot is a codespace for error codes in this file only. - // Notice that 0 is an "unset" codespace, which can be overridden with - // Error.WithDefaultCodespace(). - CodespaceUndefined CodespaceType = 0 - CodespaceRoot CodespaceType = 1 + CodespaceRoot CodespaceType = 1 // Maximum reservable codespace (2^16 - 1) MaximumCodespace CodespaceType = 65535 @@ -141,49 +138,64 @@ func ErrOutOfGas(msg string) Error { //---------------------------------------- // Error & sdkError +type cmnError = cmn.Error + // sdk Error type type Error interface { - Error() string + // Implements cmn.Error + // Error() string + // Stacktrace() cmn.Error + // Trace(offset int, format string, args ...interface{}) cmn.Error + // Data() interface{} + cmnError + + // convenience + TraceSDK(format string, args ...interface{}) Error + Code() CodeType Codespace() CodespaceType ABCILog() string ABCICode() ABCICodeType - WithDefaultCodespace(codespace CodespaceType) Error - Trace(msg string) Error - T() interface{} Result() Result QueryResult() abci.ResponseQuery } -// NewError - create an error -func NewError(codespace CodespaceType, code CodeType, msg string) Error { - return newError(codespace, code, msg) +// NewError - create an error. +func NewError(codespace CodespaceType, code CodeType, format string, args ...interface{}) Error { + return newError(codespace, code, format, args...) } -func newErrorWithRootCodespace(code CodeType, msg string) *sdkError { - return newError(CodespaceRoot, code, msg) +func newErrorWithRootCodespace(code CodeType, format string, args ...interface{}) *sdkError { + return newError(CodespaceRoot, code, format, args...) } -func newError(codespace CodespaceType, code CodeType, msg string) *sdkError { - if msg == "" { - msg = CodeToDefaultMsg(code) +func newError(codespace CodespaceType, code CodeType, format string, args ...interface{}) *sdkError { + if format == "" { + format = CodeToDefaultMsg(code) } return &sdkError{ codespace: codespace, code: code, - err: cmn.NewErrorWithT(code, msg), + cmnError: cmn.NewError(format, args...), } } type sdkError struct { codespace CodespaceType code CodeType - err cmn.Error + cmnError } // Implements ABCIError. +func (err *sdkError) TraceSDK(format string, args ...interface{}) Error { + err.Trace(1, format, args...) + return err +} + +// Implements ABCIError. +// Overrides err.Error.Error(). func (err *sdkError) Error() string { - return fmt.Sprintf("Error{%d:%d,%#v}", err.codespace, err.code, err.err) + return fmt.Sprintf("Error{%d:%d,%#v}", err.codespace, err.code, err.cmnError) } // Implements ABCIError. @@ -209,33 +221,7 @@ Code: %v ABCICode: %v Error: %#v === /ABCI Log === -`, err.codespace, err.code, err.ABCICode(), err.err) -} - -// Add tracing information with msg. -func (err *sdkError) Trace(msg string) Error { - return &sdkError{ - codespace: err.codespace, - code: err.code, - err: err.err.Trace(msg), - } -} - -// Implements Error. -func (err *sdkError) WithDefaultCodespace(cs CodespaceType) Error { - codespace := err.codespace - if codespace == CodespaceUndefined { - codespace = cs - } - return &sdkError{ - codespace: codespace, - code: err.code, - err: err.err, - } -} - -func (err *sdkError) T() interface{} { - return err.err.T() +`, err.codespace, err.code, err.ABCICode(), err.cmnError) } func (err *sdkError) Result() Result { diff --git a/x/bank/msgs.go b/x/bank/msgs.go index 48e62d835..1a871979e 100644 --- a/x/bank/msgs.go +++ b/x/bank/msgs.go @@ -27,28 +27,28 @@ func (msg MsgSend) ValidateBasic() sdk.Error { // this just makes sure all the inputs and outputs are properly formatted, // not that they actually have the money inside if len(msg.Inputs) == 0 { - return ErrNoInputs(DefaultCodespace).Trace("") + return ErrNoInputs(DefaultCodespace).TraceSDK("") } if len(msg.Outputs) == 0 { - return ErrNoOutputs(DefaultCodespace).Trace("") + return ErrNoOutputs(DefaultCodespace).TraceSDK("") } // make sure all inputs and outputs are individually valid var totalIn, totalOut sdk.Coins for _, in := range msg.Inputs { if err := in.ValidateBasic(); err != nil { - return err.Trace("") + return err.TraceSDK("") } totalIn = totalIn.Plus(in.Coins) } for _, out := range msg.Outputs { if err := out.ValidateBasic(); err != nil { - return err.Trace("") + return err.TraceSDK("") } totalOut = totalOut.Plus(out.Coins) } // make sure inputs and outputs match if !totalIn.IsEqual(totalOut) { - return sdk.ErrInvalidCoins(totalIn.String()).Trace("inputs and outputs don't match") + return sdk.ErrInvalidCoins(totalIn.String()).TraceSDK("inputs and outputs don't match") } return nil } @@ -107,11 +107,11 @@ func (msg MsgIssue) Type() string { return "bank" } // TODO: "bank/issue" func (msg MsgIssue) ValidateBasic() sdk.Error { // XXX if len(msg.Outputs) == 0 { - return ErrNoOutputs(DefaultCodespace).Trace("") + return ErrNoOutputs(DefaultCodespace).TraceSDK("") } for _, out := range msg.Outputs { if err := out.ValidateBasic(); err != nil { - return err.Trace("") + return err.TraceSDK("") } } return nil diff --git a/x/ibc/types.go b/x/ibc/types.go index 4924aec4b..a311b9869 100644 --- a/x/ibc/types.go +++ b/x/ibc/types.go @@ -65,7 +65,7 @@ func (p IBCPacket) GetSignBytes() []byte { // validator the ibc packey func (p IBCPacket) ValidateBasic() sdk.Error { if p.SrcChain == p.DestChain { - return ErrIdenticalChains(DefaultCodespace).Trace("") + return ErrIdenticalChains(DefaultCodespace).TraceSDK("") } if !p.Coins.IsValid() { return sdk.ErrInvalidCoins("")