-
Notifications
You must be signed in to change notification settings - Fork 296
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
blockchain/stake: update error types.
This updates the stake error types to leverage go 1.13 errors.Is/As functionality as well as confirm to the error infrastructure best practices.
- Loading branch information
Showing
6 changed files
with
440 additions
and
412 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,255 +1,205 @@ | ||
// Copyright (c) 2014 Conformal Systems LLC. | ||
// Copyright (c) 2015-2016 The Decred developers | ||
// Copyright (c) 2015-2020 The Decred developers | ||
// Use of this source code is governed by an ISC | ||
// license that can be found in the LICENSE file. | ||
|
||
package stake | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// ErrorCode identifies a kind of error. | ||
type ErrorCode int | ||
// ErrorKind identifies a kind of error. It has full support for errors.Is and | ||
// errors.As, so the caller can directly check against an error kind when | ||
// determining the reason for an error. | ||
type ErrorKind string | ||
|
||
// These constants are used to identify a specific RuleError. | ||
const ( | ||
// ErrSStxTooManyInputs indicates that a given SStx contains too many | ||
// inputs. | ||
ErrSStxTooManyInputs = iota | ||
ErrSStxTooManyInputs = ErrorKind("ErrSStxTooManyInputs") | ||
|
||
// ErrSStxTooManyOutputs indicates that a given SStx contains too many | ||
// outputs. | ||
ErrSStxTooManyOutputs | ||
ErrSStxTooManyOutputs = ErrorKind("ErrSStxTooManyOutputs") | ||
|
||
// ErrSStxNoOutputs indicates that a given SStx has no outputs. | ||
ErrSStxNoOutputs | ||
ErrSStxNoOutputs = ErrorKind("ErrSStxNoOutputs") | ||
|
||
// ErrSStxInvalidInput indicates that an invalid output has been used as | ||
// an input for a SStx; only non-SStx tagged outputs may be used to | ||
// purchase stake tickets. | ||
// TODO: Add this into validate | ||
// Ensure that all inputs are not tagged SStx outputs of some sort, | ||
// along with checks to make sure they exist and are available. | ||
ErrSStxInvalidInputs | ||
ErrSStxInvalidInputs = ErrorKind("ErrSStxInvalidInputs") | ||
|
||
// ErrSStxInvalidOutput indicates that the output for an SStx tx is | ||
// invalid; in particular, either the output was not tagged SStx or the | ||
// OP_RETURNs were missing or contained invalid addresses. | ||
ErrSStxInvalidOutputs | ||
ErrSStxInvalidOutputs = ErrorKind("ErrSStxInvalidOutputs") | ||
|
||
// ErrSStxInOutProportions indicates the number of inputs in an SStx | ||
// was not equal to the number of output minus one. | ||
ErrSStxInOutProportions | ||
ErrSStxInOutProportions = ErrorKind("ErrSStxInOutProportions") | ||
|
||
// ErrSStxBadCommitAmount indicates that a ticket tried to commit 0 or | ||
// a negative value as the commitment amount. | ||
ErrSStxBadCommitAmount | ||
ErrSStxBadCommitAmount = ErrorKind("ErrSStxBadCommitAmount") | ||
|
||
// ErrSStxBadChangeAmts indicates that the change amount for some SStx | ||
// was invalid, for instance spending more than its inputs. | ||
ErrSStxBadChangeAmts | ||
ErrSStxBadChangeAmts = ErrorKind("ErrSStxBadChangeAmts") | ||
|
||
// ErrSStxVerifyCalcAmts indicates that passed calculated amounts failed | ||
// to conform to the amounts found in the ticket. | ||
ErrSStxVerifyCalcAmts | ||
ErrSStxVerifyCalcAmts = ErrorKind("ErrSStxVerifyCalcAmts") | ||
|
||
// ErrSSGenWrongNumInputs indicates that a given SSGen tx contains an | ||
// invalid number of inputs. | ||
ErrSSGenWrongNumInputs | ||
ErrSSGenWrongNumInputs = ErrorKind("ErrSSGenWrongNumInputs") | ||
|
||
// ErrSSGenTooManyOutputs indicates that a given SSGen tx contains too | ||
// many outputs. | ||
ErrSSGenTooManyOutputs | ||
ErrSSGenTooManyOutputs = ErrorKind("ErrSSGenTooManyOutputs") | ||
|
||
// ErrSSGenNoOutputs indicates that a given SSGen has no outputs. | ||
ErrSSGenNoOutputs | ||
ErrSSGenNoOutputs = ErrorKind("ErrSSGenNoOutputs") | ||
|
||
// ErrSSGenWrongIndex indicates that a given SSGen sstx input was not | ||
// using the correct index. | ||
ErrSSGenWrongIndex | ||
ErrSSGenWrongIndex = ErrorKind("ErrSSGenWrongIndex") | ||
|
||
// ErrSSGenWrongTxTree indicates that a given SSGen tx input was not found in | ||
// the stake tx tree. | ||
ErrSSGenWrongTxTree | ||
ErrSSGenWrongTxTree = ErrorKind("ErrSSGenWrongTxTree") | ||
|
||
// ErrSSGenNoStakebase indicates that the SSGen tx did not contain a | ||
// valid StakeBase in the zeroeth position of inputs. | ||
ErrSSGenNoStakebase | ||
ErrSSGenNoStakebase = ErrorKind("ErrSSGenNoStakebase") | ||
|
||
// ErrSSGenNoReference indicates that there is no reference OP_RETURN | ||
// included as the first output. | ||
ErrSSGenNoReference | ||
ErrSSGenNoReference = ErrorKind("ErrSSGenNoReference") | ||
|
||
// ErrSSGenNoReference indicates that the OP_RETURN included as the | ||
// first output was corrupted in some way. | ||
ErrSSGenBadReference | ||
ErrSSGenBadReference = ErrorKind("ErrSSGenBadReference") | ||
|
||
// ErrSSGenNoVotePush indicates that there is no vote bits OP_RETURN | ||
// included as the second output. | ||
ErrSSGenNoVotePush | ||
ErrSSGenNoVotePush = ErrorKind("ErrSSGenNoVotePush") | ||
|
||
// ErrSSGenBadVotePush indicates that the OP_RETURN included as the | ||
// second output was corrupted in some way. | ||
ErrSSGenBadVotePush | ||
ErrSSGenBadVotePush = ErrorKind("ErrSSGenBadVotePush") | ||
|
||
// ErrSSGenBadGenOuts indicates that the something was wrong with the | ||
// stake generation outputs that were present after the first two | ||
// OP_RETURN pushes in an SSGen tx. | ||
ErrSSGenBadGenOuts | ||
ErrSSGenBadGenOuts = ErrorKind("ErrSSGenBadGenOuts") | ||
|
||
// ErrSSRtxWrongNumInputs indicates that a given SSRtx contains an | ||
// invalid number of inputs. | ||
ErrSSRtxWrongNumInputs | ||
ErrSSRtxWrongNumInputs = ErrorKind("ErrSSRtxWrongNumInputs") | ||
|
||
// ErrSSRtxTooManyOutputs indicates that a given SSRtx contains too many | ||
// outputs. | ||
ErrSSRtxTooManyOutputs | ||
ErrSSRtxTooManyOutputs = ErrorKind("ErrSSRtxTooManyOutputs") | ||
|
||
// ErrSSRtxNoOutputs indicates that a given SSRtx has no outputs. | ||
ErrSSRtxNoOutputs | ||
ErrSSRtxNoOutputs = ErrorKind("ErrSSRtxNoOutputs") | ||
|
||
// ErrSSRtxWrongTxTree indicates that a given SSRtx input was not found in | ||
// the stake tx tree. | ||
ErrSSRtxWrongTxTree | ||
ErrSSRtxWrongTxTree = ErrorKind("ErrSSRtxWrongTxTree") | ||
|
||
// ErrSSRtxBadGenOuts indicates that there was a non-SSRtx tagged output | ||
// present in an SSRtx. | ||
ErrSSRtxBadOuts | ||
ErrSSRtxBadOuts = ErrorKind("ErrSSRtxBadOuts") | ||
|
||
// ErrVerSStxAmts indicates there was an error verifying the calculated | ||
// SStx out amounts and the actual SStx out amounts. | ||
ErrVerSStxAmts | ||
ErrVerSStxAmts = ErrorKind("ErrVerSStxAmts") | ||
|
||
// ErrVerifyInput indicates that there was an error in verification | ||
// function input. | ||
ErrVerifyInput | ||
ErrVerifyInput = ErrorKind("ErrVerifyInput") | ||
|
||
// ErrVerifyOutType indicates that there was a non-equivalence in the | ||
// output type. | ||
ErrVerifyOutType | ||
ErrVerifyOutType = ErrorKind("ErrVerifyOutType") | ||
|
||
// ErrVerifyTooMuchFees indicates that a transaction's output gave | ||
// too much in fees after taking into accounts the limits imposed | ||
// by the SStx output's version field. | ||
ErrVerifyTooMuchFees | ||
ErrVerifyTooMuchFees = ErrorKind("ErrVerifyTooMuchFees") | ||
|
||
// ErrVerifySpendTooMuch indicates that a transaction's output spent more | ||
// than it was allowed to spend based on the calculated subsidy or return | ||
// for a vote or revocation. | ||
ErrVerifySpendTooMuch | ||
ErrVerifySpendTooMuch = ErrorKind("ErrVerifySpendTooMuch") | ||
|
||
// ErrVerifyOutputAmt indicates that for a vote/revocation spend output, | ||
// the rule was given that it must exactly match the calculated maximum, | ||
// however the amount in the output did not (e.g. it gave fees). | ||
ErrVerifyOutputAmt | ||
ErrVerifyOutputAmt = ErrorKind("ErrVerifyOutputAmt") | ||
|
||
// ErrVerifyOutPkhs indicates that the recipient of the P2PKH or P2SH | ||
// script was different from that indicated in the SStx input. | ||
ErrVerifyOutPkhs | ||
ErrVerifyOutPkhs = ErrorKind("ErrVerifyOutPkhs") | ||
|
||
// ErrDatabaseCorrupt indicates a database inconsistency. | ||
ErrDatabaseCorrupt | ||
ErrDatabaseCorrupt = ErrorKind("ErrDatabaseCorrupt") | ||
|
||
// ErrMissingDatabaseTx indicates that a node disconnection failed to | ||
// pass a database transaction when attempted to remove a very old | ||
// node. | ||
ErrMissingDatabaseTx | ||
ErrMissingDatabaseTx = ErrorKind("ErrMissingDatabaseTx") | ||
|
||
// ErrMemoryCorruption indicates that memory has somehow become corrupt, | ||
// for example invalid block header serialization from an in memory | ||
// struct. | ||
ErrMemoryCorruption | ||
ErrMemoryCorruption = ErrorKind("ErrMemoryCorruption") | ||
|
||
// ErrFindTicketIdxs indicates a failure to find the selected ticket | ||
// indexes from the block header. | ||
ErrFindTicketIdxs | ||
ErrFindTicketIdxs = ErrorKind("ErrFindTicketIdxs") | ||
|
||
// ErrMissingTicket indicates that a ticket was missing in one of the | ||
// ticket treaps when it was attempted to be fetched. | ||
ErrMissingTicket | ||
ErrMissingTicket = ErrorKind("ErrMissingTicket") | ||
|
||
// ErrDuplicateTicket indicates that a duplicate ticket was attempted | ||
// to be inserted into a ticket treap or the database. | ||
ErrDuplicateTicket | ||
ErrDuplicateTicket = ErrorKind("ErrDuplicateTicket") | ||
|
||
// ErrUnknownTicketSpent indicates that an unknown ticket was spent by | ||
// the block. | ||
ErrUnknownTicketSpent | ||
ErrUnknownTicketSpent = ErrorKind("ErrUnknownTicketSpent") | ||
) | ||
|
||
// Map of ErrorCode values back to their constant names for pretty printing. | ||
var errorCodeStrings = map[ErrorCode]string{ | ||
ErrSStxTooManyInputs: "ErrSStxTooManyInputs", | ||
ErrSStxTooManyOutputs: "ErrSStxTooManyOutputs", | ||
ErrSStxNoOutputs: "ErrSStxNoOutputs", | ||
ErrSStxInvalidInputs: "ErrSStxInvalidInputs", | ||
ErrSStxInvalidOutputs: "ErrSStxInvalidOutputs", | ||
ErrSStxInOutProportions: "ErrSStxInOutProportions", | ||
ErrSStxBadCommitAmount: "ErrSStxBadCommitAmount", | ||
ErrSStxBadChangeAmts: "ErrSStxBadChangeAmts", | ||
ErrSStxVerifyCalcAmts: "ErrSStxVerifyCalcAmts", | ||
ErrSSGenWrongNumInputs: "ErrSSGenWrongNumInputs", | ||
ErrSSGenTooManyOutputs: "ErrSSGenTooManyOutputs", | ||
ErrSSGenNoOutputs: "ErrSSGenNoOutputs", | ||
ErrSSGenWrongIndex: "ErrSSGenWrongIndex", | ||
ErrSSGenWrongTxTree: "ErrSSGenWrongTxTree", | ||
ErrSSGenNoStakebase: "ErrSSGenNoStakebase", | ||
ErrSSGenNoReference: "ErrSSGenNoReference", | ||
ErrSSGenBadReference: "ErrSSGenBadReference", | ||
ErrSSGenNoVotePush: "ErrSSGenNoVotePush", | ||
ErrSSGenBadVotePush: "ErrSSGenBadVotePush", | ||
ErrSSGenBadGenOuts: "ErrSSGenBadGenOuts", | ||
ErrSSRtxWrongNumInputs: "ErrSSRtxWrongNumInputs", | ||
ErrSSRtxTooManyOutputs: "ErrSSRtxTooManyOutputs", | ||
ErrSSRtxNoOutputs: "ErrSSRtxNoOutputs", | ||
ErrSSRtxWrongTxTree: "ErrSSRtxWrongTxTree", | ||
ErrSSRtxBadOuts: "ErrSSRtxBadOuts", | ||
ErrVerSStxAmts: "ErrVerSStxAmts", | ||
ErrVerifyInput: "ErrVerifyInput", | ||
ErrVerifyOutType: "ErrVerifyOutType", | ||
ErrVerifyTooMuchFees: "ErrVerifyTooMuchFees", | ||
ErrVerifySpendTooMuch: "ErrVerifySpendTooMuch", | ||
ErrVerifyOutputAmt: "ErrVerifyOutputAmt", | ||
ErrVerifyOutPkhs: "ErrVerifyOutPkhs", | ||
ErrDatabaseCorrupt: "ErrDatabaseCorrupt", | ||
ErrMissingDatabaseTx: "ErrMissingDatabaseTx", | ||
ErrMemoryCorruption: "ErrMemoryCorruption", | ||
ErrFindTicketIdxs: "ErrFindTicketIdxs", | ||
ErrMissingTicket: "ErrMissingTicket", | ||
ErrDuplicateTicket: "ErrDuplicateTicket", | ||
ErrUnknownTicketSpent: "ErrUnknownTicketSpent", | ||
} | ||
|
||
// String returns the ErrorCode as a human-readable name. | ||
func (e ErrorCode) String() string { | ||
if s := errorCodeStrings[e]; s != "" { | ||
return s | ||
} | ||
return fmt.Sprintf("Unknown ErrorCode (%d)", int(e)) | ||
// Error satisfies the error interface and prints human-readable errors. | ||
func (e ErrorKind) Error() string { | ||
return string(e) | ||
} | ||
|
||
// RuleError identifies a rule violation. It is used to indicate that | ||
// processing of a block or transaction failed due to one of the many validation | ||
// rules. The caller can use type assertions to determine if a failure was | ||
// specifically due to a rule violation and access the ErrorCode field to | ||
// ascertain the specific reason for the rule violation. | ||
// RuleError identifies a rule violation related to stake transactions. It has | ||
// full support for errors.Is and errors.As, so the caller can ascertain the | ||
// specific reason for the error by checking the underlying error. | ||
type RuleError struct { | ||
ErrorCode ErrorCode // Describes the kind of error | ||
Description string // Human readable description of the issue | ||
Description string | ||
Err error | ||
} | ||
|
||
// Error satisfies the error interface and prints human-readable errors. | ||
func (e RuleError) Error() string { | ||
return e.Description | ||
} | ||
|
||
// GetCode satisfies the error interface and prints human-readable errors. | ||
func (e RuleError) GetCode() ErrorCode { | ||
return e.ErrorCode | ||
// Unwrap returns the underlying wrapped rule error. | ||
func (e RuleError) Unwrap() error { | ||
return e.Err | ||
} | ||
|
||
// stakeRuleError creates a RuleError given a set of arguments. | ||
func stakeRuleError(c ErrorCode, desc string) RuleError { | ||
return RuleError{ErrorCode: c, Description: desc} | ||
func stakeRuleError(kind ErrorKind, desc string) RuleError { | ||
return RuleError{Err: kind, Description: desc} | ||
} |
Oops, something went wrong.