cosmos-sdk/types/errors.go

255 lines
6.2 KiB
Go
Raw Normal View History

2018-01-18 00:25:23 -08:00
package types
import (
"fmt"
cmn "github.com/tendermint/tmlibs/common"
abci "github.com/tendermint/abci/types"
2018-01-18 00:25:23 -08:00
)
// ABCICodeType - combined codetype / codespace
type ABCICodeType uint32
// CodeType - code identifier within codespace
type CodeType uint16
2018-01-26 06:22:56 -08:00
// CodespaceType - codespace identifier
type CodespaceType uint16
// IsOK - is everything okay?
func (code ABCICodeType) IsOK() bool {
if code == ABCICodeOK {
2018-01-26 06:22:56 -08:00
return true
}
2018-02-04 16:59:11 -08:00
return false
2018-01-26 06:22:56 -08:00
}
2018-04-18 21:49:24 -07:00
// get the abci code from the local code and codespace
func ToABCICode(space CodespaceType, code CodeType) ABCICodeType {
// TODO: Make Tendermint more aware of codespaces.
if space == CodespaceRoot && code == CodeOK {
return ABCICodeOK
}
return ABCICodeType((uint32(space) << 16) | uint32(code))
}
2018-04-18 21:49:24 -07:00
// SDK error codes
2018-01-18 00:25:23 -08:00
const (
// ABCI error codes
ABCICodeOK ABCICodeType = 0
// Base error codes
2018-03-17 19:42:54 -07:00
CodeOK CodeType = 0
CodeInternal CodeType = 1
CodeTxDecode CodeType = 2
2018-03-17 19:42:54 -07:00
CodeInvalidSequence CodeType = 3
CodeUnauthorized CodeType = 4
CodeInsufficientFunds CodeType = 5
CodeUnknownRequest CodeType = 6
CodeInvalidAddress CodeType = 7
CodeInvalidPubKey CodeType = 8
CodeUnknownAddress CodeType = 9
CodeInsufficientCoins CodeType = 10
CodeInvalidCoins CodeType = 11
2018-05-07 11:28:53 -07:00
CodeOutOfGas CodeType = 12
2018-02-13 04:30:51 -08:00
// 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
// Maximum reservable codespace (2^16 - 1)
MaximumCodespace CodespaceType = 65535
2018-01-18 00:25:23 -08:00
)
// NOTE: Don't stringer this, we'll put better messages in later.
2018-01-26 06:22:56 -08:00
func CodeToDefaultMsg(code CodeType) string {
2018-01-18 00:25:23 -08:00
switch code {
2018-01-26 04:19:33 -08:00
case CodeInternal:
2018-01-18 00:25:23 -08:00
return "Internal error"
case CodeTxDecode:
2018-01-18 00:25:23 -08:00
return "Tx parse error"
2018-03-04 00:15:26 -08:00
case CodeInvalidSequence:
return "Invalid sequence"
2018-01-18 00:25:23 -08:00
case CodeUnauthorized:
return "Unauthorized"
case CodeInsufficientFunds:
return "Insufficent funds"
case CodeUnknownRequest:
return "Unknown request"
2018-03-17 19:42:54 -07:00
case CodeInvalidAddress:
return "Invalid address"
2018-03-17 11:54:18 -07:00
case CodeInvalidPubKey:
2018-03-17 13:53:27 -07:00
return "Invalid pubkey"
2018-03-19 15:31:23 -07:00
case CodeUnknownAddress:
return "Unknown address"
2018-03-17 19:42:54 -07:00
case CodeInsufficientCoins:
return "Insufficient coins"
case CodeInvalidCoins:
return "Invalid coins"
2018-05-07 11:28:53 -07:00
case CodeOutOfGas:
return "Out of gas"
2018-01-18 00:25:23 -08:00
default:
return fmt.Sprintf("Unknown code %d", code)
}
}
//--------------------------------------------------------------------------------
// All errors are created via constructors so as to enable us to hijack them
// and inject stack traces if we really want to.
2018-02-04 16:59:11 -08:00
// nolint
2018-01-26 04:19:33 -08:00
func ErrInternal(msg string) Error {
return newErrorWithRootCodespace(CodeInternal, msg)
2018-01-18 00:25:23 -08:00
}
func ErrTxDecode(msg string) Error {
return newErrorWithRootCodespace(CodeTxDecode, msg)
2018-02-06 19:23:30 -08:00
}
2018-03-04 00:15:26 -08:00
func ErrInvalidSequence(msg string) Error {
return newErrorWithRootCodespace(CodeInvalidSequence, msg)
2018-01-18 00:25:23 -08:00
}
2018-01-26 04:19:33 -08:00
func ErrUnauthorized(msg string) Error {
return newErrorWithRootCodespace(CodeUnauthorized, msg)
2018-01-18 00:25:23 -08:00
}
2018-01-26 04:19:33 -08:00
func ErrInsufficientFunds(msg string) Error {
return newErrorWithRootCodespace(CodeInsufficientFunds, msg)
2018-01-18 00:25:23 -08:00
}
2018-01-26 04:19:33 -08:00
func ErrUnknownRequest(msg string) Error {
return newErrorWithRootCodespace(CodeUnknownRequest, msg)
2018-01-18 00:25:23 -08:00
}
2018-03-17 19:42:54 -07:00
func ErrInvalidAddress(msg string) Error {
return newErrorWithRootCodespace(CodeInvalidAddress, msg)
2018-03-17 19:42:54 -07:00
}
func ErrUnknownAddress(msg string) Error {
return newErrorWithRootCodespace(CodeUnknownAddress, msg)
2018-01-26 04:19:33 -08:00
}
2018-03-17 11:54:18 -07:00
func ErrInvalidPubKey(msg string) Error {
return newErrorWithRootCodespace(CodeInvalidPubKey, msg)
2018-01-26 04:19:33 -08:00
}
2018-03-17 19:42:54 -07:00
func ErrInsufficientCoins(msg string) Error {
return newErrorWithRootCodespace(CodeInsufficientCoins, msg)
2018-03-17 19:42:54 -07:00
}
func ErrInvalidCoins(msg string) Error {
return newErrorWithRootCodespace(CodeInvalidCoins, msg)
2018-03-17 19:42:54 -07:00
}
2018-05-07 11:28:53 -07:00
func ErrOutOfGas(msg string) Error {
return newErrorWithRootCodespace(CodeOutOfGas, msg)
}
2018-01-18 00:25:23 -08:00
//----------------------------------------
// Error & sdkError
2018-02-04 16:59:11 -08:00
// sdk Error type
2018-01-18 00:25:23 -08:00
type Error interface {
Error() string
Code() CodeType
Codespace() CodespaceType
2018-01-18 00:25:23 -08:00
ABCILog() string
ABCICode() ABCICodeType
WithDefaultCodespace(codespace CodespaceType) Error
2018-01-18 00:25:23 -08:00
Trace(msg string) Error
T() interface{}
2018-01-18 00:25:23 -08:00
Result() Result
QueryResult() abci.ResponseQuery
2018-01-18 00:25:23 -08:00
}
// NewError - create an error
func NewError(codespace CodespaceType, code CodeType, msg string) Error {
return newError(codespace, code, msg)
2018-01-18 00:25:23 -08:00
}
func newErrorWithRootCodespace(code CodeType, msg string) *sdkError {
return newError(CodespaceRoot, code, msg)
2018-01-18 00:25:23 -08:00
}
func newError(codespace CodespaceType, code CodeType, msg string) *sdkError {
2018-01-26 04:19:33 -08:00
if msg == "" {
msg = CodeToDefaultMsg(code)
2018-01-18 00:25:23 -08:00
}
return &sdkError{
codespace: codespace,
code: code,
err: cmn.NewErrorWithT(code, msg),
2018-01-18 00:25:23 -08:00
}
}
type sdkError struct {
codespace CodespaceType
code CodeType
err cmn.Error
}
2018-01-18 00:25:23 -08:00
// Implements ABCIError.
func (err *sdkError) Error() string {
return fmt.Sprintf("Error{%d:%d,%#v}", err.codespace, err.code, err.err)
2018-01-18 00:25:23 -08:00
}
// Implements ABCIError.
func (err *sdkError) ABCICode() ABCICodeType {
return ToABCICode(err.codespace, err.code)
}
// Implements Error.
func (err *sdkError) Codespace() CodespaceType {
return err.codespace
}
// Implements Error.
func (err *sdkError) Code() CodeType {
2018-01-18 00:25:23 -08:00
return err.code
}
// Implements ABCIError.
func (err *sdkError) ABCILog() string {
return fmt.Sprintf(`=== ABCI Log ===
Codespace: %v
Code: %v
ABCICode: %v
Error: %#v
=== /ABCI Log ===
`, err.codespace, err.code, err.ABCICode(), err.err)
2018-01-18 00:25:23 -08:00
}
2018-01-26 04:19:33 -08:00
// Add tracing information with msg.
2018-01-18 00:25:23 -08:00
func (err *sdkError) Trace(msg string) Error {
return &sdkError{
codespace: err.codespace,
code: err.code,
err: err.err.Trace(msg),
}
2018-01-26 06:22:56 -08:00
}
// 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,
}
2018-01-26 06:22:56 -08:00
}
func (err *sdkError) T() interface{} {
return err.err.T()
2018-01-18 00:25:23 -08:00
}
func (err *sdkError) Result() Result {
return Result{
Code: err.ABCICode(),
Log: err.ABCILog(),
}
}
// QueryResult allows us to return sdk.Error.QueryResult() in query responses
func (err *sdkError) QueryResult() abci.ResponseQuery {
return abci.ResponseQuery{
Code: uint32(err.ABCICode()),
Log: err.ABCILog(),
}
}