From 5c6243f4e4480d3543cd02f3be480c338ef66589 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 27 Nov 2020 11:39:10 +0200 Subject: [PATCH 1/4] #1477 remove TransactionBuilder and all references to it --- src/index.js | 2 - src/psbt.js | 6 +- src/transaction_builder.js | 1065 ---------- test/fixtures/transaction_builder.json | 2712 ------------------------ test/transaction_builder.spec.ts | 1001 --------- ts_src/index.ts | 1 - ts_src/psbt.ts | 6 +- ts_src/transaction_builder.ts | 1318 ------------ types/index.d.ts | 1 - types/transaction_builder.d.ts | 37 - 10 files changed, 4 insertions(+), 6145 deletions(-) delete mode 100644 src/transaction_builder.js delete mode 100644 test/fixtures/transaction_builder.json delete mode 100644 test/transaction_builder.spec.ts delete mode 100644 ts_src/transaction_builder.ts delete mode 100644 types/transaction_builder.d.ts diff --git a/src/index.js b/src/index.js index bc71f02..e27b98a 100644 --- a/src/index.js +++ b/src/index.js @@ -22,5 +22,3 @@ var script_1 = require('./script'); exports.opcodes = script_1.OPS; var transaction_1 = require('./transaction'); exports.Transaction = transaction_1.Transaction; -var transaction_builder_1 = require('./transaction_builder'); -exports.TransactionBuilder = transaction_builder_1.TransactionBuilder; diff --git a/src/psbt.js b/src/psbt.js index 5193dd3..6381669 100644 --- a/src/psbt.js +++ b/src/psbt.js @@ -69,8 +69,7 @@ class Psbt { __NON_WITNESS_UTXO_BUF_CACHE: [], __TX_IN_CACHE: {}, __TX: this.data.globalMap.unsignedTx.tx, - // Old TransactionBuilder behavior was to not confirm input values - // before signing. Even though we highly encourage people to get + // Even though we highly encourage people to get // the full parent transaction to verify values, the ability to // sign non-segwit inputs without the full transaction was often // requested. So the only way to activate is to use @ts-ignore. @@ -998,8 +997,7 @@ function getHashForSig(inputIndex, input, cache, forValidate, sighashTypes) { console.warn( 'Warning: Signing non-segwit inputs without the full parent transaction ' + 'means there is a chance that a miner could feed you incorrect information ' + - 'to trick you into paying large fees. This behavior is the same as the old ' + - 'TransactionBuilder class when signing non-segwit scripts. You are not ' + + 'to trick you into paying large fees. You are not ' + 'able to export this Psbt with toBuffer|toBase64|toHex since it is not ' + 'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' + '*********************', diff --git a/src/transaction_builder.js b/src/transaction_builder.js deleted file mode 100644 index a13c481..0000000 --- a/src/transaction_builder.js +++ /dev/null @@ -1,1065 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const baddress = require('./address'); -const bufferutils_1 = require('./bufferutils'); -const classify = require('./classify'); -const bcrypto = require('./crypto'); -const ECPair = require('./ecpair'); -const networks = require('./networks'); -const payments = require('./payments'); -const bscript = require('./script'); -const script_1 = require('./script'); -const transaction_1 = require('./transaction'); -const types = require('./types'); -const typeforce = require('typeforce'); -const SCRIPT_TYPES = classify.types; -const PREVOUT_TYPES = new Set([ - // Raw - 'p2pkh', - 'p2pk', - 'p2wpkh', - 'p2ms', - // P2SH wrapped - 'p2sh-p2pkh', - 'p2sh-p2pk', - 'p2sh-p2wpkh', - 'p2sh-p2ms', - // P2WSH wrapped - 'p2wsh-p2pkh', - 'p2wsh-p2pk', - 'p2wsh-p2ms', - // P2SH-P2WSH wrapper - 'p2sh-p2wsh-p2pkh', - 'p2sh-p2wsh-p2pk', - 'p2sh-p2wsh-p2ms', -]); -function tfMessage(type, value, message) { - try { - typeforce(type, value); - } catch (err) { - throw new Error(message); - } -} -function txIsString(tx) { - return typeof tx === 'string' || tx instanceof String; -} -function txIsTransaction(tx) { - return tx instanceof transaction_1.Transaction; -} -class TransactionBuilder { - // WARNING: maximumFeeRate is __NOT__ to be relied on, - // it's just another potential safety mechanism (safety in-depth) - constructor(network = networks.bitcoin, maximumFeeRate = 2500) { - this.network = network; - this.maximumFeeRate = maximumFeeRate; - this.__PREV_TX_SET = {}; - this.__INPUTS = []; - this.__TX = new transaction_1.Transaction(); - this.__TX.version = 2; - this.__USE_LOW_R = false; - console.warn( - 'Deprecation Warning: TransactionBuilder will be removed in the future. ' + - '(v6.x.x or later) Please use the Psbt class instead. Examples of usage ' + - 'are available in the transactions-psbt.js integration test file on our ' + - 'Github. A high level explanation is available in the psbt.ts and psbt.js ' + - 'files as well.', - ); - } - static fromTransaction(transaction, network) { - const txb = new TransactionBuilder(network); - // Copy transaction fields - txb.setVersion(transaction.version); - txb.setLockTime(transaction.locktime); - // Copy outputs (done first to avoid signature invalidation) - transaction.outs.forEach(txOut => { - txb.addOutput(txOut.script, txOut.value); - }); - // Copy inputs - transaction.ins.forEach(txIn => { - txb.__addInputUnsafe(txIn.hash, txIn.index, { - sequence: txIn.sequence, - script: txIn.script, - witness: txIn.witness, - }); - }); - // fix some things not possible through the public API - txb.__INPUTS.forEach((input, i) => { - fixMultisigOrder(input, transaction, i); - }); - return txb; - } - setLowR(setting) { - typeforce(typeforce.maybe(typeforce.Boolean), setting); - if (setting === undefined) { - setting = true; - } - this.__USE_LOW_R = setting; - return setting; - } - setLockTime(locktime) { - typeforce(types.UInt32, locktime); - // if any signatures exist, throw - if ( - this.__INPUTS.some(input => { - if (!input.signatures) return false; - return input.signatures.some(s => s !== undefined); - }) - ) { - throw new Error('No, this would invalidate signatures'); - } - this.__TX.locktime = locktime; - } - setVersion(version) { - typeforce(types.UInt32, version); - // XXX: this might eventually become more complex depending on what the versions represent - this.__TX.version = version; - } - addInput(txHash, vout, sequence, prevOutScript) { - if (!this.__canModifyInputs()) { - throw new Error('No, this would invalidate signatures'); - } - let value; - // is it a hex string? - if (txIsString(txHash)) { - // transaction hashs's are displayed in reverse order, un-reverse it - txHash = bufferutils_1.reverseBuffer(Buffer.from(txHash, 'hex')); - // is it a Transaction object? - } else if (txIsTransaction(txHash)) { - const txOut = txHash.outs[vout]; - prevOutScript = txOut.script; - value = txOut.value; - txHash = txHash.getHash(false); - } - return this.__addInputUnsafe(txHash, vout, { - sequence, - prevOutScript, - value, - }); - } - addOutput(scriptPubKey, value) { - if (!this.__canModifyOutputs()) { - throw new Error('No, this would invalidate signatures'); - } - // Attempt to get a script if it's a base58 or bech32 address string - if (typeof scriptPubKey === 'string') { - scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network); - } - return this.__TX.addOutput(scriptPubKey, value); - } - build() { - return this.__build(false); - } - buildIncomplete() { - return this.__build(true); - } - sign( - signParams, - keyPair, - redeemScript, - hashType, - witnessValue, - witnessScript, - ) { - trySign( - getSigningData( - this.network, - this.__INPUTS, - this.__needsOutputs.bind(this), - this.__TX, - signParams, - keyPair, - redeemScript, - hashType, - witnessValue, - witnessScript, - this.__USE_LOW_R, - ), - ); - } - __addInputUnsafe(txHash, vout, options) { - if (transaction_1.Transaction.isCoinbaseHash(txHash)) { - throw new Error('coinbase inputs not supported'); - } - const prevTxOut = txHash.toString('hex') + ':' + vout; - if (this.__PREV_TX_SET[prevTxOut] !== undefined) - throw new Error('Duplicate TxOut: ' + prevTxOut); - let input = {}; - // derive what we can from the scriptSig - if (options.script !== undefined) { - input = expandInput(options.script, options.witness || []); - } - // if an input value was given, retain it - if (options.value !== undefined) { - input.value = options.value; - } - // derive what we can from the previous transactions output script - if (!input.prevOutScript && options.prevOutScript) { - let prevOutType; - if (!input.pubkeys && !input.signatures) { - const expanded = expandOutput(options.prevOutScript); - if (expanded.pubkeys) { - input.pubkeys = expanded.pubkeys; - input.signatures = expanded.signatures; - } - prevOutType = expanded.type; - } - input.prevOutScript = options.prevOutScript; - input.prevOutType = prevOutType || classify.output(options.prevOutScript); - } - const vin = this.__TX.addInput( - txHash, - vout, - options.sequence, - options.scriptSig, - ); - this.__INPUTS[vin] = input; - this.__PREV_TX_SET[prevTxOut] = true; - return vin; - } - __build(allowIncomplete) { - if (!allowIncomplete) { - if (!this.__TX.ins.length) throw new Error('Transaction has no inputs'); - if (!this.__TX.outs.length) throw new Error('Transaction has no outputs'); - } - const tx = this.__TX.clone(); - // create script signatures from inputs - this.__INPUTS.forEach((input, i) => { - if (!input.prevOutType && !allowIncomplete) - throw new Error('Transaction is not complete'); - const result = build(input.prevOutType, input, allowIncomplete); - if (!result) { - if (!allowIncomplete && input.prevOutType === SCRIPT_TYPES.NONSTANDARD) - throw new Error('Unknown input type'); - if (!allowIncomplete) throw new Error('Not enough information'); - return; - } - tx.setInputScript(i, result.input); - tx.setWitness(i, result.witness); - }); - if (!allowIncomplete) { - // do not rely on this, its merely a last resort - if (this.__overMaximumFees(tx.virtualSize())) { - throw new Error('Transaction has absurd fees'); - } - } - return tx; - } - __canModifyInputs() { - return this.__INPUTS.every(input => { - if (!input.signatures) return true; - return input.signatures.every(signature => { - if (!signature) return true; - const hashType = signatureHashType(signature); - // if SIGHASH_ANYONECANPAY is set, signatures would not - // be invalidated by more inputs - return ( - (hashType & transaction_1.Transaction.SIGHASH_ANYONECANPAY) !== 0 - ); - }); - }); - } - __needsOutputs(signingHashType) { - if (signingHashType === transaction_1.Transaction.SIGHASH_ALL) { - return this.__TX.outs.length === 0; - } - // if inputs are being signed with SIGHASH_NONE, we don't strictly need outputs - // .build() will fail, but .buildIncomplete() is OK - return ( - this.__TX.outs.length === 0 && - this.__INPUTS.some(input => { - if (!input.signatures) return false; - return input.signatures.some(signature => { - if (!signature) return false; // no signature, no issue - const hashType = signatureHashType(signature); - if (hashType & transaction_1.Transaction.SIGHASH_NONE) return false; // SIGHASH_NONE doesn't care about outputs - return true; // SIGHASH_* does care - }); - }) - ); - } - __canModifyOutputs() { - const nInputs = this.__TX.ins.length; - const nOutputs = this.__TX.outs.length; - return this.__INPUTS.every(input => { - if (input.signatures === undefined) return true; - return input.signatures.every(signature => { - if (!signature) return true; - const hashType = signatureHashType(signature); - const hashTypeMod = hashType & 0x1f; - if (hashTypeMod === transaction_1.Transaction.SIGHASH_NONE) return true; - if (hashTypeMod === transaction_1.Transaction.SIGHASH_SINGLE) { - // if SIGHASH_SINGLE is set, and nInputs > nOutputs - // some signatures would be invalidated by the addition - // of more outputs - return nInputs <= nOutputs; - } - return false; - }); - }); - } - __overMaximumFees(bytes) { - // not all inputs will have .value defined - const incoming = this.__INPUTS.reduce((a, x) => a + (x.value >>> 0), 0); - // but all outputs do, and if we have any input value - // we can immediately determine if the outputs are too small - const outgoing = this.__TX.outs.reduce((a, x) => a + x.value, 0); - const fee = incoming - outgoing; - const feeRate = fee / bytes; - return feeRate > this.maximumFeeRate; - } -} -exports.TransactionBuilder = TransactionBuilder; -function expandInput(scriptSig, witnessStack, type, scriptPubKey) { - if (scriptSig.length === 0 && witnessStack.length === 0) return {}; - if (!type) { - let ssType = classify.input(scriptSig, true); - let wsType = classify.witness(witnessStack, true); - if (ssType === SCRIPT_TYPES.NONSTANDARD) ssType = undefined; - if (wsType === SCRIPT_TYPES.NONSTANDARD) wsType = undefined; - type = ssType || wsType; - } - switch (type) { - case SCRIPT_TYPES.P2WPKH: { - const { output, pubkey, signature } = payments.p2wpkh({ - witness: witnessStack, - }); - return { - prevOutScript: output, - prevOutType: SCRIPT_TYPES.P2WPKH, - pubkeys: [pubkey], - signatures: [signature], - }; - } - case SCRIPT_TYPES.P2PKH: { - const { output, pubkey, signature } = payments.p2pkh({ - input: scriptSig, - }); - return { - prevOutScript: output, - prevOutType: SCRIPT_TYPES.P2PKH, - pubkeys: [pubkey], - signatures: [signature], - }; - } - case SCRIPT_TYPES.P2PK: { - const { signature } = payments.p2pk({ input: scriptSig }); - return { - prevOutType: SCRIPT_TYPES.P2PK, - pubkeys: [undefined], - signatures: [signature], - }; - } - case SCRIPT_TYPES.P2MS: { - const { m, pubkeys, signatures } = payments.p2ms( - { - input: scriptSig, - output: scriptPubKey, - }, - { allowIncomplete: true }, - ); - return { - prevOutType: SCRIPT_TYPES.P2MS, - pubkeys, - signatures, - maxSignatures: m, - }; - } - } - if (type === SCRIPT_TYPES.P2SH) { - const { output, redeem } = payments.p2sh({ - input: scriptSig, - witness: witnessStack, - }); - const outputType = classify.output(redeem.output); - const expanded = expandInput( - redeem.input, - redeem.witness, - outputType, - redeem.output, - ); - if (!expanded.prevOutType) return {}; - return { - prevOutScript: output, - prevOutType: SCRIPT_TYPES.P2SH, - redeemScript: redeem.output, - redeemScriptType: expanded.prevOutType, - witnessScript: expanded.witnessScript, - witnessScriptType: expanded.witnessScriptType, - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - }; - } - if (type === SCRIPT_TYPES.P2WSH) { - const { output, redeem } = payments.p2wsh({ - input: scriptSig, - witness: witnessStack, - }); - const outputType = classify.output(redeem.output); - let expanded; - if (outputType === SCRIPT_TYPES.P2WPKH) { - expanded = expandInput(redeem.input, redeem.witness, outputType); - } else { - expanded = expandInput( - bscript.compile(redeem.witness), - [], - outputType, - redeem.output, - ); - } - if (!expanded.prevOutType) return {}; - return { - prevOutScript: output, - prevOutType: SCRIPT_TYPES.P2WSH, - witnessScript: redeem.output, - witnessScriptType: expanded.prevOutType, - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - }; - } - return { - prevOutType: SCRIPT_TYPES.NONSTANDARD, - prevOutScript: scriptSig, - }; -} -// could be done in expandInput, but requires the original Transaction for hashForSignature -function fixMultisigOrder(input, transaction, vin) { - if (input.redeemScriptType !== SCRIPT_TYPES.P2MS || !input.redeemScript) - return; - if (input.pubkeys.length === input.signatures.length) return; - const unmatched = input.signatures.concat(); - input.signatures = input.pubkeys.map(pubKey => { - const keyPair = ECPair.fromPublicKey(pubKey); - let match; - // check for a signature - unmatched.some((signature, i) => { - // skip if undefined || OP_0 - if (!signature) return false; - // TODO: avoid O(n) hashForSignature - const parsed = bscript.signature.decode(signature); - const hash = transaction.hashForSignature( - vin, - input.redeemScript, - parsed.hashType, - ); - // skip if signature does not match pubKey - if (!keyPair.verify(hash, parsed.signature)) return false; - // remove matched signature from unmatched - unmatched[i] = undefined; - match = signature; - return true; - }); - return match; - }); -} -function expandOutput(script, ourPubKey) { - typeforce(types.Buffer, script); - const type = classify.output(script); - switch (type) { - case SCRIPT_TYPES.P2PKH: { - if (!ourPubKey) return { type }; - // does our hash160(pubKey) match the output scripts? - const pkh1 = payments.p2pkh({ output: script }).hash; - const pkh2 = bcrypto.hash160(ourPubKey); - if (!pkh1.equals(pkh2)) return { type }; - return { - type, - pubkeys: [ourPubKey], - signatures: [undefined], - }; - } - case SCRIPT_TYPES.P2WPKH: { - if (!ourPubKey) return { type }; - // does our hash160(pubKey) match the output scripts? - const wpkh1 = payments.p2wpkh({ output: script }).hash; - const wpkh2 = bcrypto.hash160(ourPubKey); - if (!wpkh1.equals(wpkh2)) return { type }; - return { - type, - pubkeys: [ourPubKey], - signatures: [undefined], - }; - } - case SCRIPT_TYPES.P2PK: { - const p2pk = payments.p2pk({ output: script }); - return { - type, - pubkeys: [p2pk.pubkey], - signatures: [undefined], - }; - } - case SCRIPT_TYPES.P2MS: { - const p2ms = payments.p2ms({ output: script }); - return { - type, - pubkeys: p2ms.pubkeys, - signatures: p2ms.pubkeys.map(() => undefined), - maxSignatures: p2ms.m, - }; - } - } - return { type }; -} -function prepareInput(input, ourPubKey, redeemScript, witnessScript) { - if (redeemScript && witnessScript) { - const p2wsh = payments.p2wsh({ - redeem: { output: witnessScript }, - }); - const p2wshAlt = payments.p2wsh({ output: redeemScript }); - const p2sh = payments.p2sh({ redeem: { output: redeemScript } }); - const p2shAlt = payments.p2sh({ redeem: p2wsh }); - // enforces P2SH(P2WSH(...)) - if (!p2wsh.hash.equals(p2wshAlt.hash)) - throw new Error('Witness script inconsistent with prevOutScript'); - if (!p2sh.hash.equals(p2shAlt.hash)) - throw new Error('Redeem script inconsistent with prevOutScript'); - const expanded = expandOutput(p2wsh.redeem.output, ourPubKey); - if (!expanded.pubkeys) - throw new Error( - expanded.type + - ' not supported as witnessScript (' + - bscript.toASM(witnessScript) + - ')', - ); - if (input.signatures && input.signatures.some(x => x !== undefined)) { - expanded.signatures = input.signatures; - } - const signScript = witnessScript; - if (expanded.type === SCRIPT_TYPES.P2WPKH) - throw new Error('P2SH(P2WSH(P2WPKH)) is a consensus failure'); - return { - redeemScript, - redeemScriptType: SCRIPT_TYPES.P2WSH, - witnessScript, - witnessScriptType: expanded.type, - prevOutType: SCRIPT_TYPES.P2SH, - prevOutScript: p2sh.output, - hasWitness: true, - signScript, - signType: expanded.type, - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - maxSignatures: expanded.maxSignatures, - }; - } - if (redeemScript) { - const p2sh = payments.p2sh({ redeem: { output: redeemScript } }); - if (input.prevOutScript) { - let p2shAlt; - try { - p2shAlt = payments.p2sh({ output: input.prevOutScript }); - } catch (e) { - throw new Error('PrevOutScript must be P2SH'); - } - if (!p2sh.hash.equals(p2shAlt.hash)) - throw new Error('Redeem script inconsistent with prevOutScript'); - } - const expanded = expandOutput(p2sh.redeem.output, ourPubKey); - if (!expanded.pubkeys) - throw new Error( - expanded.type + - ' not supported as redeemScript (' + - bscript.toASM(redeemScript) + - ')', - ); - if (input.signatures && input.signatures.some(x => x !== undefined)) { - expanded.signatures = input.signatures; - } - let signScript = redeemScript; - if (expanded.type === SCRIPT_TYPES.P2WPKH) { - signScript = payments.p2pkh({ pubkey: expanded.pubkeys[0] }).output; - } - return { - redeemScript, - redeemScriptType: expanded.type, - prevOutType: SCRIPT_TYPES.P2SH, - prevOutScript: p2sh.output, - hasWitness: expanded.type === SCRIPT_TYPES.P2WPKH, - signScript, - signType: expanded.type, - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - maxSignatures: expanded.maxSignatures, - }; - } - if (witnessScript) { - const p2wsh = payments.p2wsh({ redeem: { output: witnessScript } }); - if (input.prevOutScript) { - const p2wshAlt = payments.p2wsh({ output: input.prevOutScript }); - if (!p2wsh.hash.equals(p2wshAlt.hash)) - throw new Error('Witness script inconsistent with prevOutScript'); - } - const expanded = expandOutput(p2wsh.redeem.output, ourPubKey); - if (!expanded.pubkeys) - throw new Error( - expanded.type + - ' not supported as witnessScript (' + - bscript.toASM(witnessScript) + - ')', - ); - if (input.signatures && input.signatures.some(x => x !== undefined)) { - expanded.signatures = input.signatures; - } - const signScript = witnessScript; - if (expanded.type === SCRIPT_TYPES.P2WPKH) - throw new Error('P2WSH(P2WPKH) is a consensus failure'); - return { - witnessScript, - witnessScriptType: expanded.type, - prevOutType: SCRIPT_TYPES.P2WSH, - prevOutScript: p2wsh.output, - hasWitness: true, - signScript, - signType: expanded.type, - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - maxSignatures: expanded.maxSignatures, - }; - } - if (input.prevOutType && input.prevOutScript) { - // embedded scripts are not possible without extra information - if (input.prevOutType === SCRIPT_TYPES.P2SH) - throw new Error( - 'PrevOutScript is ' + input.prevOutType + ', requires redeemScript', - ); - if (input.prevOutType === SCRIPT_TYPES.P2WSH) - throw new Error( - 'PrevOutScript is ' + input.prevOutType + ', requires witnessScript', - ); - if (!input.prevOutScript) throw new Error('PrevOutScript is missing'); - const expanded = expandOutput(input.prevOutScript, ourPubKey); - if (!expanded.pubkeys) - throw new Error( - expanded.type + - ' not supported (' + - bscript.toASM(input.prevOutScript) + - ')', - ); - if (input.signatures && input.signatures.some(x => x !== undefined)) { - expanded.signatures = input.signatures; - } - let signScript = input.prevOutScript; - if (expanded.type === SCRIPT_TYPES.P2WPKH) { - signScript = payments.p2pkh({ pubkey: expanded.pubkeys[0] }).output; - } - return { - prevOutType: expanded.type, - prevOutScript: input.prevOutScript, - hasWitness: expanded.type === SCRIPT_TYPES.P2WPKH, - signScript, - signType: expanded.type, - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - maxSignatures: expanded.maxSignatures, - }; - } - const prevOutScript = payments.p2pkh({ pubkey: ourPubKey }).output; - return { - prevOutType: SCRIPT_TYPES.P2PKH, - prevOutScript, - hasWitness: false, - signScript: prevOutScript, - signType: SCRIPT_TYPES.P2PKH, - pubkeys: [ourPubKey], - signatures: [undefined], - }; -} -function build(type, input, allowIncomplete) { - const pubkeys = input.pubkeys || []; - let signatures = input.signatures || []; - switch (type) { - case SCRIPT_TYPES.P2PKH: { - if (pubkeys.length === 0) break; - if (signatures.length === 0) break; - return payments.p2pkh({ pubkey: pubkeys[0], signature: signatures[0] }); - } - case SCRIPT_TYPES.P2WPKH: { - if (pubkeys.length === 0) break; - if (signatures.length === 0) break; - return payments.p2wpkh({ pubkey: pubkeys[0], signature: signatures[0] }); - } - case SCRIPT_TYPES.P2PK: { - if (pubkeys.length === 0) break; - if (signatures.length === 0) break; - return payments.p2pk({ signature: signatures[0] }); - } - case SCRIPT_TYPES.P2MS: { - const m = input.maxSignatures; - if (allowIncomplete) { - signatures = signatures.map(x => x || script_1.OPS.OP_0); - } else { - signatures = signatures.filter(x => x); - } - // if the transaction is not not complete (complete), or if signatures.length === m, validate - // otherwise, the number of OP_0's may be >= m, so don't validate (boo) - const validate = !allowIncomplete || m === signatures.length; - return payments.p2ms( - { m, pubkeys, signatures }, - { allowIncomplete, validate }, - ); - } - case SCRIPT_TYPES.P2SH: { - const redeem = build(input.redeemScriptType, input, allowIncomplete); - if (!redeem) return; - return payments.p2sh({ - redeem: { - output: redeem.output || input.redeemScript, - input: redeem.input, - witness: redeem.witness, - }, - }); - } - case SCRIPT_TYPES.P2WSH: { - const redeem = build(input.witnessScriptType, input, allowIncomplete); - if (!redeem) return; - return payments.p2wsh({ - redeem: { - output: input.witnessScript, - input: redeem.input, - witness: redeem.witness, - }, - }); - } - } -} -function canSign(input) { - return ( - input.signScript !== undefined && - input.signType !== undefined && - input.pubkeys !== undefined && - input.signatures !== undefined && - input.signatures.length === input.pubkeys.length && - input.pubkeys.length > 0 && - (input.hasWitness === false || input.value !== undefined) - ); -} -function signatureHashType(buffer) { - return buffer.readUInt8(buffer.length - 1); -} -function checkSignArgs(inputs, signParams) { - if (!PREVOUT_TYPES.has(signParams.prevOutScriptType)) { - throw new TypeError( - `Unknown prevOutScriptType "${signParams.prevOutScriptType}"`, - ); - } - tfMessage( - typeforce.Number, - signParams.vin, - `sign must include vin parameter as Number (input index)`, - ); - tfMessage( - types.Signer, - signParams.keyPair, - `sign must include keyPair parameter as Signer interface`, - ); - tfMessage( - typeforce.maybe(typeforce.Number), - signParams.hashType, - `sign hashType parameter must be a number`, - ); - const prevOutType = (inputs[signParams.vin] || []).prevOutType; - const posType = signParams.prevOutScriptType; - switch (posType) { - case 'p2pkh': - if (prevOutType && prevOutType !== 'pubkeyhash') { - throw new TypeError( - `input #${signParams.vin} is not of type p2pkh: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.witnessValue, - `${posType} requires NO witnessValue`, - ); - break; - case 'p2pk': - if (prevOutType && prevOutType !== 'pubkey') { - throw new TypeError( - `input #${signParams.vin} is not of type p2pk: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.witnessValue, - `${posType} requires NO witnessValue`, - ); - break; - case 'p2wpkh': - if (prevOutType && prevOutType !== 'witnesspubkeyhash') { - throw new TypeError( - `input #${signParams.vin} is not of type p2wpkh: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - types.Satoshi, - signParams.witnessValue, - `${posType} requires witnessValue`, - ); - break; - case 'p2ms': - if (prevOutType && prevOutType !== 'multisig') { - throw new TypeError( - `input #${signParams.vin} is not of type p2ms: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.witnessValue, - `${posType} requires NO witnessValue`, - ); - break; - case 'p2sh-p2wpkh': - if (prevOutType && prevOutType !== 'scripthash') { - throw new TypeError( - `input #${signParams.vin} is not of type p2sh-p2wpkh: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.Buffer, - signParams.redeemScript, - `${posType} requires redeemScript`, - ); - tfMessage( - types.Satoshi, - signParams.witnessValue, - `${posType} requires witnessValue`, - ); - break; - case 'p2sh-p2ms': - case 'p2sh-p2pk': - case 'p2sh-p2pkh': - if (prevOutType && prevOutType !== 'scripthash') { - throw new TypeError( - `input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.Buffer, - signParams.redeemScript, - `${posType} requires redeemScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.witnessValue, - `${posType} requires NO witnessValue`, - ); - break; - case 'p2wsh-p2ms': - case 'p2wsh-p2pk': - case 'p2wsh-p2pkh': - if (prevOutType && prevOutType !== 'witnessscripthash') { - throw new TypeError( - `input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, - ); - } - tfMessage( - typeforce.Buffer, - signParams.witnessScript, - `${posType} requires witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - types.Satoshi, - signParams.witnessValue, - `${posType} requires witnessValue`, - ); - break; - case 'p2sh-p2wsh-p2ms': - case 'p2sh-p2wsh-p2pk': - case 'p2sh-p2wsh-p2pkh': - if (prevOutType && prevOutType !== 'scripthash') { - throw new TypeError( - `input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, - ); - } - tfMessage( - typeforce.Buffer, - signParams.witnessScript, - `${posType} requires witnessScript`, - ); - tfMessage( - typeforce.Buffer, - signParams.redeemScript, - `${posType} requires witnessScript`, - ); - tfMessage( - types.Satoshi, - signParams.witnessValue, - `${posType} requires witnessScript`, - ); - break; - } -} -function trySign({ - input, - ourPubKey, - keyPair, - signatureHash, - hashType, - useLowR, -}) { - // enforce in order signing of public keys - let signed = false; - for (const [i, pubKey] of input.pubkeys.entries()) { - if (!ourPubKey.equals(pubKey)) continue; - if (input.signatures[i]) throw new Error('Signature already exists'); - // TODO: add tests - if (ourPubKey.length !== 33 && input.hasWitness) { - throw new Error( - 'BIP143 rejects uncompressed public keys in P2WPKH or P2WSH', - ); - } - const signature = keyPair.sign(signatureHash, useLowR); - input.signatures[i] = bscript.signature.encode(signature, hashType); - signed = true; - } - if (!signed) throw new Error('Key pair cannot sign for this input'); -} -function getSigningData( - network, - inputs, - needsOutputs, - tx, - signParams, - keyPair, - redeemScript, - hashType, - witnessValue, - witnessScript, - useLowR, -) { - let vin; - if (typeof signParams === 'number') { - console.warn( - 'DEPRECATED: TransactionBuilder sign method arguments ' + - 'will change in v6, please use the TxbSignArg interface', - ); - vin = signParams; - } else if (typeof signParams === 'object') { - checkSignArgs(inputs, signParams); - ({ - vin, - keyPair, - redeemScript, - hashType, - witnessValue, - witnessScript, - } = signParams); - } else { - throw new TypeError( - 'TransactionBuilder sign first arg must be TxbSignArg or number', - ); - } - if (keyPair === undefined) { - throw new Error('sign requires keypair'); - } - // TODO: remove keyPair.network matching in 4.0.0 - if (keyPair.network && keyPair.network !== network) - throw new TypeError('Inconsistent network'); - if (!inputs[vin]) throw new Error('No input at index: ' + vin); - hashType = hashType || transaction_1.Transaction.SIGHASH_ALL; - if (needsOutputs(hashType)) throw new Error('Transaction needs outputs'); - const input = inputs[vin]; - // if redeemScript was previously provided, enforce consistency - if ( - input.redeemScript !== undefined && - redeemScript && - !input.redeemScript.equals(redeemScript) - ) { - throw new Error('Inconsistent redeemScript'); - } - const ourPubKey = - keyPair.publicKey || (keyPair.getPublicKey && keyPair.getPublicKey()); - if (!canSign(input)) { - if (witnessValue !== undefined) { - if (input.value !== undefined && input.value !== witnessValue) - throw new Error('Input did not match witnessValue'); - typeforce(types.Satoshi, witnessValue); - input.value = witnessValue; - } - if (!canSign(input)) { - const prepared = prepareInput( - input, - ourPubKey, - redeemScript, - witnessScript, - ); - // updates inline - Object.assign(input, prepared); - } - if (!canSign(input)) throw Error(input.prevOutType + ' not supported'); - } - // ready to sign - let signatureHash; - if (input.hasWitness) { - signatureHash = tx.hashForWitnessV0( - vin, - input.signScript, - input.value, - hashType, - ); - } else { - signatureHash = tx.hashForSignature(vin, input.signScript, hashType); - } - return { - input, - ourPubKey, - keyPair, - signatureHash, - hashType, - useLowR: !!useLowR, - }; -} diff --git a/test/fixtures/transaction_builder.json b/test/fixtures/transaction_builder.json deleted file mode 100644 index 1564e6a..0000000 --- a/test/fixtures/transaction_builder.json +++ /dev/null @@ -1,2712 +0,0 @@ -{ - "valid": { - "build": [ - { - "description": "Transaction w/ P2PKH -> P2PKH", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000006b483045022100a3b254e1c10b5d039f36c05f323995d6e5a367d98dd78a13d5bbc3991b35720e022022fccea3897d594de0689601fbd486588d5bfa6915be2386db0397ee9a6e80b601210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff0110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2PK -> P2PKH", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000494830450221009833abb3ab49d7004c06bcc79eafd6905ada3eee91f3376ad388548034acd9a702202e84dda6ef2678c82256afcfc459aaa68e179b2bb0e6b2dc3f1410e132c5e6c301ffffffff0100f90295000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 OP_CHECKSIG", - "signs": [ - { - "prevOutScriptType": "p2pk", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 2500000000 - } - ] - }, - { - "description": "Transaction w/ P2SH(P2PKH) -> P2PKH", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000085483045022100a3b254e1c10b5d039f36c05f323995d6e5a367d98dd78a13d5bbc3991b35720e022022fccea3897d594de0689601fbd486588d5bfa6915be2386db0397ee9a6e80b601210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817981976a914751e76e8199196d454941c45d1b3a323f1433bd688acffffffff0110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "redeemScript": "OP_DUP OP_HASH160 751e76e8199196d454941c45d1b3a323f1433bd6 OP_EQUALVERIFY OP_CHECKSIG" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2SH(P2MS 2/2) -> P2PKH", - "network": "testnet", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000fd1b0100483045022100b7a9bab60c4307349de9571ce0bd26ebb9d68d4e9ab3f9173e1f736f1390a04a022020931ff70e87033cdd94bdf434e865993b2258065c5c222a53f29d077bcfa4480147304402206d79ad83f1ab12fc9feee9e66412de842fcbf8de0632beb4433d469f24f0fb4e022079e6df186582f2686a3292bde8e50dac36cb9bec3991995fe331e1daef7df8a4014c8752410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52aeffffffff0110270000000000001976a914faf1d99bf040ea9c7f8cc9f14ac6733ad75ce24688ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT", - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 faf1d99bf040ea9c7f8cc9f14ac6733ad75ce246 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2MS 2/2 -> P2PKH", - "network": "testnet", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009200483045022100b7a9bab60c4307349de9571ce0bd26ebb9d68d4e9ab3f9173e1f736f1390a04a022020931ff70e87033cdd94bdf434e865993b2258065c5c222a53f29d077bcfa4480147304402206d79ad83f1ab12fc9feee9e66412de842fcbf8de0632beb4433d469f24f0fb4e022079e6df186582f2686a3292bde8e50dac36cb9bec3991995fe331e1daef7df8a401ffffffff0110270000000000001976a914faf1d99bf040ea9c7f8cc9f14ac6733ad75ce24688ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx" - }, - { - "prevOutScriptType": "p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 faf1d99bf040ea9c7f8cc9f14ac6733ad75ce246 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2MS 2/3 -> P2PKH", - "network": "testnet", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000910047304402206b2fc7d3182e2853cab5bcffb85c3ef5470d2d05c496295538c9947af3bfd0ec0220300aa705a985c74f76c26c6d68da9b61b5c4cd5432e8c6a54623f376c8bf8cde01473044022031059c4dd6a97d84e3a4eb1ca21a9870bd1762fbd5db7c1932d75e56da78794502200f22d85be3c5f7035e89a147ee2619a066df19aff14a62e6bb3f649b6da19edf01ffffffff0110270000000000001976a914faf1d99bf040ea9c7f8cc9f14ac6733ad75ce24688ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx" - }, - { - "prevOutScriptType": "p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 faf1d99bf040ea9c7f8cc9f14ac6733ad75ce246 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2MS 2/2 (reverse order) -> P2PKH", - "network": "testnet", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009200483045022100b7a9bab60c4307349de9571ce0bd26ebb9d68d4e9ab3f9173e1f736f1390a04a022020931ff70e87033cdd94bdf434e865993b2258065c5c222a53f29d077bcfa4480147304402206d79ad83f1ab12fc9feee9e66412de842fcbf8de0632beb4433d469f24f0fb4e022079e6df186582f2686a3292bde8e50dac36cb9bec3991995fe331e1daef7df8a401ffffffff0110270000000000001976a914faf1d99bf040ea9c7f8cc9f14ac6733ad75ce24688ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT" - }, - { - "prevOutScriptType": "p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 faf1d99bf040ea9c7f8cc9f14ac6733ad75ce246 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2SH(P2MS 2/3)", - "network": "testnet", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000fd5e0100483045022100eec19e061cad41610f9b42d2b06638b6b0fec3da0de9c6858e7f8c06053979900220622936dd47e202b2ad17639cda680e52334d407149252959936bb1f38e4acc52014830450221009aac215157a74a18234fd06be27448dccee809986bbf93be457a9262f0c69a9402203ff41d7c757f0e8951e4471f205087ecff499f986400ab18210eaad9a628e33c014cc952410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe", - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Transaction w/ P2SH(P2MS 2/3), different hash types", - "network": "testnet", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000fd5e0100483045022100eec19e061cad41610f9b42d2b06638b6b0fec3da0de9c6858e7f8c06053979900220622936dd47e202b2ad17639cda680e52334d407149252959936bb1f38e4acc5201483045022100d404fb6de6cf42efb9d7948d2e8fb6618f8eba55ecd25907d18d576d9aa6f39d02205ec2e7fa7c5f8a9793732ca9d2f9aba3b2bb04ca6d467ba36940e0f695e48de5024cc952410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG", - "hashType": 1 - }, - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe", - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG", - "hashType": 2 - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Transaction w/ P2SH(P2PK) -> P2PKH", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000006c47304402201115644b134932c8a7a8e925769d130a801288d477130e2bf6fadda20b33754d02202ecefbf63844d7cb2d5868539c39f973fe019f72e5c31a707836c0d61ef317db012321033e29aea1168a835d5e386c292082db7b7807172a10ec634ad34226f36d79e70facffffffff0100f90295000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_HASH160 e89677d91455e541630d62c63718bef738b478b1 OP_EQUAL", - "signs": [ - { - "prevOutScriptType": "p2sh-p2pk", - "keyPair": "KxLDMPtVM7sLSu2v5n1LybDibw6P9FFbL4pUwJ51UDm7rp5AmXWW", - "redeemScript": "033e29aea1168a835d5e386c292082db7b7807172a10ec634ad34226f36d79e70f OP_CHECKSIG" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 2500000000 - } - ] - }, - { - "description": "Transaction w/ non-zero vin inputs", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a47304402205c80bbb5125b35d5e5a8324b1336832d29a6fc004859c8a9ff6bef47ba7fc348022018612216e57a521b2c4543f1f4fd738a76814c37c074e88adfe12464fff31cf901210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff0110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ non-default input sequence numbers, version and locktime", - "txHex": "0400000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff020000006a47304402200e7c0330f39c04e3c1b9e3daf71d106c7129c095f6ebb494d06f0ef8013b74ea022003fc0fe05e71a2a4f8434feb0632cdb6883676d0ccb9b19d7a8a9e5fc02a616401210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b9c220000110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac09990400", - "version": 4, - "locktime": 301321, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 2, - "sequence": 2147001, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ nLockTime, P2PKH -> P2PKH", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000006b483045022100e31ef1bcc6f060cb6a53675a11606b9180f4f8b1ec823113fb4c0bf1c5b99b8e02204234690c19cd89e544002d26dbcbd49bf9d1b4cfc5a617fd8ab2607acfd869b001210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff0110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588acffff0000", - "version": 1, - "locktime": 65535, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ 1 P2PKH transaction input (Issue #644)", - "network": "testnet", - "txHex": "010000000132595835c74fccf097db4ccae9dc2de621e58e0d3f697a27b469b61c7a223b39000000006a47304402202fd41f18f1d7915bc811610236e1d708f9cd3515734abd5db7ac607f030728af02206bee7d163f04c470ce55561523824eb8b3abce80c214aabf7dfb78a073ea4a70012103f29374a4c2c218a4077db9ba0b9d674cde3719560460af4eb3190d512dd5de92ffffffff01808d5b00000000001976a914ff99e06c1a4ac394b4e1cb3d3a4b2b47749e339a88ac00000000", - "version": 1, - "inputs": [ - { - "txHex": "0100000001f7e6430096cd2790bac115aaab22c0a50fb0a1794305302e1a399e81d8d354f4020000006a47304402205793a862d193264afc32713e2e14541e1ff9ebb647dd7e7e6a0051d0faa87de302205216653741ecbbed573ea2fc053209dd6980616701c27be5b958a159fc97f45a012103e877e7deb32d19250dcfe534ea82c99ad739800295cd5429a7f69e2896c36fcdfeffffff0340420f00000000001976a9145c7b8d623fba952d2387703d051d8e931a6aa0a188ac8bda2702000000001976a9145a0ef60784137d03e7868d063b05424f2f43799f88ac40420f00000000001976a9145c7b8d623fba952d2387703d051d8e931a6aa0a188ac2fcc0e00", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "cQ6483mDWwoG8o4tn6nU9Jg52RKMjPUWXSY1vycAyPRXQJ1Pn2Rq" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 ff99e06c1a4ac394b4e1cb3d3a4b2b47749e339a OP_EQUALVERIFY OP_CHECKSIG", - "value": 6000000 - } - ] - }, - { - "description": "Transaction w/ P2PKH -> P2WPKH", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000006b4830450221009a524a3257b8bd0c77ba4cba65fc00954f2030243f2eb16571838a3b951c8c07022008f5af9de672b365fd257377db1cf6da4da1b49b9637ceb651ac0eb4181dc3ca01210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff011027000000000000160014aa4d7985c57e011a8b3dd8e0e5a73aaef41629c500000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - } - ], - "outputs": [ - { - "script": "OP_0 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2PKH -> P2WSH", - "txHex": "0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000006a473044022056c99ba23eb15b3e666b188f87b04d5ef23eeda5298939cdaec35a3bddf3835602205887a5a460f299819b0c93948fafab8b2d64d8c051934431e3bb9acebef5d1b001210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff01102700000000000022002032447752937d355ca2defddcd1f6b4fc53d182f8901cebbcff42f5e381bf0b8000000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - } - ], - "outputs": [ - { - "script": "OP_0 32447752937d355ca2defddcd1f6b4fc53d182f8901cebbcff42f5e381bf0b80", - "value": 10000 - } - ] - }, - { - "description": "P2WPKH -> P2WPKH", - "txHex": "01000000000101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff011027000000000000160014aa4d7985c57e011a8b3dd8e0e5a73aaef41629c502483045022100a8fc5e4c6d7073474eff2af5d756966e75be0cdfbba299518526080ce8b584be02200f26d41082764df89e3c815b8eaf51034a3b68a25f1be51208f54222c1bb6c1601210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800000000", - "version": 1, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_0 751e76e8199196d454941c45d1b3a323f1433bd6", - "signs": [ - { - "prevOutScriptType": "p2wpkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "value": 10000 - } - ] - } - ], - "outputs": [ - { - "script": "OP_0 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2WSH(P2PK) -> P2PKH", - "txHex": "010000000001014533a3bc1e039bd787656068e135aaee10aee95a64776bfc047ee6a7c1ebdd2f0000000000ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac02473044022039725bb7291a14dd182dafdeaf3ea0d5c05c34f4617ccbaa46522ca913995c4e02203b170d072ed2e489e7424ad96d8fa888deb530be2d4c5d9aaddf111a7efdb2d3012321038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2bac00000000", - "version": 1, - "inputs": [ - { - "txId": "2fddebc1a7e67e04fc6b77645ae9ae10eeaa35e168606587d79b031ebca33345", - "vout": 0, - "prevTxScript": "OP_0 0f9ea7bae7166c980169059e39443ed13324495b0d6678ce716262e879591210", - "signs": [ - { - "prevOutScriptType": "p2wsh-p2pk", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "witnessScript": "038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_CHECKSIG", - "value": 80000 - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG", - "value": 60000 - } - ] - }, - { - "description": "SIGHASH SINGLE (random)", - "txHex": "01000000012ffb29d53528ad30c37c267fbbeda3c6fce08f5f6f5d3b1eab22193599a3612a010000006b483045022100f963f1d9564075a934d7c3cfa333bd1378859b84cba947e149926fc9ec89b5ae02202b5b912e507bae65002aff972f9752e2aeb2e22c5fdbaaad672090378184df37032102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff0260a62f01000000001976a9140de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b888ac80969800000000001976a91454d0e925d5ee0ee26768a237067dee793d01a70688ac00000000", - "version": 1, - "inputs": [ - { - "txId": "2a61a399351922ab1e3b5d6f5f8fe0fcc6a3edbb7f267cc330ad2835d529fb2f", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 3 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 19900000, - "script": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 10000000, - "script": "OP_DUP OP_HASH160 54d0e925d5ee0ee26768a237067dee793d01a706 OP_EQUALVERIFY OP_CHECKSIG" - } - ] - }, - { - "description": "SIGHASH ALL", - "txHex": "01000000037db7f0b2a345ded6ddf28da3211a7d7a95a2943e9a879493d6481b7d69613f04010000006a47304402206abb0622b8b6ca83f1f4de84830cf38bf4615dc9e47a7dcdcc489905f26aa9cb02201d2d8a7815242b88e4cd66390ca46da802238f9b1395e0d118213d30dad38184012102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff652c491e5a781a6a3c547fa8d980741acbe4623ae52907278f10e1f064f67e05000000006b483045022100de13b42804f87a09bb46def12ab4608108d8c2db41db4bc09064f9c46fcf493102205e5c759ab7b2895c9b0447e56029f6895ff7bb20e0847c564a88a3cfcf080c4f012102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffffb9fa270fa3e4dd8c79f9cbfe5f1953cba071ed081f7c277a49c33466c695db35000000006b4830450221009100a3f5b30182d1cb0172792af6947b6d8d42badb0539f2c209aece5a0628f002200ae91702ca63347e344c85fcb536f30ee97b75cdf4900de534ed5e040e71a548012102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff03204e0000000000001976a9149ed1f577c60e4be1dbf35318ec12f51d25e8577388ac30750000000000001976a914fb407e88c48921d5547d899e18a7c0a36919f54d88ac50c30000000000001976a91404ccb4eed8cfa9f6e394e945178960f5ccddb38788ac00000000", - "version": 1, - "inputs": [ - { - "txId": "043f61697d1b48d69394879a3e94a2957a7d1a21a38df2ddd6de45a3b2f0b77d", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 1 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "057ef664f0e1108f270729e53a62e4cb1a7480d9a87f543c6a1a785a1e492c65", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 1 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "35db95c66634c3497a277c1f08ed71a0cb53195ffecbf9798cdde4a30f27fab9", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 1 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 20000, - "script": "OP_DUP OP_HASH160 9ed1f577c60e4be1dbf35318ec12f51d25e85773 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 30000, - "script": "OP_DUP OP_HASH160 fb407e88c48921d5547d899e18a7c0a36919f54d OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 50000, - "script": "OP_DUP OP_HASH160 04ccb4eed8cfa9f6e394e945178960f5ccddb387 OP_EQUALVERIFY OP_CHECKSIG" - } - ] - }, - { - "description": "SIGHASH ALL | ANYONECANPAY", - "txHex": "01000000037db7f0b2a345ded6ddf28da3211a7d7a95a2943e9a879493d6481b7d69613f04010000006b483045022100bd2829550e9b3a081747281029b5f5a96bbd83bb6a92fa2f8310f1bd0d53abc90220071b469417c55cdb3b04171fd7900d2768981b7ab011553d84d24ea85d277079812102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff652c491e5a781a6a3c547fa8d980741acbe4623ae52907278f10e1f064f67e05000000006a47304402206295e17c45c6356ffb20365b696bcbb869db7e8697f4b8a684098ee2bff85feb02202905c441abe39ec9c480749236b84fdd3ebd91ecd25b559136370aacfcf2815c812102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffffb9fa270fa3e4dd8c79f9cbfe5f1953cba071ed081f7c277a49c33466c695db35000000006b483045022100f58e7c98ac8412944d575bcdece0e5966d4018f05988b5b60b6f46b8cb7a543102201c5854d3361e29b58123f34218cec2c722f5ec7a08235ebd007ec637b07c193a812102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff03204e0000000000001976a9149ed1f577c60e4be1dbf35318ec12f51d25e8577388ac30750000000000001976a914fb407e88c48921d5547d899e18a7c0a36919f54d88ac50c30000000000001976a91404ccb4eed8cfa9f6e394e945178960f5ccddb38788ac00000000", - "version": 1, - "inputs": [ - { - "txId": "043f61697d1b48d69394879a3e94a2957a7d1a21a38df2ddd6de45a3b2f0b77d", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 129 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "057ef664f0e1108f270729e53a62e4cb1a7480d9a87f543c6a1a785a1e492c65", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 129 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "35db95c66634c3497a277c1f08ed71a0cb53195ffecbf9798cdde4a30f27fab9", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 129 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 20000, - "script": "OP_DUP OP_HASH160 9ed1f577c60e4be1dbf35318ec12f51d25e85773 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 30000, - "script": "OP_DUP OP_HASH160 fb407e88c48921d5547d899e18a7c0a36919f54d OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 50000, - "script": "OP_DUP OP_HASH160 04ccb4eed8cfa9f6e394e945178960f5ccddb387 OP_EQUALVERIFY OP_CHECKSIG" - } - ] - }, - { - "description": "SIGHASH SINGLE", - "txHex": "01000000037db7f0b2a345ded6ddf28da3211a7d7a95a2943e9a879493d6481b7d69613f04010000006b483045022100e822f152bb15a1d623b91913cd0fb915e9f85a8dc6c26d51948208bbc0218e800220255f78549d9614c88eac9551429bc00224f22cdcb41a3af70d52138f7e98d333032102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff652c491e5a781a6a3c547fa8d980741acbe4623ae52907278f10e1f064f67e05000000006a47304402206f37f79adeb86e0e2da679f79ff5c3ba206c6d35cd9a21433f0de34ee83ddbc00220118cabbac5d83b3aa4c2dc01b061e4b2fe83750d85a72ae6a1752300ee5d9aff032102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffffb9fa270fa3e4dd8c79f9cbfe5f1953cba071ed081f7c277a49c33466c695db35000000006a473044022042ac843d220a56b3de05f24c85a63e71efa7e5fc7c2ec766a2ffae82a88572b0022051a816b317313ea8d90010a77c3e02d41da4a500e67e6a5347674f836f528d82032102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff03204e0000000000001976a9149ed1f577c60e4be1dbf35318ec12f51d25e8577388ac30750000000000001976a914fb407e88c48921d5547d899e18a7c0a36919f54d88ac50c30000000000001976a91404ccb4eed8cfa9f6e394e945178960f5ccddb38788ac00000000", - "version": 1, - "inputs": [ - { - "txId": "043f61697d1b48d69394879a3e94a2957a7d1a21a38df2ddd6de45a3b2f0b77d", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 3 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "057ef664f0e1108f270729e53a62e4cb1a7480d9a87f543c6a1a785a1e492c65", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 3 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "35db95c66634c3497a277c1f08ed71a0cb53195ffecbf9798cdde4a30f27fab9", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 3 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 20000, - "script": "OP_DUP OP_HASH160 9ed1f577c60e4be1dbf35318ec12f51d25e85773 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 30000, - "script": "OP_DUP OP_HASH160 fb407e88c48921d5547d899e18a7c0a36919f54d OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 50000, - "script": "OP_DUP OP_HASH160 04ccb4eed8cfa9f6e394e945178960f5ccddb387 OP_EQUALVERIFY OP_CHECKSIG" - } - ] - }, - { - "description": "SIGHASH SINGLE|ANYONECANPAY", - "txHex": "01000000037db7f0b2a345ded6ddf28da3211a7d7a95a2943e9a879493d6481b7d69613f04010000006b483045022100d05a3b6cf2f0301000b0e45c09054f2c61570ce8798ebf571eef72da3b1c94a1022016d7ef3c133fa703bae2c75158ea08d335ac698506f99b3c369c37a9e8fc4beb832102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff652c491e5a781a6a3c547fa8d980741acbe4623ae52907278f10e1f064f67e05000000006b483045022100ee6bf07b051001dcbfa062692a40adddd070303286b714825b3fb4693dd8fcdb022056610885e5053e5d47f2be3433051305abe7978ead8f7cf2d0368947aff6b307832102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffffb9fa270fa3e4dd8c79f9cbfe5f1953cba071ed081f7c277a49c33466c695db35000000006b483045022100cfc930d5b5272d0220d9da98fabec97b9e66306f735efa837f43f6adc675cad902202f9dff76b8b9ec8f613d46094f17f64d875804292d8804aa59fd295b6fc1416b832102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff03204e0000000000001976a9149ed1f577c60e4be1dbf35318ec12f51d25e8577388ac30750000000000001976a914fb407e88c48921d5547d899e18a7c0a36919f54d88ac50c30000000000001976a91404ccb4eed8cfa9f6e394e945178960f5ccddb38788ac00000000", - "version": 1, - "inputs": [ - { - "txId": "043f61697d1b48d69394879a3e94a2957a7d1a21a38df2ddd6de45a3b2f0b77d", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 131 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "057ef664f0e1108f270729e53a62e4cb1a7480d9a87f543c6a1a785a1e492c65", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 131 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "35db95c66634c3497a277c1f08ed71a0cb53195ffecbf9798cdde4a30f27fab9", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 131 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 20000, - "script": "OP_DUP OP_HASH160 9ed1f577c60e4be1dbf35318ec12f51d25e85773 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 30000, - "script": "OP_DUP OP_HASH160 fb407e88c48921d5547d899e18a7c0a36919f54d OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 50000, - "script": "OP_DUP OP_HASH160 04ccb4eed8cfa9f6e394e945178960f5ccddb387 OP_EQUALVERIFY OP_CHECKSIG" - } - ] - }, - { - "description": "SIGHASH NONE", - "txHex": "01000000037db7f0b2a345ded6ddf28da3211a7d7a95a2943e9a879493d6481b7d69613f04010000006b483045022100e7f0a1ddd2c0b81e093e029b8a503afa27fe43549b0668d2141abf35eb3a63be022037f12d12cd50fc94a135f933406a8937557de9b9566a8841ff1548c1b6984531022102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff652c491e5a781a6a3c547fa8d980741acbe4623ae52907278f10e1f064f67e05000000006a473044022008451123ec2535dab545ade9d697519e63b28df5e311ea05e0ce28d39877a7c8022061ce5dbfb7ab478dd9e05b0acfd959ac3eb2641f61958f5d352f37621073d7c0022102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffffb9fa270fa3e4dd8c79f9cbfe5f1953cba071ed081f7c277a49c33466c695db35000000006a47304402205c001bcdfb35c70d8aa3bdbc75399afb72eb7cf1926ca7c1dfcddcb4d4d3e0f8022028992fffdcd4e9f34ab726f97c24157917641c2ef99361f588e3d4147d46eea5022102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff03204e0000000000001976a9149ed1f577c60e4be1dbf35318ec12f51d25e8577388ac30750000000000001976a914fb407e88c48921d5547d899e18a7c0a36919f54d88ac50c30000000000001976a91404ccb4eed8cfa9f6e394e945178960f5ccddb38788ac00000000", - "version": 1, - "inputs": [ - { - "txId": "043f61697d1b48d69394879a3e94a2957a7d1a21a38df2ddd6de45a3b2f0b77d", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 2 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "057ef664f0e1108f270729e53a62e4cb1a7480d9a87f543c6a1a785a1e492c65", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 2 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "35db95c66634c3497a277c1f08ed71a0cb53195ffecbf9798cdde4a30f27fab9", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 2 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 20000, - "script": "OP_DUP OP_HASH160 9ed1f577c60e4be1dbf35318ec12f51d25e85773 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 30000, - "script": "OP_DUP OP_HASH160 fb407e88c48921d5547d899e18a7c0a36919f54d OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 50000, - "script": "OP_DUP OP_HASH160 04ccb4eed8cfa9f6e394e945178960f5ccddb387 OP_EQUALVERIFY OP_CHECKSIG" - } - ] - }, - { - "description": "SIGHASH NONE | ANYONECANPAY", - "txHex": "01000000037db7f0b2a345ded6ddf28da3211a7d7a95a2943e9a879493d6481b7d69613f04010000006a47304402204ed272952177aaa5a1b171c2ca5a7a3d300ffcd7e04b040c0baaa4e3561862a502207e65a5b8f99c8a632b186c8a60496a12bf3116f51909b7497413aefdc3be7bf6822102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff652c491e5a781a6a3c547fa8d980741acbe4623ae52907278f10e1f064f67e05000000006a47304402203ec365300cc67602f4cc5be027959d3667b48db34c6c87d267c94a7e210d5c1f02204843350311c0a9711cad1960b17ce9e323a1ce6f37deefc3ffe63082d480be92822102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffffb9fa270fa3e4dd8c79f9cbfe5f1953cba071ed081f7c277a49c33466c695db35000000006b48304502210084f86f905c36372eff9c54ccd509a519a3325bcace8abfeed7ed3f0d579979e902201ff330dd2402e5ca9989a8a294fa36d6cf3a093edb18d29c9d9644186a3efeb4822102f1c7eac9200f8dee7e34e59318ff2076c8b3e3ac7f43121e57569a1aec1803d4ffffffff03204e0000000000001976a9149ed1f577c60e4be1dbf35318ec12f51d25e8577388ac30750000000000001976a914fb407e88c48921d5547d899e18a7c0a36919f54d88ac50c30000000000001976a91404ccb4eed8cfa9f6e394e945178960f5ccddb38788ac00000000", - "version": 1, - "inputs": [ - { - "txId": "043f61697d1b48d69394879a3e94a2957a7d1a21a38df2ddd6de45a3b2f0b77d", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 130 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "057ef664f0e1108f270729e53a62e4cb1a7480d9a87f543c6a1a785a1e492c65", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 130 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "txId": "35db95c66634c3497a277c1f08ed71a0cb53195ffecbf9798cdde4a30f27fab9", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzRGFiqhXB7SyX6idHQkt77B8mX7adnujdg3VG47jdVK2x4wbUYg", - "hashType": 130 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 0de1f9b92d2ab6d8ead83f9a0ff5cf518dcb03b8 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 20000, - "script": "OP_DUP OP_HASH160 9ed1f577c60e4be1dbf35318ec12f51d25e85773 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 30000, - "script": "OP_DUP OP_HASH160 fb407e88c48921d5547d899e18a7c0a36919f54d OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 50000, - "script": "OP_DUP OP_HASH160 04ccb4eed8cfa9f6e394e945178960f5ccddb387 OP_EQUALVERIFY OP_CHECKSIG" - } - ] - }, - { - "description": "SIGHASH V0+V1, (P2PKH, P2WPKH) -> 2x P2PKH", - "txHex": "01000000000102fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f00000000484730440220691a19d365c8d75f921346c70271506bde136f13a4b566dd796902c262e2ec6d02202b00c4aa030eedf294552bdfc163936d2f4e91c59e7798c4471250cf07cb859501eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff0230f45e13000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac00e9a435000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac0002483045022100fddd014889f18d489b5400bfa8cb0a32301a768d934b1a0e2b55398119f26cab02207676c64c16ffa7ffaaf8e16b3b74e916687eebdfdb36b9b7997e838384d464640121025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee635711000000", - "version": 1, - "inputs": [ - { - "txId": "9f96ade4b41d5433f4eda31e1738ec2b36f6e7d1420d94a6af99801a88f7f7ff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pk", - "keyPair": "L3Wh2WPg21MWqzMFYsVC7PeBXcq1ow32KRccRihnTUnAhJaZUvg1", - "hashType": 1 - } - ], - "sequence": 4294967278, - "prevTxScript": "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432 OP_CHECKSIG" - }, - { - "txId": "8ac60eb9575db5b2d987e29f301b5b819ea83a5c6579d282d189cc04b8e151ef", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2wpkh", - "keyPair": "KzVTBhbMaKrAYagJ11VdTaBrb6yzLykLGyuMBkf9sCFPDxdT8shL", - "hashType": 1, - "value": 600000000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_0 1d0f172a0ecb48aee1be1f2687d2963ae33f71a1" - } - ], - "outputs": [ - { - "value": 324990000, - "script": "OP_DUP OP_HASH160 8280b37df378db99f66f85c95a783a76ac7a6d59 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 900000000, - "script": "OP_DUP OP_HASH160 3bde42dbee7e4dbe6a21b2d50ce2f0167faa8159 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 17 - }, - { - "description": "SIGHASH V0+V1, P2SH(P2WPKH) -> P2PKH", - "txHex": "01000000000101db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001716001479091972186c449eb1ded22b78e40d009bdf0089feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac02473044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb012103ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a2687392040000", - "version": 1, - "inputs": [ - { - "txId": "77541aeb3c4dac9260b68f74f44c973081a9d4cb2ebe8038b2d70faa201b6bdb", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wpkh", - "keyPair": "L57KYn5isHFThD4cohjJgLTZA2vaxnMMKWngnzbttF159yH9dARf", - "hashType": 1, - "redeemScript": "OP_0 79091972186c449eb1ded22b78e40d009bdf0089", - "value": 1000000000 - } - ], - "sequence": 4294967294, - "prevTxScript": "OP_HASH160 4733f37cf4db86fbc2efed2500b4f4e49f312023 OP_EQUAL" - } - ], - "outputs": [ - { - "value": 199996600, - "script": "OP_DUP OP_HASH160 a457b684d7f0d539a46a45bbc043f35b59d0d963 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 800000000, - "script": "OP_DUP OP_HASH160 fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 1170 - }, - { - "description": "Sighash V1: P2SH(P2WSH(P2MS 6/6))", - "txHex": "0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff02e6312761010000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688ac583e0f00000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac0800483045022100f902f491c4df15199e584790ae8c7202569a977accac0a09fa3f4f3b6ec3517602205961a951c4a12fa966da67b6fd75975b9de156b9895f8ab5f289ecaee12b9b3501473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502483045022100bd5294e145d729e9593f49079b74e6e4b8aeba63440408595ce0949d5c6450a702207f9c9fb45907fe0180d3f4bee499006007bb90894b5f824a26dfa5d3afec543303483045022100febf9409d7f3c091ddc4d296a483aae7b3d2a91d38f6ea2a153f7ff085fe7766022078d11972c74cd78f816152463a5e1a5d986dfb94b55cf5f7242e4f6d5df000ff81483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a088247304402201a0e125aed6a700e45d6c86017d5a9d2264c8079319d868f3f163f5d63cb5bfe02200887608f2322ca0d82df67316275371028b0b21750417d594117963fe23b67ec83cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", - "version": 1, - "inputs": [ - { - "txId": "6eb98797a21c6c10aa74edf29d618be109f48a8e94c694f3701e08ca69186436", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "L15NqbRvcqso8ZCqD8aFaZV3CTypw6svjk8oCWsAfMmNViahS2Mw", - "hashType": 1, - "witnessScript": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG", - "redeemScript": "OP_0 a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54", - "value": 987654321 - }, - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "Kwpf3fycToLH1ymZUkezFrYwTjhKaucHD861Ft5A4Tih855LBxVx", - "hashType": 2, - "witnessScript": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG", - "redeemScript": "OP_0 a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54", - "value": 987654321 - }, - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "L1EV111k2WzNTapY2etd1TaB2aWbjUgouko9YyipS2S8H8WdGkQi", - "hashType": 3, - "witnessScript": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG", - "redeemScript": "OP_0 a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54", - "value": 987654321 - }, - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "KwuvEmpBtJaw8SQLnpi3CoEHZJvv33EnYBHn13VcDuwprJqmkfSH", - "hashType": 129, - "witnessScript": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG", - "redeemScript": "OP_0 a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54", - "value": 987654321 - }, - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "L5kdM8eWyfj8pdRDWA8j5SmBwAQt2yyhqjb2ZZQxtRGJfCquC6TB", - "hashType": 130, - "witnessScript": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG", - "redeemScript": "OP_0 a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54", - "value": 987654321 - }, - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "KyT4JbJVRy5FZ6ZEZhkaocP2JSBXiF7X3Cx6DBAGLrydR9fiXQUK", - "hashType": 131, - "witnessScript": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG", - "redeemScript": "OP_0 a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54", - "value": 987654321 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_HASH160 9993a429037b5d912407a71c252019287b8d27a5 OP_EQUAL" - } - ], - "outputs": [ - { - "value": 5924925926, - "script": "OP_DUP OP_HASH160 389ffce9cd9ae88dcc0631e88a821ffdbe9bfe26 OP_EQUALVERIFY OP_CHECKSIG" - }, - { - "value": 999000, - "script": "OP_DUP OP_HASH160 7480a33f950689af511e6e84c138dbbd3c3ee415 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2PK", - "txHex": "010000000193aef40ae141694895e99e18e49d0181b086dd7c011c0241175c6eaf320099970000000049483045022100e57eba5380dcc8a7bdb5370b423dadd43070e1ca268f94bc97b2ded55ca45e9502206a43151c8af03a00f0ac86526d07981e303fc0daea8c6ed435abe8961533046d01ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac00000000", - "version": 1, - "inputs": [ - { - "txId": "97990032af6e5c1741021c017cdd86b081019de4189ee995486941e10af4ae93", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pk", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1 - } - ], - "sequence": 4294967295, - "prevTxScript": "038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2SH(P2PK)", - "txHex": "0100000001a30e865fa60f6c25a8b218bb5a6b9acc7cf3f1db2f2e3a7114b51af5d6ae811f000000006c473044022026d2b56b6cb0269bf4e80dd655b9e917019e2ccef57f4b858d03bb45a2da59d9022010519a7f327f03e7c9613e0694f929544af29d3682e7ec8f19147e7a86651ecd012321038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2bacffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac00000000", - "version": 1, - "inputs": [ - { - "txId": "1f81aed6f51ab514713a2e2fdbf1f37ccc9a6b5abb18b2a8256c0fa65f860ea3", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2pk", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "redeemScript": "038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_CHECKSIG" - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_HASH160 c99d9ebb5a4828e4e1b606dd6a51a2babebbdc09 OP_EQUAL" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2WSH(P2PK)", - "txHex": "010000000001014533a3bc1e039bd787656068e135aaee10aee95a64776bfc047ee6a7c1ebdd2f0000000000ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac02473044022039725bb7291a14dd182dafdeaf3ea0d5c05c34f4617ccbaa46522ca913995c4e02203b170d072ed2e489e7424ad96d8fa888deb530be2d4c5d9aaddf111a7efdb2d3012321038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2bac00000000", - "version": 1, - "inputs": [ - { - "txId": "2fddebc1a7e67e04fc6b77645ae9ae10eeaa35e168606587d79b031ebca33345", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2wsh-p2pk", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "witnessScript": "038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_CHECKSIG", - "value": 80000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_0 0f9ea7bae7166c980169059e39443ed13324495b0d6678ce716262e879591210" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2SH(P2WSH(P2PK))", - "txHex": "01000000000101e0779d448aaa203a96b3de14d0482e26dd75a4278ae5bb6d7cc18e6874f3866000000000232200200f9ea7bae7166c980169059e39443ed13324495b0d6678ce716262e879591210ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac024730440220014207a5f0601ed7b3c3f9d82309b32e8f76dd6776a55cb5f8684b9ff029e0850220693afd7b69471b51d9354cc1a956b68b8d48e32f6b0ad7a19bb5dd3e4499179a012321038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2bac00000000", - "version": 1, - "inputs": [ - { - "txId": "6086f374688ec17c6dbbe58a27a475dd262e48d014deb3963a20aa8a449d77e0", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2pk", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "redeemScript": "OP_0 0f9ea7bae7166c980169059e39443ed13324495b0d6678ce716262e879591210", - "witnessScript": "038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_CHECKSIG", - "value": 80000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_HASH160 6d185c7042d01ea8276dc6be6603101dc441d8a4 OP_EQUAL" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2PKH", - "txHex": "010000000176d7b05b96e69d9760bacf14e496ea01085eff32be8f4e08b299eb92057826e5000000006b4830450221009bd6ff2561437155913c289923175d3f114cca1c0e2bc5989315d5261502c2c902201b71ad90dce076a5eb872330ed729e7c2c4bc2d0513efff099dbefb3b62eab4f0121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2bffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac00000000", - "version": 1, - "inputs": [ - { - "txId": "e526780592eb99b2084e8fbe32ff5e0801ea96e414cfba60979de6965bb0d776", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2SH(P2PKH)", - "txHex": "01000000014b9ffc17c3cce03ee66980bf32d36aaa13462980c3af9d9d29ec6b97ab1c91650000000084473044022003d738d855d0c54a419ac62ebe1a1c0bf2dc6993c9585adb9a8666736658107002204d57ff62ee7efae6df73430bba62494faeba8c125a4abcf2488757a4f8877dd50121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b1976a914851a33a5ef0d4279bd5854949174e2c65b1d450088acffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac00000000", - "version": 1, - "inputs": [ - { - "txId": "65911cab976bec299d9dafc380294613aa6ad332bf8069e63ee0ccc317fc9f4b", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2pkh", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "redeemScript": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_HASH160 2162ff7c23d47a0c331f95c67d7c3e22abb12a02 OP_EQUAL" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2WSH(P2PKH)", - "txHex": "0100000000010123539877e39a273819006de1c433e09f9e9af201fc178dd0f2cf2eaa5ad53b480000000000ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac03483045022100f02a82b0a94a5d5dc4d2127ac34be62cb066713d71d56bdf5ef7810ab57a157302205f24abdde1dab554a02edcf378e98828024e57272e5e474a5b04accdca080a030121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b1976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac00000000", - "version": 1, - "inputs": [ - { - "txId": "483bd55aaa2ecff2d08d17fc01f29a9e9fe033c4e16d001938279ae377985323", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2wsh-p2pkh", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "witnessScript": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG", - "value": 80000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_0 578db4b54a6961060b71385c17d3280379a557224c52b11b19a3a1c1eef606a0" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2SH(P2WSH(P2PKH))", - "txHex": "01000000000101363dfbfe2566db77e3b1195bedf1d0daeb9ce526cd7611ba81759b2654ce415c0000000023220020578db4b54a6961060b71385c17d3280379a557224c52b11b19a3a1c1eef606a0ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac03483045022100c8bd5ebb26ba6719158650c3e7c5e80be4c886ba025c44cc41f5149b3114705a02203ac6e1f38f6c081d506f28f1b5e38ebec9e0f0fa911d0e3f68d48d8b0e77b34b0121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b1976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac00000000", - "version": 1, - "inputs": [ - { - "txId": "5c41ce54269b7581ba1176cd26e59cebdad0f1ed5b19b1e377db6625fefb3d36", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2pkh", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "witnessScript": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG", - "redeemScript": "OP_0 578db4b54a6961060b71385c17d3280379a557224c52b11b19a3a1c1eef606a0", - "value": 80000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_HASH160 44a641c4e06eb6118c99e5ed29954b705b50fb6a OP_EQUAL" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2MS 1/1", - "txHex": "010000000179310ec46e734b3490ee839c5ae4a09d28561ee9fff2d051f733d201f958d6d2000000004a00483045022100d269531f120f377ed2f94f42bef893ff2fe6544ac97fb477fa291bc6cfb7647e02200983f6a5bbd4ce6cf97f571995634805a7324cc5d8353ed954fa62477b0fcd0901ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac00000000", - "version": 1, - "inputs": [ - { - "txId": "d2d658f901d233f751d0f2ffe91e56289da0e45a9c83ee90344b736ec40e3179", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2ms", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_1 038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_1 OP_CHECKMULTISIG" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2SH(P2MS)", - "txHex": "010000000152882c661c49dd2f53bd9ced7e9f44b184888ad2fe7d86737f0efaa7aecdced1000000006f00473044022025f2e161f0a97888df948f4dcc7c04fe502510b8d8260ca9920f38d55e4d17720220271b6843224b3a34542a4df31781d048da56ee46b8c5fb99043e30abd527b2d801255121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b51aeffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac00000000", - "version": 1, - "inputs": [ - { - "txId": "d1cecdaea7fa0e7f73867dfed28a8884b1449f7eed9cbd532fdd491c662c8852", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "redeemScript": "OP_1 038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_1 OP_CHECKMULTISIG" - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_HASH160 38c064c6387d1071eeb5c3d90350054aea0b3fc1 OP_EQUAL" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2WSH(P2MS)", - "txHex": "01000000000101c1eced6216de0889d4629ff64a8af8e8ec6d0b414de0c57b46c02cc303d321fe0000000000ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac0300483045022100d4c0cbdb45915b8a3162362fa5f74556de919aeda5337fc44a7fb000e833460d022017742c37d7a061e2ae3a086c7c585c9c85e5d31af468d3e00045c0f35b8f8eb601255121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b51ae00000000", - "version": 1, - "inputs": [ - { - "txId": "fe21d303c32cc0467bc5e04d410b6dece8f88a4af69f62d48908de1662edecc1", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2wsh-p2ms", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "witnessScript": "OP_1 038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_1 OP_CHECKMULTISIG", - "value": 80000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_0 1b8c0c2878c5634c3ce738cdc568c592e99783dbd28ff4c6cb5b7b4675d9ee99" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2SH(P2WSH(P2MS))", - "txHex": "010000000001013a5a2ab0223d3b504b52af76d650329750666fbf1be13d4cb08d0d9fc550a47d00000000232200201b8c0c2878c5634c3ce738cdc568c592e99783dbd28ff4c6cb5b7b4675d9ee99ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac0300483045022100c97a5e205ce0023d3d44f846abf1f0e21b6f2646bd2496bbe92e4333fe4401be02201247e047d669f713582713e35d2eba430abc3d75a924bb500362bf47d6234ed501255121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b51ae00000000", - "version": 1, - "inputs": [ - { - "txId": "7da450c59f0d8db04c3de11bbf6f6650973250d676af524b503b3d22b02a5a3a", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "witnessScript": "OP_1 038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b OP_1 OP_CHECKMULTISIG", - "redeemScript": "OP_0 1b8c0c2878c5634c3ce738cdc568c592e99783dbd28ff4c6cb5b7b4675d9ee99", - "value": 80000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_HASH160 cc6ea17c33de7996471e40892acdd6e5f61b9b6f OP_EQUAL" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2WPKH -> P2PKH", - "txHex": "0100000000010133defbe3e28860007ff3e21222774c220cb35d554fa3e3796d25bf8ee983e1080000000000ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac0248304502210097c3006f0b390982eb47f762b2853773c6cedf83668a22d710f4c13c4fd6b15502205e26ef16a81fc818a37f3a34fc6d0700e61100ea6c6773907c9c046042c440340121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b00000000", - "version": 1, - "inputs": [ - { - "txId": "08e183e98ebf256d79e3a34f555db30c224c772212e2f37f006088e2e3fbde33", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2wpkh", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "value": 80000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_0 851a33a5ef0d4279bd5854949174e2c65b1d4500" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "P2SH(P2WPKH) -> P2PKH", - "txHex": "010000000001015df9a0b9ade2d835881704e0f53b51a4b19ecfc794ea1f3555783dd7f68659ce0000000017160014851a33a5ef0d4279bd5854949174e2c65b1d4500ffffffff0160ea0000000000001976a914851a33a5ef0d4279bd5854949174e2c65b1d450088ac02483045022100cb3929c128fec5108071b662e5af58e39ac8708882753a421455ca80462956f6022030c0f4738dd1a13fc7a34393002d25c6e8a6399f29c7db4b98f53a9475d94ca20121038de63cf582d058a399a176825c045672d5ff8ea25b64d28d4375dcdb14c02b2b00000000", - "version": 1, - "inputs": [ - { - "txId": "ce5986f6d73d7855351fea94c7cf9eb1a4513bf5e004178835d8e2adb9a0f95d", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wpkh", - "keyPair": "L2FroWqrUgsPpTMhpXcAFnVDLPTToDbveh3bhDaU4jhe7Cw6YujN", - "hashType": 1, - "redeemScript": "OP_0 851a33a5ef0d4279bd5854949174e2c65b1d4500", - "value": 80000 - } - ], - "sequence": 4294967295, - "prevTxScript": "OP_HASH160 0d061ae2c8ad224a81142a2e02181f5173b576b3 OP_EQUAL" - } - ], - "outputs": [ - { - "value": 60000, - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "locktime": 0 - }, - { - "description": "Defaults to version 2", - "txHex": "0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000006b483045022100d090736fce4387d25f9d7ba85270a3859947dbd0a19f347467c3a596e06c132402204b14c29d128f824bee953bdaf2ed4e16c7cff0b24bddb4add94b4b6c42773d8801210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff0110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": null, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 10000 - } - ], - "locktime": 0 - }, - { - "description": "P2SH(P2WSH(P2MS 2/2)), incomplete", - "network": "testnet", - "txHex": "010000000001012915794541ffa77ca795ec7c23ee989a63ccd1a71fab73e1c27ed20c4b6c69a4010000002322002024376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5afffffffff01b8820100000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac040047304402203b334650f1f13574a1c2edc76421867f7252950968bf0293c8b3ed086ab89e3d0220565cafab0a5044617e94756b948241525b2483a52504e1064d29f641fb18129e010047522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea1952ae00000000", - "version": 1, - "incomplete": true, - "inputs": [ - { - "txId": "a4696c4b0cd27ec2e173ab1fa7d1cc639a98ee237cec95a77ca7ff4145791529", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "cRAwuVuVSBZMPu7hdrYvMCZ8eevzmkExjFbaBLhqnDdrezxN3nTS", - "witnessScript": "OP_2 02bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e2 02d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea19 OP_2 OP_CHECKMULTISIG", - "redeemScript": "OP_0 24376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5af", - "value": 100000 - } - ], - "prevTxScript": "OP_HASH160 b64f1a3eacc1c8515592a6f10457e8ff90e4db6a OP_EQUAL" - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 99000 - } - ] - }, - { - "description": "P2SH(P2WSH(P2MS 2/2))", - "network": "testnet", - "txHex": "010000000001012915794541ffa77ca795ec7c23ee989a63ccd1a71fab73e1c27ed20c4b6c69a4010000002322002024376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5afffffffff01b8820100000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac040047304402203b334650f1f13574a1c2edc76421867f7252950968bf0293c8b3ed086ab89e3d0220565cafab0a5044617e94756b948241525b2483a52504e1064d29f641fb18129e0148304502210096e859827fb629b6547658c613f7c8298de151513d74b224560aa8608d521d600220736fb5564322237716ec940de44c67c428198adf5dedfda183c17aa77cd28d640147522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea1952ae00000000", - "version": 1, - "incomplete": true, - "inputs": [ - { - "txId": "a4696c4b0cd27ec2e173ab1fa7d1cc639a98ee237cec95a77ca7ff4145791529", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "cRAwuVuVSBZMPu7hdrYvMCZ8eevzmkExjFbaBLhqnDdrezxN3nTS", - "witnessScript": "OP_2 02bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e2 02d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea19 OP_2 OP_CHECKMULTISIG", - "redeemScript": "OP_0 24376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5af", - "value": 100000 - }, - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "cTUFsNeVd8TKU4yREN8nMdViNnHyNvCCYVRmRUmkMLgomiMWTiii", - "witnessScript": "OP_2 02bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e2 02d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea19 OP_2 OP_CHECKMULTISIG", - "redeemScript": "OP_0 24376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5af", - "value": 100000 - } - ], - "prevTxScript": "OP_HASH160 b64f1a3eacc1c8515592a6f10457e8ff90e4db6a OP_EQUAL" - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 99000 - } - ] - }, - { - "description": "P2SH(P2WSH(P2MS 2/3)) -> P2PKH", - "network": "testnet", - "txHex": "01000000000101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01000000232200201b48bf145648b9492ecd6d76754ea3def4b90e22e4ef7aee9ca291b2de455701ffffffff01f07e0e00000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac0400473044022036c9ecb03cb04c09be1f52766725dcfe9a815973bd2f34ce19a345f2d925a45502207b90737852d2508db104ad17612de473687e67928c045555a1ed8d495c0570d901483045022100aec0e58e4e597b35ca5a727702a0da3d4f2ef4759914da7fc80aecb3c479a6d902201ec27ea8dcca4b73ee81e4b627f52f9e627c3497f61e4beeb98f86e02979640a0169522103c411cf39aca4395c81c35921dc832a0d1585d652ab1b52ccc619ff9fbbc5787721020636d944458a4663b75a912c37dc1cd59b11f9a00106783a65ba230d929b96b02102d1448cbf19528a1a27e5958ba73d930b5b3facdbe5c30c7094951a287fcc914953ae00000000", - "version": 1, - "stages": [ - "01000000000101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01000000232200201b48bf145648b9492ecd6d76754ea3def4b90e22e4ef7aee9ca291b2de455701ffffffff01f07e0e00000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac0500473044022036c9ecb03cb04c09be1f52766725dcfe9a815973bd2f34ce19a345f2d925a45502207b90737852d2508db104ad17612de473687e67928c045555a1ed8d495c0570d901000069522103c411cf39aca4395c81c35921dc832a0d1585d652ab1b52ccc619ff9fbbc5787721020636d944458a4663b75a912c37dc1cd59b11f9a00106783a65ba230d929b96b02102d1448cbf19528a1a27e5958ba73d930b5b3facdbe5c30c7094951a287fcc914953ae00000000" - ], - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "cUxccFVBdJRq6HnyxiFMd8Z15GLThXaNLcnPBgoXLEv9iX6wuV2b", - "witnessScript": "OP_2 03c411cf39aca4395c81c35921dc832a0d1585d652ab1b52ccc619ff9fbbc57877 020636d944458a4663b75a912c37dc1cd59b11f9a00106783a65ba230d929b96b0 02d1448cbf19528a1a27e5958ba73d930b5b3facdbe5c30c7094951a287fcc9149 OP_3 OP_CHECKMULTISIG", - "redeemScript": "OP_0 1b48bf145648b9492ecd6d76754ea3def4b90e22e4ef7aee9ca291b2de455701", - "value": 1000000, - "stage": true - }, - { - "prevOutScriptType": "p2sh-p2wsh-p2ms", - "keyPair": "cVSNe9ZdZRsRvEBL8YRR7YiZmH4cLsf5FthgERWkZezJVrGseaXy", - "witnessScript": "OP_2 03c411cf39aca4395c81c35921dc832a0d1585d652ab1b52ccc619ff9fbbc57877 020636d944458a4663b75a912c37dc1cd59b11f9a00106783a65ba230d929b96b0 02d1448cbf19528a1a27e5958ba73d930b5b3facdbe5c30c7094951a287fcc9149 OP_3 OP_CHECKMULTISIG", - "redeemScript": "OP_0 1b48bf145648b9492ecd6d76754ea3def4b90e22e4ef7aee9ca291b2de455701", - "value": 1000000 - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 950000 - } - ] - } - ], - "fromTransaction": [ - { - "description": "Transaction w/ P2SH(P2MS 2/2) -> OP_RETURN | 1 OP_0 fixes to 2 OP_0, no signatures", - "network": "testnet", - "incomplete": true, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "scriptSig": "OP_0 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae", - "scriptSigAfter": "OP_0 OP_0 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Transaction w/ P2SH(P2MS 2/2) -> OP_RETURN | missing OP_0, 1 signature", - "network": "testnet", - "incomplete": true, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "scriptSig": "OP_0 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae", - "scriptSigAfter": "OP_0 OP_0 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Transaction w/ P2SH(P2MS 2/2) -> OP_RETURN | no OP_0, 2 signatures", - "network": "testnet", - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae", - "scriptSigAfter": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - } - ], - "fromTransactionSequential": [ - { - "description": "Transaction w/ P2SH(P2MS 2/3) -> ?", - "network": "testnet", - "txHex": "0100000001b033b2214568b49fda417371aba0634b0303a2b6a19884c25d03d0b91bdbe231000000006f000000004c6952210258db1bb3801f1ecde47602143beaeb9cac93251724b8e589fae5c08c1a399a9121038e803e3d84cfc821cc8bf46233a9c2bb359d529db0bcdd3f1a4f38678dd02d7f2103b83e59d848407d7f62a82c99905f5ca3e8e8f5d6400eb78a0b4b067aea0720d953aeffffffff0200e1f5050000000017a914a9974100aeee974a20cda9a2f545704a0ab54fdc87c72831010000000017a9149f57a6712ef023f85ffac631ed4263b977b2d0678700000000", - "txHexAfter": "0100000001b033b2214568b49fda417371aba0634b0303a2b6a19884c25d03d0b91bdbe23100000000b60000004730440220793d87f2a8afeb856816efa38984418c692c15170e99ca371f547454079c0dd3022074ae95e438fee1f37619fabe0ce1083c3be0d65c3defb5337833d50fdc694b13014c6952210258db1bb3801f1ecde47602143beaeb9cac93251724b8e589fae5c08c1a399a9121038e803e3d84cfc821cc8bf46233a9c2bb359d529db0bcdd3f1a4f38678dd02d7f2103b83e59d848407d7f62a82c99905f5ca3e8e8f5d6400eb78a0b4b067aea0720d953aeffffffff0200e1f5050000000017a914a9974100aeee974a20cda9a2f545704a0ab54fdc87c72831010000000017a9149f57a6712ef023f85ffac631ed4263b977b2d0678700000000", - "incomplete": true, - "inputs": [ - { - "vout": 0, - "scriptSig": "OP_0 OP_0 OP_0 OP_0 52210258db1bb3801f1ecde47602143beaeb9cac93251724b8e589fae5c08c1a399a9121038e803e3d84cfc821cc8bf46233a9c2bb359d529db0bcdd3f1a4f38678dd02d7f2103b83e59d848407d7f62a82c99905f5ca3e8e8f5d6400eb78a0b4b067aea0720d953ae", - "scriptSigAfter": "OP_0 OP_0 OP_0 30440220793d87f2a8afeb856816efa38984418c692c15170e99ca371f547454079c0dd3022074ae95e438fee1f37619fabe0ce1083c3be0d65c3defb5337833d50fdc694b1301 52210258db1bb3801f1ecde47602143beaeb9cac93251724b8e589fae5c08c1a399a9121038e803e3d84cfc821cc8bf46233a9c2bb359d529db0bcdd3f1a4f38678dd02d7f2103b83e59d848407d7f62a82c99905f5ca3e8e8f5d6400eb78a0b4b067aea0720d953ae", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "cTkcnMZoFYH1UgumzCFHv2veLMNN1PaJyHHUxFT127zhNGBqqEZ2", - "redeemScript": "OP_2 0258db1bb3801f1ecde47602143beaeb9cac93251724b8e589fae5c08c1a399a91 038e803e3d84cfc821cc8bf46233a9c2bb359d529db0bcdd3f1a4f38678dd02d7f 03b83e59d848407d7f62a82c99905f5ca3e8e8f5d6400eb78a0b4b067aea0720d9 OP_3 OP_CHECKMULTISIG" - } - ] - } - ] - } - ], - "classification": { - "hex": "01000000059c06fb641a8cd69be81ca91e68d8a115cb698396876ecd77120ec1e4ab9002279f000000b500483045022100d58f828ab39cfac592f89fe372fb520992975218698c683a893f29e39cf0080302207cc0485dab5ce621089bdd15e1f15db0ecbde8dd4bb661bcf0e3af6ecab075e6014c6952210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753aeffffffff0821dc00213d2b7993f8f2a1553800c6f2f31106da176505d0ade467b68401d795000000b400473044022028e937a7bba888fe3428f442f6e22d92ce2ddba01548c38780d40890fa6cc305022043204d0bcfb1150b045d54cf9b13462e44e2ef47fee03d3cea08e84a8060fc30014c6952210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753aeffffffffaa997ac385dc666af1f5947ef615431024eb314cac2308d5e1b903e28ca466f499000000b50048304502210093efc26facedc5f51e304aa270a7b4f1a911b2d912c3674e5c6e2ad4ac7a410402201cf0b62c240461902f9f16d8a0bc3a210b7bfcd2c06523dd4b4b63be22e85252014c6952210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753aeffffffffd9f61bf98a021ee144f33ba5a6b04274de8fcb5c05f1ff7c12367fb7a608b2dd9e000000b4004730440220456e1201c1fa727288cba7fa0054dc02d8dd6c7418cae1e97006ef0652891c9202201192d0fbf3a9c00afb99a415f2bf515509e1150805acd8de95c496c27cb6570f014c6952210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753aeffffffff1f8119e3bc7c2f451feaa79f42ec5a63502afb425c253c935e43d217d5c29bdea1000000b500483045022100f669004f770490093eba4ac4903cb7581f7d18ea9245c538585ef5367e520e4702205485fafe0be178563a599d41e0cc172bb01314ed65d0e48df19a5258f17bdbc4014c6952210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753aeffffffff0380f0fa02000000001976a91439692085cf9d27e8c1cf63e76bd32d9bd15cab8b88ac50c300000000000017a9147204bb26950ce1595255897f63d205779f033f3e875b5409000000000017a9142538893d984a4b5695e4bfde1a90a9f02fabf8e38700000000" - }, - "multisig": [ - { - "description": "P2SH(P2MS 2/2), signed in correct order", - "network": "testnet", - "txHex": "0100000001cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f0714900000000fd1c0100483045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001483045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b06576014c8752410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 0, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 1, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT", - "scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "P2SH(P2MS 2/2), signed in shuffled order", - "network": "testnet", - "txHex": "0100000001cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f0714900000000fd1c0100483045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001483045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b06576014c8752410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 1, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT", - "scriptSig": "OP_0 OP_0 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 0, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "P2SH(P2MS 2/2), manually messed up order of signatures", - "network": "testnet", - "txHex": "0100000001cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f0714900000000fd1c0100483045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001483045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b06576014c8752410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 0, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 1, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT", - "scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "P2SH(P2MS 2/3), signed by key 1 and 2", - "network": "testnet", - "txHex": "0100000001cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f0714900000000fd5e0100483045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01483045022100ae06d8269b79b5cfa0297d1d88261b0061e52fc2814948c3aa05fa78ee76894302206e0c79a5c90569d8c72a542ef9a06471cbbcd2c651b312339983dfba4f8ff463014cc952410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 0, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 1, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT", - "scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 3045022100ae06d8269b79b5cfa0297d1d88261b0061e52fc2814948c3aa05fa78ee76894302206e0c79a5c90569d8c72a542ef9a06471cbbcd2c651b312339983dfba4f8ff46301 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "P2SH(P2MS 2/3), signed by key 1 and 3", - "network": "testnet", - "txHex": "0100000001cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f0714900000000fd5e0100483045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01483045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af0014cc952410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 0, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 2, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe", - "scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "P2SH(P2MS 2/3), signed by key 3 and 1", - "network": "testnet", - "txHex": "0100000001cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f0714900000000fd5e0100483045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01483045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af0014cc952410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 2, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe", - "scriptSig": "OP_0 OP_0 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 0, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "P2SH(P2MS 2/3), signed by key 1 and 3, manually messed up order of signatures", - "network": "testnet", - "txHex": "0100000001cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f0714900000000fd5e0100483045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01483045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af0014cc952410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 0, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 2, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe", - "scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "P2SH(P2MS 2/3), signed by key 3 and 1, manually removing OP_0s", - "network": "testnet", - "txHex": "0100000001cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f0714900000000fd5e0100483045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01483045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af0014cc952410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253aeffffffff01e8030000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000", - "version": 1, - "inputs": [ - { - "txId": "4971f016798a167331bcbc67248313fbc444c6e92e4416efd06964425588f5cf", - "vout": 0, - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 2, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe", - "scriptSig": "OP_0 OP_0 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "pubKeyIndex": 0, - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "scriptSigBefore": "OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae", - "scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - } - ] - }, - "invalid": { - "build": [ - { - "exception": "Transaction has no inputs", - "inputs": [], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "exception": "Transaction has no outputs", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0 - } - ], - "outputs": [] - }, - { - "exception": "Transaction has absurd fees", - "inputs": [ - { - "txRaw": { - "inputs": [], - "outputs": [ - { - "address": "1C5XhB1UkFuyCV1CG9dmXaXGu3xDL4nAjv", - "value": 1000000000 - } - ], - "incomplete": true - }, - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzBQVXYUGDAvqG7VeU3C7ZMRYiwtsxSVVFcYGzKU9E4aUVDUquZU" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 ff99e06c1a4ac394b4e1cb3d3a4b2b47749e339a OP_EQUALVERIFY OP_CHECKSIG", - "value": 200000 - } - ] - }, - { - "description": "Incomplete transaction, nothing assumed", - "exception": "Transaction is not complete", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0 - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Incomplete transaction, known prevTxScript, thereby throws for missing signatures", - "exception": "Not enough information", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - } - ] - }, - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "prevTxScript": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG" - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Incomplete Transaction P2SH(P2MS 2/3), missing signature", - "exception": "Not enough signatures provided", - "network": "testnet", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG" - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Duplicate transaction outs", - "exception": "Duplicate TxOut: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:0", - "incomplete": true, - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0 - }, - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0 - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Transaction w/ invalid scripts", - "exception": "Invalid script", - "incomplete": true, - "txHex": "010000000100000000171a0000e028f2000000000050178500000000000d0000000e000000000000002009f691b2263260e71f363d1db51ff3100d285956a40cc0e4f8c8c2c4a80559b1ffffffff0110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000" - }, - { - "description": "Complete transaction w/ non-standard inputs", - "exception": "Unknown input type", - "txHex": "010000000100000000171a0000e028f2000000000050178500000000000d0000000e00000000000000201ff691b2263260e71f363d1db51ff3100d285956a40cc0e4f8c8c2c4a80559b1ffffffff0110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000" - } - ], - "sign": [ - { - "description": "Transaction w/ witness value mismatch", - "exception": "Input did not match witnessValue", - "network": "testnet", - "inputs": [ - { - "txHex": "01000000000101f7e6430096cd2790bac115aaab22c0a50fb0a1794305302e1a399e81d8d354f40200000000feffffff0340420f00000000001600145c7b8d623fba952d2387703d051d8e931a6aa0a18bda2702000000001976a9145a0ef60784137d03e7868d063b05424f2f43799f88ac40420f00000000001976a9145c7b8d623fba952d2387703d051d8e931a6aa0a188ac0247304402205793a862d193264afc32713e2e14541e1ff9ebb647dd7e7e6a0051d0faa87de302205216653741ecbbed573ea2fc053209dd6980616701c27be5b958a159fc97f45a012103e877e7deb32d19250dcfe534ea82c99ad739800295cd5429a7f69e2896c36fcd2fcc0e00", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2wpkh", - "keyPair": "cQ6483mDWwoG8o4tn6nU9Jg52RKMjPUWXSY1vycAyPRXQJ1Pn2Rq", - "throws": true, - "value": 22500000000 - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 ff99e06c1a4ac394b4e1cb3d3a4b2b47749e339a OP_EQUALVERIFY OP_CHECKSIG", - "value": 6000000 - } - ] - }, - { - "description": "Too many signatures - P2PKH", - "exception": "Signature already exists", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - }, - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Transaction w/ P2WPKH, signing with uncompressed public key", - "exception": "BIP143 rejects uncompressed public keys in P2WPKH or P2WSH", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_0 15a71ffa7b5bb70cddefcf364494071022efe390", - "signs": [ - { - "prevOutScriptType": "p2wpkh", - "keyPair": "5JiHJJjdufSiMxbvnyNcKtQNLYH6SvUpQnRv9yZENFDWTQKQkzC", - "value": 10000, - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_0 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", - "value": 10000 - } - ] - }, - { - "description": "Transaction w/ P2WSH(P2PK), signing with uncompressed public key", - "exception": "redeem.input or redeem.output contains uncompressed pubkey", - "inputs": [ - { - "txId": "2fddebc1a7e67e04fc6b77645ae9ae10eeaa35e168606587d79b031ebca33345", - "vout": 0, - "prevTxScript": "OP_0 5339df4de3854c4208376443ed075014ad996aa349ad6b5abf6c4d20f604d348", - "signs": [ - { - "prevOutScriptType": "p2wsh-p2pk", - "keyPair": "5JiHJJjdufSiMxbvnyNcKtQNLYH6SvUpQnRv9yZENFDWTQKQkzC", - "witnessScript": "04f56d09b32cefc818735150bf8560eefdaf30d2edb3fe557bf27682aedaed81bf9aaff7eeb496e088058ec548826c12b521dbb566a862d9b67677910c2b421e06 OP_CHECKSIG", - "value": 80000, - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG", - "value": 60000 - } - ] - }, - { - "description": "Transaction w/ P2SH(P2WSH(P2PK)), signing with uncompressed public key", - "exception": "redeem.input or redeem.output contains uncompressed pubkey", - "inputs": [ - { - "txId": "2fddebc1a7e67e04fc6b77645ae9ae10eeaa35e168606587d79b031ebca33345", - "vout": 0, - "prevTxScript": "OP_HASH160 5afe12b2827e3eac05fe3f17c59406ef262aa177 OP_EQUAL", - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2pk", - "keyPair": "5JiHJJjdufSiMxbvnyNcKtQNLYH6SvUpQnRv9yZENFDWTQKQkzC", - "redeemScript": "OP_0 5339df4de3854c4208376443ed075014ad996aa349ad6b5abf6c4d20f604d348", - "witnessScript": "04f56d09b32cefc818735150bf8560eefdaf30d2edb3fe557bf27682aedaed81bf9aaff7eeb496e088058ec548826c12b521dbb566a862d9b67677910c2b421e06 OP_CHECKSIG", - "value": 80000, - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 851a33a5ef0d4279bd5854949174e2c65b1d4500 OP_EQUALVERIFY OP_CHECKSIG", - "value": 60000 - } - ] - }, - { - "exception": "nulldata not supported as redeemScript \\(OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474\\)", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2pk", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "redeemScript": "OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "exception": "p2sh-p2pkh requires redeemScript", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "prevTxScript": "OP_HASH160 7f67f0521934a57d3039f77f9f32cf313f3ac74b OP_EQUAL", - "signs": [ - { - "prevOutScriptType": "p2sh-p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "exception": "p2wsh-p2pk requires witnessScript", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "prevTxScript": "OP_0 0f9ea7bae7166c980169059e39443ed13324495b0d6678ce716262e879591210", - "signs": [ - { - "prevOutScriptType": "p2wsh-p2pk", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "exception": "Inconsistent redeemScript", - "network": "testnet", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Inconsistent RedeemScript hash", - "exception": "Redeem script inconsistent with prevOutScript", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_HASH160 ffffffffffffffffffffffffffffffffffffffff OP_EQUAL", - "signs": [ - { - "prevOutScriptType": "p2sh-p2pkh", - "keyPair": "5JiHJJjdufSiMxbvnyNcKtQNLYH6SvUpQnRv9yZENFDWTQKQkzC", - "redeemScript": "OP_1", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_0 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", - "value": 10000 - } - ] - }, - { - "description": "Inconsistent WitnessScript hash", - "exception": "Witness script inconsistent with prevOutScript", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_0 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "signs": [ - { - "prevOutScriptType": "p2wsh-p2pkh", - "keyPair": "5JiHJJjdufSiMxbvnyNcKtQNLYH6SvUpQnRv9yZENFDWTQKQkzC", - "witnessScript": "OP_1", - "value": 10000, - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_0 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", - "value": 10000 - } - ] - }, - { - "exception": "scripthash not supported as redeemScript \\(OP_HASH160 7f67f0521934a57d3039f77f9f32cf313f3ac74b OP_EQUAL\\)", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "redeemScript": "OP_HASH160 7f67f0521934a57d3039f77f9f32cf313f3ac74b OP_EQUAL", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2sh-p2pkh: pubkeyhash", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "prevTxScript": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "signs": [ - { - "prevOutScriptType": "p2sh-p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Too many signatures - P2SH(P2MS 1/1)", - "exception": "Signature already exists", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", - "redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG" - }, - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", - "redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Wrong network for keyPair", - "exception": "Inconsistent network", - "network": "bitcoin", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx", - "network": "testnet", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "description": "Wrong key pair for P2MS redeemScript", - "exception": "Key pair cannot sign for this input", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2sh-p2ms", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2pkh: nulldata", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474", - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2pk: nulldata", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN deadbeef", - "signs": [ - { - "prevOutScriptType": "p2pk", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_RETURN deadbeef", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2wpkh: nulldata", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN deadbeef", - "signs": [ - { - "prevOutScriptType": "p2wpkh", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_RETURN deadbeef", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2ms: nulldata", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN deadbeef", - "signs": [ - { - "prevOutScriptType": "p2ms", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_RETURN deadbeef", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2sh-p2wpkh: nulldata", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN deadbeef", - "signs": [ - { - "prevOutScriptType": "p2sh-p2wpkh", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_RETURN deadbeef", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2sh-p2pk: nulldata", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN deadbeef", - "signs": [ - { - "prevOutScriptType": "p2sh-p2pk", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_RETURN deadbeef", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2wsh-p2pk: nulldata", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN deadbeef", - "signs": [ - { - "prevOutScriptType": "p2wsh-p2pk", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_RETURN deadbeef", - "value": 1000 - } - ] - }, - { - "exception": "input #0 is not of type p2sh-p2wsh-p2pk: nulldata", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN deadbeef", - "signs": [ - { - "prevOutScriptType": "p2sh-p2wsh-p2pk", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_RETURN deadbeef", - "value": 1000 - } - ] - }, - { - "exception": "Unknown prevOutScriptType \"notvalidtype\"", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "prevTxScript": "OP_RETURN deadbeef", - "signs": [ - { - "prevOutScriptType": "notvalidtype", - "keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", - "throws": true - } - ] - } - ], - "outputs": [ - { - "script": "OP_RETURN deadbeef", - "value": 1000 - } - ] - }, - { - "description": "Transaction w/ no outputs (but 1 SIGHASH_NONE)", - "exception": "Transaction needs outputs", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "hashType": 2 - } - ] - }, - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 1, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "throws": true - } - ] - } - ], - "outputs": [] - }, - { - "description": "Transaction w/ no outputs", - "exception": "Transaction needs outputs", - "inputs": [ - { - "txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "vout": 0, - "signs": [ - { - "prevOutScriptType": "p2pkh", - "keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", - "throws": true - } - ] - } - ], - "outputs": [] - } - ], - "fromTransaction": [ - { - "exception": "coinbase inputs not supported", - "txHex": "01000000010000000000000000000000000000000000000000000000000000000000000000000000006b483045022100a3b254e1c10b5d039f36c05f323995d6e5a367d98dd78a13d5bbc3991b35720e022022fccea3897d594de0689601fbd486588d5bfa6915be2386db0397ee9a6e80b601210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff0110270000000000001976a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00000000" - } - ] - } -} diff --git a/test/transaction_builder.spec.ts b/test/transaction_builder.spec.ts deleted file mode 100644 index b07462e..0000000 --- a/test/transaction_builder.spec.ts +++ /dev/null @@ -1,1001 +0,0 @@ -import * as assert from 'assert'; -import { beforeEach, describe, it } from 'mocha'; -import { - ECPair, - networks as NETWORKS, - Transaction, - TransactionBuilder, -} from '..'; -import * as baddress from '../src/address'; -import * as payments from '../src/payments'; -import * as bscript from '../src/script'; - -console.warn = (): void => { - return; -}; // Silence the Deprecation Warning - -import * as fixtures from './fixtures/transaction_builder.json'; - -function constructSign( - f: any, - txb: any, - useOldSignArgs: any, -): TransactionBuilder { - const network = (NETWORKS as any)[f.network]; - const stages = f.stages && f.stages.concat(); - - f.inputs.forEach((input: any, index: number) => { - if (!input.signs) return; - input.signs.forEach((sign: any) => { - const keyPair = ECPair.fromWIF(sign.keyPair, network); - let redeemScript; - let witnessScript; - let witnessValue; - - if (sign.redeemScript) { - redeemScript = bscript.fromASM(sign.redeemScript); - } - - if (sign.value) { - witnessValue = sign.value; - } - - if (sign.witnessScript) { - witnessScript = bscript.fromASM(sign.witnessScript); - } - - if (useOldSignArgs) { - // DEPRECATED: v6 will remove this interface - txb.sign( - index, - keyPair, - redeemScript, - sign.hashType, - witnessValue, - witnessScript, - ); - } else { - // prevOutScriptType is required, see /ts_src/transaction_builder.ts - // The PREVOUT_TYPES constant is a Set with all possible values. - txb.sign({ - prevOutScriptType: sign.prevOutScriptType, - vin: index, - keyPair, - redeemScript, - hashType: sign.hashType, - witnessValue, - witnessScript, - }); - } - - if (sign.stage) { - const tx = txb.buildIncomplete(); - assert.strictEqual(tx.toHex(), stages.shift()); - txb = TransactionBuilder.fromTransaction(tx, network); - } - }); - }); - - return txb; -} - -function construct( - f: any, - dontSign?: any, - useOldSignArgs?: any, -): TransactionBuilder { - const network = (NETWORKS as any)[f.network]; - const txb = new TransactionBuilder(network); - - if (Number.isFinite(f.version)) txb.setVersion(f.version); - if (f.locktime !== undefined) txb.setLockTime(f.locktime); - - f.inputs.forEach((input: any) => { - let prevTx; - if (input.txRaw) { - const constructed = construct(input.txRaw); - if (input.txRaw.incomplete) prevTx = constructed.buildIncomplete(); - else prevTx = constructed.build(); - } else if (input.txHex) { - prevTx = Transaction.fromHex(input.txHex); - } else { - prevTx = input.txId; - } - - let prevTxScript; - if (input.prevTxScript) { - prevTxScript = bscript.fromASM(input.prevTxScript); - } - - txb.addInput(prevTx, input.vout, input.sequence, prevTxScript); - }); - - f.outputs.forEach((output: any) => { - if (output.address) { - txb.addOutput(output.address, output.value); - } else { - txb.addOutput(bscript.fromASM(output.script), output.value); - } - }); - - if (dontSign) return txb; - return constructSign(f, txb, useOldSignArgs); -} - -// TODO: Remove loop in v6 -for (const useOldSignArgs of [false, true]) { - // Search for "useOldSignArgs" - // to find the second part of this console.warn replace - let consoleWarn: any; - if (useOldSignArgs) { - consoleWarn = console.warn; - // Silence console.warn during these tests - console.warn = (): undefined => undefined; - } - describe(`TransactionBuilder: useOldSignArgs === ${useOldSignArgs}`, () => { - // constants - const keyPair = ECPair.fromPrivateKey( - Buffer.from( - '0000000000000000000000000000000000000000000000000000000000000001', - 'hex', - ), - ); - const scripts = [ - '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH', - '1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP', - ].map(x => { - return baddress.toOutputScript(x); - }); - const txHash = Buffer.from( - '0e7cea811c0be9f73c0aca591034396e7264473fc25c1ca45195d7417b36cbe2', - 'hex', - ); - - describe('fromTransaction', () => { - fixtures.valid.build.forEach(f => { - it('returns TransactionBuilder, with ' + f.description, () => { - const network = (NETWORKS as any)[f.network || 'bitcoin']; - - const tx = Transaction.fromHex(f.txHex); - const txb = TransactionBuilder.fromTransaction(tx, network); - const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build(); - - assert.strictEqual(txAfter.toHex(), f.txHex); - assert.strictEqual(txb.network, network); - }); - }); - - fixtures.valid.fromTransaction.forEach(f => { - it('returns TransactionBuilder, with ' + f.description, () => { - const tx = new Transaction(); - - f.inputs.forEach(input => { - const txHash2 = Buffer.from(input.txId, 'hex').reverse() as Buffer; - - tx.addInput( - txHash2, - input.vout, - undefined, - bscript.fromASM(input.scriptSig), - ); - }); - - f.outputs.forEach(output => { - tx.addOutput(bscript.fromASM(output.script), output.value); - }); - - const txb = TransactionBuilder.fromTransaction(tx); - const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build(); - - txAfter.ins.forEach((input, i) => { - assert.strictEqual( - bscript.toASM(input.script), - f.inputs[i].scriptSigAfter, - ); - }); - - txAfter.outs.forEach((output, i) => { - assert.strictEqual( - bscript.toASM(output.script), - f.outputs[i].script, - ); - }); - }); - }); - - fixtures.valid.fromTransactionSequential.forEach(f => { - it('with ' + f.description, () => { - const network = (NETWORKS as any)[f.network]; - const tx = Transaction.fromHex(f.txHex); - const txb = TransactionBuilder.fromTransaction(tx, network); - - tx.ins.forEach((input, i) => { - assert.strictEqual( - bscript.toASM(input.script), - f.inputs[i].scriptSig, - ); - }); - - constructSign(f, txb, useOldSignArgs); - const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build(); - - txAfter.ins.forEach((input, i) => { - assert.strictEqual( - bscript.toASM(input.script), - f.inputs[i].scriptSigAfter, - ); - }); - - assert.strictEqual(txAfter.toHex(), f.txHexAfter); - }); - }); - - it('classifies transaction inputs', () => { - const tx = Transaction.fromHex(fixtures.valid.classification.hex); - const txb = TransactionBuilder.fromTransaction(tx); - - (txb as any).__INPUTS.forEach((i: any) => { - assert.strictEqual(i.prevOutType, 'scripthash'); - assert.strictEqual(i.redeemScriptType, 'multisig'); - }); - }); - - fixtures.invalid.fromTransaction.forEach(f => { - it('throws ' + f.exception, () => { - const tx = Transaction.fromHex(f.txHex); - - assert.throws(() => { - TransactionBuilder.fromTransaction(tx); - }, new RegExp(f.exception)); - }); - }); - }); - - describe('addInput', () => { - let txb: TransactionBuilder; - beforeEach(() => { - txb = new TransactionBuilder(); - }); - - it('accepts a txHash, index [and sequence number]', () => { - const vin = txb.addInput(txHash, 1, 54); - assert.strictEqual(vin, 0); - - const txIn = (txb as any).__TX.ins[0]; - assert.strictEqual(txIn.hash, txHash); - assert.strictEqual(txIn.index, 1); - assert.strictEqual(txIn.sequence, 54); - assert.strictEqual((txb as any).__INPUTS[0].prevOutScript, undefined); - }); - - it('accepts a txHash, index [, sequence number and scriptPubKey]', () => { - const vin = txb.addInput(txHash, 1, 54, scripts[1]); - assert.strictEqual(vin, 0); - - const txIn = (txb as any).__TX.ins[0]; - assert.strictEqual(txIn.hash, txHash); - assert.strictEqual(txIn.index, 1); - assert.strictEqual(txIn.sequence, 54); - assert.strictEqual((txb as any).__INPUTS[0].prevOutScript, scripts[1]); - }); - - it('accepts a prevTx, index [and sequence number]', () => { - const prevTx = new Transaction(); - prevTx.addOutput(scripts[0], 0); - prevTx.addOutput(scripts[1], 1); - - const vin = txb.addInput(prevTx, 1, 54); - assert.strictEqual(vin, 0); - - const txIn = (txb as any).__TX.ins[0]; - assert.deepStrictEqual(txIn.hash, prevTx.getHash()); - assert.strictEqual(txIn.index, 1); - assert.strictEqual(txIn.sequence, 54); - assert.strictEqual((txb as any).__INPUTS[0].prevOutScript, scripts[1]); - }); - - it('returns the input index', () => { - assert.strictEqual(txb.addInput(txHash, 0), 0); - assert.strictEqual(txb.addInput(txHash, 1), 1); - }); - - it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', () => { - txb.addInput(txHash, 0); - txb.addOutput(scripts[0], 1000); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - }); - - assert.throws(() => { - txb.addInput(txHash, 0); - }, /No, this would invalidate signatures/); - }); - }); - - describe('addOutput', () => { - let txb: TransactionBuilder; - beforeEach(() => { - txb = new TransactionBuilder(); - }); - - it('accepts an address string and value', () => { - const { address } = payments.p2pkh({ pubkey: keyPair.publicKey }); - const vout = txb.addOutput(address!, 1000); - assert.strictEqual(vout, 0); - - const txout = (txb as any).__TX.outs[0]; - assert.deepStrictEqual(txout.script, scripts[0]); - assert.strictEqual(txout.value, 1000); - }); - - it('accepts a ScriptPubKey and value', () => { - const vout = txb.addOutput(scripts[0], 1000); - assert.strictEqual(vout, 0); - - const txout = (txb as any).__TX.outs[0]; - assert.deepStrictEqual(txout.script, scripts[0]); - assert.strictEqual(txout.value, 1000); - }); - - it('throws if address is of the wrong network', () => { - assert.throws(() => { - txb.addOutput('2NGHjvjw83pcVFgMcA7QvSMh2c246rxLVz9', 1000); - }, /2NGHjvjw83pcVFgMcA7QvSMh2c246rxLVz9 has no matching Script/); - }); - - it('add second output after signed first input with SIGHASH_NONE', () => { - txb.addInput(txHash, 0); - txb.addOutput(scripts[0], 2000); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - hashType: Transaction.SIGHASH_NONE, - }); - assert.strictEqual(txb.addOutput(scripts[1], 9000), 1); - }); - - it('add first output after signed first input with SIGHASH_NONE', () => { - txb.addInput(txHash, 0); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - hashType: Transaction.SIGHASH_NONE, - }); - assert.strictEqual(txb.addOutput(scripts[0], 2000), 0); - }); - - it('add second output after signed first input with SIGHASH_SINGLE', () => { - txb.addInput(txHash, 0); - txb.addOutput(scripts[0], 2000); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - hashType: Transaction.SIGHASH_SINGLE, - }); - assert.strictEqual(txb.addOutput(scripts[1], 9000), 1); - }); - - it('add first output after signed first input with SIGHASH_SINGLE', () => { - txb.addInput(txHash, 0); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - hashType: Transaction.SIGHASH_SINGLE, - }); - assert.throws(() => { - txb.addOutput(scripts[0], 2000); - }, /No, this would invalidate signatures/); - }); - - it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', () => { - txb.addInput(txHash, 0); - txb.addOutput(scripts[0], 2000); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - }); - - assert.throws(() => { - txb.addOutput(scripts[1], 9000); - }, /No, this would invalidate signatures/); - }); - }); - - describe('setLockTime', () => { - it('throws if if there exist any scriptSigs', () => { - const txb = new TransactionBuilder(); - txb.addInput(txHash, 0); - txb.addOutput(scripts[0], 100); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - }); - - assert.throws(() => { - txb.setLockTime(65535); - }, /No, this would invalidate signatures/); - }); - }); - - describe('sign', () => { - it('supports the alternative abstract interface { publicKey, sign }', () => { - const innerKeyPair = { - publicKey: ECPair.makeRandom({ - rng: (): Buffer => { - return Buffer.alloc(32, 1); - }, - }).publicKey, - sign: (): Buffer => { - return Buffer.alloc(64, 0x5f); - }, - }; - - const txb = new TransactionBuilder(); - txb.setVersion(1); - txb.addInput( - 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - 1, - ); - txb.addOutput('1111111111111111111114oLvT2', 100000); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair: innerKeyPair, - }); - assert.strictEqual( - txb.build().toHex(), - '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + - 'ffffffff010000006a47304402205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f' + - '5f5f5f5f5f5f5f5f5f5f5f5f5f02205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f' + - '5f5f5f5f5f5f5f5f5f5f5f5f5f5f0121031b84c5567b126440995d3ed5aaba0565' + - 'd71e1834604819ff9c17f5e9d5dd078fffffffff01a0860100000000001976a914' + - '000000000000000000000000000000000000000088ac00000000', - ); - }); - - it('supports low R signature signing', () => { - let txb = new TransactionBuilder(); - txb.setVersion(1); - txb.addInput( - 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - 1, - ); - txb.addOutput('1111111111111111111114oLvT2', 100000); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - }); - // high R - assert.strictEqual( - txb.build().toHex(), - '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + - 'ffffffff010000006b483045022100b872677f35c9c14ad9c41d83649fb049250f' + - '32574e0b2547d67e209ed14ff05d022059b36ad058be54e887a1a311d5c393cb49' + - '41f6b93a0b090845ec67094de8972b01210279be667ef9dcbbac55a06295ce870b' + - '07029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a9' + - '14000000000000000000000000000000000000000088ac00000000', - ); - - txb = new TransactionBuilder(); - txb.setVersion(1); - txb.addInput( - 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - 1, - ); - txb.addOutput('1111111111111111111114oLvT2', 100000); - txb.setLowR(); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - }); - // low R - assert.strictEqual( - txb.build().toHex(), - '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + - 'ffffffff010000006a473044022012a601efa8756ebe83e9ac7a7db061c3147e3b' + - '49d8be67685799fe51a4c8c62f02204d568d301d5ce14af390d566d4fd50e7b8ee' + - '48e71ec67786c029e721194dae3601210279be667ef9dcbbac55a06295ce870b07' + - '029bfcdb2dce28d959f2815b16f81798ffffffff01a0860100000000001976a914' + - '000000000000000000000000000000000000000088ac00000000', - ); - }); - - it('fails when missing required arguments', () => { - const txb = new TransactionBuilder(); - txb.setVersion(1); - txb.addInput( - 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - 1, - ); - txb.addOutput('1111111111111111111114oLvT2', 100000); - assert.throws(() => { - (txb as any).sign(); - }, /TransactionBuilder sign first arg must be TxbSignArg or number/); - assert.throws(() => { - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 1, - keyPair, - }); - }, /No input at index: 1/); - assert.throws(() => { - (txb as any).sign({ - prevOutScriptType: 'p2pkh', - keyPair, - }); - }, /sign must include vin parameter as Number \(input index\)/); - assert.throws(() => { - (txb as any).sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair: {}, - }); - }, /sign must include keyPair parameter as Signer interface/); - assert.throws(() => { - (txb as any).sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair, - hashType: 'string', - }); - }, /sign hashType parameter must be a number/); - if (useOldSignArgs) { - assert.throws(() => { - txb.sign(0); - }, /sign requires keypair/); - } - }); - - fixtures.invalid.sign.forEach(f => { - it( - 'throws ' + - f.exception + - (f.description ? ' (' + f.description + ')' : ''), - () => { - const txb = construct(f, true); - - let threw = false; - (f.inputs as any).forEach( - (input: any, index: number): void => { - input.signs.forEach((sign: any) => { - const keyPairNetwork = (NETWORKS as any)[ - sign.network || f.network - ]; - const keyPair2 = ECPair.fromWIF(sign.keyPair, keyPairNetwork); - let redeemScript: Buffer | undefined; - let witnessScript: Buffer | undefined; - - if (sign.redeemScript) { - redeemScript = bscript.fromASM(sign.redeemScript); - } - - if (sign.witnessScript) { - witnessScript = bscript.fromASM(sign.witnessScript); - } - - if (sign.throws) { - assert.throws(() => { - txb.sign({ - prevOutScriptType: sign.prevOutScriptType, - vin: index, - keyPair: keyPair2, - redeemScript, - hashType: sign.hashType, - witnessValue: sign.value, - witnessScript, - }); - }, new RegExp(f.exception)); - threw = true; - } else { - txb.sign({ - prevOutScriptType: sign.prevOutScriptType, - vin: index, - keyPair: keyPair2, - redeemScript, - hashType: sign.hashType, - witnessValue: sign.value, - witnessScript, - }); - } - }); - }, - ); - - assert.strictEqual(threw, true); - }, - ); - }); - }); - - describe('build', () => { - fixtures.valid.build.forEach(f => { - it('builds "' + f.description + '"', () => { - const txb = construct(f, undefined, useOldSignArgs); - const tx = f.incomplete ? txb.buildIncomplete() : txb.build(); - - assert.strictEqual(tx.toHex(), f.txHex); - }); - }); - - // TODO: remove duplicate test code - fixtures.invalid.build.forEach(f => { - describe('for ' + (f.description || f.exception), () => { - it('throws ' + f.exception, () => { - assert.throws(() => { - let txb; - if (f.txHex) { - txb = TransactionBuilder.fromTransaction( - Transaction.fromHex(f.txHex), - ); - } else { - txb = construct(f, undefined, useOldSignArgs); - } - - txb.build(); - }, new RegExp(f.exception)); - }); - - // if throws on incomplete too, enforce that - if (f.incomplete) { - it('throws ' + f.exception, () => { - assert.throws(() => { - let txb; - if (f.txHex) { - txb = TransactionBuilder.fromTransaction( - Transaction.fromHex(f.txHex), - ); - } else { - txb = construct(f, undefined, useOldSignArgs); - } - - txb.buildIncomplete(); - }, new RegExp(f.exception)); - }); - } else { - it('does not throw if buildIncomplete', () => { - let txb; - if (f.txHex) { - txb = TransactionBuilder.fromTransaction( - Transaction.fromHex(f.txHex), - ); - } else { - txb = construct(f, undefined, useOldSignArgs); - } - - txb.buildIncomplete(); - }); - } - }); - }); - - it('for incomplete with 0 signatures', () => { - const randomTxData = - '010000000001010001000000000000000000000000000000000000000000000000' + - '0000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4' + - '207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2' + - 'c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f7' + - '4d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d345102' + - '5c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000'; - const randomAddress = '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'; - - const randomTx = Transaction.fromHex(randomTxData); - const txb = new TransactionBuilder(); - txb.addInput(randomTx, 0); - txb.addOutput(randomAddress, 1000); - const tx = txb.buildIncomplete(); - assert(tx); - }); - - it('for incomplete P2SH with 0 signatures', () => { - const inp = Buffer.from( - '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be9' + - '59391c100000000000ffffffff0100c817a80400000017a91471a8ec07ff69c6c4' + - 'fee489184c462a9b1b9237488700000000', - 'hex', - ); // arbitrary P2SH input - const inpTx = Transaction.fromBuffer(inp); - - const txb = new TransactionBuilder(NETWORKS.testnet); - txb.addInput(inpTx, 0); - txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8); // arbitrary output - - txb.buildIncomplete(); - }); - - it('for incomplete P2WPKH with 0 signatures', () => { - const inp = Buffer.from( - '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be9' + - '59391c100000000000ffffffff0100c817a8040000001600141a15805e1f4040c9' + - 'f68ccc887fca2e63547d794b00000000', - 'hex', - ); - const inpTx = Transaction.fromBuffer(inp); - - const txb = new TransactionBuilder(NETWORKS.testnet); - txb.addInput(inpTx, 0); - txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8); // arbitrary output - - txb.buildIncomplete(); - }); - - it('for incomplete P2WSH with 0 signatures', () => { - const inpTx = Transaction.fromBuffer( - Buffer.from( - '010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80b' + - 'e959391c100000000000ffffffff0100c817a80400000022002072df76fcc0b2' + - '31b94bdf7d8c25d7eef4716597818d211e19ade7813bff7a250200000000', - 'hex', - ), - ); - - const txb = new TransactionBuilder(NETWORKS.testnet); - txb.addInput(inpTx, 0); - txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8); // arbitrary output - - txb.buildIncomplete(); - }); - }); - - describe('multisig', () => { - fixtures.valid.multisig.forEach(f => { - it(f.description, () => { - const network = (NETWORKS as any)[f.network]; - let txb = construct(f, true); - let tx: Transaction; - - f.inputs.forEach((input, i) => { - const redeemScript = bscript.fromASM(input.redeemScript); - - input.signs.forEach(sign => { - // rebuild the transaction each-time after the first - if (tx) { - // manually override the scriptSig? - if (sign.scriptSigBefore) { - tx.ins[i].script = bscript.fromASM(sign.scriptSigBefore); - } - - // rebuild - txb = TransactionBuilder.fromTransaction(tx, network); - } - - const keyPair2 = ECPair.fromWIF(sign.keyPair, network); - txb.sign({ - prevOutScriptType: sign.prevOutScriptType, - vin: i, - keyPair: keyPair2, - redeemScript, - hashType: (sign as any).hashType, - }); - - // update the tx - tx = txb.buildIncomplete(); - - // now verify the serialized scriptSig is as expected - assert.strictEqual( - bscript.toASM(tx.ins[i].script), - sign.scriptSig, - ); - }); - }); - - tx = txb.build(); - assert.strictEqual(tx.toHex(), f.txHex); - }); - }); - }); - - describe('various edge case', () => { - const network = NETWORKS.testnet; - - it('should warn of high fee for segwit transaction based on VSize, not Size', () => { - const rawtx = - '01000000000104fdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a' + - '1df90000000000fffffffffdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a1df9' + - '0100000000ffffffffa2ef7aaab316a3e5b5b0a78d1d35c774b95a079f9f0c762277a49caf1f26bca40000' + - '000000ffffffffa2ef7aaab316a3e5b5b0a78d1d35c774b95a079f9f0c762277a49caf1f26bca401000000' + - '00ffffffff0100040000000000001976a914cf307285359ab7ef6a2daa0522c7908ddf5fe7a988ac024730' + - '440220113324438816338406841775e079b04c50d04f241da652a4035b1017ea1ecf5502205802191eb49c' + - '54bf2a5667aea72e51c3ca92085efc60f12d1ebda3a64aff343201210283409659355b6d1cc3c32decd5d5' + - '61abaac86c37a353b52895a5e6c196d6f44802483045022100dc2892874e6d8708e3f5a058c5c9263cdf03' + - '969492270f89ee4933caf6daf8bb0220391dfe61a002709b63b9d64422d3db09b727839d1287e10a128a5d' + - 'b52a82309301210283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f448024830' + - '450221009e3ed3a6ae93a018f443257b43e47b55cf7f7f3547d8807178072234686b22160220576121cfe6' + - '77c7eddf5575ea0a7c926247df6eca723c4f85df306e8bc08ea2df01210283409659355b6d1cc3c32decd5' + - 'd561abaac86c37a353b52895a5e6c196d6f44802473044022007be81ffd4297441ab10e740fc9bab9545a2' + - '194a565cd6aa4cc38b8eaffa343402201c5b4b61d73fa38e49c1ee68cc0e6dfd2f5dae453dd86eb142e87a' + - '0bafb1bc8401210283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f44800000000'; - const txb = TransactionBuilder.fromTransaction( - Transaction.fromHex(rawtx), - ); - (txb as any).__INPUTS[0].value = 241530; - (txb as any).__INPUTS[1].value = 241530; - (txb as any).__INPUTS[2].value = 248920; - (txb as any).__INPUTS[3].value = 248920; - - assert.throws(() => { - txb.build(); - }, new RegExp('Transaction has absurd fees')); - }); - - it('should classify witness inputs with witness = true during multisigning', () => { - const innerKeyPair = ECPair.fromWIF( - 'cRAwuVuVSBZMPu7hdrYvMCZ8eevzmkExjFbaBLhqnDdrezxN3nTS', - network, - ); - const witnessScript = Buffer.from( - '522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e3' + - '52e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532' + - 'b9ea1952ae', - 'hex', - ); - const redeemScript = Buffer.from( - '002024376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5af', - 'hex', - ); - const scriptPubKey = Buffer.from( - 'a914b64f1a3eacc1c8515592a6f10457e8ff90e4db6a87', - 'hex', - ); - const txb = new TransactionBuilder(network); - txb.setVersion(1); - txb.addInput( - 'a4696c4b0cd27ec2e173ab1fa7d1cc639a98ee237cec95a77ca7ff4145791529', - 1, - 0xffffffff, - scriptPubKey, - ); - txb.addOutput(scriptPubKey, 99000); - txb.sign({ - prevOutScriptType: 'p2sh-p2wsh-p2ms', - vin: 0, - keyPair: innerKeyPair, - redeemScript, - witnessValue: 100000, - witnessScript, - }); - - // 2-of-2 signed only once - const tx = txb.buildIncomplete(); - - // Only input is segwit, so txid should be accurate with the final tx - assert.strictEqual( - tx.getId(), - 'f15d0a65b21b4471405b21a099f8b18e1ae4d46d55efbd0f4766cf11ad6cb821', - ); - - const txHex = tx.toHex(); - TransactionBuilder.fromTransaction(Transaction.fromHex(txHex)); - }); - - it('should handle badly pre-filled OP_0s', () => { - // OP_0 is used where a signature is missing - const redeemScripSig = bscript.fromASM( - 'OP_0 OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17' + - 'be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621eb' + - 'd9691d6b48c0d4283d7d01 52410479be667ef9dcbbac55a06295ce870b07029bf' + - 'cdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b44' + - '8a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778' + - 'e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f6326' + - '53266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c' + - '845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99' + - '934c2231b6cb9fd7584b8e67253ae', - ); - const redeemScript = bscript.fromASM( - 'OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f' + - '81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d' + - '4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c70' + - '9ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe5' + - '2a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce03' + - '6f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67' + - '2 OP_3 OP_CHECKMULTISIG', - ); - - const tx = new Transaction(); - tx.addInput( - Buffer.from( - 'cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f07149', - 'hex', - ), - 0, - undefined, - redeemScripSig, - ); - tx.addOutput( - Buffer.from( - '76a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac', - 'hex', - ), - 1000, - ); - - // now import the Transaction - const txb = TransactionBuilder.fromTransaction(tx, NETWORKS.testnet); - - const keyPair2 = ECPair.fromWIF( - '91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe', - network, - ); - txb.sign({ - prevOutScriptType: 'p2sh-p2ms', - vin: 0, - keyPair: keyPair2, - redeemScript, - }); - - const tx2 = txb.build(); - assert.strictEqual( - tx2.getId(), - 'eab59618a564e361adef6d918bd792903c3d41bcf1220137364fb847880467f9', - ); - assert.strictEqual( - bscript.toASM(tx2.ins[0].script), - 'OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b' + - '63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691' + - 'd6b48c0d4283d7d01 3045022100a346c61738304eac5e7702188764d19cdf68f4' + - '466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881' + - 'd7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870' + - 'b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a' + - '8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07' + - 'cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceae' + - 'ef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5' + - '229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f35' + - '66500a99934c2231b6cb9fd7584b8e67253ae', - ); - }); - - it('should not classify blank scripts as nonstandard', () => { - let txb = new TransactionBuilder(); - txb.setVersion(1); - txb.addInput( - 'aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31', - 0, - ); - - const incomplete = txb.buildIncomplete().toHex(); - const innerKeyPair = ECPair.fromWIF( - 'L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy', - ); - - // sign, as expected - txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair: innerKeyPair, - }); - const txId = txb.build().getId(); - assert.strictEqual( - txId, - '54f097315acbaedb92a95455da3368eb45981cdae5ffbc387a9afc872c0f29b3', - ); - - // and, repeat - txb = TransactionBuilder.fromTransaction( - Transaction.fromHex(incomplete), - ); - txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000); - txb.sign({ - prevOutScriptType: 'p2pkh', - vin: 0, - keyPair: innerKeyPair, - }); - const txId2 = txb.build().getId(); - assert.strictEqual(txId, txId2); - // TODO: Remove me in v6 - if (useOldSignArgs) { - console.warn = consoleWarn; - } - }); - }); - }); -} diff --git a/ts_src/index.ts b/ts_src/index.ts index b9aa49c..c425d96 100644 --- a/ts_src/index.ts +++ b/ts_src/index.ts @@ -12,7 +12,6 @@ export { Block } from './block'; export { Psbt, PsbtTxInput, PsbtTxOutput } from './psbt'; export { OPS as opcodes } from './script'; export { Transaction } from './transaction'; -export { TransactionBuilder } from './transaction_builder'; export { BIP32Interface } from 'bip32'; export { ECPairInterface, Signer, SignerAsync } from './ecpair'; diff --git a/ts_src/psbt.ts b/ts_src/psbt.ts index c55e6bc..d5eb9f9 100644 --- a/ts_src/psbt.ts +++ b/ts_src/psbt.ts @@ -117,8 +117,7 @@ export class Psbt { __NON_WITNESS_UTXO_BUF_CACHE: [], __TX_IN_CACHE: {}, __TX: (this.data.globalMap.unsignedTx as PsbtTransaction).tx, - // Old TransactionBuilder behavior was to not confirm input values - // before signing. Even though we highly encourage people to get + // Even though we highly encourage people to get // the full parent transaction to verify values, the ability to // sign non-segwit inputs without the full transaction was often // requested. So the only way to activate is to use @ts-ignore. @@ -1295,8 +1294,7 @@ function getHashForSig( console.warn( 'Warning: Signing non-segwit inputs without the full parent transaction ' + 'means there is a chance that a miner could feed you incorrect information ' + - 'to trick you into paying large fees. This behavior is the same as the old ' + - 'TransactionBuilder class when signing non-segwit scripts. You are not ' + + 'to trick you into paying large fees. You are not ' + 'able to export this Psbt with toBuffer|toBase64|toHex since it is not ' + 'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' + '*********************', diff --git a/ts_src/transaction_builder.ts b/ts_src/transaction_builder.ts deleted file mode 100644 index 1edf0f2..0000000 --- a/ts_src/transaction_builder.ts +++ /dev/null @@ -1,1318 +0,0 @@ -import * as baddress from './address'; -import { reverseBuffer } from './bufferutils'; -import * as classify from './classify'; -import * as bcrypto from './crypto'; -import { Signer } from './ecpair'; -import * as ECPair from './ecpair'; -import { Network } from './networks'; -import * as networks from './networks'; -import { Payment } from './payments'; -import * as payments from './payments'; -import * as bscript from './script'; -import { OPS as ops } from './script'; -import { Output, Transaction } from './transaction'; -import * as types from './types'; -const typeforce = require('typeforce'); - -const SCRIPT_TYPES = classify.types; - -const PREVOUT_TYPES: Set = new Set([ - // Raw - 'p2pkh', - 'p2pk', - 'p2wpkh', - 'p2ms', - // P2SH wrapped - 'p2sh-p2pkh', - 'p2sh-p2pk', - 'p2sh-p2wpkh', - 'p2sh-p2ms', - // P2WSH wrapped - 'p2wsh-p2pkh', - 'p2wsh-p2pk', - 'p2wsh-p2ms', - // P2SH-P2WSH wrapper - 'p2sh-p2wsh-p2pkh', - 'p2sh-p2wsh-p2pk', - 'p2sh-p2wsh-p2ms', -]); - -type MaybeBuffer = Buffer | undefined; -type TxbSignatures = Buffer[] | MaybeBuffer[]; -type TxbPubkeys = MaybeBuffer[]; -type TxbWitness = Buffer[]; -type TxbScriptType = string; -type TxbScript = Buffer; - -interface TxbInput { - value?: number; - hasWitness?: boolean; - signScript?: TxbScript; - signType?: TxbScriptType; - prevOutScript?: TxbScript; - redeemScript?: TxbScript; - redeemScriptType?: TxbScriptType; - prevOutType?: TxbScriptType; - pubkeys?: TxbPubkeys; - signatures?: TxbSignatures; - witness?: TxbWitness; - witnessScript?: TxbScript; - witnessScriptType?: TxbScriptType; - script?: TxbScript; - sequence?: number; - scriptSig?: TxbScript; - maxSignatures?: number; -} - -interface TxbOutput { - type: string; - pubkeys?: TxbPubkeys; - signatures?: TxbSignatures; - maxSignatures?: number; -} - -interface TxbSignArg { - prevOutScriptType: string; - vin: number; - keyPair: Signer; - redeemScript?: Buffer; - hashType?: number; - witnessValue?: number; - witnessScript?: Buffer; -} - -function tfMessage(type: any, value: any, message: string): void { - try { - typeforce(type, value); - } catch (err) { - throw new Error(message); - } -} - -function txIsString(tx: Buffer | string | Transaction): tx is string { - return typeof tx === 'string' || tx instanceof String; -} - -function txIsTransaction(tx: Buffer | string | Transaction): tx is Transaction { - return tx instanceof Transaction; -} - -export class TransactionBuilder { - static fromTransaction( - transaction: Transaction, - network?: Network, - ): TransactionBuilder { - const txb = new TransactionBuilder(network); - - // Copy transaction fields - txb.setVersion(transaction.version); - txb.setLockTime(transaction.locktime); - - // Copy outputs (done first to avoid signature invalidation) - transaction.outs.forEach(txOut => { - txb.addOutput(txOut.script, (txOut as Output).value); - }); - - // Copy inputs - transaction.ins.forEach(txIn => { - txb.__addInputUnsafe(txIn.hash, txIn.index, { - sequence: txIn.sequence, - script: txIn.script, - witness: txIn.witness, - }); - }); - - // fix some things not possible through the public API - txb.__INPUTS.forEach((input, i) => { - fixMultisigOrder(input, transaction, i); - }); - - return txb; - } - - private __PREV_TX_SET: { [index: string]: boolean }; - private __INPUTS: TxbInput[]; - private __TX: Transaction; - private __USE_LOW_R: boolean; - - // WARNING: maximumFeeRate is __NOT__ to be relied on, - // it's just another potential safety mechanism (safety in-depth) - constructor( - public network: Network = networks.bitcoin, - public maximumFeeRate: number = 2500, - ) { - this.__PREV_TX_SET = {}; - this.__INPUTS = []; - this.__TX = new Transaction(); - this.__TX.version = 2; - this.__USE_LOW_R = false; - console.warn( - 'Deprecation Warning: TransactionBuilder will be removed in the future. ' + - '(v6.x.x or later) Please use the Psbt class instead. Examples of usage ' + - 'are available in the transactions-psbt.js integration test file on our ' + - 'Github. A high level explanation is available in the psbt.ts and psbt.js ' + - 'files as well.', - ); - } - - setLowR(setting?: boolean): boolean { - typeforce(typeforce.maybe(typeforce.Boolean), setting); - if (setting === undefined) { - setting = true; - } - this.__USE_LOW_R = setting; - return setting; - } - - setLockTime(locktime: number): void { - typeforce(types.UInt32, locktime); - - // if any signatures exist, throw - if ( - this.__INPUTS.some(input => { - if (!input.signatures) return false; - - return input.signatures.some(s => s !== undefined); - }) - ) { - throw new Error('No, this would invalidate signatures'); - } - - this.__TX.locktime = locktime; - } - - setVersion(version: number): void { - typeforce(types.UInt32, version); - - // XXX: this might eventually become more complex depending on what the versions represent - this.__TX.version = version; - } - - addInput( - txHash: Buffer | string | Transaction, - vout: number, - sequence?: number, - prevOutScript?: Buffer, - ): number { - if (!this.__canModifyInputs()) { - throw new Error('No, this would invalidate signatures'); - } - - let value: number | undefined; - - // is it a hex string? - if (txIsString(txHash)) { - // transaction hashs's are displayed in reverse order, un-reverse it - txHash = reverseBuffer(Buffer.from(txHash, 'hex')); - - // is it a Transaction object? - } else if (txIsTransaction(txHash)) { - const txOut = txHash.outs[vout]; - prevOutScript = txOut.script; - value = (txOut as Output).value; - - txHash = txHash.getHash(false) as Buffer; - } - - return this.__addInputUnsafe(txHash, vout, { - sequence, - prevOutScript, - value, - }); - } - - addOutput(scriptPubKey: string | Buffer, value: number): number { - if (!this.__canModifyOutputs()) { - throw new Error('No, this would invalidate signatures'); - } - - // Attempt to get a script if it's a base58 or bech32 address string - if (typeof scriptPubKey === 'string') { - scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network); - } - - return this.__TX.addOutput(scriptPubKey, value); - } - - build(): Transaction { - return this.__build(false); - } - - buildIncomplete(): Transaction { - return this.__build(true); - } - - sign( - signParams: number | TxbSignArg, - keyPair?: Signer, - redeemScript?: Buffer, - hashType?: number, - witnessValue?: number, - witnessScript?: Buffer, - ): void { - trySign( - getSigningData( - this.network, - this.__INPUTS, - this.__needsOutputs.bind(this), - this.__TX, - signParams, - keyPair, - redeemScript, - hashType, - witnessValue, - witnessScript, - this.__USE_LOW_R, - ), - ); - } - - private __addInputUnsafe( - txHash: Buffer, - vout: number, - options: TxbInput, - ): number { - if (Transaction.isCoinbaseHash(txHash)) { - throw new Error('coinbase inputs not supported'); - } - - const prevTxOut = txHash.toString('hex') + ':' + vout; - if (this.__PREV_TX_SET[prevTxOut] !== undefined) - throw new Error('Duplicate TxOut: ' + prevTxOut); - - let input: TxbInput = {}; - - // derive what we can from the scriptSig - if (options.script !== undefined) { - input = expandInput(options.script, options.witness || []); - } - - // if an input value was given, retain it - if (options.value !== undefined) { - input.value = options.value; - } - - // derive what we can from the previous transactions output script - if (!input.prevOutScript && options.prevOutScript) { - let prevOutType; - - if (!input.pubkeys && !input.signatures) { - const expanded = expandOutput(options.prevOutScript); - if (expanded.pubkeys) { - input.pubkeys = expanded.pubkeys; - input.signatures = expanded.signatures; - } - - prevOutType = expanded.type; - } - - input.prevOutScript = options.prevOutScript; - input.prevOutType = prevOutType || classify.output(options.prevOutScript); - } - - const vin = this.__TX.addInput( - txHash, - vout, - options.sequence, - options.scriptSig, - ); - this.__INPUTS[vin] = input; - this.__PREV_TX_SET[prevTxOut] = true; - return vin; - } - - private __build(allowIncomplete?: boolean): Transaction { - if (!allowIncomplete) { - if (!this.__TX.ins.length) throw new Error('Transaction has no inputs'); - if (!this.__TX.outs.length) throw new Error('Transaction has no outputs'); - } - - const tx = this.__TX.clone(); - - // create script signatures from inputs - this.__INPUTS.forEach((input, i) => { - if (!input.prevOutType && !allowIncomplete) - throw new Error('Transaction is not complete'); - - const result = build(input.prevOutType!, input, allowIncomplete); - if (!result) { - if (!allowIncomplete && input.prevOutType === SCRIPT_TYPES.NONSTANDARD) - throw new Error('Unknown input type'); - if (!allowIncomplete) throw new Error('Not enough information'); - return; - } - - tx.setInputScript(i, result.input!); - tx.setWitness(i, result.witness!); - }); - - if (!allowIncomplete) { - // do not rely on this, its merely a last resort - if (this.__overMaximumFees(tx.virtualSize())) { - throw new Error('Transaction has absurd fees'); - } - } - - return tx; - } - - private __canModifyInputs(): boolean { - return this.__INPUTS.every(input => { - if (!input.signatures) return true; - - return input.signatures.every(signature => { - if (!signature) return true; - const hashType = signatureHashType(signature); - - // if SIGHASH_ANYONECANPAY is set, signatures would not - // be invalidated by more inputs - return (hashType & Transaction.SIGHASH_ANYONECANPAY) !== 0; - }); - }); - } - - private __needsOutputs(signingHashType: number): boolean { - if (signingHashType === Transaction.SIGHASH_ALL) { - return this.__TX.outs.length === 0; - } - - // if inputs are being signed with SIGHASH_NONE, we don't strictly need outputs - // .build() will fail, but .buildIncomplete() is OK - return ( - this.__TX.outs.length === 0 && - this.__INPUTS.some(input => { - if (!input.signatures) return false; - - return input.signatures.some(signature => { - if (!signature) return false; // no signature, no issue - const hashType = signatureHashType(signature); - if (hashType & Transaction.SIGHASH_NONE) return false; // SIGHASH_NONE doesn't care about outputs - return true; // SIGHASH_* does care - }); - }) - ); - } - - private __canModifyOutputs(): boolean { - const nInputs = this.__TX.ins.length; - const nOutputs = this.__TX.outs.length; - - return this.__INPUTS.every(input => { - if (input.signatures === undefined) return true; - - return input.signatures.every(signature => { - if (!signature) return true; - const hashType = signatureHashType(signature); - - const hashTypeMod = hashType & 0x1f; - if (hashTypeMod === Transaction.SIGHASH_NONE) return true; - if (hashTypeMod === Transaction.SIGHASH_SINGLE) { - // if SIGHASH_SINGLE is set, and nInputs > nOutputs - // some signatures would be invalidated by the addition - // of more outputs - return nInputs <= nOutputs; - } - return false; - }); - }); - } - - private __overMaximumFees(bytes: number): boolean { - // not all inputs will have .value defined - const incoming = this.__INPUTS.reduce((a, x) => a + (x.value! >>> 0), 0); - - // but all outputs do, and if we have any input value - // we can immediately determine if the outputs are too small - const outgoing = this.__TX.outs.reduce( - (a, x) => a + (x as Output).value, - 0, - ); - const fee = incoming - outgoing; - const feeRate = fee / bytes; - - return feeRate > this.maximumFeeRate; - } -} - -function expandInput( - scriptSig: Buffer, - witnessStack: Buffer[], - type?: string, - scriptPubKey?: Buffer, -): TxbInput { - if (scriptSig.length === 0 && witnessStack.length === 0) return {}; - if (!type) { - let ssType: string | undefined = classify.input(scriptSig, true); - let wsType: string | undefined = classify.witness(witnessStack, true); - if (ssType === SCRIPT_TYPES.NONSTANDARD) ssType = undefined; - if (wsType === SCRIPT_TYPES.NONSTANDARD) wsType = undefined; - type = ssType || wsType; - } - - switch (type) { - case SCRIPT_TYPES.P2WPKH: { - const { output, pubkey, signature } = payments.p2wpkh({ - witness: witnessStack, - }); - - return { - prevOutScript: output, - prevOutType: SCRIPT_TYPES.P2WPKH, - pubkeys: [pubkey], - signatures: [signature], - }; - } - - case SCRIPT_TYPES.P2PKH: { - const { output, pubkey, signature } = payments.p2pkh({ - input: scriptSig, - }); - - return { - prevOutScript: output, - prevOutType: SCRIPT_TYPES.P2PKH, - pubkeys: [pubkey], - signatures: [signature], - }; - } - - case SCRIPT_TYPES.P2PK: { - const { signature } = payments.p2pk({ input: scriptSig }); - - return { - prevOutType: SCRIPT_TYPES.P2PK, - pubkeys: [undefined], - signatures: [signature], - }; - } - - case SCRIPT_TYPES.P2MS: { - const { m, pubkeys, signatures } = payments.p2ms( - { - input: scriptSig, - output: scriptPubKey, - }, - { allowIncomplete: true }, - ); - - return { - prevOutType: SCRIPT_TYPES.P2MS, - pubkeys, - signatures, - maxSignatures: m, - }; - } - } - - if (type === SCRIPT_TYPES.P2SH) { - const { output, redeem } = payments.p2sh({ - input: scriptSig, - witness: witnessStack, - }); - - const outputType = classify.output(redeem!.output!); - const expanded = expandInput( - redeem!.input!, - redeem!.witness!, - outputType, - redeem!.output, - ); - if (!expanded.prevOutType) return {}; - - return { - prevOutScript: output, - prevOutType: SCRIPT_TYPES.P2SH, - redeemScript: redeem!.output, - redeemScriptType: expanded.prevOutType, - witnessScript: expanded.witnessScript, - witnessScriptType: expanded.witnessScriptType, - - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - }; - } - - if (type === SCRIPT_TYPES.P2WSH) { - const { output, redeem } = payments.p2wsh({ - input: scriptSig, - witness: witnessStack, - }); - const outputType = classify.output(redeem!.output!); - let expanded; - if (outputType === SCRIPT_TYPES.P2WPKH) { - expanded = expandInput(redeem!.input!, redeem!.witness!, outputType); - } else { - expanded = expandInput( - bscript.compile(redeem!.witness!), - [], - outputType, - redeem!.output, - ); - } - if (!expanded.prevOutType) return {}; - - return { - prevOutScript: output, - prevOutType: SCRIPT_TYPES.P2WSH, - witnessScript: redeem!.output, - witnessScriptType: expanded.prevOutType, - - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - }; - } - - return { - prevOutType: SCRIPT_TYPES.NONSTANDARD, - prevOutScript: scriptSig, - }; -} - -// could be done in expandInput, but requires the original Transaction for hashForSignature -function fixMultisigOrder( - input: TxbInput, - transaction: Transaction, - vin: number, -): void { - if (input.redeemScriptType !== SCRIPT_TYPES.P2MS || !input.redeemScript) - return; - if (input.pubkeys!.length === input.signatures!.length) return; - - const unmatched = input.signatures!.concat(); - - input.signatures = input.pubkeys!.map(pubKey => { - const keyPair = ECPair.fromPublicKey(pubKey!); - let match: Buffer | undefined; - - // check for a signature - unmatched.some((signature, i) => { - // skip if undefined || OP_0 - if (!signature) return false; - - // TODO: avoid O(n) hashForSignature - const parsed = bscript.signature.decode(signature); - const hash = transaction.hashForSignature( - vin, - input.redeemScript!, - parsed.hashType, - ); - - // skip if signature does not match pubKey - if (!keyPair.verify(hash, parsed.signature)) return false; - - // remove matched signature from unmatched - unmatched[i] = undefined; - match = signature; - - return true; - }); - - return match; - }); -} - -function expandOutput(script: Buffer, ourPubKey?: Buffer): TxbOutput { - typeforce(types.Buffer, script); - const type = classify.output(script); - - switch (type) { - case SCRIPT_TYPES.P2PKH: { - if (!ourPubKey) return { type }; - - // does our hash160(pubKey) match the output scripts? - const pkh1 = payments.p2pkh({ output: script }).hash; - const pkh2 = bcrypto.hash160(ourPubKey); - if (!pkh1!.equals(pkh2)) return { type }; - - return { - type, - pubkeys: [ourPubKey], - signatures: [undefined], - }; - } - - case SCRIPT_TYPES.P2WPKH: { - if (!ourPubKey) return { type }; - - // does our hash160(pubKey) match the output scripts? - const wpkh1 = payments.p2wpkh({ output: script }).hash; - const wpkh2 = bcrypto.hash160(ourPubKey); - if (!wpkh1!.equals(wpkh2)) return { type }; - - return { - type, - pubkeys: [ourPubKey], - signatures: [undefined], - }; - } - - case SCRIPT_TYPES.P2PK: { - const p2pk = payments.p2pk({ output: script }); - return { - type, - pubkeys: [p2pk.pubkey], - signatures: [undefined], - }; - } - - case SCRIPT_TYPES.P2MS: { - const p2ms = payments.p2ms({ output: script }); - return { - type, - pubkeys: p2ms.pubkeys, - signatures: p2ms.pubkeys!.map((): undefined => undefined), - maxSignatures: p2ms.m, - }; - } - } - - return { type }; -} - -function prepareInput( - input: TxbInput, - ourPubKey: Buffer, - redeemScript?: Buffer, - witnessScript?: Buffer, -): TxbInput { - if (redeemScript && witnessScript) { - const p2wsh = payments.p2wsh({ - redeem: { output: witnessScript }, - }) as Payment; - const p2wshAlt = payments.p2wsh({ output: redeemScript }) as Payment; - const p2sh = payments.p2sh({ redeem: { output: redeemScript } }) as Payment; - const p2shAlt = payments.p2sh({ redeem: p2wsh }) as Payment; - - // enforces P2SH(P2WSH(...)) - if (!p2wsh.hash!.equals(p2wshAlt.hash!)) - throw new Error('Witness script inconsistent with prevOutScript'); - if (!p2sh.hash!.equals(p2shAlt.hash!)) - throw new Error('Redeem script inconsistent with prevOutScript'); - - const expanded = expandOutput(p2wsh.redeem!.output!, ourPubKey); - if (!expanded.pubkeys) - throw new Error( - expanded.type + - ' not supported as witnessScript (' + - bscript.toASM(witnessScript) + - ')', - ); - if (input.signatures && input.signatures.some(x => x !== undefined)) { - expanded.signatures = input.signatures; - } - - const signScript = witnessScript; - if (expanded.type === SCRIPT_TYPES.P2WPKH) - throw new Error('P2SH(P2WSH(P2WPKH)) is a consensus failure'); - - return { - redeemScript, - redeemScriptType: SCRIPT_TYPES.P2WSH, - - witnessScript, - witnessScriptType: expanded.type, - - prevOutType: SCRIPT_TYPES.P2SH, - prevOutScript: p2sh.output, - - hasWitness: true, - signScript, - signType: expanded.type, - - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - maxSignatures: expanded.maxSignatures, - }; - } - - if (redeemScript) { - const p2sh = payments.p2sh({ redeem: { output: redeemScript } }) as Payment; - - if (input.prevOutScript) { - let p2shAlt; - try { - p2shAlt = payments.p2sh({ output: input.prevOutScript }) as Payment; - } catch (e) { - throw new Error('PrevOutScript must be P2SH'); - } - if (!p2sh.hash!.equals(p2shAlt.hash!)) - throw new Error('Redeem script inconsistent with prevOutScript'); - } - - const expanded = expandOutput(p2sh.redeem!.output!, ourPubKey); - if (!expanded.pubkeys) - throw new Error( - expanded.type + - ' not supported as redeemScript (' + - bscript.toASM(redeemScript) + - ')', - ); - if (input.signatures && input.signatures.some(x => x !== undefined)) { - expanded.signatures = input.signatures; - } - - let signScript = redeemScript; - if (expanded.type === SCRIPT_TYPES.P2WPKH) { - signScript = payments.p2pkh({ pubkey: expanded.pubkeys[0] }).output!; - } - - return { - redeemScript, - redeemScriptType: expanded.type, - - prevOutType: SCRIPT_TYPES.P2SH, - prevOutScript: p2sh.output, - - hasWitness: expanded.type === SCRIPT_TYPES.P2WPKH, - signScript, - signType: expanded.type, - - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - maxSignatures: expanded.maxSignatures, - }; - } - - if (witnessScript) { - const p2wsh = payments.p2wsh({ redeem: { output: witnessScript } }); - - if (input.prevOutScript) { - const p2wshAlt = payments.p2wsh({ output: input.prevOutScript }); - if (!p2wsh.hash!.equals(p2wshAlt.hash!)) - throw new Error('Witness script inconsistent with prevOutScript'); - } - - const expanded = expandOutput(p2wsh.redeem!.output!, ourPubKey); - if (!expanded.pubkeys) - throw new Error( - expanded.type + - ' not supported as witnessScript (' + - bscript.toASM(witnessScript) + - ')', - ); - if (input.signatures && input.signatures.some(x => x !== undefined)) { - expanded.signatures = input.signatures; - } - - const signScript = witnessScript; - if (expanded.type === SCRIPT_TYPES.P2WPKH) - throw new Error('P2WSH(P2WPKH) is a consensus failure'); - - return { - witnessScript, - witnessScriptType: expanded.type, - - prevOutType: SCRIPT_TYPES.P2WSH, - prevOutScript: p2wsh.output, - - hasWitness: true, - signScript, - signType: expanded.type, - - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - maxSignatures: expanded.maxSignatures, - }; - } - - if (input.prevOutType && input.prevOutScript) { - // embedded scripts are not possible without extra information - if (input.prevOutType === SCRIPT_TYPES.P2SH) - throw new Error( - 'PrevOutScript is ' + input.prevOutType + ', requires redeemScript', - ); - if (input.prevOutType === SCRIPT_TYPES.P2WSH) - throw new Error( - 'PrevOutScript is ' + input.prevOutType + ', requires witnessScript', - ); - if (!input.prevOutScript) throw new Error('PrevOutScript is missing'); - - const expanded = expandOutput(input.prevOutScript, ourPubKey); - if (!expanded.pubkeys) - throw new Error( - expanded.type + - ' not supported (' + - bscript.toASM(input.prevOutScript) + - ')', - ); - if (input.signatures && input.signatures.some(x => x !== undefined)) { - expanded.signatures = input.signatures; - } - - let signScript = input.prevOutScript; - if (expanded.type === SCRIPT_TYPES.P2WPKH) { - signScript = payments.p2pkh({ pubkey: expanded.pubkeys[0] }) - .output as Buffer; - } - - return { - prevOutType: expanded.type, - prevOutScript: input.prevOutScript, - - hasWitness: expanded.type === SCRIPT_TYPES.P2WPKH, - signScript, - signType: expanded.type, - - pubkeys: expanded.pubkeys, - signatures: expanded.signatures, - maxSignatures: expanded.maxSignatures, - }; - } - - const prevOutScript = payments.p2pkh({ pubkey: ourPubKey }).output; - return { - prevOutType: SCRIPT_TYPES.P2PKH, - prevOutScript, - - hasWitness: false, - signScript: prevOutScript, - signType: SCRIPT_TYPES.P2PKH, - - pubkeys: [ourPubKey], - signatures: [undefined], - }; -} - -function build( - type: string, - input: TxbInput, - allowIncomplete?: boolean, -): Payment | undefined { - const pubkeys = (input.pubkeys || []) as Buffer[]; - let signatures = (input.signatures || []) as Buffer[]; - - switch (type) { - case SCRIPT_TYPES.P2PKH: { - if (pubkeys.length === 0) break; - if (signatures.length === 0) break; - - return payments.p2pkh({ pubkey: pubkeys[0], signature: signatures[0] }); - } - case SCRIPT_TYPES.P2WPKH: { - if (pubkeys.length === 0) break; - if (signatures.length === 0) break; - - return payments.p2wpkh({ pubkey: pubkeys[0], signature: signatures[0] }); - } - case SCRIPT_TYPES.P2PK: { - if (pubkeys.length === 0) break; - if (signatures.length === 0) break; - - return payments.p2pk({ signature: signatures[0] }); - } - case SCRIPT_TYPES.P2MS: { - const m = input.maxSignatures; - if (allowIncomplete) { - signatures = signatures.map(x => x || ops.OP_0); - } else { - signatures = signatures.filter(x => x); - } - - // if the transaction is not not complete (complete), or if signatures.length === m, validate - // otherwise, the number of OP_0's may be >= m, so don't validate (boo) - const validate = !allowIncomplete || m === signatures.length; - return payments.p2ms( - { m, pubkeys, signatures }, - { allowIncomplete, validate }, - ); - } - case SCRIPT_TYPES.P2SH: { - const redeem = build(input.redeemScriptType!, input, allowIncomplete); - if (!redeem) return; - - return payments.p2sh({ - redeem: { - output: redeem.output || input.redeemScript, - input: redeem.input, - witness: redeem.witness, - }, - }); - } - case SCRIPT_TYPES.P2WSH: { - const redeem = build(input.witnessScriptType!, input, allowIncomplete); - if (!redeem) return; - - return payments.p2wsh({ - redeem: { - output: input.witnessScript, - input: redeem.input, - witness: redeem.witness, - }, - }); - } - } -} - -function canSign(input: TxbInput): boolean { - return ( - input.signScript !== undefined && - input.signType !== undefined && - input.pubkeys !== undefined && - input.signatures !== undefined && - input.signatures.length === input.pubkeys.length && - input.pubkeys.length > 0 && - (input.hasWitness === false || input.value !== undefined) - ); -} - -function signatureHashType(buffer: Buffer): number { - return buffer.readUInt8(buffer.length - 1); -} - -function checkSignArgs(inputs: TxbInput[], signParams: TxbSignArg): void { - if (!PREVOUT_TYPES.has(signParams.prevOutScriptType)) { - throw new TypeError( - `Unknown prevOutScriptType "${signParams.prevOutScriptType}"`, - ); - } - tfMessage( - typeforce.Number, - signParams.vin, - `sign must include vin parameter as Number (input index)`, - ); - tfMessage( - types.Signer, - signParams.keyPair, - `sign must include keyPair parameter as Signer interface`, - ); - tfMessage( - typeforce.maybe(typeforce.Number), - signParams.hashType, - `sign hashType parameter must be a number`, - ); - const prevOutType = (inputs[signParams.vin] || []).prevOutType; - const posType = signParams.prevOutScriptType; - switch (posType) { - case 'p2pkh': - if (prevOutType && prevOutType !== 'pubkeyhash') { - throw new TypeError( - `input #${signParams.vin} is not of type p2pkh: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.witnessValue, - `${posType} requires NO witnessValue`, - ); - break; - case 'p2pk': - if (prevOutType && prevOutType !== 'pubkey') { - throw new TypeError( - `input #${signParams.vin} is not of type p2pk: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.witnessValue, - `${posType} requires NO witnessValue`, - ); - break; - case 'p2wpkh': - if (prevOutType && prevOutType !== 'witnesspubkeyhash') { - throw new TypeError( - `input #${signParams.vin} is not of type p2wpkh: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - types.Satoshi, - signParams.witnessValue, - `${posType} requires witnessValue`, - ); - break; - case 'p2ms': - if (prevOutType && prevOutType !== 'multisig') { - throw new TypeError( - `input #${signParams.vin} is not of type p2ms: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.witnessValue, - `${posType} requires NO witnessValue`, - ); - break; - case 'p2sh-p2wpkh': - if (prevOutType && prevOutType !== 'scripthash') { - throw new TypeError( - `input #${signParams.vin} is not of type p2sh-p2wpkh: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.Buffer, - signParams.redeemScript, - `${posType} requires redeemScript`, - ); - tfMessage( - types.Satoshi, - signParams.witnessValue, - `${posType} requires witnessValue`, - ); - break; - case 'p2sh-p2ms': - case 'p2sh-p2pk': - case 'p2sh-p2pkh': - if (prevOutType && prevOutType !== 'scripthash') { - throw new TypeError( - `input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, - ); - } - tfMessage( - typeforce.value(undefined), - signParams.witnessScript, - `${posType} requires NO witnessScript`, - ); - tfMessage( - typeforce.Buffer, - signParams.redeemScript, - `${posType} requires redeemScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.witnessValue, - `${posType} requires NO witnessValue`, - ); - break; - case 'p2wsh-p2ms': - case 'p2wsh-p2pk': - case 'p2wsh-p2pkh': - if (prevOutType && prevOutType !== 'witnessscripthash') { - throw new TypeError( - `input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, - ); - } - tfMessage( - typeforce.Buffer, - signParams.witnessScript, - `${posType} requires witnessScript`, - ); - tfMessage( - typeforce.value(undefined), - signParams.redeemScript, - `${posType} requires NO redeemScript`, - ); - tfMessage( - types.Satoshi, - signParams.witnessValue, - `${posType} requires witnessValue`, - ); - break; - case 'p2sh-p2wsh-p2ms': - case 'p2sh-p2wsh-p2pk': - case 'p2sh-p2wsh-p2pkh': - if (prevOutType && prevOutType !== 'scripthash') { - throw new TypeError( - `input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, - ); - } - tfMessage( - typeforce.Buffer, - signParams.witnessScript, - `${posType} requires witnessScript`, - ); - tfMessage( - typeforce.Buffer, - signParams.redeemScript, - `${posType} requires witnessScript`, - ); - tfMessage( - types.Satoshi, - signParams.witnessValue, - `${posType} requires witnessScript`, - ); - break; - } -} - -function trySign({ - input, - ourPubKey, - keyPair, - signatureHash, - hashType, - useLowR, -}: SigningData): void { - // enforce in order signing of public keys - let signed = false; - for (const [i, pubKey] of input.pubkeys!.entries()) { - if (!ourPubKey.equals(pubKey!)) continue; - if (input.signatures![i]) throw new Error('Signature already exists'); - - // TODO: add tests - if (ourPubKey.length !== 33 && input.hasWitness) { - throw new Error( - 'BIP143 rejects uncompressed public keys in P2WPKH or P2WSH', - ); - } - - const signature = keyPair.sign(signatureHash, useLowR); - input.signatures![i] = bscript.signature.encode(signature, hashType); - signed = true; - } - - if (!signed) throw new Error('Key pair cannot sign for this input'); -} - -interface SigningData { - input: TxbInput; - ourPubKey: Buffer; - keyPair: Signer; - signatureHash: Buffer; - hashType: number; - useLowR: boolean; -} - -type HashTypeCheck = (hashType: number) => boolean; - -function getSigningData( - network: Network, - inputs: TxbInput[], - needsOutputs: HashTypeCheck, - tx: Transaction, - signParams: number | TxbSignArg, - keyPair?: Signer, - redeemScript?: Buffer, - hashType?: number, - witnessValue?: number, - witnessScript?: Buffer, - useLowR?: boolean, -): SigningData { - let vin: number; - if (typeof signParams === 'number') { - console.warn( - 'DEPRECATED: TransactionBuilder sign method arguments ' + - 'will change in v6, please use the TxbSignArg interface', - ); - vin = signParams; - } else if (typeof signParams === 'object') { - checkSignArgs(inputs, signParams); - ({ - vin, - keyPair, - redeemScript, - hashType, - witnessValue, - witnessScript, - } = signParams); - } else { - throw new TypeError( - 'TransactionBuilder sign first arg must be TxbSignArg or number', - ); - } - if (keyPair === undefined) { - throw new Error('sign requires keypair'); - } - // TODO: remove keyPair.network matching in 4.0.0 - if (keyPair.network && keyPair.network !== network) - throw new TypeError('Inconsistent network'); - if (!inputs[vin]) throw new Error('No input at index: ' + vin); - - hashType = hashType || Transaction.SIGHASH_ALL; - if (needsOutputs(hashType)) throw new Error('Transaction needs outputs'); - - const input = inputs[vin]; - - // if redeemScript was previously provided, enforce consistency - if ( - input.redeemScript !== undefined && - redeemScript && - !input.redeemScript.equals(redeemScript) - ) { - throw new Error('Inconsistent redeemScript'); - } - - const ourPubKey = - keyPair.publicKey || (keyPair.getPublicKey && keyPair.getPublicKey()); - if (!canSign(input)) { - if (witnessValue !== undefined) { - if (input.value !== undefined && input.value !== witnessValue) - throw new Error('Input did not match witnessValue'); - typeforce(types.Satoshi, witnessValue); - input.value = witnessValue; - } - - if (!canSign(input)) { - const prepared = prepareInput( - input, - ourPubKey, - redeemScript, - witnessScript, - ); - - // updates inline - Object.assign(input, prepared); - } - - if (!canSign(input)) throw Error(input.prevOutType + ' not supported'); - } - - // ready to sign - let signatureHash: Buffer; - if (input.hasWitness) { - signatureHash = tx.hashForWitnessV0( - vin, - input.signScript as Buffer, - input.value as number, - hashType, - ); - } else { - signatureHash = tx.hashForSignature( - vin, - input.signScript as Buffer, - hashType, - ); - } - - return { - input, - ourPubKey, - keyPair, - signatureHash, - hashType, - useLowR: !!useLowR, - }; -} diff --git a/types/index.d.ts b/types/index.d.ts index c8f2a00..f63a986 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -10,7 +10,6 @@ export { Block } from './block'; export { Psbt, PsbtTxInput, PsbtTxOutput } from './psbt'; export { OPS as opcodes } from './script'; export { Transaction } from './transaction'; -export { TransactionBuilder } from './transaction_builder'; export { BIP32Interface } from 'bip32'; export { ECPairInterface, Signer, SignerAsync } from './ecpair'; export { Network } from './networks'; diff --git a/types/transaction_builder.d.ts b/types/transaction_builder.d.ts deleted file mode 100644 index a80fc0f..0000000 --- a/types/transaction_builder.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Signer } from './ecpair'; -import { Network } from './networks'; -import { Transaction } from './transaction'; -interface TxbSignArg { - prevOutScriptType: string; - vin: number; - keyPair: Signer; - redeemScript?: Buffer; - hashType?: number; - witnessValue?: number; - witnessScript?: Buffer; -} -export declare class TransactionBuilder { - network: Network; - maximumFeeRate: number; - static fromTransaction(transaction: Transaction, network?: Network): TransactionBuilder; - private __PREV_TX_SET; - private __INPUTS; - private __TX; - private __USE_LOW_R; - constructor(network?: Network, maximumFeeRate?: number); - setLowR(setting?: boolean): boolean; - setLockTime(locktime: number): void; - setVersion(version: number): void; - addInput(txHash: Buffer | string | Transaction, vout: number, sequence?: number, prevOutScript?: Buffer): number; - addOutput(scriptPubKey: string | Buffer, value: number): number; - build(): Transaction; - buildIncomplete(): Transaction; - sign(signParams: number | TxbSignArg, keyPair?: Signer, redeemScript?: Buffer, hashType?: number, witnessValue?: number, witnessScript?: Buffer): void; - private __addInputUnsafe; - private __build; - private __canModifyInputs; - private __needsOutputs; - private __canModifyOutputs; - private __overMaximumFees; -} -export {}; From c2175518842e580da60994858db02c98528679ef Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 27 Nov 2020 12:02:07 +0200 Subject: [PATCH 2/4] #1477 remove non-public dependecies of TransactionBuilder (classify & templates)) --- src/classify.js | 59 ---- src/templates/multisig/index.js | 6 - src/templates/multisig/input.js | 23 -- src/templates/multisig/output.js | 27 -- src/templates/nulldata.js | 15 - src/templates/pubkey/index.js | 6 - src/templates/pubkey/input.js | 12 - src/templates/pubkey/output.js | 17 -- src/templates/pubkeyhash/index.js | 6 - src/templates/pubkeyhash/input.js | 16 - src/templates/pubkeyhash/output.js | 20 -- src/templates/scripthash/index.js | 6 - src/templates/scripthash/input.js | 50 ---- src/templates/scripthash/output.js | 18 -- src/templates/witnesscommitment/index.js | 4 - src/templates/witnesscommitment/output.js | 34 --- src/templates/witnesspubkeyhash/index.js | 6 - src/templates/witnesspubkeyhash/input.js | 19 -- src/templates/witnesspubkeyhash/output.js | 17 -- src/templates/witnessscripthash/index.js | 6 - src/templates/witnessscripthash/input.js | 39 --- src/templates/witnessscripthash/output.js | 17 -- test/classify.spec.ts | 180 ------------ test/fixtures/templates.json | 273 +----------------- ts_src/classify.ts | 71 ----- ts_src/templates/multisig/index.ts | 4 - ts_src/templates/multisig/input.ts | 31 -- ts_src/templates/multisig/output.ts | 33 --- ts_src/templates/nulldata.ts | 16 - ts_src/templates/pubkey/index.ts | 4 - ts_src/templates/pubkey/input.ts | 16 - ts_src/templates/pubkey/output.ts | 18 -- ts_src/templates/pubkeyhash/index.ts | 4 - ts_src/templates/pubkeyhash/input.ts | 17 -- ts_src/templates/pubkeyhash/output.ts | 20 -- ts_src/templates/scripthash/index.ts | 4 - ts_src/templates/scripthash/input.ts | 61 ---- ts_src/templates/scripthash/output.ts | 18 -- ts_src/templates/witnesscommitment/index.ts | 3 - ts_src/templates/witnesscommitment/output.ts | 40 --- ts_src/templates/witnesspubkeyhash/index.ts | 4 - ts_src/templates/witnesspubkeyhash/input.ts | 21 -- ts_src/templates/witnesspubkeyhash/output.ts | 13 - ts_src/templates/witnessscripthash/index.ts | 4 - ts_src/templates/witnessscripthash/input.ts | 47 --- ts_src/templates/witnessscripthash/output.ts | 13 - types/classify.d.ts | 15 - types/templates/multisig/index.d.ts | 3 - types/templates/multisig/input.d.ts | 5 - types/templates/multisig/output.d.ts | 5 - types/templates/nulldata.d.ts | 8 - types/templates/pubkey/index.d.ts | 3 - types/templates/pubkey/input.d.ts | 5 - types/templates/pubkey/output.d.ts | 5 - types/templates/pubkeyhash/index.d.ts | 3 - types/templates/pubkeyhash/input.d.ts | 5 - types/templates/pubkeyhash/output.d.ts | 4 - types/templates/scripthash/index.d.ts | 3 - types/templates/scripthash/input.d.ts | 4 - types/templates/scripthash/output.d.ts | 4 - types/templates/witnesscommitment/index.d.ts | 2 - types/templates/witnesscommitment/output.d.ts | 6 - types/templates/witnesspubkeyhash/index.d.ts | 3 - types/templates/witnesspubkeyhash/input.d.ts | 5 - types/templates/witnesspubkeyhash/output.d.ts | 4 - types/templates/witnessscripthash/index.d.ts | 3 - types/templates/witnessscripthash/input.d.ts | 4 - types/templates/witnessscripthash/output.d.ts | 4 - 68 files changed, 1 insertion(+), 1440 deletions(-) delete mode 100644 src/classify.js delete mode 100644 src/templates/multisig/index.js delete mode 100644 src/templates/multisig/input.js delete mode 100644 src/templates/multisig/output.js delete mode 100644 src/templates/nulldata.js delete mode 100644 src/templates/pubkey/index.js delete mode 100644 src/templates/pubkey/input.js delete mode 100644 src/templates/pubkey/output.js delete mode 100644 src/templates/pubkeyhash/index.js delete mode 100644 src/templates/pubkeyhash/input.js delete mode 100644 src/templates/pubkeyhash/output.js delete mode 100644 src/templates/scripthash/index.js delete mode 100644 src/templates/scripthash/input.js delete mode 100644 src/templates/scripthash/output.js delete mode 100644 src/templates/witnesscommitment/index.js delete mode 100644 src/templates/witnesscommitment/output.js delete mode 100644 src/templates/witnesspubkeyhash/index.js delete mode 100644 src/templates/witnesspubkeyhash/input.js delete mode 100644 src/templates/witnesspubkeyhash/output.js delete mode 100644 src/templates/witnessscripthash/index.js delete mode 100644 src/templates/witnessscripthash/input.js delete mode 100644 src/templates/witnessscripthash/output.js delete mode 100644 test/classify.spec.ts delete mode 100644 ts_src/classify.ts delete mode 100644 ts_src/templates/multisig/index.ts delete mode 100644 ts_src/templates/multisig/input.ts delete mode 100644 ts_src/templates/multisig/output.ts delete mode 100644 ts_src/templates/nulldata.ts delete mode 100644 ts_src/templates/pubkey/index.ts delete mode 100644 ts_src/templates/pubkey/input.ts delete mode 100644 ts_src/templates/pubkey/output.ts delete mode 100644 ts_src/templates/pubkeyhash/index.ts delete mode 100644 ts_src/templates/pubkeyhash/input.ts delete mode 100644 ts_src/templates/pubkeyhash/output.ts delete mode 100644 ts_src/templates/scripthash/index.ts delete mode 100644 ts_src/templates/scripthash/input.ts delete mode 100644 ts_src/templates/scripthash/output.ts delete mode 100644 ts_src/templates/witnesscommitment/index.ts delete mode 100644 ts_src/templates/witnesscommitment/output.ts delete mode 100644 ts_src/templates/witnesspubkeyhash/index.ts delete mode 100644 ts_src/templates/witnesspubkeyhash/input.ts delete mode 100644 ts_src/templates/witnesspubkeyhash/output.ts delete mode 100644 ts_src/templates/witnessscripthash/index.ts delete mode 100644 ts_src/templates/witnessscripthash/input.ts delete mode 100644 ts_src/templates/witnessscripthash/output.ts delete mode 100644 types/classify.d.ts delete mode 100644 types/templates/multisig/index.d.ts delete mode 100644 types/templates/multisig/input.d.ts delete mode 100644 types/templates/multisig/output.d.ts delete mode 100644 types/templates/nulldata.d.ts delete mode 100644 types/templates/pubkey/index.d.ts delete mode 100644 types/templates/pubkey/input.d.ts delete mode 100644 types/templates/pubkey/output.d.ts delete mode 100644 types/templates/pubkeyhash/index.d.ts delete mode 100644 types/templates/pubkeyhash/input.d.ts delete mode 100644 types/templates/pubkeyhash/output.d.ts delete mode 100644 types/templates/scripthash/index.d.ts delete mode 100644 types/templates/scripthash/input.d.ts delete mode 100644 types/templates/scripthash/output.d.ts delete mode 100644 types/templates/witnesscommitment/index.d.ts delete mode 100644 types/templates/witnesscommitment/output.d.ts delete mode 100644 types/templates/witnesspubkeyhash/index.d.ts delete mode 100644 types/templates/witnesspubkeyhash/input.d.ts delete mode 100644 types/templates/witnesspubkeyhash/output.d.ts delete mode 100644 types/templates/witnessscripthash/index.d.ts delete mode 100644 types/templates/witnessscripthash/input.d.ts delete mode 100644 types/templates/witnessscripthash/output.d.ts diff --git a/src/classify.js b/src/classify.js deleted file mode 100644 index 70c600c..0000000 --- a/src/classify.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const script_1 = require('./script'); -const multisig = require('./templates/multisig'); -const nullData = require('./templates/nulldata'); -const pubKey = require('./templates/pubkey'); -const pubKeyHash = require('./templates/pubkeyhash'); -const scriptHash = require('./templates/scripthash'); -const witnessCommitment = require('./templates/witnesscommitment'); -const witnessPubKeyHash = require('./templates/witnesspubkeyhash'); -const witnessScriptHash = require('./templates/witnessscripthash'); -const types = { - P2MS: 'multisig', - NONSTANDARD: 'nonstandard', - NULLDATA: 'nulldata', - P2PK: 'pubkey', - P2PKH: 'pubkeyhash', - P2SH: 'scripthash', - P2WPKH: 'witnesspubkeyhash', - P2WSH: 'witnessscripthash', - WITNESS_COMMITMENT: 'witnesscommitment', -}; -exports.types = types; -function classifyOutput(script) { - if (witnessPubKeyHash.output.check(script)) return types.P2WPKH; - if (witnessScriptHash.output.check(script)) return types.P2WSH; - if (pubKeyHash.output.check(script)) return types.P2PKH; - if (scriptHash.output.check(script)) return types.P2SH; - // XXX: optimization, below functions .decompile before use - const chunks = script_1.decompile(script); - if (!chunks) throw new TypeError('Invalid script'); - if (multisig.output.check(chunks)) return types.P2MS; - if (pubKey.output.check(chunks)) return types.P2PK; - if (witnessCommitment.output.check(chunks)) return types.WITNESS_COMMITMENT; - if (nullData.output.check(chunks)) return types.NULLDATA; - return types.NONSTANDARD; -} -exports.output = classifyOutput; -function classifyInput(script, allowIncomplete) { - // XXX: optimization, below functions .decompile before use - const chunks = script_1.decompile(script); - if (!chunks) throw new TypeError('Invalid script'); - if (pubKeyHash.input.check(chunks)) return types.P2PKH; - if (scriptHash.input.check(chunks, allowIncomplete)) return types.P2SH; - if (multisig.input.check(chunks, allowIncomplete)) return types.P2MS; - if (pubKey.input.check(chunks)) return types.P2PK; - return types.NONSTANDARD; -} -exports.input = classifyInput; -function classifyWitness(script, allowIncomplete) { - // XXX: optimization, below functions .decompile before use - const chunks = script_1.decompile(script); - if (!chunks) throw new TypeError('Invalid script'); - if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH; - if (witnessScriptHash.input.check(chunks, allowIncomplete)) - return types.P2WSH; - return types.NONSTANDARD; -} -exports.witness = classifyWitness; diff --git a/src/templates/multisig/index.js b/src/templates/multisig/index.js deleted file mode 100644 index b8cd6c4..0000000 --- a/src/templates/multisig/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const input = require('./input'); -exports.input = input; -const output = require('./output'); -exports.output = output; diff --git a/src/templates/multisig/input.js b/src/templates/multisig/input.js deleted file mode 100644 index 403c2f7..0000000 --- a/src/templates/multisig/input.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; -// OP_0 [signatures ...] -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const script_1 = require('../../script'); -function partialSignature(value) { - return ( - value === script_1.OPS.OP_0 || bscript.isCanonicalScriptSignature(value) - ); -} -function check(script, allowIncomplete) { - const chunks = bscript.decompile(script); - if (chunks.length < 2) return false; - if (chunks[0] !== script_1.OPS.OP_0) return false; - if (allowIncomplete) { - return chunks.slice(1).every(partialSignature); - } - return chunks.slice(1).every(bscript.isCanonicalScriptSignature); -} -exports.check = check; -check.toJSON = () => { - return 'multisig input'; -}; diff --git a/src/templates/multisig/output.js b/src/templates/multisig/output.js deleted file mode 100644 index 0896605..0000000 --- a/src/templates/multisig/output.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; -// m [pubKeys ...] n OP_CHECKMULTISIG -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const script_1 = require('../../script'); -const types = require('../../types'); -const OP_INT_BASE = script_1.OPS.OP_RESERVED; // OP_1 - 1 -function check(script, allowIncomplete) { - const chunks = bscript.decompile(script); - if (chunks.length < 4) return false; - if (chunks[chunks.length - 1] !== script_1.OPS.OP_CHECKMULTISIG) return false; - if (!types.Number(chunks[0])) return false; - if (!types.Number(chunks[chunks.length - 2])) return false; - const m = chunks[0] - OP_INT_BASE; - const n = chunks[chunks.length - 2] - OP_INT_BASE; - if (m <= 0) return false; - if (n > 16) return false; - if (m > n) return false; - if (n !== chunks.length - 3) return false; - if (allowIncomplete) return true; - const keys = chunks.slice(1, -2); - return keys.every(bscript.isCanonicalPubKey); -} -exports.check = check; -check.toJSON = () => { - return 'multi-sig output'; -}; diff --git a/src/templates/nulldata.js b/src/templates/nulldata.js deleted file mode 100644 index 50355d3..0000000 --- a/src/templates/nulldata.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -// OP_RETURN {data} -const bscript = require('../script'); -const OPS = bscript.OPS; -function check(script) { - const buffer = bscript.compile(script); - return buffer.length > 1 && buffer[0] === OPS.OP_RETURN; -} -exports.check = check; -check.toJSON = () => { - return 'null data output'; -}; -const output = { check }; -exports.output = output; diff --git a/src/templates/pubkey/index.js b/src/templates/pubkey/index.js deleted file mode 100644 index b8cd6c4..0000000 --- a/src/templates/pubkey/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const input = require('./input'); -exports.input = input; -const output = require('./output'); -exports.output = output; diff --git a/src/templates/pubkey/input.js b/src/templates/pubkey/input.js deleted file mode 100644 index 9715b80..0000000 --- a/src/templates/pubkey/input.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; -// {signature} -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -function check(script) { - const chunks = bscript.decompile(script); - return chunks.length === 1 && bscript.isCanonicalScriptSignature(chunks[0]); -} -exports.check = check; -check.toJSON = () => { - return 'pubKey input'; -}; diff --git a/src/templates/pubkey/output.js b/src/templates/pubkey/output.js deleted file mode 100644 index 2edb731..0000000 --- a/src/templates/pubkey/output.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; -// {pubKey} OP_CHECKSIG -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const script_1 = require('../../script'); -function check(script) { - const chunks = bscript.decompile(script); - return ( - chunks.length === 2 && - bscript.isCanonicalPubKey(chunks[0]) && - chunks[1] === script_1.OPS.OP_CHECKSIG - ); -} -exports.check = check; -check.toJSON = () => { - return 'pubKey output'; -}; diff --git a/src/templates/pubkeyhash/index.js b/src/templates/pubkeyhash/index.js deleted file mode 100644 index b8cd6c4..0000000 --- a/src/templates/pubkeyhash/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const input = require('./input'); -exports.input = input; -const output = require('./output'); -exports.output = output; diff --git a/src/templates/pubkeyhash/input.js b/src/templates/pubkeyhash/input.js deleted file mode 100644 index 14d72cc..0000000 --- a/src/templates/pubkeyhash/input.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; -// {signature} {pubKey} -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -function check(script) { - const chunks = bscript.decompile(script); - return ( - chunks.length === 2 && - bscript.isCanonicalScriptSignature(chunks[0]) && - bscript.isCanonicalPubKey(chunks[1]) - ); -} -exports.check = check; -check.toJSON = () => { - return 'pubKeyHash input'; -}; diff --git a/src/templates/pubkeyhash/output.js b/src/templates/pubkeyhash/output.js deleted file mode 100644 index 079e1ed..0000000 --- a/src/templates/pubkeyhash/output.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -// OP_DUP OP_HASH160 {pubKeyHash} OP_EQUALVERIFY OP_CHECKSIG -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const script_1 = require('../../script'); -function check(script) { - const buffer = bscript.compile(script); - return ( - buffer.length === 25 && - buffer[0] === script_1.OPS.OP_DUP && - buffer[1] === script_1.OPS.OP_HASH160 && - buffer[2] === 0x14 && - buffer[23] === script_1.OPS.OP_EQUALVERIFY && - buffer[24] === script_1.OPS.OP_CHECKSIG - ); -} -exports.check = check; -check.toJSON = () => { - return 'pubKeyHash output'; -}; diff --git a/src/templates/scripthash/index.js b/src/templates/scripthash/index.js deleted file mode 100644 index b8cd6c4..0000000 --- a/src/templates/scripthash/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const input = require('./input'); -exports.input = input; -const output = require('./output'); -exports.output = output; diff --git a/src/templates/scripthash/input.js b/src/templates/scripthash/input.js deleted file mode 100644 index 999cc83..0000000 --- a/src/templates/scripthash/input.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; -// {serialized scriptPubKey script} -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const p2ms = require('../multisig'); -const p2pk = require('../pubkey'); -const p2pkh = require('../pubkeyhash'); -const p2wpkho = require('../witnesspubkeyhash/output'); -const p2wsho = require('../witnessscripthash/output'); -function check(script, allowIncomplete) { - const chunks = bscript.decompile(script); - if (chunks.length < 1) return false; - const lastChunk = chunks[chunks.length - 1]; - if (!Buffer.isBuffer(lastChunk)) return false; - const scriptSigChunks = bscript.decompile( - bscript.compile(chunks.slice(0, -1)), - ); - const redeemScriptChunks = bscript.decompile(lastChunk); - // is redeemScript a valid script? - if (!redeemScriptChunks) return false; - // is redeemScriptSig push only? - if (!bscript.isPushOnly(scriptSigChunks)) return false; - // is witness? - if (chunks.length === 1) { - return ( - p2wsho.check(redeemScriptChunks) || p2wpkho.check(redeemScriptChunks) - ); - } - // match types - if ( - p2pkh.input.check(scriptSigChunks) && - p2pkh.output.check(redeemScriptChunks) - ) - return true; - if ( - p2ms.input.check(scriptSigChunks, allowIncomplete) && - p2ms.output.check(redeemScriptChunks) - ) - return true; - if ( - p2pk.input.check(scriptSigChunks) && - p2pk.output.check(redeemScriptChunks) - ) - return true; - return false; -} -exports.check = check; -check.toJSON = () => { - return 'scriptHash input'; -}; diff --git a/src/templates/scripthash/output.js b/src/templates/scripthash/output.js deleted file mode 100644 index 3797003..0000000 --- a/src/templates/scripthash/output.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; -// OP_HASH160 {scriptHash} OP_EQUAL -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const script_1 = require('../../script'); -function check(script) { - const buffer = bscript.compile(script); - return ( - buffer.length === 23 && - buffer[0] === script_1.OPS.OP_HASH160 && - buffer[1] === 0x14 && - buffer[22] === script_1.OPS.OP_EQUAL - ); -} -exports.check = check; -check.toJSON = () => { - return 'scriptHash output'; -}; diff --git a/src/templates/witnesscommitment/index.js b/src/templates/witnesscommitment/index.js deleted file mode 100644 index 099ac72..0000000 --- a/src/templates/witnesscommitment/index.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const output = require('./output'); -exports.output = output; diff --git a/src/templates/witnesscommitment/output.js b/src/templates/witnesscommitment/output.js deleted file mode 100644 index fb1d59c..0000000 --- a/src/templates/witnesscommitment/output.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; -// OP_RETURN {aa21a9ed} {commitment} -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const script_1 = require('../../script'); -const types = require('../../types'); -const typeforce = require('typeforce'); -const HEADER = Buffer.from('aa21a9ed', 'hex'); -function check(script) { - const buffer = bscript.compile(script); - return ( - buffer.length > 37 && - buffer[0] === script_1.OPS.OP_RETURN && - buffer[1] === 0x24 && - buffer.slice(2, 6).equals(HEADER) - ); -} -exports.check = check; -check.toJSON = () => { - return 'Witness commitment output'; -}; -function encode(commitment) { - typeforce(types.Hash256bit, commitment); - const buffer = Buffer.allocUnsafe(36); - HEADER.copy(buffer, 0); - commitment.copy(buffer, 4); - return bscript.compile([script_1.OPS.OP_RETURN, buffer]); -} -exports.encode = encode; -function decode(buffer) { - typeforce(check, buffer); - return bscript.decompile(buffer)[1].slice(4, 36); -} -exports.decode = decode; diff --git a/src/templates/witnesspubkeyhash/index.js b/src/templates/witnesspubkeyhash/index.js deleted file mode 100644 index b8cd6c4..0000000 --- a/src/templates/witnesspubkeyhash/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const input = require('./input'); -exports.input = input; -const output = require('./output'); -exports.output = output; diff --git a/src/templates/witnesspubkeyhash/input.js b/src/templates/witnesspubkeyhash/input.js deleted file mode 100644 index 4343584..0000000 --- a/src/templates/witnesspubkeyhash/input.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; -// {signature} {pubKey} -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -function isCompressedCanonicalPubKey(pubKey) { - return bscript.isCanonicalPubKey(pubKey) && pubKey.length === 33; -} -function check(script) { - const chunks = bscript.decompile(script); - return ( - chunks.length === 2 && - bscript.isCanonicalScriptSignature(chunks[0]) && - isCompressedCanonicalPubKey(chunks[1]) - ); -} -exports.check = check; -check.toJSON = () => { - return 'witnessPubKeyHash input'; -}; diff --git a/src/templates/witnesspubkeyhash/output.js b/src/templates/witnesspubkeyhash/output.js deleted file mode 100644 index ea5ed1e..0000000 --- a/src/templates/witnesspubkeyhash/output.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; -// OP_0 {pubKeyHash} -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const script_1 = require('../../script'); -function check(script) { - const buffer = bscript.compile(script); - return ( - buffer.length === 22 && - buffer[0] === script_1.OPS.OP_0 && - buffer[1] === 0x14 - ); -} -exports.check = check; -check.toJSON = () => { - return 'Witness pubKeyHash output'; -}; diff --git a/src/templates/witnessscripthash/index.js b/src/templates/witnessscripthash/index.js deleted file mode 100644 index b8cd6c4..0000000 --- a/src/templates/witnessscripthash/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -const input = require('./input'); -exports.input = input; -const output = require('./output'); -exports.output = output; diff --git a/src/templates/witnessscripthash/input.js b/src/templates/witnessscripthash/input.js deleted file mode 100644 index f69a810..0000000 --- a/src/templates/witnessscripthash/input.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; -// {serialized scriptPubKey script} -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const typeforce = require('typeforce'); -const p2ms = require('../multisig'); -const p2pk = require('../pubkey'); -const p2pkh = require('../pubkeyhash'); -function check(chunks, allowIncomplete) { - typeforce(typeforce.Array, chunks); - if (chunks.length < 1) return false; - const witnessScript = chunks[chunks.length - 1]; - if (!Buffer.isBuffer(witnessScript)) return false; - const witnessScriptChunks = bscript.decompile(witnessScript); - // is witnessScript a valid script? - if (!witnessScriptChunks || witnessScriptChunks.length === 0) return false; - const witnessRawScriptSig = bscript.compile(chunks.slice(0, -1)); - // match types - if ( - p2pkh.input.check(witnessRawScriptSig) && - p2pkh.output.check(witnessScriptChunks) - ) - return true; - if ( - p2ms.input.check(witnessRawScriptSig, allowIncomplete) && - p2ms.output.check(witnessScriptChunks) - ) - return true; - if ( - p2pk.input.check(witnessRawScriptSig) && - p2pk.output.check(witnessScriptChunks) - ) - return true; - return false; -} -exports.check = check; -check.toJSON = () => { - return 'witnessScriptHash input'; -}; diff --git a/src/templates/witnessscripthash/output.js b/src/templates/witnessscripthash/output.js deleted file mode 100644 index f69a429..0000000 --- a/src/templates/witnessscripthash/output.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; -// OP_0 {scriptHash} -Object.defineProperty(exports, '__esModule', { value: true }); -const bscript = require('../../script'); -const script_1 = require('../../script'); -function check(script) { - const buffer = bscript.compile(script); - return ( - buffer.length === 34 && - buffer[0] === script_1.OPS.OP_0 && - buffer[1] === 0x20 - ); -} -exports.check = check; -check.toJSON = () => { - return 'Witness scriptHash output'; -}; diff --git a/test/classify.spec.ts b/test/classify.spec.ts deleted file mode 100644 index 931250e..0000000 --- a/test/classify.spec.ts +++ /dev/null @@ -1,180 +0,0 @@ -import * as assert from 'assert'; -import { describe, it } from 'mocha'; -import * as classify from '../src/classify'; -import * as bscript from '../src/script'; - -import * as fixtures from './fixtures/templates.json'; - -import * as multisig from '../src/templates/multisig'; -import * as nullData from '../src/templates/nulldata'; -import * as pubKey from '../src/templates/pubkey'; -import * as pubKeyHash from '../src/templates/pubkeyhash'; -import * as scriptHash from '../src/templates/scripthash'; -import * as witnessCommitment from '../src/templates/witnesscommitment'; -import * as witnessPubKeyHash from '../src/templates/witnesspubkeyhash'; -import * as witnessScriptHash from '../src/templates/witnessscripthash'; - -const tmap = { - pubKey, - pubKeyHash, - scriptHash, - witnessPubKeyHash, - witnessScriptHash, - multisig, - nullData, - witnessCommitment, -}; - -describe('classify', () => { - describe('input', () => { - fixtures.valid.forEach(f => { - if (!f.input) return; - - it('classifies ' + f.input + ' as ' + f.type, () => { - const input = bscript.fromASM(f.input); - const type = classify.input(input); - - assert.strictEqual(type, f.type); - }); - }); - - fixtures.valid.forEach(f => { - if (!f.input) return; - if (!f.typeIncomplete) return; - - it('classifies incomplete ' + f.input + ' as ' + f.typeIncomplete, () => { - const input = bscript.fromASM(f.input); - const type = classify.input(input, true); - - assert.strictEqual(type, f.typeIncomplete); - }); - }); - }); - - describe('classifyOutput', () => { - fixtures.valid.forEach(f => { - if (!f.output) return; - - it('classifies ' + f.output + ' as ' + f.type, () => { - const output = bscript.fromASM(f.output); - const type = classify.output(output); - - assert.strictEqual(type, f.type); - }); - }); - }); - [ - 'pubKey', - 'pubKeyHash', - 'scriptHash', - 'witnessPubKeyHash', - 'witnessScriptHash', - 'multisig', - 'nullData', - 'witnessCommitment', - ].forEach(name => { - const inputType = (tmap as any)[name].input; - const outputType = (tmap as any)[name].output; - - describe(name + '.input.check', () => { - fixtures.valid.forEach(f => { - if (name.toLowerCase() === classify.types.P2WPKH) return; - if (name.toLowerCase() === classify.types.P2WSH) return; - const expected = name.toLowerCase() === f.type.toLowerCase(); - - if (inputType && f.input) { - const input = bscript.fromASM(f.input); - - it('returns ' + expected + ' for ' + f.input, () => { - assert.strictEqual(inputType.check(input), expected); - }); - - if (f.typeIncomplete) { - const expectedIncomplete = name.toLowerCase() === f.typeIncomplete; - - it('returns ' + expected + ' for ' + f.input, () => { - assert.strictEqual( - inputType.check(input, true), - expectedIncomplete, - ); - }); - } - } - }); - - if (!(fixtures.invalid as any)[name]) return; - - (fixtures.invalid as any)[name].inputs.forEach((f: any) => { - if (!f.input && !f.inputHex) return; - - it( - 'returns false for ' + - f.description + - ' (' + - (f.input || f.inputHex) + - ')', - () => { - let input; - - if (f.input) { - input = bscript.fromASM(f.input); - } else { - input = Buffer.from(f.inputHex, 'hex'); - } - - assert.strictEqual(inputType.check(input), false); - }, - ); - }); - }); - - describe(name + '.output.check', () => { - fixtures.valid.forEach(f => { - const expected = name.toLowerCase() === f.type; - - if (outputType && f.output) { - it('returns ' + expected + ' for ' + f.output, () => { - const output = bscript.fromASM(f.output); - - if ( - name.toLowerCase() === 'nulldata' && - f.type === classify.types.WITNESS_COMMITMENT - ) - return; - if ( - name.toLowerCase() === 'witnesscommitment' && - f.type === classify.types.NULLDATA - ) - return; - assert.strictEqual(outputType.check(output), expected); - }); - } - }); - - if (!(fixtures.invalid as any)[name]) return; - - (fixtures.invalid as any)[name].outputs.forEach((f: any) => { - if (!f.output && !f.outputHex) return; - - it( - 'returns false for ' + - f.description + - ' (' + - (f.output || f.outputHex) + - ')', - () => { - let output; - - if (f.output) { - output = bscript.fromASM(f.output); - } else { - output = Buffer.from(f.outputHex, 'hex'); - } - - assert.strictEqual(outputType.check(output), false); - }, - ); - }); - }); - }); -}); diff --git a/test/fixtures/templates.json b/test/fixtures/templates.json index 61728c0..848d264 100644 --- a/test/fixtures/templates.json +++ b/test/fixtures/templates.json @@ -255,276 +255,5 @@ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ] } - ], - "invalid": { - "pubKey": { - "inputs": [ - { - "description": "non-canonical signature (too short)", - "input": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf7593" - }, - { - "description": "non-canonical signature (too long)", - "input": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca28ffffffff01" - }, - { - "description": "non-canonical signature (invalid hashType)", - "input": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca28ff" - } - ], - "outputs": [ - { - "description": "non-canonical pubkey (too short)", - "output": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce OP_CHECKSIG" - }, - { - "description": "non-canonical pubkey (too long)", - "output": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1ffffff OP_CHECKSIG" - }, - { - "description": "last operator is wrong for pubkey-output", - "outputHex": "21027a71801ab59336de37785c50005b6abd8ea859eecce1edbe8e81afa74ee5c752ae" - }, - { - "description": "missing OP_CHECKSIG", - "outputHex": "21027a71801ab59336de37785c50005b6abd8ea859eecce1edbe8e81afa74ee5c752" - }, - { - "description": "non-canonical pubkey (bad prefix)", - "output": "427a71801ab59336de37785c50005b6abd8ea859eecce1edbe8e81afa74ee5c752 OP_CHECKSIG" - }, - { - "description": "has extra opcode at the end isPubKeyOutput", - "output": "027a71801ab59336de37785c50005b6abd8ea859eecce1edbe8e81afa74ee5c752 OP_CHECKSIG OP_0" - } - ] - }, - "pubKeyHash": { - "inputs": [ - { - "description": "pubKeyHash input : extraneous data", - "input": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 ffffffff" - } - ], - "outputs": [ - { - "description": "non-minimal encoded isPubKeyHashOutput (non BIP62 compliant)", - "outputHex": "76a94c14aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac" - }, - { - "description": "bad OP_DUP isPubKeyHashOutput", - "outputHex": "aca914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac" - }, - { - "description": "bad OP_HASH160 isPubKeyHashOutput", - "outputHex": "76ac14aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac" - }, - { - "description": "bad OP_EQUALVERIFY isPubKeyHashOutput", - "outputHex": "76a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5acac" - }, - { - "description": "bad OP_CHECKSIG isPubKeyHashOutput", - "outputHex": "76a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c58888" - }, - { - "description": "bad length isPubKeyHashOutput", - "outputHex": "76a920aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac" - }, - { - "description": "has something at the end isPubKeyHashOutput", - "outputHex": "76a920aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac00" - }, - { - "exception": "Expected Buffer\\(Length: 20\\), got Buffer\\(Length: 2\\)", - "hash": "ffff" - } - ] - }, - "scriptHash": { - "inputs": [ - { - "description": "redeemScript not data", - "input": "OP_0 304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501 OP_RESERVED" - }, - { - "description": "redeemScript is a signature, therefore not a valid script", - "input": "OP_0 3045022100e12b17b3a4c80c401a1687487bd2bafee9e5f1f8f1ffc6180ce186672ad7b43a02205e316d1e5e71822f5ef301b694e578fa9c94af4f5f098c952c833f4691307f4e01" - } - ], - "outputs": [ - { - "description": "non-minimal encoded isScriptHashOutput (non BIP62 compliant)", - "outputHex": "a94c14c286a1af0947f58d1ad787385b1c2c4a976f9e7187" - }, - { - "description": "wrong OP_HASH160 opcode", - "outputHex": "ac4c14c286a1af0947f58d1ad787385b1c2c4a976f9e7187" - }, - { - "description": "wrong length marker", - "outputHex": "a916c286a1af0947f58d1ad787385b1c2c4a976f9e7187" - }, - { - "description": "wrong OP_EQUAL opcode", - "outputHex": "a914c286a1af0947f58d1ad787385b1c2c4a976f9e7188" - }, - { - "exception": "Expected Buffer\\(Length: 20\\), got Buffer\\(Length: 3\\)", - "hash": "ffffff" - } - ] - }, - "multisig": { - "inputs": [ - { - "description": "Not enough signatures provided", - "type": "multisig", - "output": "OP_2 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_2 OP_CHECKMULTISIG", - "signatures": [] - }, - { - "exception": "Not enough signatures provided", - "output": "OP_2 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a OP_2 OP_CHECKMULTISIG", - "signatures": [ - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801" - ] - }, - { - "exception": "Too many signatures provided", - "output": "OP_2 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a OP_2 OP_CHECKMULTISIG", - "signatures": [ - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", - "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" - ] - } - ], - "outputs": [ - { - "description": "OP_CHECKMULTISIG not found", - "output": "OP_0 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_2 OP_HASH160" - }, - { - "description": "less than 4 chunks", - "output": "OP_0 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 OP_HASH160" - }, - { - "description": "m === 0", - "output": "OP_0 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_2 OP_CHECKMULTISIG" - }, - { - "description": "m < OP_1", - "output": "OP_1NEGATE 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_2 OP_CHECKMULTISIG" - }, - { - "description": "m > OP_16", - "output": "OP_NOP 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_2 OP_CHECKMULTISIG" - }, - { - "description": "n === 0", - "output": "OP_1 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_0 OP_CHECKMULTISIG" - }, - { - "description": "n < OP_1", - "output": "OP_1 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_1NEGATE OP_CHECKMULTISIG" - }, - { - "description": "n > OP_16", - "output": "OP_1 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_NOP OP_CHECKMULTISIG" - }, - { - "description": "n < m", - "output": "OP_2 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 OP_1 OP_CHECKMULTISIG" - }, - { - "description": "n < len(pubKeys)", - "output": "OP_2 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 OP_2 OP_CHECKMULTISIG" - }, - { - "description": "n > len(pubKeys)", - "output": "OP_1 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 OP_2 OP_CHECKMULTISIG" - }, - { - "description": "m is data", - "output": "ffff 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 OP_1 OP_CHECKMULTISIG" - }, - { - "description": "n is data", - "output": "OP_1 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 ffff OP_CHECKMULTISIG" - }, - { - "description": "non-canonical pubKey (bad length)", - "output": "OP_1 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffff OP_1 OP_CHECKMULTISIG" - }, - { - "exception": "Not enough pubKeys provided", - "m": 4, - "pubKeys": [ - "02ea1297665dd733d444f31ec2581020004892cdaaf3dd6c0107c615afb839785f", - "02fab2dea1458990793f56f42e4a47dbf35a12a351f26fa5d7e0cc7447eaafa21f", - "036c6802ce7e8113723dd92cdb852e492ebb157a871ca532c3cb9ed08248ff0e19" - ], - "signatures": [ - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801" - ] - } - ] - }, - "witnessPubKeyHash": { - "inputs": [], - "outputs": [ - { - "description": "wrong version", - "outputHex": "51149090909090909090909090909090909090909090" - }, - { - "description": "wrong length marker", - "outputHex": "00209090909090909090909090909090909090909090" - }, - { - "exception": "Expected Buffer\\(Length: 20\\), got Buffer\\(Length: 3\\)", - "hash": "ffffff" - } - ] - }, - "witnessScriptHash": { - "inputs": [], - "outputs": [ - { - "description": "wrong version", - "outputHex": "51209090909090909090909090909090909090909090909090909090909090909090" - }, - { - "description": "wrong length marker", - "outputHex": "00219090909090909090909090909090909090909090909090909090909090909090" - }, - { - "exception": "Expected Buffer\\(Length: 32\\), got Buffer\\(Length: 3\\)", - "hash": "ffffff" - } - ] - }, - "witnessCommitment": { - "inputs": [], - "outputs": [ - { - "exception": "", - "commitment": "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd" - }, - { - "description": "wrong OPCODE at the start", - "scriptPubKeyHex": "6024aa21a9ed4db4fb830efe3e804337413ffe8ad7393af301e0ec8e71b6e6f2b860a56f4dcd" - }, - { - "description": "wrong length marker", - "scriptPubKeyHex": "6a23aa21a9ed4db4fb830efe3e804337413ffe8ad7393af301e0ec8e71b6e6f2b860a56f4dcd" - }, - { - "description": "commitment of wrong length", - "scriptPubKeyHex": "6a23aa21a9ed4db4fb830efe3e804337413ffe8ad7393af301e0ec8e71b6e6f2b860a56f4d" - } - ] - } - } + ] } diff --git a/ts_src/classify.ts b/ts_src/classify.ts deleted file mode 100644 index 319e934..0000000 --- a/ts_src/classify.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { decompile } from './script'; -import * as multisig from './templates/multisig'; -import * as nullData from './templates/nulldata'; -import * as pubKey from './templates/pubkey'; -import * as pubKeyHash from './templates/pubkeyhash'; -import * as scriptHash from './templates/scripthash'; -import * as witnessCommitment from './templates/witnesscommitment'; -import * as witnessPubKeyHash from './templates/witnesspubkeyhash'; -import * as witnessScriptHash from './templates/witnessscripthash'; - -const types = { - P2MS: 'multisig' as string, - NONSTANDARD: 'nonstandard' as string, - NULLDATA: 'nulldata' as string, - P2PK: 'pubkey' as string, - P2PKH: 'pubkeyhash' as string, - P2SH: 'scripthash' as string, - P2WPKH: 'witnesspubkeyhash' as string, - P2WSH: 'witnessscripthash' as string, - WITNESS_COMMITMENT: 'witnesscommitment' as string, -}; - -function classifyOutput(script: Buffer): string { - if (witnessPubKeyHash.output.check(script)) return types.P2WPKH; - if (witnessScriptHash.output.check(script)) return types.P2WSH; - if (pubKeyHash.output.check(script)) return types.P2PKH; - if (scriptHash.output.check(script)) return types.P2SH; - - // XXX: optimization, below functions .decompile before use - const chunks = decompile(script); - if (!chunks) throw new TypeError('Invalid script'); - - if (multisig.output.check(chunks)) return types.P2MS; - if (pubKey.output.check(chunks)) return types.P2PK; - if (witnessCommitment.output.check(chunks)) return types.WITNESS_COMMITMENT; - if (nullData.output.check(chunks)) return types.NULLDATA; - - return types.NONSTANDARD; -} - -function classifyInput(script: Buffer, allowIncomplete?: boolean): string { - // XXX: optimization, below functions .decompile before use - const chunks = decompile(script); - if (!chunks) throw new TypeError('Invalid script'); - - if (pubKeyHash.input.check(chunks)) return types.P2PKH; - if (scriptHash.input.check(chunks, allowIncomplete)) return types.P2SH; - if (multisig.input.check(chunks, allowIncomplete)) return types.P2MS; - if (pubKey.input.check(chunks)) return types.P2PK; - - return types.NONSTANDARD; -} - -function classifyWitness(script: Buffer[], allowIncomplete?: boolean): string { - // XXX: optimization, below functions .decompile before use - const chunks = decompile(script); - if (!chunks) throw new TypeError('Invalid script'); - - if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH; - if (witnessScriptHash.input.check(chunks as Buffer[], allowIncomplete)) - return types.P2WSH; - - return types.NONSTANDARD; -} - -export { - classifyInput as input, - classifyOutput as output, - classifyWitness as witness, - types, -}; diff --git a/ts_src/templates/multisig/index.ts b/ts_src/templates/multisig/index.ts deleted file mode 100644 index aa2bdcb..0000000 --- a/ts_src/templates/multisig/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as input from './input'; -import * as output from './output'; - -export { input, output }; diff --git a/ts_src/templates/multisig/input.ts b/ts_src/templates/multisig/input.ts deleted file mode 100644 index 31fe416..0000000 --- a/ts_src/templates/multisig/input.ts +++ /dev/null @@ -1,31 +0,0 @@ -// OP_0 [signatures ...] - -import { Stack } from '../../payments'; -import * as bscript from '../../script'; -import { OPS } from '../../script'; - -function partialSignature(value: number | Buffer): boolean { - return ( - value === OPS.OP_0 || bscript.isCanonicalScriptSignature(value as Buffer) - ); -} - -export function check( - script: Buffer | Stack, - allowIncomplete?: boolean, -): boolean { - const chunks = bscript.decompile(script) as Stack; - if (chunks.length < 2) return false; - if (chunks[0] !== OPS.OP_0) return false; - - if (allowIncomplete) { - return chunks.slice(1).every(partialSignature); - } - - return (chunks.slice(1) as Buffer[]).every( - bscript.isCanonicalScriptSignature, - ); -} -check.toJSON = (): string => { - return 'multisig input'; -}; diff --git a/ts_src/templates/multisig/output.ts b/ts_src/templates/multisig/output.ts deleted file mode 100644 index 20c2162..0000000 --- a/ts_src/templates/multisig/output.ts +++ /dev/null @@ -1,33 +0,0 @@ -// m [pubKeys ...] n OP_CHECKMULTISIG - -import { Stack } from '../../payments'; -import * as bscript from '../../script'; -import { OPS } from '../../script'; -import * as types from '../../types'; -const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1 - -export function check( - script: Buffer | Stack, - allowIncomplete?: boolean, -): boolean { - const chunks = bscript.decompile(script) as Stack; - - if (chunks.length < 4) return false; - if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false; - if (!types.Number(chunks[0])) return false; - if (!types.Number(chunks[chunks.length - 2])) return false; - const m = (chunks[0] as number) - OP_INT_BASE; - const n = (chunks[chunks.length - 2] as number) - OP_INT_BASE; - - if (m <= 0) return false; - if (n > 16) return false; - if (m > n) return false; - if (n !== chunks.length - 3) return false; - if (allowIncomplete) return true; - - const keys = chunks.slice(1, -2) as Buffer[]; - return keys.every(bscript.isCanonicalPubKey); -} -check.toJSON = (): string => { - return 'multi-sig output'; -}; diff --git a/ts_src/templates/nulldata.ts b/ts_src/templates/nulldata.ts deleted file mode 100644 index 99b5c44..0000000 --- a/ts_src/templates/nulldata.ts +++ /dev/null @@ -1,16 +0,0 @@ -// OP_RETURN {data} -import * as bscript from '../script'; -const OPS = bscript.OPS; - -export function check(script: Buffer | Array): boolean { - const buffer = bscript.compile(script); - - return buffer.length > 1 && buffer[0] === OPS.OP_RETURN; -} -check.toJSON = (): string => { - return 'null data output'; -}; - -const output = { check }; - -export { output }; diff --git a/ts_src/templates/pubkey/index.ts b/ts_src/templates/pubkey/index.ts deleted file mode 100644 index aa2bdcb..0000000 --- a/ts_src/templates/pubkey/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as input from './input'; -import * as output from './output'; - -export { input, output }; diff --git a/ts_src/templates/pubkey/input.ts b/ts_src/templates/pubkey/input.ts deleted file mode 100644 index 745e6d9..0000000 --- a/ts_src/templates/pubkey/input.ts +++ /dev/null @@ -1,16 +0,0 @@ -// {signature} - -import { Stack } from '../../payments'; -import * as bscript from '../../script'; - -export function check(script: Buffer | Stack): boolean { - const chunks = bscript.decompile(script) as Stack; - - return ( - chunks.length === 1 && - bscript.isCanonicalScriptSignature(chunks[0] as Buffer) - ); -} -check.toJSON = (): string => { - return 'pubKey input'; -}; diff --git a/ts_src/templates/pubkey/output.ts b/ts_src/templates/pubkey/output.ts deleted file mode 100644 index 1b2c391..0000000 --- a/ts_src/templates/pubkey/output.ts +++ /dev/null @@ -1,18 +0,0 @@ -// {pubKey} OP_CHECKSIG - -import { Stack } from '../../payments'; -import * as bscript from '../../script'; -import { OPS } from '../../script'; - -export function check(script: Buffer | Stack): boolean { - const chunks = bscript.decompile(script) as Stack; - - return ( - chunks.length === 2 && - bscript.isCanonicalPubKey(chunks[0] as Buffer) && - chunks[1] === OPS.OP_CHECKSIG - ); -} -check.toJSON = (): string => { - return 'pubKey output'; -}; diff --git a/ts_src/templates/pubkeyhash/index.ts b/ts_src/templates/pubkeyhash/index.ts deleted file mode 100644 index aa2bdcb..0000000 --- a/ts_src/templates/pubkeyhash/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as input from './input'; -import * as output from './output'; - -export { input, output }; diff --git a/ts_src/templates/pubkeyhash/input.ts b/ts_src/templates/pubkeyhash/input.ts deleted file mode 100644 index de93968..0000000 --- a/ts_src/templates/pubkeyhash/input.ts +++ /dev/null @@ -1,17 +0,0 @@ -// {signature} {pubKey} - -import { Stack } from '../../payments'; -import * as bscript from '../../script'; - -export function check(script: Buffer | Stack): boolean { - const chunks = bscript.decompile(script) as Stack; - - return ( - chunks.length === 2 && - bscript.isCanonicalScriptSignature(chunks[0] as Buffer) && - bscript.isCanonicalPubKey(chunks[1] as Buffer) - ); -} -check.toJSON = (): string => { - return 'pubKeyHash input'; -}; diff --git a/ts_src/templates/pubkeyhash/output.ts b/ts_src/templates/pubkeyhash/output.ts deleted file mode 100644 index 248c210..0000000 --- a/ts_src/templates/pubkeyhash/output.ts +++ /dev/null @@ -1,20 +0,0 @@ -// OP_DUP OP_HASH160 {pubKeyHash} OP_EQUALVERIFY OP_CHECKSIG - -import * as bscript from '../../script'; -import { OPS } from '../../script'; - -export function check(script: Buffer | Array): boolean { - const buffer = bscript.compile(script); - - return ( - buffer.length === 25 && - buffer[0] === OPS.OP_DUP && - buffer[1] === OPS.OP_HASH160 && - buffer[2] === 0x14 && - buffer[23] === OPS.OP_EQUALVERIFY && - buffer[24] === OPS.OP_CHECKSIG - ); -} -check.toJSON = (): string => { - return 'pubKeyHash output'; -}; diff --git a/ts_src/templates/scripthash/index.ts b/ts_src/templates/scripthash/index.ts deleted file mode 100644 index aa2bdcb..0000000 --- a/ts_src/templates/scripthash/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as input from './input'; -import * as output from './output'; - -export { input, output }; diff --git a/ts_src/templates/scripthash/input.ts b/ts_src/templates/scripthash/input.ts deleted file mode 100644 index 3ef8aab..0000000 --- a/ts_src/templates/scripthash/input.ts +++ /dev/null @@ -1,61 +0,0 @@ -// {serialized scriptPubKey script} - -import * as bscript from '../../script'; -import * as p2ms from '../multisig'; -import * as p2pk from '../pubkey'; -import * as p2pkh from '../pubkeyhash'; -import * as p2wpkho from '../witnesspubkeyhash/output'; -import * as p2wsho from '../witnessscripthash/output'; - -export function check( - script: Buffer | Array, - allowIncomplete?: boolean, -): boolean { - const chunks = bscript.decompile(script)!; - if (chunks.length < 1) return false; - - const lastChunk = chunks[chunks.length - 1]; - if (!Buffer.isBuffer(lastChunk)) return false; - - const scriptSigChunks = bscript.decompile( - bscript.compile(chunks.slice(0, -1)), - )!; - const redeemScriptChunks = bscript.decompile(lastChunk); - - // is redeemScript a valid script? - if (!redeemScriptChunks) return false; - - // is redeemScriptSig push only? - if (!bscript.isPushOnly(scriptSigChunks)) return false; - - // is witness? - if (chunks.length === 1) { - return ( - p2wsho.check(redeemScriptChunks) || p2wpkho.check(redeemScriptChunks) - ); - } - - // match types - if ( - p2pkh.input.check(scriptSigChunks) && - p2pkh.output.check(redeemScriptChunks) - ) - return true; - - if ( - p2ms.input.check(scriptSigChunks, allowIncomplete) && - p2ms.output.check(redeemScriptChunks) - ) - return true; - - if ( - p2pk.input.check(scriptSigChunks) && - p2pk.output.check(redeemScriptChunks) - ) - return true; - - return false; -} -check.toJSON = (): string => { - return 'scriptHash input'; -}; diff --git a/ts_src/templates/scripthash/output.ts b/ts_src/templates/scripthash/output.ts deleted file mode 100644 index aea8e24..0000000 --- a/ts_src/templates/scripthash/output.ts +++ /dev/null @@ -1,18 +0,0 @@ -// OP_HASH160 {scriptHash} OP_EQUAL - -import * as bscript from '../../script'; -import { OPS } from '../../script'; - -export function check(script: Buffer | Array): boolean { - const buffer = bscript.compile(script); - - return ( - buffer.length === 23 && - buffer[0] === OPS.OP_HASH160 && - buffer[1] === 0x14 && - buffer[22] === OPS.OP_EQUAL - ); -} -check.toJSON = (): string => { - return 'scriptHash output'; -}; diff --git a/ts_src/templates/witnesscommitment/index.ts b/ts_src/templates/witnesscommitment/index.ts deleted file mode 100644 index d5c166d..0000000 --- a/ts_src/templates/witnesscommitment/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as output from './output'; - -export { output }; diff --git a/ts_src/templates/witnesscommitment/output.ts b/ts_src/templates/witnesscommitment/output.ts deleted file mode 100644 index 482798f..0000000 --- a/ts_src/templates/witnesscommitment/output.ts +++ /dev/null @@ -1,40 +0,0 @@ -// OP_RETURN {aa21a9ed} {commitment} - -import * as bscript from '../../script'; -import { OPS } from '../../script'; -import * as types from '../../types'; - -const typeforce = require('typeforce'); - -const HEADER: Buffer = Buffer.from('aa21a9ed', 'hex'); - -export function check(script: Buffer | Array): boolean { - const buffer = bscript.compile(script); - - return ( - buffer.length > 37 && - buffer[0] === OPS.OP_RETURN && - buffer[1] === 0x24 && - buffer.slice(2, 6).equals(HEADER) - ); -} - -check.toJSON = (): string => { - return 'Witness commitment output'; -}; - -export function encode(commitment: Buffer): Buffer { - typeforce(types.Hash256bit, commitment); - - const buffer = Buffer.allocUnsafe(36); - HEADER.copy(buffer, 0); - commitment.copy(buffer, 4); - - return bscript.compile([OPS.OP_RETURN, buffer]); -} - -export function decode(buffer: Buffer): Buffer { - typeforce(check, buffer); - - return (bscript.decompile(buffer)![1] as Buffer).slice(4, 36); -} diff --git a/ts_src/templates/witnesspubkeyhash/index.ts b/ts_src/templates/witnesspubkeyhash/index.ts deleted file mode 100644 index aa2bdcb..0000000 --- a/ts_src/templates/witnesspubkeyhash/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as input from './input'; -import * as output from './output'; - -export { input, output }; diff --git a/ts_src/templates/witnesspubkeyhash/input.ts b/ts_src/templates/witnesspubkeyhash/input.ts deleted file mode 100644 index 26fe63d..0000000 --- a/ts_src/templates/witnesspubkeyhash/input.ts +++ /dev/null @@ -1,21 +0,0 @@ -// {signature} {pubKey} - -import { Stack } from '../../payments'; -import * as bscript from '../../script'; - -function isCompressedCanonicalPubKey(pubKey: Buffer): boolean { - return bscript.isCanonicalPubKey(pubKey) && pubKey.length === 33; -} - -export function check(script: Buffer | Stack): boolean { - const chunks = bscript.decompile(script) as Stack; - - return ( - chunks.length === 2 && - bscript.isCanonicalScriptSignature(chunks[0] as Buffer) && - isCompressedCanonicalPubKey(chunks[1] as Buffer) - ); -} -check.toJSON = (): string => { - return 'witnessPubKeyHash input'; -}; diff --git a/ts_src/templates/witnesspubkeyhash/output.ts b/ts_src/templates/witnesspubkeyhash/output.ts deleted file mode 100644 index bfd6690..0000000 --- a/ts_src/templates/witnesspubkeyhash/output.ts +++ /dev/null @@ -1,13 +0,0 @@ -// OP_0 {pubKeyHash} - -import * as bscript from '../../script'; -import { OPS } from '../../script'; - -export function check(script: Buffer | Array): boolean { - const buffer = bscript.compile(script); - - return buffer.length === 22 && buffer[0] === OPS.OP_0 && buffer[1] === 0x14; -} -check.toJSON = (): string => { - return 'Witness pubKeyHash output'; -}; diff --git a/ts_src/templates/witnessscripthash/index.ts b/ts_src/templates/witnessscripthash/index.ts deleted file mode 100644 index aa2bdcb..0000000 --- a/ts_src/templates/witnessscripthash/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as input from './input'; -import * as output from './output'; - -export { input, output }; diff --git a/ts_src/templates/witnessscripthash/input.ts b/ts_src/templates/witnessscripthash/input.ts deleted file mode 100644 index 0f63330..0000000 --- a/ts_src/templates/witnessscripthash/input.ts +++ /dev/null @@ -1,47 +0,0 @@ -// {serialized scriptPubKey script} - -import * as bscript from '../../script'; -const typeforce = require('typeforce'); - -import * as p2ms from '../multisig'; -import * as p2pk from '../pubkey'; -import * as p2pkh from '../pubkeyhash'; - -export function check(chunks: Buffer[], allowIncomplete?: boolean): boolean { - typeforce(typeforce.Array, chunks); - if (chunks.length < 1) return false; - - const witnessScript = chunks[chunks.length - 1]; - if (!Buffer.isBuffer(witnessScript)) return false; - - const witnessScriptChunks = bscript.decompile(witnessScript); - - // is witnessScript a valid script? - if (!witnessScriptChunks || witnessScriptChunks.length === 0) return false; - - const witnessRawScriptSig = bscript.compile(chunks.slice(0, -1)); - - // match types - if ( - p2pkh.input.check(witnessRawScriptSig) && - p2pkh.output.check(witnessScriptChunks) - ) - return true; - - if ( - p2ms.input.check(witnessRawScriptSig, allowIncomplete) && - p2ms.output.check(witnessScriptChunks) - ) - return true; - - if ( - p2pk.input.check(witnessRawScriptSig) && - p2pk.output.check(witnessScriptChunks) - ) - return true; - - return false; -} -check.toJSON = (): string => { - return 'witnessScriptHash input'; -}; diff --git a/ts_src/templates/witnessscripthash/output.ts b/ts_src/templates/witnessscripthash/output.ts deleted file mode 100644 index 7d4f33a..0000000 --- a/ts_src/templates/witnessscripthash/output.ts +++ /dev/null @@ -1,13 +0,0 @@ -// OP_0 {scriptHash} - -import * as bscript from '../../script'; -import { OPS } from '../../script'; - -export function check(script: Buffer | Array): boolean { - const buffer = bscript.compile(script); - - return buffer.length === 34 && buffer[0] === OPS.OP_0 && buffer[1] === 0x20; -} -check.toJSON = (): string => { - return 'Witness scriptHash output'; -}; diff --git a/types/classify.d.ts b/types/classify.d.ts deleted file mode 100644 index 6ea4754..0000000 --- a/types/classify.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -declare const types: { - P2MS: string; - NONSTANDARD: string; - NULLDATA: string; - P2PK: string; - P2PKH: string; - P2SH: string; - P2WPKH: string; - P2WSH: string; - WITNESS_COMMITMENT: string; -}; -declare function classifyOutput(script: Buffer): string; -declare function classifyInput(script: Buffer, allowIncomplete?: boolean): string; -declare function classifyWitness(script: Buffer[], allowIncomplete?: boolean): string; -export { classifyInput as input, classifyOutput as output, classifyWitness as witness, types, }; diff --git a/types/templates/multisig/index.d.ts b/types/templates/multisig/index.d.ts deleted file mode 100644 index f6288e2..0000000 --- a/types/templates/multisig/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as input from './input'; -import * as output from './output'; -export { input, output }; diff --git a/types/templates/multisig/input.d.ts b/types/templates/multisig/input.d.ts deleted file mode 100644 index 6d46515..0000000 --- a/types/templates/multisig/input.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from '../../payments'; -export declare function check(script: Buffer | Stack, allowIncomplete?: boolean): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/multisig/output.d.ts b/types/templates/multisig/output.d.ts deleted file mode 100644 index 6d46515..0000000 --- a/types/templates/multisig/output.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from '../../payments'; -export declare function check(script: Buffer | Stack, allowIncomplete?: boolean): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/nulldata.d.ts b/types/templates/nulldata.d.ts deleted file mode 100644 index bf6497c..0000000 --- a/types/templates/nulldata.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export declare function check(script: Buffer | Array): boolean; -export declare namespace check { - var toJSON: () => string; -} -declare const output: { - check: typeof check; -}; -export { output }; diff --git a/types/templates/pubkey/index.d.ts b/types/templates/pubkey/index.d.ts deleted file mode 100644 index f6288e2..0000000 --- a/types/templates/pubkey/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as input from './input'; -import * as output from './output'; -export { input, output }; diff --git a/types/templates/pubkey/input.d.ts b/types/templates/pubkey/input.d.ts deleted file mode 100644 index 4b70d2d..0000000 --- a/types/templates/pubkey/input.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from '../../payments'; -export declare function check(script: Buffer | Stack): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/pubkey/output.d.ts b/types/templates/pubkey/output.d.ts deleted file mode 100644 index 4b70d2d..0000000 --- a/types/templates/pubkey/output.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from '../../payments'; -export declare function check(script: Buffer | Stack): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/pubkeyhash/index.d.ts b/types/templates/pubkeyhash/index.d.ts deleted file mode 100644 index f6288e2..0000000 --- a/types/templates/pubkeyhash/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as input from './input'; -import * as output from './output'; -export { input, output }; diff --git a/types/templates/pubkeyhash/input.d.ts b/types/templates/pubkeyhash/input.d.ts deleted file mode 100644 index 4b70d2d..0000000 --- a/types/templates/pubkeyhash/input.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from '../../payments'; -export declare function check(script: Buffer | Stack): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/pubkeyhash/output.d.ts b/types/templates/pubkeyhash/output.d.ts deleted file mode 100644 index d66d8ac..0000000 --- a/types/templates/pubkeyhash/output.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export declare function check(script: Buffer | Array): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/scripthash/index.d.ts b/types/templates/scripthash/index.d.ts deleted file mode 100644 index f6288e2..0000000 --- a/types/templates/scripthash/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as input from './input'; -import * as output from './output'; -export { input, output }; diff --git a/types/templates/scripthash/input.d.ts b/types/templates/scripthash/input.d.ts deleted file mode 100644 index 14bbd5b..0000000 --- a/types/templates/scripthash/input.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export declare function check(script: Buffer | Array, allowIncomplete?: boolean): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/scripthash/output.d.ts b/types/templates/scripthash/output.d.ts deleted file mode 100644 index d66d8ac..0000000 --- a/types/templates/scripthash/output.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export declare function check(script: Buffer | Array): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/witnesscommitment/index.d.ts b/types/templates/witnesscommitment/index.d.ts deleted file mode 100644 index c37ee7c..0000000 --- a/types/templates/witnesscommitment/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import * as output from './output'; -export { output }; diff --git a/types/templates/witnesscommitment/output.d.ts b/types/templates/witnesscommitment/output.d.ts deleted file mode 100644 index ec155a2..0000000 --- a/types/templates/witnesscommitment/output.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export declare function check(script: Buffer | Array): boolean; -export declare namespace check { - var toJSON: () => string; -} -export declare function encode(commitment: Buffer): Buffer; -export declare function decode(buffer: Buffer): Buffer; diff --git a/types/templates/witnesspubkeyhash/index.d.ts b/types/templates/witnesspubkeyhash/index.d.ts deleted file mode 100644 index f6288e2..0000000 --- a/types/templates/witnesspubkeyhash/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as input from './input'; -import * as output from './output'; -export { input, output }; diff --git a/types/templates/witnesspubkeyhash/input.d.ts b/types/templates/witnesspubkeyhash/input.d.ts deleted file mode 100644 index 4b70d2d..0000000 --- a/types/templates/witnesspubkeyhash/input.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from '../../payments'; -export declare function check(script: Buffer | Stack): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/witnesspubkeyhash/output.d.ts b/types/templates/witnesspubkeyhash/output.d.ts deleted file mode 100644 index d66d8ac..0000000 --- a/types/templates/witnesspubkeyhash/output.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export declare function check(script: Buffer | Array): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/witnessscripthash/index.d.ts b/types/templates/witnessscripthash/index.d.ts deleted file mode 100644 index f6288e2..0000000 --- a/types/templates/witnessscripthash/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as input from './input'; -import * as output from './output'; -export { input, output }; diff --git a/types/templates/witnessscripthash/input.d.ts b/types/templates/witnessscripthash/input.d.ts deleted file mode 100644 index 767df3a..0000000 --- a/types/templates/witnessscripthash/input.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export declare function check(chunks: Buffer[], allowIncomplete?: boolean): boolean; -export declare namespace check { - var toJSON: () => string; -} diff --git a/types/templates/witnessscripthash/output.d.ts b/types/templates/witnessscripthash/output.d.ts deleted file mode 100644 index d66d8ac..0000000 --- a/types/templates/witnessscripthash/output.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export declare function check(script: Buffer | Array): boolean; -export declare namespace check { - var toJSON: () => string; -} From b56273a391d8434b5e079b4bd6310916be8c979d Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 27 Nov 2020 12:09:04 +0200 Subject: [PATCH 3/4] #1477 move script.ts test data from templates.json to script.json; remove templates.json --- test/fixtures/script.json | 257 ++++++++++++++++++++++++++++++++++ test/fixtures/templates.json | 259 ----------------------------------- test/script.spec.ts | 3 +- 3 files changed, 258 insertions(+), 261 deletions(-) delete mode 100644 test/fixtures/templates.json diff --git a/test/fixtures/script.json b/test/fixtures/script.json index 5046757..545c8f3 100644 --- a/test/fixtures/script.json +++ b/test/fixtures/script.json @@ -175,6 +175,263 @@ "script": "6a24aa21a9ed4db4fb830efe3e804337413ffe8ad7393af301e0ec8e71b6e6f2b860a56f4dcd" } ], + "valid2": [ + { + "type": "pubkey", + "pubKey": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "signature": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "output": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 OP_CHECKSIG", + "input": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "inputHex": "47304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "outputHex": "2102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1ac", + "inputStack": [ + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801" + ] + }, + { + "type": "pubkeyhash", + "pubKey": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "signature": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "output": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", + "input": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "inputHex": "47304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca28012102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "outputHex": "76a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac", + "inputStack": [ + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1" + ] + }, + { + "type": "multisig", + "pubKeys": [ + "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a" + ], + "signatures": [ + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" + ], + "output": "OP_2 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a OP_2 OP_CHECKMULTISIG", + "input": "OP_0 304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", + "inputHex": "0047304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801483045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", + "outputHex": "522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", + "inputStack": [ + "", + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" + ] + }, + { + "type": "multisig", + "pubKeys": [ + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340", + "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34" + ], + "signatures": [ + "3045022100fe324541215798b2df68cbd44039615e23c506d4ec1a05572064392a98196b82022068c849fa6699206da2fc6d7848efc1d3804a5816d6293615fe34c1a7f34e1c2f01", + "3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901", + "3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01" + ], + "output": "OP_3 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 OP_3 OP_CHECKMULTISIG", + "input": "OP_0 3045022100fe324541215798b2df68cbd44039615e23c506d4ec1a05572064392a98196b82022068c849fa6699206da2fc6d7848efc1d3804a5816d6293615fe34c1a7f34e1c2f01 3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901 3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01", + "inputHex": "00483045022100fe324541215798b2df68cbd44039615e23c506d4ec1a05572064392a98196b82022068c849fa6699206da2fc6d7848efc1d3804a5816d6293615fe34c1a7f34e1c2f01473044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901483045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01", + "outputHex": "53210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817982102b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f84834021024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a3453ae", + "inputStack": [ + "", + "3045022100fe324541215798b2df68cbd44039615e23c506d4ec1a05572064392a98196b82022068c849fa6699206da2fc6d7848efc1d3804a5816d6293615fe34c1a7f34e1c2f01", + "3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901", + "3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01" + ] + }, + { + "type": "scripthash", + "redeemScript": "OP_2 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a OP_2 OP_CHECKMULTISIG", + "redeemScriptSig": "OP_0 304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", + "input": "OP_0 304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501 522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", + "output": "OP_HASH160 722ff0bc2c3f47b35c20df646c395594da24e90e OP_EQUAL", + "inputHex": "0047304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801483045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d14050147522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", + "outputHex": "a914722ff0bc2c3f47b35c20df646c395594da24e90e87", + "inputStack": [ + "", + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", + "522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae" + ] + }, + { + "type": "witnesspubkeyhash", + "pubKey": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", + "signature": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "output": "OP_0 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", + "outputHex": "0014aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", + "inputStack": [ + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1" + ] + }, + { + "type": "witnessscripthash", + "witnessScript": "OP_2 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a OP_2 OP_CHECKMULTISIG", + "witnessData": [ + "", + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" + ], + "output": "OP_0 32447752937d355ca2defddcd1f6b4fc53d182f8901cebbcff42f5e381bf0b80", + "outputHex": "002032447752937d355ca2defddcd1f6b4fc53d182f8901cebbcff42f5e381bf0b80", + "inputStack": [ + "", + "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", + "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", + "522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae" + ] + }, + { + "type": "nulldata", + "data": [ + "06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474" + ], + "output": "OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474", + "outputHex": "6a2606deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474" + }, + { + "type": "nulldata", + "data": [ + "deadffffffffffffffffffffffffffffffffbeef", + "deadffffffffffffffffffffffffffffffffbeef" + ], + "output": "OP_RETURN deadffffffffffffffffffffffffffffffffbeef deadffffffffffffffffffffffffffffffffbeef", + "outputHex": "6a14deadffffffffffffffffffffffffffffffffbeef14deadffffffffffffffffffffffffffffffffbeef" + }, + { + "type": "nulldata", + "data": [ + "deadffffffffffffffffffffffffffffffffbeef" + ], + "output": "OP_RETURN deadffffffffffffffffffffffffffffffffbeef", + "outputHex": "6a14deadffffffffffffffffffffffffffffffffbeef" + }, + { + "type": "nonstandard", + "typeIncomplete": "multisig", + "pubKeys": [ + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340", + "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34" + ], + "signatures": [ + null, + "3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901", + "3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01" + ], + "input": "OP_0 OP_0 3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901 3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01", + "inputHex": "0000473044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901483045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01", + "inputStack": [ + "", + "", + "3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901", + "3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01" + ] + }, + { + "type": "nonstandard", + "typeIncomplete": "multisig", + "pubKeys": [ + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340", + "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34" + ], + "signatures": [ + null, + null, + null + ], + "input": "OP_0 OP_0 OP_0 OP_0", + "inputHex": "00000000", + "inputStack": [ + "", + "", + "", + "" + ] + }, + { + "type": "scripthash", + "redeemScript": "OP_2 0327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a49372 03251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f 02cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde47 OP_3 OP_CHECKMULTISIG", + "redeemScriptSig": "OP_0 304502210093efc26facedc5f51e304aa270a7b4f1a911b2d912c3674e5c6e2ad4ac7a410402201cf0b62c240461902f9f16d8a0bc3a210b7bfcd2c06523dd4b4b63be22e8525201", + "input": "OP_0 304502210093efc26facedc5f51e304aa270a7b4f1a911b2d912c3674e5c6e2ad4ac7a410402201cf0b62c240461902f9f16d8a0bc3a210b7bfcd2c06523dd4b4b63be22e8525201 52210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753ae", + "inputHex": "0048304502210093efc26facedc5f51e304aa270a7b4f1a911b2d912c3674e5c6e2ad4ac7a410402201cf0b62c240461902f9f16d8a0bc3a210b7bfcd2c06523dd4b4b63be22e85252014c6952210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753ae", + "output": "OP_HASH160 fcc42dd4aa770d75cb6796bbd7853a325e746659 OP_EQUAL", + "outputHex": "a914fcc42dd4aa770d75cb6796bbd7853a325e74665987" + }, + { + "type": "nonstandard", + "typeIncomplete": "scripthash", + "pubKeys": [ + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a" + ], + "signatures": [ + null, + "30450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a801" + ], + "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", + "redeemScriptSig": "OP_0 OP_0 30450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a801", + "input": "OP_0 OP_0 30450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a801 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae", + "inputHex": "00004830450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a8014c8752410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae", + "inputStack": [ + "", + "", + "30450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a801", + "52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" + ] + }, + { + "type": "nonstandard", + "output": "OP_HASH256 6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 OP_EQUAL", + "outputHex": "aa206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d619000000000087" + }, + { + "type": "nonstandard", + "output": "OP_0 OP_0 OP_0 OP_CHECKMULTISIG", + "outputHex": "000000ae" + }, + { + "type": "nonstandard", + "output": "OP_0", + "outputHex": "00" + }, + { + "type": "nonstandard", + "input": "OP_0 00", + "inputHex": "000100", + "inputStack": [ + "", + "00" + ] + }, + { + "type": "nonstandard", + "input": "OP_6", + "inputHex": "56", + "nonstandard": { + "input": "06", + "inputHex": "0106" + }, + "inputStack": [ + "06" + ] + }, + { + "type": "nonstandard", + "input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "inputHex": "4cff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "inputStack": [ + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ] + } + ], "invalid": { "decompile": [ { diff --git a/test/fixtures/templates.json b/test/fixtures/templates.json deleted file mode 100644 index 848d264..0000000 --- a/test/fixtures/templates.json +++ /dev/null @@ -1,259 +0,0 @@ -{ - "valid": [ - { - "type": "pubkey", - "pubKey": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", - "signature": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "output": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 OP_CHECKSIG", - "input": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "inputHex": "47304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "outputHex": "2102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1ac", - "inputStack": [ - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801" - ] - }, - { - "type": "pubkeyhash", - "pubKey": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", - "signature": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "output": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG", - "input": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", - "inputHex": "47304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca28012102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", - "outputHex": "76a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac", - "inputStack": [ - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1" - ] - }, - { - "type": "multisig", - "pubKeys": [ - "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", - "0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a" - ], - "signatures": [ - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" - ], - "output": "OP_2 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a OP_2 OP_CHECKMULTISIG", - "input": "OP_0 304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", - "inputHex": "0047304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801483045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", - "outputHex": "522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", - "inputStack": [ - "", - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" - ] - }, - { - "type": "multisig", - "pubKeys": [ - "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340", - "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34" - ], - "signatures": [ - "3045022100fe324541215798b2df68cbd44039615e23c506d4ec1a05572064392a98196b82022068c849fa6699206da2fc6d7848efc1d3804a5816d6293615fe34c1a7f34e1c2f01", - "3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901", - "3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01" - ], - "output": "OP_3 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340 024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34 OP_3 OP_CHECKMULTISIG", - "input": "OP_0 3045022100fe324541215798b2df68cbd44039615e23c506d4ec1a05572064392a98196b82022068c849fa6699206da2fc6d7848efc1d3804a5816d6293615fe34c1a7f34e1c2f01 3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901 3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01", - "inputHex": "00483045022100fe324541215798b2df68cbd44039615e23c506d4ec1a05572064392a98196b82022068c849fa6699206da2fc6d7848efc1d3804a5816d6293615fe34c1a7f34e1c2f01473044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901483045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01", - "outputHex": "53210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817982102b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f84834021024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a3453ae", - "inputStack": [ - "", - "3045022100fe324541215798b2df68cbd44039615e23c506d4ec1a05572064392a98196b82022068c849fa6699206da2fc6d7848efc1d3804a5816d6293615fe34c1a7f34e1c2f01", - "3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901", - "3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01" - ] - }, - { - "type": "scripthash", - "redeemScript": "OP_2 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a OP_2 OP_CHECKMULTISIG", - "redeemScriptSig": "OP_0 304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", - "input": "OP_0 304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801 3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501 522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", - "output": "OP_HASH160 722ff0bc2c3f47b35c20df646c395594da24e90e OP_EQUAL", - "inputHex": "0047304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801483045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d14050147522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae", - "outputHex": "a914722ff0bc2c3f47b35c20df646c395594da24e90e87", - "inputStack": [ - "", - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", - "522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae" - ] - }, - { - "type": "witnesspubkeyhash", - "pubKey": "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1", - "signature": "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "output": "OP_0 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", - "outputHex": "0014aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5", - "inputStack": [ - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1" - ] - }, - { - "type": "witnessscripthash", - "witnessScript": "OP_2 02359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1 0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a OP_2 OP_CHECKMULTISIG", - "witnessData": [ - "", - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501" - ], - "output": "OP_0 32447752937d355ca2defddcd1f6b4fc53d182f8901cebbcff42f5e381bf0b80", - "outputHex": "002032447752937d355ca2defddcd1f6b4fc53d182f8901cebbcff42f5e381bf0b80", - "inputStack": [ - "", - "304402207515cf147d201f411092e6be5a64a6006f9308fad7b2a8fdaab22cd86ce764c202200974b8aca7bf51dbf54150d3884e1ae04f675637b926ec33bf75939446f6ca2801", - "3045022100ef253c1faa39e65115872519e5f0a33bbecf430c0f35cf562beabbad4da24d8d02201742be8ee49812a73adea3007c9641ce6725c32cd44ddb8e3a3af460015d140501", - "522102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1210395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a52ae" - ] - }, - { - "type": "nulldata", - "data": [ - "06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474" - ], - "output": "OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474", - "outputHex": "6a2606deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474" - }, - { - "type": "nulldata", - "data": [ - "deadffffffffffffffffffffffffffffffffbeef", - "deadffffffffffffffffffffffffffffffffbeef" - ], - "output": "OP_RETURN deadffffffffffffffffffffffffffffffffbeef deadffffffffffffffffffffffffffffffffbeef", - "outputHex": "6a14deadffffffffffffffffffffffffffffffffbeef14deadffffffffffffffffffffffffffffffffbeef" - }, - { - "type": "nulldata", - "data": [ - "deadffffffffffffffffffffffffffffffffbeef" - ], - "output": "OP_RETURN deadffffffffffffffffffffffffffffffffbeef", - "outputHex": "6a14deadffffffffffffffffffffffffffffffffbeef" - }, - { - "type": "nonstandard", - "typeIncomplete": "multisig", - "pubKeys": [ - "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340", - "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34" - ], - "signatures": [ - null, - "3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901", - "3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01" - ], - "input": "OP_0 OP_0 3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901 3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01", - "inputHex": "0000473044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901483045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01", - "inputStack": [ - "", - "", - "3044022001ab168e80b863fdec694350b587339bb72a37108ac3c989849251444d13ebba02201811272023e3c1038478eb972a82d3ad431bfc2408e88e4da990f1a7ecbb263901", - "3045022100aaeb7204c17eee2f2c4ff1c9f8b39b79e75e7fbf33e92cc67ac51be8f15b75f90220659eee314a4943a6384d2b154fa5821ef7a084814d7ee2c6f9f7f0ffb53be34b01" - ] - }, - { - "type": "nonstandard", - "typeIncomplete": "multisig", - "pubKeys": [ - "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340", - "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34" - ], - "signatures": [ - null, - null, - null - ], - "input": "OP_0 OP_0 OP_0 OP_0", - "inputHex": "00000000", - "inputStack": [ - "", - "", - "", - "" - ] - }, - { - "type": "scripthash", - "redeemScript": "OP_2 0327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a49372 03251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f 02cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde47 OP_3 OP_CHECKMULTISIG", - "redeemScriptSig": "OP_0 304502210093efc26facedc5f51e304aa270a7b4f1a911b2d912c3674e5c6e2ad4ac7a410402201cf0b62c240461902f9f16d8a0bc3a210b7bfcd2c06523dd4b4b63be22e8525201", - "input": "OP_0 304502210093efc26facedc5f51e304aa270a7b4f1a911b2d912c3674e5c6e2ad4ac7a410402201cf0b62c240461902f9f16d8a0bc3a210b7bfcd2c06523dd4b4b63be22e8525201 52210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753ae", - "inputHex": "0048304502210093efc26facedc5f51e304aa270a7b4f1a911b2d912c3674e5c6e2ad4ac7a410402201cf0b62c240461902f9f16d8a0bc3a210b7bfcd2c06523dd4b4b63be22e85252014c6952210327e023a353d111808f61d554c2e1934721eaf87f33b7a771e807006908a493722103251670bb6a179a0d43b75476c7e580c0ba274378a18077e8de0832c870e5381f2102cca7f9a64425a0466d26d5c7e9eb3ad6b64cd48ea89edb38bc08f58a792dde4753ae", - "output": "OP_HASH160 fcc42dd4aa770d75cb6796bbd7853a325e746659 OP_EQUAL", - "outputHex": "a914fcc42dd4aa770d75cb6796bbd7853a325e74665987" - }, - { - "type": "nonstandard", - "typeIncomplete": "scripthash", - "pubKeys": [ - "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", - "04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a" - ], - "signatures": [ - null, - "30450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a801" - ], - "redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG", - "redeemScriptSig": "OP_0 OP_0 30450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a801", - "input": "OP_0 OP_0 30450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a801 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae", - "inputHex": "00004830450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a8014c8752410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae", - "inputStack": [ - "", - "", - "30450221009c92c1ae1767ac04e424da7f6db045d979b08cde86b1ddba48621d59a109d818022004f5bb21ad72255177270abaeb2d7940ac18f1e5ca1f53db4f3fd1045647a8a801", - "52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae" - ] - }, - { - "type": "nonstandard", - "output": "OP_HASH256 6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 OP_EQUAL", - "outputHex": "aa206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d619000000000087" - }, - { - "type": "nonstandard", - "output": "OP_0 OP_0 OP_0 OP_CHECKMULTISIG", - "outputHex": "000000ae" - }, - { - "type": "nonstandard", - "output": "OP_0", - "outputHex": "00" - }, - { - "type": "nonstandard", - "input": "OP_0 00", - "inputHex": "000100", - "inputStack": [ - "", - "00" - ] - }, - { - "type": "nonstandard", - "input": "OP_6", - "inputHex": "56", - "nonstandard": { - "input": "06", - "inputHex": "0106" - }, - "inputStack": [ - "06" - ] - }, - { - "type": "nonstandard", - "input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "inputHex": "4cff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "inputStack": [ - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - ] - } - ] -} diff --git a/test/script.spec.ts b/test/script.spec.ts index fe5fa63..d593ab1 100644 --- a/test/script.spec.ts +++ b/test/script.spec.ts @@ -2,7 +2,6 @@ import * as assert from 'assert'; import { describe, it } from 'mocha'; import * as bscript from '../src/script'; import * as fixtures from './fixtures/script.json'; -import * as fixtures2 from './fixtures/templates.json'; const minimalData = require('minimaldata'); describe('script', () => { @@ -57,7 +56,7 @@ describe('script', () => { }); describe('fromASM/toASM (templates)', () => { - fixtures2.valid.forEach(f => { + fixtures.valid2.forEach(f => { if (f.inputHex) { const ih = bscript.toASM(Buffer.from(f.inputHex, 'hex')); From ec61b996ad3c783208fe200275660066d70d7248 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Wed, 2 Dec 2020 11:54:32 +0200 Subject: [PATCH 4/4] #1477 do not remove comments refering TransactionBuilder, but instead mention that TransactionBuilder was removed --- ts_src/psbt.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ts_src/psbt.ts b/ts_src/psbt.ts index d5eb9f9..6c56132 100644 --- a/ts_src/psbt.ts +++ b/ts_src/psbt.ts @@ -117,6 +117,8 @@ export class Psbt { __NON_WITNESS_UTXO_BUF_CACHE: [], __TX_IN_CACHE: {}, __TX: (this.data.globalMap.unsignedTx as PsbtTransaction).tx, + // Psbt's predecesor (TransactionBuilder - now removed) behavior + // was to not confirm input values before signing. // Even though we highly encourage people to get // the full parent transaction to verify values, the ability to // sign non-segwit inputs without the full transaction was often @@ -1294,7 +1296,8 @@ function getHashForSig( console.warn( 'Warning: Signing non-segwit inputs without the full parent transaction ' + 'means there is a chance that a miner could feed you incorrect information ' + - 'to trick you into paying large fees. You are not ' + + 'to trick you into paying large fees. This behavior is the same as Psbt\'s predecesor ' + + '(TransactionBuilder - now removed) when signing non-segwit scripts. You are not ' + 'able to export this Psbt with toBuffer|toBase64|toHex since it is not ' + 'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' + '*********************',