github.com/Finschia/finschia-sdk@v0.48.1/types/errors/errors.go (about) 1 package errors 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/pkg/errors" 8 ) 9 10 // RootCodespace is the codespace for all errors defined in this package 11 const RootCodespace = "sdk" 12 13 // UndefinedCodespace when we explicitly declare no codespace 14 const UndefinedCodespace = "undefined" 15 16 var ( 17 // errInternal should never be exposed, but we reserve this code for non-specified errors 18 errInternal = Register(UndefinedCodespace, 1, "internal") //nolint:deadcode,unused,varcheck 19 20 // ErrTxDecode is returned if we cannot parse a transaction 21 ErrTxDecode = Register(RootCodespace, 2, "tx parse error") 22 23 // ErrInvalidSequence is used the sequence number (nonce) is incorrect 24 // for the signature 25 ErrInvalidSequence = Register(RootCodespace, 3, "invalid sequence") 26 27 // ErrUnauthorized is used whenever a request without sufficient 28 // authorization is handled. 29 ErrUnauthorized = Register(RootCodespace, 4, "unauthorized") 30 31 // ErrInsufficientFunds is used when the account cannot pay requested amount. 32 ErrInsufficientFunds = Register(RootCodespace, 5, "insufficient funds") 33 34 // ErrUnknownRequest to doc 35 ErrUnknownRequest = Register(RootCodespace, 6, "unknown request") 36 37 // ErrInvalidAddress to doc 38 ErrInvalidAddress = Register(RootCodespace, 7, "invalid address") 39 40 // ErrInvalidPubKey to doc 41 ErrInvalidPubKey = Register(RootCodespace, 8, "invalid pubkey") 42 43 // ErrUnknownAddress to doc 44 ErrUnknownAddress = Register(RootCodespace, 9, "unknown address") 45 46 // ErrInvalidCoins to doc 47 ErrInvalidCoins = Register(RootCodespace, 10, "invalid coins") 48 49 // ErrOutOfGas to doc 50 ErrOutOfGas = Register(RootCodespace, 11, "out of gas") 51 52 // ErrMemoTooLarge to doc 53 ErrMemoTooLarge = Register(RootCodespace, 12, "memo too large") 54 55 // ErrInsufficientFee to doc 56 ErrInsufficientFee = Register(RootCodespace, 13, "insufficient fee") 57 58 // ErrTooManySignatures to doc 59 ErrTooManySignatures = Register(RootCodespace, 14, "maximum number of signatures exceeded") 60 61 // ErrNoSignatures to doc 62 ErrNoSignatures = Register(RootCodespace, 15, "no signatures supplied") 63 64 // ErrJSONMarshal defines an ABCI typed JSON marshalling error 65 ErrJSONMarshal = Register(RootCodespace, 16, "failed to marshal JSON bytes") 66 67 // ErrJSONUnmarshal defines an ABCI typed JSON unmarshalling error 68 ErrJSONUnmarshal = Register(RootCodespace, 17, "failed to unmarshal JSON bytes") 69 70 // ErrInvalidRequest defines an ABCI typed error where the request contains 71 // invalid data. 72 ErrInvalidRequest = Register(RootCodespace, 18, "invalid request") 73 74 // ErrTxInMempoolCache defines an ABCI typed error where a tx already exists 75 // in the mempool. 76 ErrTxInMempoolCache = Register(RootCodespace, 19, "tx already in mempool") 77 78 // ErrMempoolIsFull defines an ABCI typed error where the mempool is full. 79 ErrMempoolIsFull = Register(RootCodespace, 20, "mempool is full") 80 81 // ErrTxTooLarge defines an ABCI typed error where tx is too large. 82 ErrTxTooLarge = Register(RootCodespace, 21, "tx too large") 83 84 // ErrKeyNotFound defines an error when the key doesn't exist 85 ErrKeyNotFound = Register(RootCodespace, 22, "key not found") 86 87 // ErrWrongPassword defines an error when the key password is invalid. 88 ErrWrongPassword = Register(RootCodespace, 23, "invalid account password") 89 90 // ErrorInvalidSigner defines an error when the tx intended signer does not match the given signer. 91 ErrorInvalidSigner = Register(RootCodespace, 24, "tx intended signer does not match the given signer") 92 93 // ErrorInvalidGasAdjustment defines an error for an invalid gas adjustment 94 ErrorInvalidGasAdjustment = Register(RootCodespace, 25, "invalid gas adjustment") 95 96 // ErrInvalidHeight defines an error for an invalid height 97 ErrInvalidHeight = Register(RootCodespace, 26, "invalid height") 98 99 // ErrInvalidVersion defines a general error for an invalid version 100 ErrInvalidVersion = Register(RootCodespace, 27, "invalid version") 101 102 // ErrInvalidChainID defines an error when the chain-id is invalid. 103 ErrInvalidChainID = Register(RootCodespace, 28, "invalid chain-id") 104 105 // ErrInvalidType defines an error an invalid type. 106 ErrInvalidType = Register(RootCodespace, 29, "invalid type") 107 108 // ErrTxTimeoutHeight defines an error for when a tx is rejected out due to an 109 // explicitly set timeout height. 110 ErrTxTimeoutHeight = Register(RootCodespace, 30, "tx timeout height") 111 112 // ErrUnknownExtensionOptions defines an error for unknown extension options. 113 ErrUnknownExtensionOptions = Register(RootCodespace, 31, "unknown extension options") 114 115 // ErrWrongSequence defines an error where the account sequence defined in 116 // the signer info doesn't match the account's actual sequence number. 117 ErrWrongSequence = Register(RootCodespace, 32, "incorrect account sequence") 118 119 // ErrPackAny defines an error when packing a protobuf message to Any fails. 120 ErrPackAny = Register(RootCodespace, 33, "failed packing protobuf message to Any") 121 122 // ErrUnpackAny defines an error when unpacking a protobuf message from Any fails. 123 ErrUnpackAny = Register(RootCodespace, 34, "failed unpacking protobuf message from Any") 124 125 // ErrLogic defines an internal logic error, e.g. an invariant or assertion 126 // that is violated. It is a programmer error, not a user-facing error. 127 ErrLogic = Register(RootCodespace, 35, "internal logic error") 128 129 // ErrConflict defines a conflict error, e.g. when two goroutines try to access 130 // the same resource and one of them fails. 131 ErrConflict = Register(RootCodespace, 36, "conflict") 132 133 // ErrNotSupported is returned when we call a branch of a code which is currently not 134 // supported. 135 ErrNotSupported = Register(RootCodespace, 37, "feature not supported") 136 137 // ErrNotFound defines an error when requested entity doesn't exist in the state. 138 ErrNotFound = Register(RootCodespace, 38, "not found") 139 140 // ErrIO should be used to wrap internal errors caused by external operation. 141 // Examples: not DB domain error, file writing etc... 142 ErrIO = Register(RootCodespace, 39, "Internal IO error") 143 144 // ErrAppConfig defines an error occurred if min-gas-prices field in BaseConfig is empty. 145 ErrAppConfig = Register(RootCodespace, 40, "error in app.toml") 146 147 // ErrPanic is only set when we recover from a panic, so we know to 148 // redact potentially sensitive system info 149 ErrPanic = Register(UndefinedCodespace, 111222, "panic") 150 ) 151 152 // Register returns an error instance that should be used as the base for 153 // creating error instances during runtime. 154 // 155 // Popular root errors are declared in this package, but extensions may want to 156 // declare custom codes. This function ensures that no error code is used 157 // twice. Attempt to reuse an error code results in panic. 158 // 159 // Use this function only during a program startup phase. 160 func Register(codespace string, code uint32, description string) *Error { 161 // TODO - uniqueness is (codespace, code) combo 162 if e := getUsed(codespace, code); e != nil { 163 panic(fmt.Sprintf("error with code %d is already registered: %q", code, e.desc)) 164 } 165 166 err := New(codespace, code, description) 167 setUsed(err) 168 169 return err 170 } 171 172 // usedCodes is keeping track of used codes to ensure their uniqueness. No two 173 // error instances should share the same (codespace, code) tuple. 174 var usedCodes = map[string]*Error{} 175 176 func errorID(codespace string, code uint32) string { 177 return fmt.Sprintf("%s:%d", codespace, code) 178 } 179 180 func getUsed(codespace string, code uint32) *Error { 181 return usedCodes[errorID(codespace, code)] 182 } 183 184 func setUsed(err *Error) { 185 usedCodes[errorID(err.codespace, err.code)] = err 186 } 187 188 // ABCIError will resolve an error code/log from an abci result into 189 // an error message. If the code is registered, it will map it back to 190 // the canonical error, so we can do eg. ErrNotFound.Is(err) on something 191 // we get back from an external API. 192 // 193 // This should *only* be used in clients, not in the server side. 194 // The server (abci app / blockchain) should only refer to registered errors 195 func ABCIError(codespace string, code uint32, log string) error { 196 if e := getUsed(codespace, code); e != nil { 197 return Wrap(e, log) 198 } 199 // This is a unique error, will never match on .Is() 200 // Use Wrap here to get a stack trace 201 return Wrap(New(codespace, code, "unknown"), log) 202 } 203 204 // Error represents a root error. 205 // 206 // Weave framework is using root error to categorize issues. Each instance 207 // created during the runtime should wrap one of the declared root errors. This 208 // allows error tests and returning all errors to the client in a safe manner. 209 // 210 // All popular root errors are declared in this package. If an extension has to 211 // declare a custom root error, always use Register function to ensure 212 // error code uniqueness. 213 type Error struct { 214 codespace string 215 code uint32 216 desc string 217 } 218 219 func New(codespace string, code uint32, desc string) *Error { 220 return &Error{codespace: codespace, code: code, desc: desc} 221 } 222 223 func (e Error) Error() string { 224 return e.desc 225 } 226 227 func (e Error) ABCICode() uint32 { 228 return e.code 229 } 230 231 func (e Error) Codespace() string { 232 return e.codespace 233 } 234 235 // Is check if given error instance is of a given kind/type. This involves 236 // unwrapping given error using the Cause method if available. 237 func (e *Error) Is(err error) bool { 238 // Reflect usage is necessary to correctly compare with 239 // a nil implementation of an error. 240 if e == nil { 241 return isNilErr(err) 242 } 243 244 for { 245 if err == e { 246 return true 247 } 248 249 // If this is a collection of errors, this function must return 250 // true if at least one from the group match. 251 if u, ok := err.(unpacker); ok { 252 for _, er := range u.Unpack() { 253 if e.Is(er) { 254 return true 255 } 256 } 257 } 258 259 if c, ok := err.(causer); ok { 260 err = c.Cause() 261 } else { 262 return false 263 } 264 } 265 } 266 267 // Wrap extends this error with an additional information. 268 // It's a handy function to call Wrap with sdk errors. 269 func (e *Error) Wrap(desc string) error { return Wrap(e, desc) } 270 271 // Wrapf extends this error with an additional information. 272 // It's a handy function to call Wrapf with sdk errors. 273 func (e *Error) Wrapf(desc string, args ...interface{}) error { return Wrapf(e, desc, args...) } 274 275 func isNilErr(err error) bool { 276 // Reflect usage is necessary to correctly compare with 277 // a nil implementation of an error. 278 if err == nil { 279 return true 280 } 281 if reflect.ValueOf(err).Kind() == reflect.Struct { 282 return false 283 } 284 return reflect.ValueOf(err).IsNil() 285 } 286 287 // Wrap extends given error with an additional information. 288 // 289 // If the wrapped error does not provide ABCICode method (ie. stdlib errors), 290 // it will be labeled as internal error. 291 // 292 // If err is nil, this returns nil, avoiding the need for an if statement when 293 // wrapping a error returned at the end of a function 294 func Wrap(err error, description string) error { 295 if err == nil { 296 return nil 297 } 298 299 // If this error does not carry the stacktrace information yet, attach 300 // one. This should be done only once per error at the lowest frame 301 // possible (most inner wrap). 302 if stackTrace(err) == nil { 303 err = errors.WithStack(err) 304 } 305 306 return &wrappedError{ 307 parent: err, 308 msg: description, 309 } 310 } 311 312 // Wrapf extends given error with an additional information. 313 // 314 // This function works like Wrap function with additional functionality of 315 // formatting the input as specified. 316 func Wrapf(err error, format string, args ...interface{}) error { 317 desc := fmt.Sprintf(format, args...) 318 return Wrap(err, desc) 319 } 320 321 type wrappedError struct { 322 // This error layer description. 323 msg string 324 // The underlying error that triggered this one. 325 parent error 326 } 327 328 func (e *wrappedError) Error() string { 329 return fmt.Sprintf("%s: %s", e.msg, e.parent.Error()) 330 } 331 332 func (e *wrappedError) Cause() error { 333 return e.parent 334 } 335 336 // Is reports whether any error in e's chain matches a target. 337 func (e *wrappedError) Is(target error) bool { 338 if e == target { 339 return true 340 } 341 342 w := e.Cause() 343 for { 344 if w == target { 345 return true 346 } 347 348 x, ok := w.(causer) 349 if ok { 350 w = x.Cause() 351 } 352 if x == nil { 353 return false 354 } 355 } 356 } 357 358 // Unwrap implements the built-in errors.Unwrap 359 func (e *wrappedError) Unwrap() error { 360 return e.parent 361 } 362 363 // Recover captures a panic and stop its propagation. If panic happens it is 364 // transformed into a ErrPanic instance and assigned to given error. Call this 365 // function using defer in order to work as expected. 366 func Recover(err *error) { 367 if r := recover(); r != nil { 368 *err = Wrapf(ErrPanic, "%v", r) 369 } 370 } 371 372 // WithType is a helper to augment an error with a corresponding type message 373 func WithType(err error, obj interface{}) error { 374 return Wrap(err, fmt.Sprintf("%T", obj)) 375 } 376 377 // IsOf checks if a received error is caused by one of the target errors. 378 // It extends the errors.Is functionality to a list of errors. 379 func IsOf(received error, targets ...error) bool { 380 for _, t := range targets { 381 if errors.Is(received, t) { 382 return true 383 } 384 } 385 return false 386 } 387 388 // causer is an interface implemented by an error that supports wrapping. Use 389 // it to test if an error wraps another error instance. 390 type causer interface { 391 Cause() error 392 } 393 394 type unpacker interface { 395 Unpack() []error 396 }