This adds an additional validation check to the chain initialization process to validate that none of the IDs of the choices in the given chain params are blank. It also adds a test for the new validation logic.
828 lines
34 KiB
Go
828 lines
34 KiB
Go
// Copyright (c) 2014-2016 The btcsuite developers
|
|
// Copyright (c) 2015-2023 The Decred developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package blockchain
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/decred/dcrd/chaincfg/chainhash"
|
|
)
|
|
|
|
// AssertError identifies an error that indicates an internal code consistency
|
|
// issue and should be treated as a critical and unrecoverable error.
|
|
type AssertError string
|
|
|
|
// Error returns the assertion error as a human-readable string and satisfies
|
|
// the error interface.
|
|
func (e AssertError) Error() string {
|
|
return "assertion failed: " + string(e)
|
|
}
|
|
|
|
// Is implements the interface to work with the standard library's errors.Is.
|
|
//
|
|
// It returns true in the following cases:
|
|
// - The target is AssertError
|
|
func (e AssertError) Is(target error) bool {
|
|
var err AssertError
|
|
return errors.As(target, &err)
|
|
}
|
|
|
|
// 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 ErrorKind.
|
|
const (
|
|
// ErrDuplicateBlock indicates a block with the same hash already
|
|
// exists.
|
|
ErrDuplicateBlock = ErrorKind("ErrDuplicateBlock")
|
|
|
|
// ErrMissingParent indicates that the block was an orphan.
|
|
ErrMissingParent = ErrorKind("ErrMissingParent")
|
|
|
|
// ErrNoBlockData indicates an attempt to perform an operation on a block
|
|
// that requires all data to be available does not have the data. This is
|
|
// typically because the header is known, but the full data has not been
|
|
// received yet.
|
|
ErrNoBlockData = ErrorKind("ErrNoBlockData")
|
|
|
|
// ErrBlockTooBig indicates the serialized block size exceeds the
|
|
// maximum allowed size.
|
|
ErrBlockTooBig = ErrorKind("ErrBlockTooBig")
|
|
|
|
// ErrWrongBlockSize indicates that the block size in the header is not
|
|
// the actual serialized size of the block.
|
|
ErrWrongBlockSize = ErrorKind("ErrWrongBlockSize")
|
|
|
|
// ErrBlockVersionTooOld indicates the block version is too old and is
|
|
// no longer accepted since the majority of the network has upgraded
|
|
// to a newer version.
|
|
ErrBlockVersionTooOld = ErrorKind("ErrBlockVersionTooOld")
|
|
|
|
// ErrBadStakeVersion indicates the block version is too old and is no
|
|
// longer accepted since the majority of the network has upgraded to a
|
|
// newer version.
|
|
ErrBadStakeVersion = ErrorKind("ErrBadStakeVersion")
|
|
|
|
// ErrInvalidTime indicates the time in the passed block has a precision
|
|
// that is more than one second. The chain consensus rules require
|
|
// timestamps to have a maximum precision of one second.
|
|
ErrInvalidTime = ErrorKind("ErrInvalidTime")
|
|
|
|
// ErrTimeTooOld indicates the time is either before the median time of the
|
|
// last several blocks per the chain consensus rules or prior to the time
|
|
// that is required by max difficulty limitations on the test network.
|
|
ErrTimeTooOld = ErrorKind("ErrTimeTooOld")
|
|
|
|
// ErrTimeTooNew indicates the time is too far in the future as compared
|
|
// the current time.
|
|
ErrTimeTooNew = ErrorKind("ErrTimeTooNew")
|
|
|
|
// ErrUnexpectedDifficulty indicates specified bits do not align with
|
|
// the expected value either because it doesn't match the calculated
|
|
// value based on difficulty regarding the rules or it is out of the
|
|
// valid range.
|
|
ErrUnexpectedDifficulty = ErrorKind("ErrUnexpectedDifficulty")
|
|
|
|
// ErrHighHash indicates the block does not hash to a value which is
|
|
// lower than the required target difficultly.
|
|
ErrHighHash = ErrorKind("ErrHighHash")
|
|
|
|
// ErrBadMerkleRoot indicates the calculated merkle root does not match
|
|
// the expected value.
|
|
ErrBadMerkleRoot = ErrorKind("ErrBadMerkleRoot")
|
|
|
|
// ErrBadCommitmentRoot indicates the calculated commitment root does
|
|
// not match the expected value.
|
|
ErrBadCommitmentRoot = ErrorKind("ErrBadCommitmentRoot")
|
|
|
|
// ErrForkTooOld indicates a block is attempting to fork the block chain
|
|
// before the fork rejection checkpoint.
|
|
ErrForkTooOld = ErrorKind("ErrForkTooOld")
|
|
|
|
// ErrBadMaxDiffCheckpoint indicates a block on the version 3 test network
|
|
// at the height used to activate maximum difficulty semantics does not
|
|
// match the expected one.
|
|
ErrBadMaxDiffCheckpoint = ErrorKind("ErrBadMaxDiffCheckpoint")
|
|
|
|
// ErrNoTransactions indicates the block does not have at least one
|
|
// transaction. A valid block must have at least the coinbase transaction.
|
|
ErrNoTransactions = ErrorKind("ErrNoTransactions")
|
|
|
|
// ErrNoTxInputs indicates a transaction does not have any inputs. A
|
|
// valid transaction must have at least one input.
|
|
ErrNoTxInputs = ErrorKind("ErrNoTxInputs")
|
|
|
|
// ErrNoTxOutputs indicates a transaction does not have any outputs. A
|
|
// valid transaction must have at least one output.
|
|
ErrNoTxOutputs = ErrorKind("ErrNoTxOutputs")
|
|
|
|
// ErrTxTooBig indicates a transaction exceeds the maximum allowed size
|
|
// when serialized.
|
|
ErrTxTooBig = ErrorKind("ErrTxTooBig")
|
|
|
|
// ErrBadTxOutValue indicates an output value for a transaction is
|
|
// invalid in some way such as being out of range.
|
|
ErrBadTxOutValue = ErrorKind("ErrBadTxOutValue")
|
|
|
|
// ErrDuplicateTxInputs indicates a transaction references the same
|
|
// input more than once.
|
|
ErrDuplicateTxInputs = ErrorKind("ErrDuplicateTxInputs")
|
|
|
|
// ErrTxVersionTooHigh indicates a transaction version is higher than the
|
|
// maximum version allowed by the active consensus rules.
|
|
ErrTxVersionTooHigh = ErrorKind("ErrTxVersionTooHigh")
|
|
|
|
// ErrBadTxInput indicates a transaction input is invalid in some way
|
|
// such as referencing a previous transaction outpoint which is out of
|
|
// range or not referencing one at all.
|
|
ErrBadTxInput = ErrorKind("ErrBadTxInput")
|
|
|
|
// ErrScriptVersionTooHigh indicates a transaction script version is higher
|
|
// than the maximum version allowed by the active consensus rules.
|
|
ErrScriptVersionTooHigh = ErrorKind("ErrScriptVersionTooHigh")
|
|
|
|
// ErrMissingTxOut indicates a transaction output referenced by an input
|
|
// either does not exist or has already been spent.
|
|
ErrMissingTxOut = ErrorKind("ErrMissingTxOut")
|
|
|
|
// ErrUnfinalizedTx indicates a transaction has not been finalized.
|
|
// A valid block may only contain finalized transactions.
|
|
ErrUnfinalizedTx = ErrorKind("ErrUnfinalizedTx")
|
|
|
|
// ErrDuplicateTx indicates a block contains an identical transaction
|
|
// (or at least two transactions which hash to the same value). A
|
|
// valid block may only contain unique transactions.
|
|
ErrDuplicateTx = ErrorKind("ErrDuplicateTx")
|
|
|
|
// ErrOverwriteTx indicates a block contains a transaction that has
|
|
// the same hash as a previous transaction which has not been fully
|
|
// spent.
|
|
ErrOverwriteTx = ErrorKind("ErrOverwriteTx")
|
|
|
|
// ErrImmatureSpend indicates a transaction is attempting to spend a
|
|
// coinbase that has not yet reached the required maturity.
|
|
ErrImmatureSpend = ErrorKind("ErrImmatureSpend")
|
|
|
|
// ErrSpendTooHigh indicates a transaction is attempting to spend more
|
|
// value than the sum of all of its inputs.
|
|
ErrSpendTooHigh = ErrorKind("ErrSpendTooHigh")
|
|
|
|
// ErrBadFees indicates the total fees for a block are invalid due to
|
|
// exceeding the maximum possible value.
|
|
ErrBadFees = ErrorKind("ErrBadFees")
|
|
|
|
// ErrTooManySigOps indicates the total number of signature operations
|
|
// for a transaction or block exceed the maximum allowed limits.
|
|
ErrTooManySigOps = ErrorKind("ErrTooManySigOps")
|
|
|
|
// ErrFirstTxNotCoinbase indicates the first transaction in a block
|
|
// is not a coinbase transaction.
|
|
ErrFirstTxNotCoinbase = ErrorKind("ErrFirstTxNotCoinbase")
|
|
|
|
// ErrCoinbaseHeight indicates that the encoded height in the coinbase
|
|
// is incorrect.
|
|
ErrCoinbaseHeight = ErrorKind("ErrCoinbaseHeight")
|
|
|
|
// ErrMultipleCoinbases indicates a block contains more than one
|
|
// coinbase transaction.
|
|
ErrMultipleCoinbases = ErrorKind("ErrMultipleCoinbases")
|
|
|
|
// ErrStakeTxInRegularTree indicates a stake transaction was found in
|
|
// the regular transaction tree.
|
|
ErrStakeTxInRegularTree = ErrorKind("ErrStakeTxInRegularTree")
|
|
|
|
// ErrRegTxInStakeTree indicates that a regular transaction was found in
|
|
// the stake transaction tree.
|
|
ErrRegTxInStakeTree = ErrorKind("ErrRegTxInStakeTree")
|
|
|
|
// ErrBadCoinbaseScriptLen indicates the length of the signature script
|
|
// for a coinbase transaction is not within the valid range.
|
|
ErrBadCoinbaseScriptLen = ErrorKind("ErrBadCoinbaseScriptLen")
|
|
|
|
// ErrBadCoinbaseValue indicates the amount of a coinbase value does
|
|
// not match the expected value of the subsidy plus the sum of all fees.
|
|
ErrBadCoinbaseValue = ErrorKind("ErrBadCoinbaseValue")
|
|
|
|
// ErrBadCoinbaseOutpoint indicates that the outpoint used by a coinbase
|
|
// as input was non-null.
|
|
ErrBadCoinbaseOutpoint = ErrorKind("ErrBadCoinbaseOutpoint")
|
|
|
|
// ErrBadCoinbaseFraudProof indicates that the fraud proof for a coinbase
|
|
// input was non-null.
|
|
ErrBadCoinbaseFraudProof = ErrorKind("ErrBadCoinbaseFraudProof")
|
|
|
|
// ErrBadCoinbaseAmountIn indicates that the AmountIn (=subsidy) for a
|
|
// coinbase input was incorrect.
|
|
ErrBadCoinbaseAmountIn = ErrorKind("ErrBadCoinbaseAmountIn")
|
|
|
|
// ErrBadStakebaseAmountIn indicates that the AmountIn (=subsidy) for a
|
|
// stakebase input was incorrect.
|
|
ErrBadStakebaseAmountIn = ErrorKind("ErrBadStakebaseAmountIn")
|
|
|
|
// ErrBadStakebaseScriptLen indicates the length of the signature script
|
|
// for a stakebase transaction is not within the valid range.
|
|
ErrBadStakebaseScriptLen = ErrorKind("ErrBadStakebaseScriptLen")
|
|
|
|
// ErrBadStakebaseScrVal indicates the signature script for a stakebase
|
|
// transaction was not set to the network consensus value.
|
|
ErrBadStakebaseScrVal = ErrorKind("ErrBadStakebaseScrVal")
|
|
|
|
// ErrScriptMalformed indicates a transaction script is malformed in
|
|
// some way. For example, it might be longer than the maximum allowed
|
|
// length or fail to parse.
|
|
ErrScriptMalformed = ErrorKind("ErrScriptMalformed")
|
|
|
|
// ErrScriptValidation indicates the result of executing a transaction
|
|
// script failed. The error covers any failure when executing scripts
|
|
// such as signature verification failures and execution past the end
|
|
// of the stack.
|
|
ErrScriptValidation = ErrorKind("ErrScriptValidation")
|
|
|
|
// ErrNotEnoughStake indicates that there was for some SStx in a given block,
|
|
// the given SStx did not have enough stake to meet the network target.
|
|
ErrNotEnoughStake = ErrorKind("ErrNotEnoughStake")
|
|
|
|
// ErrStakeBelowMinimum indicates that for some SStx in a given block,
|
|
// the given SStx had an amount of stake below the minimum network target.
|
|
ErrStakeBelowMinimum = ErrorKind("ErrStakeBelowMinimum")
|
|
|
|
// ErrNonstandardStakeTx indicates that a block contained a stake tx that
|
|
// was not one of the allowed types of a stake transactions.
|
|
ErrNonstandardStakeTx = ErrorKind("ErrNonstandardStakeTx")
|
|
|
|
// ErrNotEnoughVotes indicates that a block contained less than a majority
|
|
// of voters.
|
|
ErrNotEnoughVotes = ErrorKind("ErrNotEnoughVotes")
|
|
|
|
// ErrTooManyVotes indicates that a block contained more than the maximum
|
|
// allowable number of votes.
|
|
ErrTooManyVotes = ErrorKind("ErrTooManyVotes")
|
|
|
|
// ErrFreshStakeMismatch indicates that a block's header contained a different
|
|
// number of SStx as compared to what was found in the block.
|
|
ErrFreshStakeMismatch = ErrorKind("ErrFreshStakeMismatch")
|
|
|
|
// ErrTooManySStxs indicates that more than the allowed number of SStx was
|
|
// found in a block.
|
|
ErrTooManySStxs = ErrorKind("ErrTooManySStxs")
|
|
|
|
// ErrInvalidEarlyStakeTx indicates that a tx type other than SStx was found
|
|
// in the stake tx tree before the period when stake validation begins, or
|
|
// before the stake tx type could possibly be included in the block.
|
|
ErrInvalidEarlyStakeTx = ErrorKind("ErrInvalidEarlyStakeTx")
|
|
|
|
// ErrTicketUnavailable indicates that a vote in the block spent a ticket
|
|
// that could not be found.
|
|
ErrTicketUnavailable = ErrorKind("ErrTicketUnavailable")
|
|
|
|
// ErrVotesOnWrongBlock indicates that an SSGen voted on a block that is not
|
|
// the block's parent, and so was ineligible for inclusion into that block.
|
|
ErrVotesOnWrongBlock = ErrorKind("ErrVotesOnWrongBlock")
|
|
|
|
// ErrVotesMismatch indicates that the number of SSGen in the block was not
|
|
// equivalent to the number of votes provided in the block header.
|
|
ErrVotesMismatch = ErrorKind("ErrVotesMismatch")
|
|
|
|
// ErrIncongruentVotebit indicates that the first votebit in votebits was not
|
|
// the same as that determined by the majority of voters in the SSGen tx
|
|
// included in the block.
|
|
ErrIncongruentVotebit = ErrorKind("ErrIncongruentVotebit")
|
|
|
|
// ErrInvalidSSRtx indicates than an SSRtx in a block could not be found to
|
|
// have a valid missed sstx input as per the stake ticket database.
|
|
ErrInvalidSSRtx = ErrorKind("ErrInvalidSSRtx")
|
|
|
|
// ErrInvalidRevNum indicates that the number of revocations from the
|
|
// header was not the same as the number of SSRtx included in the block.
|
|
ErrRevocationsMismatch = ErrorKind("ErrRevocationsMismatch")
|
|
|
|
// ErrTooManyRevocations indicates more revocations were found in a block
|
|
// than were allowed.
|
|
ErrTooManyRevocations = ErrorKind("ErrTooManyRevocations")
|
|
|
|
// ErrTicketCommitment indicates that a ticket commitment contains an amount
|
|
// that does not coincide with the associated ticket input amount.
|
|
ErrTicketCommitment = ErrorKind("ErrTicketCommitment")
|
|
|
|
// ErrInvalidVoteInput indicates that an input to a vote transaction is
|
|
// either not a stake ticket submission or is not a supported version.
|
|
ErrInvalidVoteInput = ErrorKind("ErrInvalidVoteInput")
|
|
|
|
// ErrBadNumPayees indicates that either a vote or revocation transaction
|
|
// does not make the correct number of payments per the associated ticket
|
|
// commitments.
|
|
ErrBadNumPayees = ErrorKind("ErrBadNumPayees")
|
|
|
|
// ErrBadPayeeScriptVersion indicates that either a vote or revocation
|
|
// transaction output that corresponds to a ticket commitment does not use
|
|
// a supported script version.
|
|
ErrBadPayeeScriptVersion = ErrorKind("ErrBadPayeeScriptVersion")
|
|
|
|
// ErrBadPayeeScriptType indicates that either a vote or revocation
|
|
// transaction output that corresponds to a ticket commitment does not pay
|
|
// to the same script type required by the commitment.
|
|
ErrBadPayeeScriptType = ErrorKind("ErrBadPayeeScriptType")
|
|
|
|
// ErrBadPayeeScriptType indicates that either a vote or revocation
|
|
// transaction output that corresponds to a ticket commitment does not pay
|
|
// to the hash required by the commitment.
|
|
ErrMismatchedPayeeHash = ErrorKind("ErrMismatchedPayeeHash")
|
|
|
|
// ErrBadPayeeValue indicates that either a vote or revocation transaction
|
|
// output that corresponds to a ticket commitment does not pay the expected
|
|
// amount required by the commitment.
|
|
ErrBadPayeeValue = ErrorKind("ErrBadPayeeValue")
|
|
|
|
// ErrSSGenSubsidy indicates that there was an error in the amount of subsidy
|
|
// generated in the vote.
|
|
ErrSSGenSubsidy = ErrorKind("ErrSSGenSubsidy")
|
|
|
|
// ErrImmatureTicketSpend indicates that a vote or revocation is attempting
|
|
// to spend a ticket submission output that has not yet reached the required
|
|
// maturity.
|
|
ErrImmatureTicketSpend = ErrorKind("ErrImmatureTicketSpend")
|
|
|
|
// ErrTicketInputScript indicates that a ticket input is not one of the
|
|
// supported script forms or versions.
|
|
ErrTicketInputScript = ErrorKind("ErrTicketInputScript")
|
|
|
|
// ErrInvalidRevokeInput indicates that an input to a revocation transaction
|
|
// is either not a stake ticket submission or is not a supported version.
|
|
ErrInvalidRevokeInput = ErrorKind("ErrInvalidRevokeInput")
|
|
|
|
// ErrTxSStxOutSpend indicates that a non SSGen or SSRtx tx attempted to spend
|
|
// an OP_SSTX tagged output from an SStx.
|
|
ErrTxSStxOutSpend = ErrorKind("ErrTxSStxOutSpend")
|
|
|
|
// ErrRegTxCreateStakeOut indicates that a regular tx attempted to create
|
|
// a stake tagged output.
|
|
ErrRegTxCreateStakeOut = ErrorKind("ErrRegTxCreateStakeOut")
|
|
|
|
// ErrInvalidFinalState indicates that the final state of the PRNG included
|
|
// in the block differed from the calculated final state.
|
|
ErrInvalidFinalState = ErrorKind("ErrInvalidFinalState")
|
|
|
|
// ErrPoolSize indicates an error in the ticket pool size for this block.
|
|
ErrPoolSize = ErrorKind("ErrPoolSize")
|
|
|
|
// ErrForceReorgSameBlock indicates that a reorganization was attempted to
|
|
// be forced to the same block.
|
|
ErrForceReorgSameBlock = ErrorKind("ErrForceReorgSameBlock")
|
|
|
|
// ErrForceReorgWrongChain indicates that a reorganization was attempted
|
|
// to be forced, but the chain indicated was not mirrored by b.bestChain.
|
|
ErrForceReorgWrongChain = ErrorKind("ErrForceReorgWrongChain")
|
|
|
|
// ErrForceReorgMissingChild indicates that a reorganization was attempted
|
|
// to be forced, but the child node to reorganize to could not be found.
|
|
ErrForceReorgMissingChild = ErrorKind("ErrForceReorgMissingChild")
|
|
|
|
// ErrBadStakebaseValue indicates that a block's stake tx tree has spent
|
|
// more than it is allowed.
|
|
ErrBadStakebaseValue = ErrorKind("ErrBadStakebaseValue")
|
|
|
|
// ErrStakeFees indicates an error with the fees found in the stake
|
|
// transaction tree.
|
|
ErrStakeFees = ErrorKind("ErrStakeFees")
|
|
|
|
// ErrNoStakeTx indicates there were no stake transactions found in a
|
|
// block after stake validation height.
|
|
ErrNoStakeTx = ErrorKind("ErrNoStakeTx")
|
|
|
|
// ErrBadBlockHeight indicates that a block header's embedded block height
|
|
// was different from where it was actually embedded in the block chain.
|
|
ErrBadBlockHeight = ErrorKind("ErrBadBlockHeight")
|
|
|
|
// ErrBlockOneTx indicates that block height 1 failed to correctly generate
|
|
// the block one initial payout transaction.
|
|
ErrBlockOneTx = ErrorKind("ErrBlockOneTx")
|
|
|
|
// ErrBlockOneInputs indicates that block height 1 coinbase transaction
|
|
// input zero was incorrect in some way.
|
|
ErrBlockOneInputs = ErrorKind("ErrBlockOneInputs")
|
|
|
|
// ErrBlockOneOutputs indicates that block height 1 failed to incorporate
|
|
// the ledger addresses correctly into the transaction's outputs.
|
|
ErrBlockOneOutputs = ErrorKind("ErrBlockOneOutputs")
|
|
|
|
// ErrNoTreasury indicates that there was no treasury payout present in the
|
|
// coinbase of a block after height 1 and prior to the activation of the
|
|
// decentralized treasury.
|
|
ErrNoTreasury = ErrorKind("ErrNoTreasury")
|
|
|
|
// ErrExpiredTx indicates that the transaction is currently expired.
|
|
ErrExpiredTx = ErrorKind("ErrExpiredTx")
|
|
|
|
// ErrExpiryTxSpentEarly indicates that an output from a transaction
|
|
// that included an expiry field was spent before coinbase maturity
|
|
// many blocks had passed in the blockchain.
|
|
ErrExpiryTxSpentEarly = ErrorKind("ErrExpiryTxSpentEarly")
|
|
|
|
// ErrFraudAmountIn indicates the witness amount given was fraudulent.
|
|
ErrFraudAmountIn = ErrorKind("ErrFraudAmountIn")
|
|
|
|
// ErrFraudBlockHeight indicates the witness block height given was
|
|
// fraudulent.
|
|
ErrFraudBlockHeight = ErrorKind("ErrFraudBlockHeight")
|
|
|
|
// ErrFraudBlockIndex indicates the witness block index given was
|
|
// fraudulent.
|
|
ErrFraudBlockIndex = ErrorKind("ErrFraudBlockIndex")
|
|
|
|
// ErrZeroValueOutputSpend indicates that a transaction attempted to spend a
|
|
// zero value output.
|
|
ErrZeroValueOutputSpend = ErrorKind("ErrZeroValueOutputSpend")
|
|
|
|
// ErrInvalidEarlyVoteBits indicates that a block before stake validation
|
|
// height had an unallowed vote bits value.
|
|
ErrInvalidEarlyVoteBits = ErrorKind("ErrInvalidEarlyVoteBits")
|
|
|
|
// ErrInvalidEarlyFinalState indicates that a block before stake validation
|
|
// height had a non-zero final state.
|
|
ErrInvalidEarlyFinalState = ErrorKind("ErrInvalidEarlyFinalState")
|
|
|
|
// ErrKnownInvalidBlock indicates that this block has previously failed
|
|
// validation.
|
|
ErrKnownInvalidBlock = ErrorKind("ErrKnownInvalidBlock")
|
|
|
|
// ErrInvalidAncestorBlock indicates that an ancestor of this block has
|
|
// failed validation.
|
|
ErrInvalidAncestorBlock = ErrorKind("ErrInvalidAncestorBlock")
|
|
|
|
// ErrInvalidTemplateParent indicates that a block template builds on a
|
|
// block that is either not the current best chain tip or its parent.
|
|
ErrInvalidTemplateParent = ErrorKind("ErrInvalidTemplateParent")
|
|
|
|
// ErrUnknownPiKey indicates that the provided public Pi Key is not
|
|
// a well known key.
|
|
ErrUnknownPiKey = ErrorKind("ErrUnknownPiKey")
|
|
|
|
// ErrInvalidPiSignature indicates that a treasury spend transaction
|
|
// was not properly signed.
|
|
ErrInvalidPiSignature = ErrorKind("ErrInvalidPiSignature")
|
|
|
|
// ErrInvalidTVoteWindow indicates that a treasury spend transaction
|
|
// appeared in a block that is prior to a valid treasury vote window.
|
|
ErrInvalidTVoteWindow = ErrorKind("ErrInvalidTVoteWindow")
|
|
|
|
// ErrNotTVI indicates that a treasury spend transaction appeared in a
|
|
// block that is not at a TVI interval.
|
|
ErrNotTVI = ErrorKind("ErrNotTVI")
|
|
|
|
// ErrInvalidTSpendWindow indicates that this treasury spend
|
|
// transaction is outside of the allowed window.
|
|
ErrInvalidTSpendWindow = ErrorKind("ErrInvalidTSpendWindow")
|
|
|
|
// ErrNotEnoughTSpendVotes indicates that a treasury spend transaction
|
|
// does not have enough votes to be included in block.
|
|
ErrNotEnoughTSpendVotes = ErrorKind("ErrNotEnoughTSpendVotes")
|
|
|
|
// ErrInvalidTSpendValueIn indicates that a treasury spend transaction
|
|
// ValueIn does not match the encoded copy in the first TxOut.
|
|
ErrInvalidTSpendValueIn = ErrorKind("ErrInvalidTSpendValueIn")
|
|
|
|
// ErrTSpendExists indicates that a duplicate treasury spend
|
|
// transaction has been mined on a TVI in the current best chain.
|
|
ErrTSpendExists = ErrorKind("ErrTSpendExists")
|
|
|
|
// ErrInvalidExpenditure indicates that a treasury spend transaction
|
|
// expenditure is out of range.
|
|
ErrInvalidExpenditure = ErrorKind("ErrInvalidExpenditure")
|
|
|
|
// ErrFirstTxNotTreasurybase indicates the first transaction in a block
|
|
// is not a treasurybase transaction.
|
|
ErrFirstTxNotTreasurybase = ErrorKind("ErrFirstTxNotTreasurybase")
|
|
|
|
// ErrBadTreasurybaseOutpoint indicates that the outpoint used by a
|
|
// treasurybase as input was non-null.
|
|
ErrBadTreasurybaseOutpoint = ErrorKind("ErrBadTreasurybaseOutpoint")
|
|
|
|
// ErrBadTreasurybaseFraudProof indicates that the fraud proof for a
|
|
// treasurybase input was non-null.
|
|
ErrBadTreasurybaseFraudProof = ErrorKind("ErrBadTreasurybaseFraudProof")
|
|
|
|
// ErrBadTreasurybaseScriptLen indicates the length of the signature script
|
|
// for a treasurybase transaction is not within the valid range.
|
|
ErrBadTreasurybaseScriptLen = ErrorKind("ErrBadTreasurybaseScriptLen")
|
|
|
|
// ErrTreasurybaseTxNotOpReturn indicates the second output of a
|
|
// treasury base transaction is not an OP_RETURN.
|
|
ErrTreasurybaseTxNotOpReturn = ErrorKind("ErrTreasurybaseTxNotOpReturn")
|
|
|
|
// ErrTreasurybaseHeight indicates that the encoded height in the
|
|
// treasurybase is incorrect.
|
|
ErrTreasurybaseHeight = ErrorKind("ErrTreasurybaseHeight")
|
|
|
|
// ErrInvalidTreasurybaseTxOutputs indicates that the transaction does
|
|
// not have the correct number of outputs.
|
|
ErrInvalidTreasurybaseTxOutputs = ErrorKind("ErrInvalidTreasurybaseTxOutputs")
|
|
|
|
// ErrInvalidTreasurybaseVersion indicates that the transaction output
|
|
// has the wrong version.
|
|
ErrInvalidTreasurybaseVersion = ErrorKind("ErrInvalidTreasurybaseVersion")
|
|
|
|
// ErrInvalidTreasurybaseScript indicates that the transaction output
|
|
// script is invalid.
|
|
ErrInvalidTreasurybaseScript = ErrorKind("ErrInvalidTreasurybaseScript")
|
|
|
|
// ErrTreasurybaseOutValue ensures that the OP_TADD value of a
|
|
// treasurybase is not the expected amount.
|
|
ErrTreasurybaseOutValue = ErrorKind("ErrTreasurybaseOutValue")
|
|
|
|
// ErrMultipleTreasurybases indicates a block contains more than one
|
|
// treasurybase transaction.
|
|
ErrMultipleTreasurybases = ErrorKind("ErrMultipleTreasurybases")
|
|
|
|
// ErrBadTreasurybaseAmountIn indicates that a block contains an
|
|
// invalid treasury contribution.
|
|
ErrBadTreasurybaseAmountIn = ErrorKind("ErrBadTreasurybaseAmountIn")
|
|
|
|
// ErrBadTSpendOutpoint indicates that the outpoint used by a
|
|
// treasury spend as input was non-null.
|
|
ErrBadTSpendOutpoint = ErrorKind("ErrBadTSpendOutpoint")
|
|
|
|
// ErrBadTSpendFraudProof indicates that the fraud proof for a treasury
|
|
// spend transaction input was non-null.
|
|
ErrBadTSpendFraudProof = ErrorKind("ErrBadTSpendFraudProof")
|
|
|
|
// ErrBadTSpendScriptLen indicates the length of the signature script
|
|
// for a treasury spend transaction is not within the valid range.
|
|
ErrBadTSpendScriptLen = ErrorKind("ErrBadTSpendScriptLen")
|
|
|
|
// ErrInvalidTAddChange indicates the change output of a TAdd is zero.
|
|
ErrInvalidTAddChange = ErrorKind("ErrInvalidTAddChange")
|
|
|
|
// ErrTooManyTAdds indicates the number of treasury adds in a given
|
|
// block is larger than the maximum allowed.
|
|
ErrTooManyTAdds = ErrorKind("ErrTooManyTAdds")
|
|
|
|
// ErrTicketExhaustion indicates extending a given block with another one
|
|
// would result in an unrecoverable chain due to ticket exhaustion.
|
|
ErrTicketExhaustion = ErrorKind("ErrTicketExhaustion")
|
|
|
|
// ErrDBTooOldToUpgrade indicates the database version is prior to the
|
|
// minimum supported version for which upgrades are supported.
|
|
ErrDBTooOldToUpgrade = ErrorKind("ErrDBTooOldToUpgrade")
|
|
|
|
// ErrUnknownBlock indicates a requested block does not exist.
|
|
ErrUnknownBlock = ErrorKind("ErrUnknownBlock")
|
|
|
|
// ErrNoFilter indicates a filter for a given block hash does not exist.
|
|
ErrNoFilter = ErrorKind("ErrNoFilter")
|
|
|
|
// ErrNoTreasuryBalance indicates the treasury balance for a given block
|
|
// hash does not exist.
|
|
ErrNoTreasuryBalance = ErrorKind("ErrNoTreasuryBalance")
|
|
|
|
// ErrInvalidateGenesisBlock indicates an attempt to invalidate the genesis
|
|
// block which is not allowed.
|
|
ErrInvalidateGenesisBlock = ErrorKind("ErrInvalidateGenesisBlock")
|
|
|
|
// ErrSerializeHeader indicates an attempt to serialize a block header failed.
|
|
ErrSerializeHeader = ErrorKind("ErrSerializeHeader")
|
|
|
|
// ------------------------------------------
|
|
// Errors related to the UTXO backend.
|
|
// ------------------------------------------
|
|
|
|
// ErrUtxoBackend indicates that a general error was encountered when
|
|
// accessing the UTXO backend.
|
|
ErrUtxoBackend = ErrorKind("ErrUtxoBackend")
|
|
|
|
// ErrUtxoBackendCorruption indicates that underlying data being accessed in
|
|
// the UTXO backend is corrupted.
|
|
ErrUtxoBackendCorruption = ErrorKind("ErrUtxoBackendCorruption")
|
|
|
|
// ErrUtxoBackendNotOpen indicates that the UTXO backend was accessed before
|
|
// it was opened or after it was closed.
|
|
ErrUtxoBackendNotOpen = ErrorKind("ErrUtxoBackendNotOpen")
|
|
|
|
// ErrUtxoBackendTxClosed indicates an attempt was made to commit or rollback
|
|
// a UTXO backend transaction that has already had one of those operations
|
|
// performed.
|
|
ErrUtxoBackendTxClosed = ErrorKind("ErrUtxoBackendTxClosed")
|
|
|
|
// -----------------------------------------------------------------
|
|
// Errors related to the automatic ticket revocations agenda.
|
|
// -----------------------------------------------------------------
|
|
|
|
// ErrInvalidRevocationTxVersion indicates that the revocation is the wrong
|
|
// transaction version.
|
|
ErrInvalidRevocationTxVersion = ErrorKind("ErrInvalidRevocationTxVersion")
|
|
|
|
// ErrNoExpiredTicketRevocation indicates that the block does not contain a
|
|
// revocation for a ticket that is becoming expired as of that block.
|
|
ErrNoExpiredTicketRevocation = ErrorKind("ErrNoExpiredTicketRevocation")
|
|
|
|
// ErrNoMissedTicketRevocation indicates that the block does not contain a
|
|
// revocation for a ticket that is becoming missed as of that block.
|
|
ErrNoMissedTicketRevocation = ErrorKind("ErrNoMissedTicketRevocation")
|
|
|
|
// -----------------------------------------------------------------
|
|
// Errors related to deployment validation.
|
|
// -----------------------------------------------------------------
|
|
|
|
// ErrUnknownDeploymentID indicates a deployment id does not exist.
|
|
ErrUnknownDeploymentID = ErrorKind("ErrUnknownDeploymentID")
|
|
|
|
// ErrUnknownDeploymentVersion indicates a version for a given deployment id
|
|
// was specified that does not exist.
|
|
ErrUnknownDeploymentVersion = ErrorKind("ErrUnknownDeploymentVersion")
|
|
|
|
// ErrDuplicateDeployment indicates a duplicate deployment id exists in the
|
|
// network parameter deployment definitions.
|
|
ErrDuplicateDeployment = ErrorKind("ErrDuplicateDeployment")
|
|
|
|
// ErrUnknownDeploymentChoice indicates a choice id for a deployment does
|
|
// not exist.
|
|
ErrUnknownDeploymentChoice = ErrorKind("ErrUnknownDeploymentChoice")
|
|
|
|
// ErrDeploymentBadMask indicates the mask for a deployment is invalid in
|
|
// some way. For example, if it is equal to zero or does not consist of
|
|
// only consecutive bits set.
|
|
ErrDeploymentBadMask = ErrorKind("ErrDeploymentBadMask")
|
|
|
|
// ErrDeploymentTooManyChoices indicates there are more choices defined for
|
|
// a deployment that its mask can represent.
|
|
ErrDeploymentTooManyChoices = ErrorKind("ErrDeploymentTooManyChoices")
|
|
|
|
// ErrDeploymentMissingChoiceID indicates a choice id is not set.
|
|
ErrDeploymentMissingChoiceID = ErrorKind("ErrDeploymentMissingChoiceID")
|
|
|
|
// ErrDeploymentBadChoiceBits indicates the choice bits that represent a
|
|
// deployment vote choice are invalid in some way. For example, when they
|
|
// are all zero and the choice is not also marked as abstain or they are not
|
|
// covered by the mask.
|
|
ErrDeploymentBadChoiceBits = ErrorKind("ErrDeploymentBadChoiceBits")
|
|
|
|
// ErrDeploymentNonExclusiveFlags indicates a deployment choice has an
|
|
// invalid flag combination.
|
|
ErrDeploymentNonExclusiveFlags = ErrorKind("ErrDeploymentNonExclusiveFlags")
|
|
|
|
// ErrDeploymentDuplicateChoice indicates a duplicate deployment choice id
|
|
// exists.
|
|
ErrDeploymentDuplicateChoice = ErrorKind("ErrDeploymentDuplicateChoice")
|
|
|
|
// ErrDeploymentMissingAbstain indicates a deployment vote does not have a
|
|
// choice that is marked as abstain.
|
|
ErrDeploymentMissingAbstain = ErrorKind("ErrDeploymentMissingAbstain")
|
|
|
|
// ErrDeploymentTooManyAbstain indicates a deployment vote has more than one
|
|
// choice that is marked as the abstaining choice.
|
|
ErrDeploymentTooManyAbstain = ErrorKind("ErrDeploymentTooManyAbstain")
|
|
|
|
// ErrDeploymentMissingNo indicates a deployment vote does not have a choice
|
|
// that is marked as the no choice.
|
|
ErrDeploymentMissingNo = ErrorKind("ErrDeploymentMissingNo")
|
|
|
|
// ErrDeploymentTooManyNo indicates a deployment vote has more than one
|
|
// choice that is marked as the no choice.
|
|
ErrDeploymentTooManyNo = ErrorKind("ErrDeploymentTooManyNo")
|
|
|
|
// ErrDeploymentChoiceAbstain indicates the forced choice id for a
|
|
// deployment is the unusable abstaining choice.
|
|
ErrDeploymentChoiceAbstain = ErrorKind("ErrDeploymentChoiceAbstain")
|
|
|
|
// ErrForcedMainNetChoice indicates a forced choice id is configured for a
|
|
// deployment on the main network.
|
|
ErrForcedMainNetChoice = ErrorKind("ErrForcedMainNetChoice")
|
|
)
|
|
|
|
// Error satisfies the error interface and prints human-readable errors.
|
|
func (e ErrorKind) Error() string {
|
|
return string(e)
|
|
}
|
|
|
|
// ContextError wraps an error with additional context. It has full support for
|
|
// errors.Is and errors.As, so the caller can ascertain the specific wrapped
|
|
// error.
|
|
//
|
|
// RawErr contains the original error in the case where an error has been
|
|
// converted.
|
|
type ContextError struct {
|
|
Err error
|
|
Description string
|
|
RawErr error
|
|
}
|
|
|
|
// Error satisfies the error interface and prints human-readable errors.
|
|
func (e ContextError) Error() string {
|
|
return e.Description
|
|
}
|
|
|
|
// Unwrap returns the underlying wrapped error.
|
|
func (e ContextError) Unwrap() error {
|
|
return e.Err
|
|
}
|
|
|
|
// contextError creates a ContextError given a set of arguments.
|
|
func contextError(kind ErrorKind, desc string) ContextError {
|
|
return ContextError{Err: kind, Description: desc}
|
|
}
|
|
|
|
// unknownBlockError create a ContextError with the kind of error set to
|
|
// ErrUnknownBlock and a description that includes the provided hash.
|
|
func unknownBlockError(hash *chainhash.Hash) ContextError {
|
|
str := fmt.Sprintf("block %s is not known", hash)
|
|
return contextError(ErrUnknownBlock, str)
|
|
}
|
|
|
|
// 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. It has full support for errors.Is and errors.As, so the caller can
|
|
// ascertain the specific reason for the rule violation.
|
|
type RuleError struct {
|
|
Err error
|
|
Description string
|
|
}
|
|
|
|
// Error satisfies the error interface and prints human-readable errors.
|
|
func (e RuleError) Error() string {
|
|
return e.Description
|
|
}
|
|
|
|
// Unwrap returns the underlying wrapped error.
|
|
func (e RuleError) Unwrap() error {
|
|
return e.Err
|
|
}
|
|
|
|
// ruleError creates a RuleError given a set of arguments.
|
|
func ruleError(kind ErrorKind, desc string) RuleError {
|
|
return RuleError{Err: kind, Description: desc}
|
|
}
|
|
|
|
// MultiError houses several errors as a single error that provides full support
|
|
// for errors.Is and errors.As so the caller can easily determine if any of the
|
|
// errors match any specific error or error type. Note that this differs from
|
|
// typical wrapped error chains which only represent a single error.
|
|
type MultiError []error
|
|
|
|
// Error satisfies the error interface and prints human-readable errors.
|
|
func (e MultiError) Error() string {
|
|
if len(e) == 1 {
|
|
return e[0].Error()
|
|
}
|
|
|
|
var builder strings.Builder
|
|
builder.WriteString("multiple errors (")
|
|
builder.WriteString(strconv.Itoa(len(e)))
|
|
builder.WriteString("):\n")
|
|
const maxErrs = 5
|
|
i := 0
|
|
for ; i < len(e) && i < maxErrs; i++ {
|
|
builder.WriteString(" - ")
|
|
builder.WriteString(e[i].Error())
|
|
builder.WriteRune('\n')
|
|
}
|
|
if len(e) > maxErrs {
|
|
builder.WriteString(" - ... ")
|
|
builder.WriteString(strconv.Itoa(len(e) - maxErrs))
|
|
builder.WriteString(" more error(s)")
|
|
builder.WriteRune('\n')
|
|
}
|
|
|
|
return builder.String()
|
|
}
|
|
|
|
// Is implements the interface to work with the standard library's errors.Is.
|
|
//
|
|
// It iterates each of the errors in the multi error and calls errors.Is on it
|
|
// until the first one that matches target is found, in which case it returns
|
|
// true. Otherwise, it returns false.
|
|
//
|
|
// This means it keeps all of the same semantics typically provided by Is in
|
|
// terms of unwrapping error chains.
|
|
func (e MultiError) Is(target error) bool {
|
|
for _, err := range e {
|
|
if errors.Is(err, target) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// As implements the interface to work with the standard library's errors.As.
|
|
//
|
|
// It iterates each of the errors in the multi error and calls errors.As on it
|
|
// until the first one that matches target is found, in which case it returns
|
|
// true. Otherwise, it returns false.
|
|
//
|
|
// This means it keeps all of the same semantics typically provided by As in
|
|
// terms of unwrapping error chains and setting the target to the matched error.
|
|
func (e MultiError) As(target interface{}) bool {
|
|
for _, err := range e {
|
|
if errors.As(err, target) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|