2018-01-18 00:25:23 -08:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2018-04-17 19:16:21 -07:00
|
|
|
|
|
|
|
cmn "github.com/tendermint/tmlibs/common"
|
2018-04-02 03:44:55 -07:00
|
|
|
|
|
|
|
abci "github.com/tendermint/abci/types"
|
2018-01-18 00:25:23 -08:00
|
|
|
)
|
|
|
|
|
2018-04-17 19:16:21 -07:00
|
|
|
// ABCICodeType - combined codetype / codespace
|
|
|
|
type ABCICodeType uint32
|
|
|
|
|
|
|
|
// CodeType - code identifier within codespace
|
|
|
|
type CodeType uint16
|
2018-01-26 06:22:56 -08:00
|
|
|
|
2018-04-17 19:16:21 -07: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
|
2018-04-17 19:16:21 -07:00
|
|
|
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 (
|
2018-04-17 19:16:21 -07:00
|
|
|
// ABCI error codes
|
|
|
|
ABCICodeOK ABCICodeType = 0
|
|
|
|
|
|
|
|
// Base error codes
|
2018-03-17 19:42:54 -07:00
|
|
|
CodeOK CodeType = 0
|
|
|
|
CodeInternal CodeType = 1
|
2018-03-27 11:00:27 -07:00
|
|
|
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
|
|
|
|
2018-04-17 19:16:21 -07: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"
|
2018-03-20 18:40:58 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
return newErrorWithRootCodespace(CodeInternal, msg)
|
2018-01-18 00:25:23 -08:00
|
|
|
}
|
2018-03-20 18:40:58 -07:00
|
|
|
func ErrTxDecode(msg string) Error {
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
return newErrorWithRootCodespace(CodeInvalidAddress, msg)
|
2018-03-17 19:42:54 -07:00
|
|
|
}
|
|
|
|
func ErrUnknownAddress(msg string) Error {
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
return newErrorWithRootCodespace(CodeInsufficientCoins, msg)
|
2018-03-17 19:42:54 -07:00
|
|
|
}
|
|
|
|
func ErrInvalidCoins(msg string) Error {
|
2018-04-17 19:16:21 -07:00
|
|
|
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
|
2018-04-17 19:16:21 -07:00
|
|
|
Code() CodeType
|
|
|
|
Codespace() CodespaceType
|
2018-01-18 00:25:23 -08:00
|
|
|
ABCILog() string
|
2018-04-17 19:16:21 -07:00
|
|
|
ABCICode() ABCICodeType
|
|
|
|
WithDefaultCodespace(codespace CodespaceType) Error
|
2018-01-18 00:25:23 -08:00
|
|
|
Trace(msg string) Error
|
2018-04-17 19:16:21 -07:00
|
|
|
T() interface{}
|
2018-01-18 00:25:23 -08:00
|
|
|
Result() Result
|
2018-04-02 03:44:55 -07:00
|
|
|
QueryResult() abci.ResponseQuery
|
2018-01-18 00:25:23 -08:00
|
|
|
}
|
|
|
|
|
2018-04-17 19:16:21 -07: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
|
|
|
}
|
|
|
|
|
2018-04-17 19:16:21 -07:00
|
|
|
func newErrorWithRootCodespace(code CodeType, msg string) *sdkError {
|
|
|
|
return newError(CodespaceRoot, code, msg)
|
2018-01-18 00:25:23 -08:00
|
|
|
}
|
|
|
|
|
2018-04-17 19:16:21 -07: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{
|
2018-04-17 19:16:21 -07:00
|
|
|
codespace: codespace,
|
|
|
|
code: code,
|
|
|
|
err: cmn.NewErrorWithT(code, msg),
|
2018-01-18 00:25:23 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 19:16:21 -07: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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
return fmt.Sprintf("Error{%d:%d,%#v}", err.codespace, err.code, err.err)
|
2018-01-18 00:25:23 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Implements ABCIError.
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
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 {
|
2018-04-17 19:16:21 -07:00
|
|
|
return &sdkError{
|
|
|
|
codespace: err.codespace,
|
|
|
|
code: err.code,
|
|
|
|
err: err.err.Trace(msg),
|
|
|
|
}
|
2018-01-26 06:22:56 -08:00
|
|
|
}
|
|
|
|
|
2018-04-17 19:16:21 -07: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
|
|
|
}
|
|
|
|
|
2018-04-17 19:16:21 -07: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(),
|
|
|
|
}
|
|
|
|
}
|
2018-04-02 03:44:55 -07:00
|
|
|
|
|
|
|
// 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(),
|
|
|
|
}
|
|
|
|
}
|