txscript: convert all new segwit error types to ErrorCode's

This commit is contained in:
Olaoluwa Osuntokun 2017-04-26 16:33:28 -07:00 committed by Dave Collins
parent 80dd96ac5d
commit ff6cb25e89
4 changed files with 101 additions and 60 deletions

View file

@ -259,7 +259,7 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error {
if len(witness) != 2 { if len(witness) != 2 {
err := fmt.Sprintf("should have exactly two "+ err := fmt.Sprintf("should have exactly two "+
"items in witness, instead have %v", len(witness)) "items in witness, instead have %v", len(witness))
return scriptError(ErrWitnessScriptMismatch, err) return scriptError(ErrWitnessProgramMismatch, err)
} }
// Now we'll resume execution as if it were a regular // Now we'll resume execution as if it were a regular
@ -280,7 +280,6 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error {
vm.SetStack(witness) vm.SetStack(witness)
case payToWitnessScriptHashDataSize: // P2WSH case payToWitnessScriptHashDataSize: // P2WSH
// Additionally, The witness stack MUST NOT be empty at // Additionally, The witness stack MUST NOT be empty at
// this point. // this point.
if len(witness) == 0 { if len(witness) == 0 {
@ -303,7 +302,7 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error {
// the witness stack matches the witness program. // the witness stack matches the witness program.
witnessHash := sha256.Sum256(witnessScript) witnessHash := sha256.Sum256(witnessScript)
if !bytes.Equal(witnessHash[:], vm.witnessProgram) { if !bytes.Equal(witnessHash[:], vm.witnessProgram) {
return scriptError(ErrWitnessScriptMismatch, return scriptError(ErrWitnessProgramMismatch,
"witness program hash mismatch") "witness program hash mismatch")
} }
@ -330,8 +329,9 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error {
return scriptError(ErrWitnessProgramWrongLength, errStr) return scriptError(ErrWitnessProgramWrongLength, errStr)
} }
} else if vm.hasFlag(ScriptVerifyDiscourageUpgradeableWitnessProgram) { } else if vm.hasFlag(ScriptVerifyDiscourageUpgradeableWitnessProgram) {
return fmt.Errorf("new witness program versions invalid: %v", errStr := fmt.Sprintf("new witness program versions "+
vm.witnessVersion) "invalid: %v", vm.witnessProgram)
return scriptError(ErrDiscourageUpgradableWitnessProgram, errStr)
} else { } else {
// If we encounter an unknown witness program version and we // If we encounter an unknown witness program version and we
// aren't discouraging future unknown witness based soft-forks, // aren't discouraging future unknown witness based soft-forks,

View file

@ -209,6 +209,15 @@ const (
// operations. // operations.
ErrNullFail ErrNullFail
// ErrWitnessMalleated is returned if ScriptVerifyWitness is set and a
// native p2wsh program is encountered which has a non-empty sigScript.
ErrWitnessMalleated
// ErrWitnessMalleatedP2SH is returned if ScriptVerifyWitness if set
// and the validation logic for nested p2sh encounters a sigScript
// which isn't *exactyl* a datapush of the witness program.
ErrWitnessMalleatedP2SH
// ------------------------------- // -------------------------------
// Failures related to soft forks. // Failures related to soft forks.
// ------------------------------- // -------------------------------
@ -227,34 +236,46 @@ const (
// reached. // reached.
ErrUnsatisfiedLockTime ErrUnsatisfiedLockTime
// ErrMinimalIf is returned if ScriptVerifyWitness is set and the
// operand of an OP_IF/OP_NOF_IF are not either an empty vector or
// [0x01].
ErrMinimalIf
// ErrDiscourageUpgradableWitnessProgram is returned if
// ScriptVerifyWitness is set and the versino of an executing witness
// program is outside the set of currently defined witness program
// vesions.
ErrDiscourageUpgradableWitnessProgram
// ----------------------------------------
// Failures related to segregated witness.
// ----------------------------------------
// ErrWitnessProgramEmpty is returned if ScriptVerifyWitness is set and // ErrWitnessProgramEmpty is returned if ScriptVerifyWitness is set and
// the witness stack itself is empty. // the witness stack itself is empty.
ErrWitnessProgramEmpty ErrWitnessProgramEmpty
// ErrWitnessScriptMismatch is returned if ScriptVerifyWitness is set // ErrWitnessProgramMismatch is returned if ScriptVerifyWitness is set
// and the witness itself for a p2wkh witness program isn't *exactly* 2 // and the witness itself for a p2wkh witness program isn't *exactly* 2
// items. // items or if the witness for a p2wsh isn't the sha255 of the witness
ErrWitnessScriptMismatch // script.
ErrWitnessProgramMismatch
// ErrWitnessProgramWrongLength is returned if ScriptVerifyWitness is // ErrWitnessProgramWrongLength is returned if ScriptVerifyWitness is
// set and the length of the witness program violates the length as // set and the length of the witness program violates the length as
// dictated by the current witness version. // dictated by the current witness version.
ErrWitnessProgramWrongLength ErrWitnessProgramWrongLength
// ErrWitnessMalleated is returned if ScriptVerifyWitness is set and a
// native p2wsh program is encountered which has a non-empty sigScript.
ErrWitnessMalleated
// ErrWitnessMalleatedP2SH is returned if ScriptVerifyWitness if set
// and the validation logic for nested p2sh encounters a sigScript
// which isn't *exactyl* a datapush of the witness program.
ErrWitnessMalleatedP2SH
// ErrWitnessUnexpected is returned if ScriptVerifyWitness is set and a // ErrWitnessUnexpected is returned if ScriptVerifyWitness is set and a
// transaction includes witness data but doesn't spend an which is a // transaction includes witness data but doesn't spend an which is a
// witness program (nested or native). // witness program (nested or native).
ErrWitnessUnexpected ErrWitnessUnexpected
// ErrWitnessPubKeyType is returned if ScriptVerifyWitness is set and
// the public key used in either a check-sig or check-multi-sig isn't
// serialized in a compressed format.
ErrWitnessPubKeyType
// numErrorCodes is the maximum error code number used in tests. This // numErrorCodes is the maximum error code number used in tests. This
// entry MUST be the last entry in the enum. // entry MUST be the last entry in the enum.
numErrorCodes numErrorCodes
@ -262,47 +283,56 @@ const (
// Map of ErrorCode values back to their constant names for pretty printing. // Map of ErrorCode values back to their constant names for pretty printing.
var errorCodeStrings = map[ErrorCode]string{ var errorCodeStrings = map[ErrorCode]string{
ErrInternal: "ErrInternal", ErrInternal: "ErrInternal",
ErrInvalidFlags: "ErrInvalidFlags", ErrInvalidFlags: "ErrInvalidFlags",
ErrInvalidIndex: "ErrInvalidIndex", ErrInvalidIndex: "ErrInvalidIndex",
ErrUnsupportedAddress: "ErrUnsupportedAddress", ErrUnsupportedAddress: "ErrUnsupportedAddress",
ErrNotMultisigScript: "ErrNotMultisigScript", ErrNotMultisigScript: "ErrNotMultisigScript",
ErrTooManyRequiredSigs: "ErrTooManyRequiredSigs", ErrTooManyRequiredSigs: "ErrTooManyRequiredSigs",
ErrTooMuchNullData: "ErrTooMuchNullData", ErrTooMuchNullData: "ErrTooMuchNullData",
ErrEarlyReturn: "ErrEarlyReturn", ErrEarlyReturn: "ErrEarlyReturn",
ErrEmptyStack: "ErrEmptyStack", ErrEmptyStack: "ErrEmptyStack",
ErrEvalFalse: "ErrEvalFalse", ErrEvalFalse: "ErrEvalFalse",
ErrScriptUnfinished: "ErrScriptUnfinished", ErrScriptUnfinished: "ErrScriptUnfinished",
ErrInvalidProgramCounter: "ErrInvalidProgramCounter", ErrInvalidProgramCounter: "ErrInvalidProgramCounter",
ErrScriptTooBig: "ErrScriptTooBig", ErrScriptTooBig: "ErrScriptTooBig",
ErrElementTooBig: "ErrElementTooBig", ErrElementTooBig: "ErrElementTooBig",
ErrTooManyOperations: "ErrTooManyOperations", ErrTooManyOperations: "ErrTooManyOperations",
ErrStackOverflow: "ErrStackOverflow", ErrStackOverflow: "ErrStackOverflow",
ErrInvalidPubKeyCount: "ErrInvalidPubKeyCount", ErrInvalidPubKeyCount: "ErrInvalidPubKeyCount",
ErrInvalidSignatureCount: "ErrInvalidSignatureCount", ErrInvalidSignatureCount: "ErrInvalidSignatureCount",
ErrNumberTooBig: "ErrNumberTooBig", ErrNumberTooBig: "ErrNumberTooBig",
ErrVerify: "ErrVerify", ErrVerify: "ErrVerify",
ErrEqualVerify: "ErrEqualVerify", ErrEqualVerify: "ErrEqualVerify",
ErrNumEqualVerify: "ErrNumEqualVerify", ErrNumEqualVerify: "ErrNumEqualVerify",
ErrCheckSigVerify: "ErrCheckSigVerify", ErrCheckSigVerify: "ErrCheckSigVerify",
ErrCheckMultiSigVerify: "ErrCheckMultiSigVerify", ErrCheckMultiSigVerify: "ErrCheckMultiSigVerify",
ErrDisabledOpcode: "ErrDisabledOpcode", ErrDisabledOpcode: "ErrDisabledOpcode",
ErrReservedOpcode: "ErrReservedOpcode", ErrReservedOpcode: "ErrReservedOpcode",
ErrMalformedPush: "ErrMalformedPush", ErrMalformedPush: "ErrMalformedPush",
ErrInvalidStackOperation: "ErrInvalidStackOperation", ErrInvalidStackOperation: "ErrInvalidStackOperation",
ErrUnbalancedConditional: "ErrUnbalancedConditional", ErrUnbalancedConditional: "ErrUnbalancedConditional",
ErrMinimalData: "ErrMinimalData", ErrMinimalData: "ErrMinimalData",
ErrInvalidSigHashType: "ErrInvalidSigHashType", ErrInvalidSigHashType: "ErrInvalidSigHashType",
ErrSigDER: "ErrSigDER", ErrSigDER: "ErrSigDER",
ErrSigHighS: "ErrSigHighS", ErrSigHighS: "ErrSigHighS",
ErrNotPushOnly: "ErrNotPushOnly", ErrNotPushOnly: "ErrNotPushOnly",
ErrSigNullDummy: "ErrSigNullDummy", ErrSigNullDummy: "ErrSigNullDummy",
ErrPubKeyType: "ErrPubKeyType", ErrPubKeyType: "ErrPubKeyType",
ErrCleanStack: "ErrCleanStack", ErrCleanStack: "ErrCleanStack",
ErrNullFail: "ErrNullFail", ErrNullFail: "ErrNullFail",
ErrDiscourageUpgradableNOPs: "ErrDiscourageUpgradableNOPs", ErrDiscourageUpgradableNOPs: "ErrDiscourageUpgradableNOPs",
ErrNegativeLockTime: "ErrNegativeLockTime", ErrNegativeLockTime: "ErrNegativeLockTime",
ErrUnsatisfiedLockTime: "ErrUnsatisfiedLockTime", ErrUnsatisfiedLockTime: "ErrUnsatisfiedLockTime",
ErrWitnessProgramEmpty: "ErrWitnessProgramEmpty",
ErrWitnessProgramMismatch: "ErrWitnessProgramMismatch",
ErrWitnessProgramWrongLength: "ErrWitnessProgramWrongLength",
ErrWitnessMalleated: "ErrWitnessMalleated",
ErrWitnessMalleatedP2SH: "ErrWitnessMalleatedP2SH",
ErrWitnessUnexpected: "ErrWitnessUnexpected",
ErrMinimalIf: "ErrMinimalIf",
ErrWitnessPubKeyType: "ErrWitnessPubKeyType",
ErrDiscourageUpgradableWitnessProgram: "ErrDiscourageUpgradableWitnessProgram",
} }
// String returns the ErrorCode as a human-readable name. // String returns the ErrorCode as a human-readable name.

View file

@ -57,6 +57,15 @@ func TestErrorCodeStringer(t *testing.T) {
{ErrDiscourageUpgradableNOPs, "ErrDiscourageUpgradableNOPs"}, {ErrDiscourageUpgradableNOPs, "ErrDiscourageUpgradableNOPs"},
{ErrNegativeLockTime, "ErrNegativeLockTime"}, {ErrNegativeLockTime, "ErrNegativeLockTime"},
{ErrUnsatisfiedLockTime, "ErrUnsatisfiedLockTime"}, {ErrUnsatisfiedLockTime, "ErrUnsatisfiedLockTime"},
{ErrWitnessProgramEmpty, "ErrWitnessProgramEmpty"},
{ErrWitnessProgramMismatch, "ErrWitnessProgramMismatch"},
{ErrWitnessProgramWrongLength, "ErrWitnessProgramWrongLength"},
{ErrWitnessMalleated, "ErrWitnessMalleated"},
{ErrWitnessMalleatedP2SH, "ErrWitnessMalleatedP2SH"},
{ErrWitnessUnexpected, "ErrWitnessUnexpected"},
{ErrMinimalIf, "ErrMinimalIf"},
{ErrWitnessPubKeyType, "ErrWitnessPubKeyType"},
{ErrDiscourageUpgradableWitnessProgram, "ErrDiscourageUpgradableWitnessProgram"},
{0xffff, "Unknown ErrorCode (65535)"}, {0xffff, "Unknown ErrorCode (65535)"},
} }

View file

@ -446,12 +446,14 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) {
case *btcutil.AddressWitnessPubKeyHash: case *btcutil.AddressWitnessPubKeyHash:
if addr == nil { if addr == nil {
return nil, ErrUnsupportedAddress return nil, scriptError(ErrUnsupportedAddress,
nilAddrErrStr)
} }
return payToWitnessPubKeyHashScript(addr.ScriptAddress()) return payToWitnessPubKeyHashScript(addr.ScriptAddress())
case *btcutil.AddressWitnessScriptHash: case *btcutil.AddressWitnessScriptHash:
if addr == nil { if addr == nil {
return nil, ErrUnsupportedAddress return nil, scriptError(ErrUnsupportedAddress,
nilAddrErrStr)
} }
return payToWitnessScriptHashScript(addr.ScriptAddress()) return payToWitnessScriptHashScript(addr.ScriptAddress())
} }