Convert script errors to RuleErrors.
This commit modifies the error return type for errors during script validation to use the RuleError so they are consistent with the rest of the errors. This also helps the calling code differentiate blocks rejected due to script parsing and validation errors as opposed to internal issues such as inability to read from the disk. To accomplish this, two new two new RuleErrors, ErrScriptMalformed and ErrScriptValidation, have been added. Also, the errors for script parsing issues and script validation errors have been improved to include both transaction hashes and indexes involved in the validation effort. Previously script parsing issues had almost no additional information as to which transaction input/outputs the failing script came from.
This commit is contained in:
parent
cf3ad14d4d
commit
a22da99f91
3 changed files with 38 additions and 12 deletions
13
error.go
13
error.go
|
@ -151,6 +151,17 @@ const (
|
|||
// coinbase transaction for version 2 and higher blocks does not match
|
||||
// the expected value.
|
||||
ErrBadCoinbaseHeight
|
||||
|
||||
// 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
|
||||
|
||||
// ErrScriptValidation indicates the result of executing transaction
|
||||
// script failed. The error covers any failure when executing scripts
|
||||
// such signature verification failures and execution past the end of
|
||||
// the stack.
|
||||
ErrScriptValidation
|
||||
)
|
||||
|
||||
// Map of ErrorCode values back to their constant names for pretty printing.
|
||||
|
@ -187,6 +198,8 @@ var errorCodeStrings = map[ErrorCode]string{
|
|||
ErrBadCoinbaseValue: "ErrBadCoinbaseValue",
|
||||
ErrMissingCoinbaseHeight: "ErrMissingCoinbaseHeight",
|
||||
ErrBadCoinbaseHeight: "ErrBadCoinbaseHeight",
|
||||
ErrScriptMalformed: "ErrScriptMalformed",
|
||||
ErrScriptValidation: "ErrScriptValidation",
|
||||
}
|
||||
|
||||
// String returns the ErrorCode as a human-readable name.
|
||||
|
|
|
@ -48,6 +48,8 @@ func TestErrorCodeStringer(t *testing.T) {
|
|||
{btcchain.ErrBadCoinbaseValue, "ErrBadCoinbaseValue"},
|
||||
{btcchain.ErrMissingCoinbaseHeight, "ErrMissingCoinbaseHeight"},
|
||||
{btcchain.ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"},
|
||||
{btcchain.ErrScriptMalformed, "ErrScriptMalformed"},
|
||||
{btcchain.ErrScriptValidation, "ErrScriptValidation"},
|
||||
{0xffff, "Unknown ErrorCode (65535)"},
|
||||
}
|
||||
|
||||
|
|
35
scriptval.go
35
scriptval.go
|
@ -51,15 +51,15 @@ out:
|
|||
select {
|
||||
case txVI := <-v.validateChan:
|
||||
// Ensure the referenced input transaction is available.
|
||||
//txIn := txVI.tx.MsgTx().TxIn[txVI.txInIdx]
|
||||
txIn := txVI.txIn
|
||||
txInHash := &txIn.PreviousOutpoint.Hash
|
||||
originTx, exists := v.txStore[*txInHash]
|
||||
originTxHash := &txIn.PreviousOutpoint.Hash
|
||||
originTx, exists := v.txStore[*originTxHash]
|
||||
if !exists || originTx.Err != nil || originTx.Tx == nil {
|
||||
err := fmt.Errorf("unable to find input "+
|
||||
str := fmt.Sprintf("unable to find input "+
|
||||
"transaction %v referenced from "+
|
||||
"transaction %v", txInHash,
|
||||
"transaction %v", originTxHash,
|
||||
txVI.tx.Sha())
|
||||
err := ruleError(ErrMissingTx, str)
|
||||
v.sendResult(err)
|
||||
break out
|
||||
}
|
||||
|
@ -69,10 +69,12 @@ out:
|
|||
// is available.
|
||||
originTxIndex := txIn.PreviousOutpoint.Index
|
||||
if originTxIndex >= uint32(len(originMsgTx.TxOut)) {
|
||||
err := fmt.Errorf("out of bounds "+
|
||||
str := fmt.Sprintf("out of bounds "+
|
||||
"input index %d in transaction %v "+
|
||||
"referenced from transaction %v",
|
||||
originTxIndex, txInHash, txVI.tx.Sha())
|
||||
originTxIndex, originTxHash,
|
||||
txVI.tx.Sha())
|
||||
err := ruleError(ErrBadTxInput, str)
|
||||
v.sendResult(err)
|
||||
break out
|
||||
}
|
||||
|
@ -83,17 +85,26 @@ out:
|
|||
engine, err := btcscript.NewScript(sigScript, pkScript,
|
||||
txVI.txInIndex, txVI.tx.MsgTx(), v.flags)
|
||||
if err != nil {
|
||||
str := fmt.Sprintf("failed to parse input "+
|
||||
"%s:%d which references output %s:%d - "+
|
||||
"%v (input script bytes %x, prev output "+
|
||||
"script bytes %x)", txVI.tx.Sha(),
|
||||
txVI.txInIndex, originTxHash,
|
||||
originTxIndex, err, sigScript, pkScript)
|
||||
err := ruleError(ErrScriptMalformed, str)
|
||||
v.sendResult(err)
|
||||
break out
|
||||
}
|
||||
|
||||
// Execute the script pair.
|
||||
if err := engine.Execute(); err != nil {
|
||||
err := fmt.Errorf("validate of input "+
|
||||
"%d from transaction %s failed: %v "+
|
||||
"(input script bytes %x, prev output "+
|
||||
"script bytes %x)", txVI.txInIndex,
|
||||
txInHash, err, sigScript, pkScript)
|
||||
str := fmt.Sprintf("failed to validate input "+
|
||||
"%s:%d which references output %s:%d - "+
|
||||
"%v (input script bytes %x, prev output "+
|
||||
"script bytes %x)", txVI.tx.Sha(),
|
||||
txVI.txInIndex, originTxHash,
|
||||
originTxIndex, err, sigScript, pkScript)
|
||||
err := ruleError(ErrScriptValidation, str)
|
||||
v.sendResult(err)
|
||||
break out
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue