mirror of
https://github.com/btcsuite/btcd.git
synced 2025-02-23 22:47:01 +01:00
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
|
// coinbase transaction for version 2 and higher blocks does not match
|
||||||
// the expected value.
|
// the expected value.
|
||||||
ErrBadCoinbaseHeight
|
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.
|
// Map of ErrorCode values back to their constant names for pretty printing.
|
||||||
|
@ -187,6 +198,8 @@ var errorCodeStrings = map[ErrorCode]string{
|
||||||
ErrBadCoinbaseValue: "ErrBadCoinbaseValue",
|
ErrBadCoinbaseValue: "ErrBadCoinbaseValue",
|
||||||
ErrMissingCoinbaseHeight: "ErrMissingCoinbaseHeight",
|
ErrMissingCoinbaseHeight: "ErrMissingCoinbaseHeight",
|
||||||
ErrBadCoinbaseHeight: "ErrBadCoinbaseHeight",
|
ErrBadCoinbaseHeight: "ErrBadCoinbaseHeight",
|
||||||
|
ErrScriptMalformed: "ErrScriptMalformed",
|
||||||
|
ErrScriptValidation: "ErrScriptValidation",
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the ErrorCode as a human-readable name.
|
// String returns the ErrorCode as a human-readable name.
|
||||||
|
|
|
@ -48,6 +48,8 @@ func TestErrorCodeStringer(t *testing.T) {
|
||||||
{btcchain.ErrBadCoinbaseValue, "ErrBadCoinbaseValue"},
|
{btcchain.ErrBadCoinbaseValue, "ErrBadCoinbaseValue"},
|
||||||
{btcchain.ErrMissingCoinbaseHeight, "ErrMissingCoinbaseHeight"},
|
{btcchain.ErrMissingCoinbaseHeight, "ErrMissingCoinbaseHeight"},
|
||||||
{btcchain.ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"},
|
{btcchain.ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"},
|
||||||
|
{btcchain.ErrScriptMalformed, "ErrScriptMalformed"},
|
||||||
|
{btcchain.ErrScriptValidation, "ErrScriptValidation"},
|
||||||
{0xffff, "Unknown ErrorCode (65535)"},
|
{0xffff, "Unknown ErrorCode (65535)"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
scriptval.go
35
scriptval.go
|
@ -51,15 +51,15 @@ out:
|
||||||
select {
|
select {
|
||||||
case txVI := <-v.validateChan:
|
case txVI := <-v.validateChan:
|
||||||
// Ensure the referenced input transaction is available.
|
// Ensure the referenced input transaction is available.
|
||||||
//txIn := txVI.tx.MsgTx().TxIn[txVI.txInIdx]
|
|
||||||
txIn := txVI.txIn
|
txIn := txVI.txIn
|
||||||
txInHash := &txIn.PreviousOutpoint.Hash
|
originTxHash := &txIn.PreviousOutpoint.Hash
|
||||||
originTx, exists := v.txStore[*txInHash]
|
originTx, exists := v.txStore[*originTxHash]
|
||||||
if !exists || originTx.Err != nil || originTx.Tx == nil {
|
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 referenced from "+
|
||||||
"transaction %v", txInHash,
|
"transaction %v", originTxHash,
|
||||||
txVI.tx.Sha())
|
txVI.tx.Sha())
|
||||||
|
err := ruleError(ErrMissingTx, str)
|
||||||
v.sendResult(err)
|
v.sendResult(err)
|
||||||
break out
|
break out
|
||||||
}
|
}
|
||||||
|
@ -69,10 +69,12 @@ out:
|
||||||
// is available.
|
// is available.
|
||||||
originTxIndex := txIn.PreviousOutpoint.Index
|
originTxIndex := txIn.PreviousOutpoint.Index
|
||||||
if originTxIndex >= uint32(len(originMsgTx.TxOut)) {
|
if originTxIndex >= uint32(len(originMsgTx.TxOut)) {
|
||||||
err := fmt.Errorf("out of bounds "+
|
str := fmt.Sprintf("out of bounds "+
|
||||||
"input index %d in transaction %v "+
|
"input index %d in transaction %v "+
|
||||||
"referenced from transaction %v",
|
"referenced from transaction %v",
|
||||||
originTxIndex, txInHash, txVI.tx.Sha())
|
originTxIndex, originTxHash,
|
||||||
|
txVI.tx.Sha())
|
||||||
|
err := ruleError(ErrBadTxInput, str)
|
||||||
v.sendResult(err)
|
v.sendResult(err)
|
||||||
break out
|
break out
|
||||||
}
|
}
|
||||||
|
@ -83,17 +85,26 @@ out:
|
||||||
engine, err := btcscript.NewScript(sigScript, pkScript,
|
engine, err := btcscript.NewScript(sigScript, pkScript,
|
||||||
txVI.txInIndex, txVI.tx.MsgTx(), v.flags)
|
txVI.txInIndex, txVI.tx.MsgTx(), v.flags)
|
||||||
if err != nil {
|
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)
|
v.sendResult(err)
|
||||||
break out
|
break out
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the script pair.
|
// Execute the script pair.
|
||||||
if err := engine.Execute(); err != nil {
|
if err := engine.Execute(); err != nil {
|
||||||
err := fmt.Errorf("validate of input "+
|
str := fmt.Sprintf("failed to validate input "+
|
||||||
"%d from transaction %s failed: %v "+
|
"%s:%d which references output %s:%d - "+
|
||||||
"(input script bytes %x, prev output "+
|
"%v (input script bytes %x, prev output "+
|
||||||
"script bytes %x)", txVI.txInIndex,
|
"script bytes %x)", txVI.tx.Sha(),
|
||||||
txInHash, err, sigScript, pkScript)
|
txVI.txInIndex, originTxHash,
|
||||||
|
originTxIndex, err, sigScript, pkScript)
|
||||||
|
err := ruleError(ErrScriptValidation, str)
|
||||||
v.sendResult(err)
|
v.sendResult(err)
|
||||||
break out
|
break out
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue