[DEV-98] Move script flags from relay rules to consensus (#49)

* [DEV-98] Move script flags from relay rules to consensus

* [DEV-98] remove flags from script_tests.json

* [DEV-98] fix multisig and remove test that assume no minimal data rule

* [DEV-98] rename bip16 bool to isP2sh

* [DEV-98] add sighash type to overly long signature in script_tests.json

* [DEV-98] add test for NUMEQUAL for non equal numbers script_tests.json

* [DEV-98] remove debugging if

* [DEV-98] remove ErrCleanStack from EVAL_FALSE

* [DEV-98] change isP2sh to isP2SH to comply with Go style

* [DEV-98] add ScriptNoFlags to explictly indicate for empty ScriptFlags

* [DEV-98] rename ErrPubKeyType -> ErrPubKeyFormat

* [DEV-98] rename PUBKEYTYPE -> PUBKEYFORMAT
This commit is contained in:
Ori Newman 2018-08-23 17:45:49 +03:00 committed by Svarog
parent c65d9aa168
commit b4b71eec01
20 changed files with 1087 additions and 1465 deletions

View File

@ -40,7 +40,7 @@ func TestCheckBlockScripts(t *testing.T) {
return
}
scriptFlags := txscript.ScriptBip16
scriptFlags := txscript.ScriptNoFlags
err = checkBlockScripts(blocks[0], view, scriptFlags, nil)
if err != nil {
t.Errorf("Transaction script validation failed: %v\n", err)

View File

@ -955,12 +955,6 @@ func (dag *BlockDAG) checkConnectBlock(node *blockNode, block *util.Block, view
return err
}
// BIP0016 describes a pay-to-script-hash type that is considered a
// "standard" type. The rules for this BIP only apply to transactions
// after the timestamp defined by txscript.Bip16Activation. See
// https://en.bitcoin.it/wiki/BIP_0016 for more details.
enforceBIP0016 := node.timestamp >= txscript.Bip16Activation.Unix()
// The number of signature operations must be less than the maximum
// allowed per block. Note that the preliminary sanity checks on a
// block also include a check similar to this one, but this check
@ -971,19 +965,17 @@ func (dag *BlockDAG) checkConnectBlock(node *blockNode, block *util.Block, view
totalSigOps := 0
for i, tx := range transactions {
numsigOps := CountSigOps(tx)
if enforceBIP0016 {
// Since the first (and only the first) transaction has
// already been verified to be a coinbase transaction,
// use i == 0 as an optimization for the flag to
// countP2SHSigOps for whether or not the transaction is
// a coinbase transaction rather than having to do a
// full coinbase check again.
numP2SHSigOps, err := CountP2SHSigOps(tx, i == 0, view)
if err != nil {
return err
}
numsigOps += numP2SHSigOps
// Since the first (and only the first) transaction has
// already been verified to be a coinbase transaction,
// use i == 0 as an optimization for the flag to
// countP2SHSigOps for whether or not the transaction is
// a coinbase transaction rather than having to do a
// full coinbase check again.
numP2SHSigOps, err := CountP2SHSigOps(tx, i == 0, view)
if err != nil {
return err
}
numsigOps += numP2SHSigOps
// Check for overflow or going over the limits. We have to do
// this on every loop iteration to avoid overflow.
@ -1065,12 +1057,7 @@ func (dag *BlockDAG) checkConnectBlock(node *blockNode, block *util.Block, view
runScripts = false
}
// Blocks created after the BIP0016 activation time need to have the
// pay-to-script-hash checks enabled.
var scriptFlags txscript.ScriptFlags
if enforceBIP0016 {
scriptFlags |= txscript.ScriptBip16
}
scriptFlags := txscript.ScriptNoFlags
// We obtain the MTP of the *previous* block in order to
// determine if transactions in the current block are final.

View File

@ -10,8 +10,8 @@ import (
"github.com/daglabs/btcd/blockdag"
"github.com/daglabs/btcd/txscript"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/wire"
)
const (
@ -84,12 +84,7 @@ func calcMinRequiredTxRelayFee(serializedSize int64, minRelayTxFee util.Amount)
// to ensure they are "standard". A standard transaction input within the
// context of this function is one whose referenced public key script is of a
// standard form and, for pay-to-script-hash, does not have more than
// maxStandardP2SHSigOps signature operations. However, it should also be noted
// that standard inputs also are those which have a clean stack after execution
// and only contain pushed data in their signature scripts. This function does
// not perform those checks because the script engine already does this more
// accurately and concisely via the txscript.ScriptVerifyCleanStack and
// txscript.ScriptVerifySigPushOnly flags.
// maxStandardP2SHSigOps signature operations.
func checkInputsStandard(tx *util.Tx, utxoView *blockdag.UtxoViewpoint) error {
// NOTE: The reference implementation also does a coinbase check here,
// but coinbases have already been rejected prior to calling this

File diff suppressed because one or more lines are too long

View File

@ -17,9 +17,9 @@ import (
type ScriptFlags uint32
const (
// ScriptBip16 defines whether the bip16 threshold has passed and thus
// pay-to-script hash transactions will be fully validated.
ScriptBip16 ScriptFlags = 1 << iota
// ScriptNoFlags is used when you want to use ScriptFlags without raising any flags
ScriptNoFlags ScriptFlags = 0
// ScriptDiscourageUpgradableNops defines whether to verify that
// NOP1 through NOP10 are reserved for future soft-fork upgrades. This
@ -27,40 +27,13 @@ const (
// blocks as this flag is only for stricter standard transaction
// checks. This flag is only applied when the above opcodes are
// executed.
ScriptDiscourageUpgradableNops
// ScriptVerifyCleanStack defines that the stack must contain only
// one stack element after evaluation and that the element must be
// true if interpreted as a boolean. This is rule 6 of BIP0062.
// This flag should never be used without the ScriptBip16 flag.
ScriptVerifyCleanStack
// ScriptVerifyLowS defines that signtures are required to comply with
// the DER format and whose S value is <= order / 2. This is rule 5
// of BIP0062.
ScriptVerifyLowS
// ScriptVerifyMinimalData defines that signatures must use the smallest
// push operator. This is both rules 3 and 4 of BIP0062.
ScriptVerifyMinimalData
// ScriptVerifyNullFail defines that signatures must be empty if
// a CHECKSIG or CHECKMULTISIG operation fails.
ScriptVerifyNullFail
// ScriptVerifySigPushOnly defines that signature scripts must contain
// only pushed data. This is rule 2 of BIP0062.
ScriptVerifySigPushOnly
// ScriptVerifyStrictEncoding defines that signature scripts and
// public keys must follow the strict encoding requirements.
ScriptVerifyStrictEncoding
ScriptDiscourageUpgradableNops ScriptFlags = 1 << iota
)
const (
// MaxStackSize is the maximum combined height of stack and alt stack
// during execution.
MaxStackSize = 1000
MaxStackSize = 244
// MaxScriptSize is the maximum allowed length of a raw script.
MaxScriptSize = 10000
@ -82,8 +55,8 @@ type Engine struct {
numOps int
flags ScriptFlags
sigCache *SigCache
bip16 bool // treat execution as pay-to-script-hash
savedFirstStack [][]byte // stack from first script for bip16 scripts
isP2SH bool // treat execution as pay-to-script-hash
savedFirstStack [][]byte // stack from first script for ps2h scripts
}
// hasFlag returns whether the script engine instance has the passed flag set.
@ -143,7 +116,7 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error {
// Ensure all executed data push opcodes use the minimal encoding when
// the minimal data verification flag is set.
if vm.dstack.verifyMinimalData && vm.isBranchExecuting() &&
if vm.isBranchExecuting() &&
pop.opcode.value >= 0 && pop.opcode.value <= OpPushData4 {
if err := pop.checkMinimalDataPush(); err != nil {
@ -228,15 +201,16 @@ func (vm *Engine) CheckErrorCondition(finalScript bool) error {
"error check when script unfinished")
}
if finalScript && vm.hasFlag(ScriptVerifyCleanStack) &&
vm.dstack.Depth() != 1 {
if finalScript {
if vm.dstack.Depth() > 1 {
str := fmt.Sprintf("stack contains %d unexpected items",
vm.dstack.Depth()-1)
return scriptError(ErrCleanStack, str)
} else if vm.dstack.Depth() < 1 {
return scriptError(ErrEmptyStack,
"stack empty at end of script execution")
str := fmt.Sprintf("stack contains %d unexpected items",
vm.dstack.Depth()-1)
return scriptError(ErrCleanStack, str)
} else if vm.dstack.Depth() < 1 {
return scriptError(ErrEmptyStack,
"stack empty at end of script execution")
}
}
v, err := vm.dstack.PopBool()
@ -302,10 +276,10 @@ func (vm *Engine) Step() (done bool, err error) {
vm.numOps = 0 // number of ops is per script.
vm.scriptOff = 0
if vm.scriptIdx == 0 && vm.bip16 {
if vm.scriptIdx == 0 && vm.isP2SH {
vm.scriptIdx++
vm.savedFirstStack = vm.GetStack()
} else if vm.scriptIdx == 1 && vm.bip16 {
} else if vm.scriptIdx == 1 && vm.isP2SH {
// Put us past the end for CheckErrorCondition()
vm.scriptIdx++
// Check script ran successfully and pull the script
@ -382,10 +356,6 @@ func (vm *Engine) currentScript() []parsedOpcode {
// checkHashTypeEncoding returns whether or not the passed hashtype adheres to
// the strict encoding requirements if enabled.
func (vm *Engine) checkHashTypeEncoding(hashType SigHashType) error {
if !vm.hasFlag(ScriptVerifyStrictEncoding) {
return nil
}
sigHashType := hashType & ^SigHashAnyOneCanPay
if sigHashType < SigHashAll || sigHashType > SigHashSingle {
str := fmt.Sprintf("invalid hash type 0x%x", hashType)
@ -397,10 +367,6 @@ func (vm *Engine) checkHashTypeEncoding(hashType SigHashType) error {
// checkPubKeyEncoding returns whether or not the passed public key adheres to
// the strict encoding requirements if enabled.
func (vm *Engine) checkPubKeyEncoding(pubKey []byte) error {
if !vm.hasFlag(ScriptVerifyStrictEncoding) {
return nil
}
if len(pubKey) == 33 && (pubKey[0] == 0x02 || pubKey[0] == 0x03) {
// Compressed
return nil
@ -410,7 +376,7 @@ func (vm *Engine) checkPubKeyEncoding(pubKey []byte) error {
return nil
}
return scriptError(ErrPubKeyType, "unsupported public key type")
return scriptError(ErrPubKeyFormat, "unsupported public key type")
}
// checkSignatureEncoding returns whether or not the passed signature adheres to
@ -542,13 +508,11 @@ func (vm *Engine) checkSignatureEncoding(sig []byte) error {
// valid transaction with the complement while still being a valid
// signature that verifies. This would result in changing the
// transaction hash and thus is source of malleability.
if vm.hasFlag(ScriptVerifyLowS) {
sValue := new(big.Int).SetBytes(sig[rLen+6 : rLen+6+sLen])
if sValue.Cmp(halfOrder) > 0 {
return scriptError(ErrSigHighS,
"signature is not canonical due to "+
"unnecessarily high S value")
}
sValue := new(big.Int).SetBytes(sig[rLen+6 : rLen+6+sLen])
if sValue.Cmp(halfOrder) > 0 {
return scriptError(ErrSigHighS,
"signature is not canonical due to "+
"unnecessarily high S value")
}
return nil
@ -622,64 +586,43 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags
"false stack entry at end of script execution")
}
// The clean stack flag (ScriptVerifyCleanStack) is not allowed without
// the pay-to-script-hash (P2SH) evaluation (ScriptBip16) flag.
//
// Recall that evaluating a P2SH script without the flag set results in
// non-P2SH evaluation which leaves the P2SH inputs on the stack. Thus,
// allowing the clean stack flag without the P2SH flag would make it
// possible to have a situation where P2SH would not be a soft fork when
// it should be.
vm := Engine{flags: flags, sigCache: sigCache}
if vm.hasFlag(ScriptVerifyCleanStack) && !vm.hasFlag(ScriptBip16) {
return nil, scriptError(ErrInvalidFlags,
"invalid flags combination")
}
// The signature script must only contain data pushes when the
// associated flag is set.
if vm.hasFlag(ScriptVerifySigPushOnly) && !IsPushOnlyScript(scriptSig) {
parsedScriptSig, err := parseScriptAndVerifySize(scriptSig)
if err != nil {
return nil, err
}
// The signature script must only contain data pushes
if !isPushOnly(parsedScriptSig) {
return nil, scriptError(ErrNotPushOnly,
"signature script is not push only")
}
parsedScriptPubKey, err := parseScriptAndVerifySize(scriptPubKey)
if err != nil {
return nil, err
}
// The engine stores the scripts in parsed form using a slice. This
// allows multiple scripts to be executed in sequence. For example,
// with a pay-to-script-hash transaction, there will be ultimately be
// a third script to execute.
scripts := [][]byte{scriptSig, scriptPubKey}
vm.scripts = make([][]parsedOpcode, len(scripts))
for i, scr := range scripts {
if len(scr) > MaxScriptSize {
str := fmt.Sprintf("script size %d is larger than max "+
"allowed size %d", len(scr), MaxScriptSize)
return nil, scriptError(ErrScriptTooBig, str)
}
var err error
vm.scripts[i], err = parseScript(scr)
if err != nil {
return nil, err
}
}
vm.scripts = [][]parsedOpcode{parsedScriptSig, parsedScriptPubKey}
// Advance the program counter to the public key script if the signature
// script is empty since there is nothing to execute for it in that
// case.
if len(scripts[0]) == 0 {
if len(scriptSig) == 0 {
vm.scriptIdx++
}
if vm.hasFlag(ScriptBip16) && isScriptHash(vm.scripts[1]) {
if isScriptHash(vm.scripts[1]) {
// Only accept input scripts that push data for P2SH.
if !isPushOnly(vm.scripts[0]) {
return nil, scriptError(ErrNotPushOnly,
"pay to script hash is not push only")
}
vm.bip16 = true
}
if vm.hasFlag(ScriptVerifyMinimalData) {
vm.dstack.verifyMinimalData = true
vm.astack.verifyMinimalData = true
vm.isP2SH = true
}
vm.tx = *tx
@ -687,3 +630,12 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags
return &vm, nil
}
func parseScriptAndVerifySize(script []byte) ([]parsedOpcode, error) {
if len(script) > MaxScriptSize {
str := fmt.Sprintf("script size %d is larger than max "+
"allowed size %d", len(script), MaxScriptSize)
return nil, scriptError(ErrScriptTooBig, str)
}
return parseScript(script)
}

View File

@ -41,7 +41,7 @@ func TestBadPC(t *testing.T) {
}),
Index: 0,
},
SignatureScript: mustParseShortForm("NOP"),
SignatureScript: mustParseShortForm(""),
Sequence: 4294967295,
},
},
@ -145,56 +145,6 @@ func TestCheckErrorCondition(t *testing.T) {
}
}
// TestInvalidFlagCombinations ensures the script engine returns the expected
// error when disallowed flag combinations are specified.
func TestInvalidFlagCombinations(t *testing.T) {
t.Parallel()
tests := []ScriptFlags{
ScriptVerifyCleanStack,
}
// tx with almost empty scripts.
tx := &wire.MsgTx{
Version: 1,
TxIn: []*wire.TxIn{
{
PreviousOutPoint: wire.OutPoint{
Hash: daghash.Hash([32]byte{
0xc9, 0x97, 0xa5, 0xe5,
0x6e, 0x10, 0x41, 0x02,
0xfa, 0x20, 0x9c, 0x6a,
0x85, 0x2d, 0xd9, 0x06,
0x60, 0xa2, 0x0b, 0x2d,
0x9c, 0x35, 0x24, 0x23,
0xed, 0xce, 0x25, 0x85,
0x7f, 0xcd, 0x37, 0x04,
}),
Index: 0,
},
SignatureScript: []uint8{OpNop},
Sequence: 4294967295,
},
},
TxOut: []*wire.TxOut{
{
Value: 1000000000,
PkScript: nil,
},
},
LockTime: 0,
}
pkScript := []byte{OpNop}
for i, test := range tests {
_, err := NewEngine(pkScript, tx, 0, test, nil)
if !IsErrorCode(err, ErrInvalidFlags) {
t.Fatalf("TestInvalidFlagCombinations #%d unexpected "+
"error: %v", i, err)
}
}
}
// TestCheckPubKeyEncoding ensures the internal checkPubKeyEncoding function
// works as expected.
func TestCheckPubKeyEncoding(t *testing.T) {
@ -240,7 +190,7 @@ func TestCheckPubKeyEncoding(t *testing.T) {
},
}
vm := Engine{flags: ScriptVerifyStrictEncoding}
vm := Engine{}
for _, test := range tests {
err := vm.checkPubKeyEncoding(test.key)
if err != nil && test.isValid {
@ -412,7 +362,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
},
}
vm := Engine{flags: ScriptVerifyStrictEncoding}
vm := Engine{}
for _, test := range tests {
err := vm.checkSignatureEncoding(test.sig)
if err != nil && test.isValid {

View File

@ -166,9 +166,8 @@ const (
// Failures related to malleability.
// ---------------------------------
// ErrMinimalData is returned when the ScriptVerifyMinimalData flag
// is set and the script contains push operations that do not use
// the minimal opcode required.
// ErrMinimalData is returned when the script contains
// push operations that do not use the minimal opcode required.
ErrMinimalData
// ErrInvalidSigHashType is returned when a signature hash type is not
@ -189,23 +188,20 @@ const (
ErrSigHighS
// ErrNotPushOnly is returned when a script that is required to only
// push data to the stack performs other operations. A couple of cases
// where this applies is for a pay-to-script-hash signature script when
// bip16 is active and when the ScriptVerifySigPushOnly flag is set.
// push data to the stack performs other operations.
ErrNotPushOnly
// ErrPubKeyType is returned when the ScriptVerifyStrictEncoding
// flag is set and the script contains invalid public keys.
ErrPubKeyType
// ErrPubKeyFormat is returned when the script contains invalid public keys.
// A valid pubkey should be in uncompressed format as a 64 byte string prefixed with 0x04,
// or to be in compressed format as a 32 byte string prefixed with 0x02 or 0x03 to signal oddness.
ErrPubKeyFormat
// ErrCleanStack is returned when the ScriptVerifyCleanStack flag
// is set, and after evalution, the stack does not contain only a
// single element.
// ErrCleanStack is returned when after evalution, the stack
// contains more than one element.
ErrCleanStack
// ErrNullFail is returned when the ScriptVerifyNullFail flag is
// set and signatures are not empty on failed checksig or checkmultisig
// operations.
// ErrNullFail is returned when signatures are not empty
// on failed checksig or checkmultisig operations.
ErrNullFail
// -------------------------------
@ -268,7 +264,7 @@ var errorCodeStrings = map[ErrorCode]string{
ErrSigDER: "ErrSigDER",
ErrSigHighS: "ErrSigHighS",
ErrNotPushOnly: "ErrNotPushOnly",
ErrPubKeyType: "ErrPubKeyType",
ErrPubKeyFormat: "ErrPubKeyFormat",
ErrCleanStack: "ErrCleanStack",
ErrNullFail: "ErrNullFail",
ErrDiscourageUpgradableNOPs: "ErrDiscourageUpgradableNOPs",

View File

@ -51,7 +51,7 @@ func TestErrorCodeStringer(t *testing.T) {
{ErrSigDER, "ErrSigDER"},
{ErrSigHighS, "ErrSigHighS"},
{ErrNotPushOnly, "ErrNotPushOnly"},
{ErrPubKeyType, "ErrPubKeyType"},
{ErrPubKeyFormat, "ErrPubKeyFormat"},
{ErrCleanStack, "ErrCleanStack"},
{ErrNullFail, "ErrNullFail"},
{ErrDiscourageUpgradableNOPs, "ErrDiscourageUpgradableNOPs"},

View File

@ -162,8 +162,7 @@ func ExampleSignTxOutput() {
// Prove that the transaction has been validly signed by executing the
// script pair.
flags := txscript.ScriptBip16 |
txscript.ScriptDiscourageUpgradableNops
flags := txscript.ScriptDiscourageUpgradableNops
vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0, flags, nil)
if err != nil {
fmt.Println(err)

View File

@ -1101,7 +1101,7 @@ func opcodeCheckLockTimeVerify(op *parsedOpcode, vm *Engine) error {
if err != nil {
return err
}
lockTime, err := makeScriptNum(so, vm.dstack.verifyMinimalData, 5)
lockTime, err := makeScriptNum(so, 5)
if err != nil {
return err
}
@ -1164,7 +1164,7 @@ func opcodeCheckSequenceVerify(op *parsedOpcode, vm *Engine) error {
if err != nil {
return err
}
stackSequence, err := makeScriptNum(so, vm.dstack.verifyMinimalData, 5)
stackSequence, err := makeScriptNum(so, 5)
if err != nil {
return err
}
@ -2043,7 +2043,7 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error {
valid = signature.Verify(hash, pubKey)
}
if !valid && vm.hasFlag(ScriptVerifyNullFail) && len(sigBytes) > 0 {
if !valid && len(sigBytes) > 0 {
str := "signature not empty on failed checksig"
return scriptError(ErrNullFail, str)
}
@ -2248,7 +2248,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
}
}
if !success && vm.hasFlag(ScriptVerifyNullFail) {
if !success {
for _, sig := range signatures {
if len(sig.signature) > 0 {
str := "not all signatures empty on failed checkmultisig"

View File

@ -133,24 +133,8 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) {
switch flag {
case "":
// Nothing.
case "CLEANSTACK":
flags |= ScriptVerifyCleanStack
case "DISCOURAGE_UPGRADABLE_NOPS":
flags |= ScriptDiscourageUpgradableNops
case "LOW_S":
flags |= ScriptVerifyLowS
case "MINIMALDATA":
flags |= ScriptVerifyMinimalData
case "NONE":
// Nothing.
case "NULLFAIL":
flags |= ScriptVerifyNullFail
case "P2SH":
flags |= ScriptBip16
case "SIGPUSHONLY":
flags |= ScriptVerifySigPushOnly
case "STRICTENC":
flags |= ScriptVerifyStrictEncoding
default:
return flags, fmt.Errorf("invalid flag: %s", flag)
}
@ -167,12 +151,14 @@ func parseExpectedResult(expected string) ([]ErrorCode, error) {
return nil, nil
case "UNKNOWN_ERROR":
return []ErrorCode{ErrNumberTooBig, ErrMinimalData}, nil
case "PUBKEYTYPE":
return []ErrorCode{ErrPubKeyType}, nil
case "PUBKEYFORMAT":
return []ErrorCode{ErrPubKeyFormat}, nil
case "SIG_DER":
return []ErrorCode{ErrSigDER, ErrInvalidSigHashType}, nil
case "EVAL_FALSE":
return []ErrorCode{ErrEvalFalse, ErrEmptyStack}, nil
case "EMPTY_STACK":
return []ErrorCode{ErrEmptyStack}, nil
case "EQUALVERIFY":
return []ErrorCode{ErrEqualVerify}, nil
case "NULLFAIL":

View File

@ -8,17 +8,11 @@ import (
"bytes"
"encoding/binary"
"fmt"
"time"
"github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/wire"
)
// Bip16Activation is the timestamp where BIP0016 is valid to use in the
// blockchain. To be used to determine if BIP0016 should be called for or not.
// This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012.
var Bip16Activation = time.Unix(1333238400, 0)
// SigHashType represents hash type bits at the end of a signature.
type SigHashType uint32
@ -424,17 +418,17 @@ func GetSigOpCount(script []byte) int {
}
// GetPreciseSigOpCount returns the number of signature operations in
// scriptPubKey. If bip16 is true then scriptSig may be searched for the
// scriptPubKey. If p2sh is true then scriptSig may be searched for the
// Pay-To-Script-Hash script in order to find the precise number of signature
// operations in the transaction. If the script fails to parse, then the count
// up to the point of failure is returned.
func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int {
func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, isP2SH bool) int {
// Don't check error since parseScript returns the parsed-up-to-error
// list of pops.
pops, _ := parseScript(scriptPubKey)
// Treat non P2SH transactions as normal.
if !(bip16 && isScriptHash(pops)) {
if !(isP2SH && isScriptHash(pops)) {
return getSigOpCount(pops, true)
}

View File

@ -47,6 +47,11 @@ type scriptNum int64
// checkMinimalDataEncoding returns whether or not the passed byte array adheres
// to the minimal encoding requirements.
// An error will be returned if it will determined that
// the encoding is not represented with the smallest possible
// number of bytes or is the negative 0 encoding, [0x80]. For example, consider
// the number 127. It could be encoded as [0x7f], [0x7f 0x00],
// [0x7f 0x00 0x00 ...], etc. All forms except [0x7f] will return an error
func checkMinimalDataEncoding(v []byte) error {
if len(v) == 0 {
return nil
@ -167,13 +172,6 @@ func (n scriptNum) Int32() int32 {
// bytes and therefore will pass that value to this function resulting in an
// allowed range of [-2^31 + 1, 2^31 - 1].
//
// The requireMinimal flag causes an error to be returned if additional checks
// on the encoding determine it is not represented with the smallest possible
// number of bytes or is the negative 0 encoding, [0x80]. For example, consider
// the number 127. It could be encoded as [0x7f], [0x7f 0x00],
// [0x7f 0x00 0x00 ...], etc. All forms except [0x7f] will return an error with
// requireMinimal enabled.
//
// The scriptNumLen is the maximum number of bytes the encoded value can be
// before an ErrStackNumberTooBig is returned. This effectively limits the
// range of allowed values.
@ -182,7 +180,7 @@ func (n scriptNum) Int32() int32 {
// overflows.
//
// See the Bytes function documentation for example encodings.
func makeScriptNum(v []byte, requireMinimal bool, scriptNumLen int) (scriptNum, error) {
func makeScriptNum(v []byte, scriptNumLen int) (scriptNum, error) {
// Interpreting data requires that it is not larger than
// the the passed scriptNumLen value.
if len(v) > scriptNumLen {
@ -192,11 +190,8 @@ func makeScriptNum(v []byte, requireMinimal bool, scriptNumLen int) (scriptNum,
return 0, scriptError(ErrNumberTooBig, str)
}
// Enforce minimal encoded if requested.
if requireMinimal {
if err := checkMinimalDataEncoding(v); err != nil {
return 0, err
}
if err := checkMinimalDataEncoding(v); err != nil {
return 0, err
}
// Zero is encoded as an empty byte slice.

View File

@ -97,105 +97,88 @@ func TestMakeScriptNum(t *testing.T) {
errMinimalData := scriptError(ErrMinimalData, "")
tests := []struct {
serialized []byte
num scriptNum
numLen int
minimalEncoding bool
err error
serialized []byte
num scriptNum
numLen int
err error
}{
// Minimal encoding must reject negative 0.
{hexToBytes("80"), 0, defaultScriptNumLen, true, errMinimalData},
{hexToBytes("80"), 0, defaultScriptNumLen, errMinimalData},
// Minimally encoded valid values with minimal encoding flag.
// Should not error and return expected integral number.
{nil, 0, defaultScriptNumLen, true, nil},
{hexToBytes("01"), 1, defaultScriptNumLen, true, nil},
{hexToBytes("81"), -1, defaultScriptNumLen, true, nil},
{hexToBytes("7f"), 127, defaultScriptNumLen, true, nil},
{hexToBytes("ff"), -127, defaultScriptNumLen, true, nil},
{hexToBytes("8000"), 128, defaultScriptNumLen, true, nil},
{hexToBytes("8080"), -128, defaultScriptNumLen, true, nil},
{hexToBytes("8100"), 129, defaultScriptNumLen, true, nil},
{hexToBytes("8180"), -129, defaultScriptNumLen, true, nil},
{hexToBytes("0001"), 256, defaultScriptNumLen, true, nil},
{hexToBytes("0081"), -256, defaultScriptNumLen, true, nil},
{hexToBytes("ff7f"), 32767, defaultScriptNumLen, true, nil},
{hexToBytes("ffff"), -32767, defaultScriptNumLen, true, nil},
{hexToBytes("008000"), 32768, defaultScriptNumLen, true, nil},
{hexToBytes("008080"), -32768, defaultScriptNumLen, true, nil},
{hexToBytes("ffff00"), 65535, defaultScriptNumLen, true, nil},
{hexToBytes("ffff80"), -65535, defaultScriptNumLen, true, nil},
{hexToBytes("000008"), 524288, defaultScriptNumLen, true, nil},
{hexToBytes("000088"), -524288, defaultScriptNumLen, true, nil},
{hexToBytes("000070"), 7340032, defaultScriptNumLen, true, nil},
{hexToBytes("0000f0"), -7340032, defaultScriptNumLen, true, nil},
{hexToBytes("00008000"), 8388608, defaultScriptNumLen, true, nil},
{hexToBytes("00008080"), -8388608, defaultScriptNumLen, true, nil},
{hexToBytes("ffffff7f"), 2147483647, defaultScriptNumLen, true, nil},
{hexToBytes("ffffffff"), -2147483647, defaultScriptNumLen, true, nil},
{hexToBytes("ffffffff7f"), 549755813887, 5, true, nil},
{hexToBytes("ffffffffff"), -549755813887, 5, true, nil},
{hexToBytes("ffffffffffffff7f"), 9223372036854775807, 8, true, nil},
{hexToBytes("ffffffffffffffff"), -9223372036854775807, 8, true, nil},
{hexToBytes("ffffffffffffffff7f"), -1, 9, true, nil},
{hexToBytes("ffffffffffffffffff"), 1, 9, true, nil},
{hexToBytes("ffffffffffffffffff7f"), -1, 10, true, nil},
{hexToBytes("ffffffffffffffffffff"), 1, 10, true, nil},
{nil, 0, defaultScriptNumLen, nil},
{hexToBytes("01"), 1, defaultScriptNumLen, nil},
{hexToBytes("81"), -1, defaultScriptNumLen, nil},
{hexToBytes("7f"), 127, defaultScriptNumLen, nil},
{hexToBytes("ff"), -127, defaultScriptNumLen, nil},
{hexToBytes("8000"), 128, defaultScriptNumLen, nil},
{hexToBytes("8080"), -128, defaultScriptNumLen, nil},
{hexToBytes("8100"), 129, defaultScriptNumLen, nil},
{hexToBytes("8180"), -129, defaultScriptNumLen, nil},
{hexToBytes("0001"), 256, defaultScriptNumLen, nil},
{hexToBytes("0081"), -256, defaultScriptNumLen, nil},
{hexToBytes("ff7f"), 32767, defaultScriptNumLen, nil},
{hexToBytes("ffff"), -32767, defaultScriptNumLen, nil},
{hexToBytes("008000"), 32768, defaultScriptNumLen, nil},
{hexToBytes("008080"), -32768, defaultScriptNumLen, nil},
{hexToBytes("ffff00"), 65535, defaultScriptNumLen, nil},
{hexToBytes("ffff80"), -65535, defaultScriptNumLen, nil},
{hexToBytes("000008"), 524288, defaultScriptNumLen, nil},
{hexToBytes("000088"), -524288, defaultScriptNumLen, nil},
{hexToBytes("000070"), 7340032, defaultScriptNumLen, nil},
{hexToBytes("0000f0"), -7340032, defaultScriptNumLen, nil},
{hexToBytes("00008000"), 8388608, defaultScriptNumLen, nil},
{hexToBytes("00008080"), -8388608, defaultScriptNumLen, nil},
{hexToBytes("ffffff7f"), 2147483647, defaultScriptNumLen, nil},
{hexToBytes("ffffffff"), -2147483647, defaultScriptNumLen, nil},
{hexToBytes("ffffffff7f"), 549755813887, 5, nil},
{hexToBytes("ffffffffff"), -549755813887, 5, nil},
{hexToBytes("ffffffffffffff7f"), 9223372036854775807, 8, nil},
{hexToBytes("ffffffffffffffff"), -9223372036854775807, 8, nil},
{hexToBytes("ffffffffffffffff7f"), -1, 9, nil},
{hexToBytes("ffffffffffffffffff"), 1, 9, nil},
{hexToBytes("ffffffffffffffffff7f"), -1, 10, nil},
{hexToBytes("ffffffffffffffffffff"), 1, 10, nil},
// Minimally encoded values that are out of range for data that
// is interpreted as script numbers with the minimal encoding
// flag set. Should error and return 0.
{hexToBytes("0000008000"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("0000008080"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("0000009000"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("0000009080"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("ffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("ffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("0000000001"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("0000000081"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("ffffffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("ffffffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("ffffffffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("ffffffffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("ffffffffffffff7f"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("ffffffffffffffff"), 0, defaultScriptNumLen, true, errNumTooBig},
{hexToBytes("0000008000"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("0000008080"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("0000009000"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("0000009080"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("ffffffff00"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("ffffffff80"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("0000000001"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("0000000081"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("ffffffffffff00"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("ffffffffffff80"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("ffffffffffffff00"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("ffffffffffffff80"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("ffffffffffffff7f"), 0, defaultScriptNumLen, errNumTooBig},
{hexToBytes("ffffffffffffffff"), 0, defaultScriptNumLen, errNumTooBig},
// Non-minimally encoded, but otherwise valid values with
// minimal encoding flag. Should error and return 0.
{hexToBytes("00"), 0, defaultScriptNumLen, true, errMinimalData}, // 0
{hexToBytes("0100"), 0, defaultScriptNumLen, true, errMinimalData}, // 1
{hexToBytes("7f00"), 0, defaultScriptNumLen, true, errMinimalData}, // 127
{hexToBytes("800000"), 0, defaultScriptNumLen, true, errMinimalData}, // 128
{hexToBytes("810000"), 0, defaultScriptNumLen, true, errMinimalData}, // 129
{hexToBytes("000100"), 0, defaultScriptNumLen, true, errMinimalData}, // 256
{hexToBytes("ff7f00"), 0, defaultScriptNumLen, true, errMinimalData}, // 32767
{hexToBytes("00800000"), 0, defaultScriptNumLen, true, errMinimalData}, // 32768
{hexToBytes("ffff0000"), 0, defaultScriptNumLen, true, errMinimalData}, // 65535
{hexToBytes("00000800"), 0, defaultScriptNumLen, true, errMinimalData}, // 524288
{hexToBytes("00007000"), 0, defaultScriptNumLen, true, errMinimalData}, // 7340032
{hexToBytes("0009000100"), 0, 5, true, errMinimalData}, // 16779520
// Non-minimally encoded, but otherwise valid values without
// minimal encoding flag. Should not error and return expected
// integral number.
{hexToBytes("00"), 0, defaultScriptNumLen, false, nil},
{hexToBytes("0100"), 1, defaultScriptNumLen, false, nil},
{hexToBytes("7f00"), 127, defaultScriptNumLen, false, nil},
{hexToBytes("800000"), 128, defaultScriptNumLen, false, nil},
{hexToBytes("810000"), 129, defaultScriptNumLen, false, nil},
{hexToBytes("000100"), 256, defaultScriptNumLen, false, nil},
{hexToBytes("ff7f00"), 32767, defaultScriptNumLen, false, nil},
{hexToBytes("00800000"), 32768, defaultScriptNumLen, false, nil},
{hexToBytes("ffff0000"), 65535, defaultScriptNumLen, false, nil},
{hexToBytes("00000800"), 524288, defaultScriptNumLen, false, nil},
{hexToBytes("00007000"), 7340032, defaultScriptNumLen, false, nil},
{hexToBytes("0009000100"), 16779520, 5, false, nil},
{hexToBytes("00"), 0, defaultScriptNumLen, errMinimalData}, // 0
{hexToBytes("0100"), 0, defaultScriptNumLen, errMinimalData}, // 1
{hexToBytes("7f00"), 0, defaultScriptNumLen, errMinimalData}, // 127
{hexToBytes("800000"), 0, defaultScriptNumLen, errMinimalData}, // 128
{hexToBytes("810000"), 0, defaultScriptNumLen, errMinimalData}, // 129
{hexToBytes("000100"), 0, defaultScriptNumLen, errMinimalData}, // 256
{hexToBytes("ff7f00"), 0, defaultScriptNumLen, errMinimalData}, // 32767
{hexToBytes("00800000"), 0, defaultScriptNumLen, errMinimalData}, // 32768
{hexToBytes("ffff0000"), 0, defaultScriptNumLen, errMinimalData}, // 65535
{hexToBytes("00000800"), 0, defaultScriptNumLen, errMinimalData}, // 524288
{hexToBytes("00007000"), 0, defaultScriptNumLen, errMinimalData}, // 7340032
{hexToBytes("0009000100"), 0, 5, errMinimalData}, // 16779520
}
for _, test := range tests {
// Ensure the error code is of the expected type and the error
// code matches the value specified in the test instance.
gotNum, err := makeScriptNum(test.serialized, test.minimalEncoding,
gotNum, err := makeScriptNum(test.serialized,
test.numLen)
if e := tstCheckScriptError(err, test.err); e != nil {
t.Errorf("makeScriptNum(%#x): %v", test.serialized, e)

View File

@ -314,9 +314,7 @@ sigLoop:
}
}
// Extra opcode to handle the extra arg consumed (due to previous bugs
// in the reference implementation).
builder := NewScriptBuilder().AddOp(OpFalse)
builder := NewScriptBuilder()
doneSigs := 0
// This assumes that addresses are in the same order as in the script.
for _, addr := range addresses {

View File

@ -55,8 +55,9 @@ func mkGetScript(scripts map[string][]byte) ScriptDB {
func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byte) error {
tx.TxIn[idx].SignatureScript = sigScript
var flags ScriptFlags
vm, err := NewEngine(pkScript, tx, idx,
ScriptBip16, nil)
flags, nil)
if err != nil {
return fmt.Errorf("failed to make script engine for %s: %v",
msg, err)
@ -91,7 +92,6 @@ func TestSignTxOutput(t *testing.T) {
// make script based on key.
// sign with magic pixie dust.
hashTypes := []SigHashType{
SigHashOld, // no longer used but should act like all
SigHashAll,
SigHashNone,
SigHashSingle,
@ -1498,7 +1498,7 @@ var sigScriptTests = []tstSigScript{
scriptAtWrongIndex: false,
},
{
name: "hashType SigHashAnyoneCanPay",
name: "hashType SigHashAll | SigHashAnyoneCanPay",
inputs: []tstInput{
{
txout: wire.NewTxOut(coinbaseVal, uncompressedPkScript),
@ -1507,17 +1507,31 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false,
},
},
hashType: SigHashAll | SigHashAnyOneCanPay,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "hashType SigHashAnyoneCanPay",
inputs: []tstInput{
{
txout: wire.NewTxOut(coinbaseVal, uncompressedPkScript),
sigscriptGenerates: true,
inputValidates: false,
indexOutOfRange: false,
},
},
hashType: SigHashAnyOneCanPay,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "hashType non-standard",
name: "hashType non-exist",
inputs: []tstInput{
{
txout: wire.NewTxOut(coinbaseVal, uncompressedPkScript),
sigscriptGenerates: true,
inputValidates: true,
inputValidates: false,
indexOutOfRange: false,
},
},
@ -1658,7 +1672,7 @@ nexttest:
}
// Validate tx input scripts
scriptFlags := ScriptBip16
var scriptFlags ScriptFlags
for j := range tx.TxIn {
vm, err := NewEngine(sigScriptTests[i].
inputs[j].txout.PkScript, tx, j, scriptFlags, nil)

View File

@ -36,8 +36,7 @@ func fromBool(v bool) []byte {
// changed it *must* be deep-copied first to avoid changing other values on the
// stack.
type stack struct {
stk [][]byte
verifyMinimalData bool
stk [][]byte
}
// Depth returns the number of items on the stack.
@ -86,7 +85,7 @@ func (s *stack) PopInt() (scriptNum, error) {
return 0, err
}
return makeScriptNum(so, s.verifyMinimalData, defaultScriptNumLen)
return makeScriptNum(so, defaultScriptNumLen)
}
// PopBool pops the value off the top of the stack, converts it into a bool, and
@ -123,7 +122,7 @@ func (s *stack) PeekInt(idx int32) (scriptNum, error) {
return 0, err
}
return makeScriptNum(so, s.verifyMinimalData, defaultScriptNumLen)
return makeScriptNum(so, defaultScriptNumLen)
}
// PeekBool returns the Nth item on the stack as a bool without removing it.

View File

@ -186,7 +186,7 @@ func TestStack(t *testing.T) {
},
{
"popInt 0",
[][]byte{{0x0}},
[][]byte{{}},
func(s *stack) error {
v, err := s.PopInt()
if err != nil {
@ -200,22 +200,6 @@ func TestStack(t *testing.T) {
nil,
nil,
},
{
"popInt -0",
[][]byte{{0x80}},
func(s *stack) error {
v, err := s.PopInt()
if err != nil {
return err
}
if v != 0 {
return errors.New("-0 != 0 on popInt")
}
return nil
},
nil,
nil,
},
{
"popInt 1",
[][]byte{{0x01}},
@ -232,23 +216,6 @@ func TestStack(t *testing.T) {
nil,
nil,
},
{
"popInt 1 leading 0",
[][]byte{{0x01, 0x00, 0x00, 0x00}},
func(s *stack) error {
v, err := s.PopInt()
if err != nil {
return err
}
if v != 1 {
fmt.Printf("%v != %v\n", v, 1)
return errors.New("1 != 1 on popInt")
}
return nil
},
nil,
nil,
},
{
"popInt -1",
[][]byte{{0x81}},
@ -265,23 +232,6 @@ func TestStack(t *testing.T) {
nil,
nil,
},
{
"popInt -1 leading 0",
[][]byte{{0x01, 0x00, 0x00, 0x80}},
func(s *stack) error {
v, err := s.PopInt()
if err != nil {
return err
}
if v != -1 {
fmt.Printf("%v != %v\n", v, -1)
return errors.New("-1 != -1 on popInt")
}
return nil
},
nil,
nil,
},
// Triggers the multibyte case in asInt
{
"popInt -513",
@ -300,24 +250,6 @@ func TestStack(t *testing.T) {
nil,
nil,
},
// Confirm that the asInt code doesn't modify the base data.
{
"peekint nomodify -1",
[][]byte{{0x01, 0x00, 0x00, 0x80}},
func(s *stack) error {
v, err := s.PeekInt(0)
if err != nil {
return err
}
if v != -1 {
fmt.Printf("%v != %v\n", v, -1)
return errors.New("-1 != -1 on popInt")
}
return nil
},
nil,
[][]byte{{0x01, 0x00, 0x00, 0x80}},
},
{
"PushInt 0",
nil,
@ -852,24 +784,6 @@ func TestStack(t *testing.T) {
nil,
[][]byte{{1}},
},
{
"Peek int 2",
[][]byte{{0}},
func(s *stack) error {
// Peek int is otherwise pretty well tested,
// just check it works.
val, err := s.PeekInt(0)
if err != nil {
return err
}
if val != 0 {
return errors.New("invalid result")
}
return nil
},
nil,
[][]byte{{0}},
},
{
"pop int",
nil,

View File

@ -26,13 +26,7 @@ const (
//
// TODO: This definition does not belong here. It belongs in a policy
// package.
StandardVerifyFlags = ScriptBip16 |
ScriptVerifyStrictEncoding |
ScriptVerifyMinimalData |
ScriptDiscourageUpgradableNops |
ScriptVerifyCleanStack |
ScriptVerifyNullFail |
ScriptVerifyLowS
StandardVerifyFlags = ScriptDiscourageUpgradableNops
)
// ScriptClass is an enumeration for the list of standard types of script.
@ -227,7 +221,7 @@ type ScriptInfo struct {
// pair. It will error if the pair is in someway invalid such that they can not
// be analysed, i.e. if they do not parse or the pkScript is not a push-only
// script
func CalcScriptInfo(sigScript, pkScript []byte, bip16 bool) (*ScriptInfo, error) {
func CalcScriptInfo(sigScript, pkScript []byte, isP2SH bool) (*ScriptInfo, error) {
sigPops, err := parseScript(sigScript)
if err != nil {
return nil, err
@ -253,7 +247,7 @@ func CalcScriptInfo(sigScript, pkScript []byte, bip16 bool) (*ScriptInfo, error)
// All entries pushed to stack (or are OP_RESERVED and exec will fail).
si.NumInputs = len(sigPops)
if si.PkScriptClass == ScriptHashTy && bip16 {
if si.PkScriptClass == ScriptHashTy && isP2SH {
// The pay-to-hash-script is the final data push of the
// signature script.
script := sigPops[len(sigPops)-1].data
@ -552,7 +546,7 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa
copy(pushes.RecipientHash160[:], pops[9].data)
copy(pushes.RefundHash160[:], pops[16].data)
if pops[2].data != nil {
locktime, err := makeScriptNum(pops[2].data, true, 5)
locktime, err := makeScriptNum(pops[2].data, 5)
if err != nil {
return nil, nil
}
@ -563,7 +557,7 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa
return nil, nil
}
if pops[11].data != nil {
locktime, err := makeScriptNum(pops[11].data, true, 5)
locktime, err := makeScriptNum(pops[11].data, 5)
if err != nil {
return nil, nil
}

View File

@ -379,7 +379,7 @@ func TestCalcScriptInfo(t *testing.T) {
sigScript string
pkScript string
bip16 bool
isP2SH bool
scriptInfo ScriptInfo
scriptInfoErr error
@ -392,7 +392,7 @@ func TestCalcScriptInfo(t *testing.T) {
"SWAP ABS EQUAL",
pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" +
"3152205ec4f59c",
bip16: true,
isP2SH: true,
scriptInfoErr: scriptError(ErrMalformedPush, ""),
},
{
@ -402,7 +402,7 @@ func TestCalcScriptInfo(t *testing.T) {
"SWAP ABS",
pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" +
"3152205ec4f59c74 EQUAL",
bip16: true,
isP2SH: true,
scriptInfoErr: scriptError(ErrMalformedPush, ""),
},
{
@ -413,7 +413,7 @@ func TestCalcScriptInfo(t *testing.T) {
"CHECKSIG",
pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" +
"3152205ec4f59c74 EQUAL",
bip16: true,
isP2SH: true,
scriptInfo: ScriptInfo{
PkScriptClass: ScriptHashTy,
NumInputs: 3,
@ -429,7 +429,7 @@ func TestCalcScriptInfo(t *testing.T) {
"SWAP ABS EQUAL",
pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" +
"3152205ec4f59c74 EQUAL",
bip16: true,
isP2SH: true,
scriptInfo: ScriptInfo{
PkScriptClass: ScriptHashTy,
NumInputs: 3,
@ -449,7 +449,7 @@ func TestCalcScriptInfo(t *testing.T) {
"161718191a1b1c1d1e1f2021 DATA_33 0x010203040" +
"5060708090a0b0c0d0e0f101112131415161718191a1" +
"b1c1d1e1f2021 3 CHECKMULTISIG",
bip16: true,
isP2SH: true,
scriptInfo: ScriptInfo{
PkScriptClass: MultiSigTy,
NumInputs: 4,
@ -463,7 +463,7 @@ func TestCalcScriptInfo(t *testing.T) {
sigScript := mustParseShortForm(test.sigScript)
pkScript := mustParseShortForm(test.pkScript)
si, err := CalcScriptInfo(sigScript, pkScript, test.bip16)
si, err := CalcScriptInfo(sigScript, pkScript, test.isP2SH)
if e := tstCheckScriptError(err, test.scriptInfoErr); e != nil {
t.Errorf("scriptinfo test %q: %v", test.name, e)
continue