From 6cacea6f31aa18cce61bed562d730c55ac3709d3 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Tue, 3 Jul 2018 21:43:34 +1000 Subject: [PATCH] rm templates export, rename to classify --- src/address.js | 22 +- src/{templates/index.js => classify.js} | 32 +- src/index.js | 4 - src/transaction_builder.js | 16 +- test/classify.js | 157 ++++++++ test/templates.js | 514 ------------------------ 6 files changed, 188 insertions(+), 557 deletions(-) rename src/{templates/index.js => classify.js} (71%) create mode 100644 test/classify.js delete mode 100644 test/templates.js diff --git a/src/address.js b/src/address.js index 13fa69c..e71bd46 100644 --- a/src/address.js +++ b/src/address.js @@ -2,10 +2,10 @@ const Buffer = require('safe-buffer').Buffer const bech32 = require('bech32') const bs58check = require('bs58check') const bscript = require('./script') -const btemplates = require('./templates') const networks = require('./networks') const typeforce = require('typeforce') const types = require('./types') +const payments = require('./payments') function fromBase58Check (address) { const payload = bs58check.decode(address) @@ -48,15 +48,15 @@ function toBech32 (data, version, prefix) { return bech32.encode(prefix, words) } -function fromOutputScript (outputScript, network) { +function fromOutputScript (output, network) { network = network || networks.bitcoin - if (btemplates.pubKeyHash.output.check(outputScript)) return toBase58Check(bscript.compile(outputScript).slice(3, 23), network.pubKeyHash) - if (btemplates.scriptHash.output.check(outputScript)) return toBase58Check(bscript.compile(outputScript).slice(2, 22), network.scriptHash) - if (btemplates.witnessPubKeyHash.output.check(outputScript)) return toBech32(bscript.compile(outputScript).slice(2, 22), 0, network.bech32) - if (btemplates.witnessScriptHash.output.check(outputScript)) return toBech32(bscript.compile(outputScript).slice(2, 34), 0, network.bech32) + try { return payments.p2pkh({ output, network }).address } catch (e) {} + try { return payments.p2sh({ output, network }).address } catch (e) {} + try { return payments.p2wpkh({ output, network }).address } catch (e) {} + try { return payments.p2wsh({ output, network }).address } catch (e) {} - throw new Error(bscript.toASM(outputScript) + ' has no matching Address') + throw new Error(bscript.toASM(output) + ' has no matching Address') } function toOutputScript (address, network) { @@ -68,8 +68,8 @@ function toOutputScript (address, network) { } catch (e) {} if (decode) { - if (decode.version === network.pubKeyHash) return btemplates.pubKeyHash.output.encode(decode.hash) - if (decode.version === network.scriptHash) return btemplates.scriptHash.output.encode(decode.hash) + if (decode.version === network.pubKeyHash) return payments.p2pkh({ hash: decode.hash }).output + if (decode.version === network.scriptHash) return payments.p2sh({ hash: decode.hash }).output } else { try { decode = fromBech32(address) @@ -78,8 +78,8 @@ function toOutputScript (address, network) { if (decode) { if (decode.prefix !== network.bech32) throw new Error(address + ' has an invalid prefix') if (decode.version === 0) { - if (decode.data.length === 20) return btemplates.witnessPubKeyHash.output.encode(decode.data) - if (decode.data.length === 32) return btemplates.witnessScriptHash.output.encode(decode.data) + if (decode.data.length === 20) return payments.p2wpkh({ hash: decode.data }).output + if (decode.data.length === 32) return payments.p2wsh({ hash: decode.data }).output } } } diff --git a/src/templates/index.js b/src/classify.js similarity index 71% rename from src/templates/index.js rename to src/classify.js index 94ce996..0b98fa6 100644 --- a/src/templates/index.js +++ b/src/classify.js @@ -1,12 +1,12 @@ -const decompile = require('../script').decompile -const multisig = require('./multisig') -const nullData = require('./nulldata') -const pubKey = require('./pubkey') -const pubKeyHash = require('./pubkeyhash') -const scriptHash = require('./scripthash') -const witnessPubKeyHash = require('./witnesspubkeyhash') -const witnessScriptHash = require('./witnessscripthash') -const witnessCommitment = require('./witnesscommitment') +const decompile = require('./script').decompile +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 witnessPubKeyHash = require('./templates/witnesspubkeyhash') +const witnessScriptHash = require('./templates/witnessscripthash') +const witnessCommitment = require('./templates/witnesscommitment') const types = { MULTISIG: 'multisig', @@ -63,16 +63,8 @@ function classifyWitness (script, allowIncomplete) { } module.exports = { - classifyInput: classifyInput, - classifyOutput: classifyOutput, - classifyWitness: classifyWitness, - multisig: multisig, - nullData: nullData, - pubKey: pubKey, - pubKeyHash: pubKeyHash, - scriptHash: scriptHash, - witnessPubKeyHash: witnessPubKeyHash, - witnessScriptHash: witnessScriptHash, - witnessCommitment: witnessCommitment, + input: classifyInput, + output: classifyOutput, + witness: classifyWitness, types: types } diff --git a/src/index.js b/src/index.js index 603c64f..213e98a 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,4 @@ const script = require('./script') -const templates = require('./templates') -for (let key in templates) { - script[key] = templates[key] -} module.exports = { Block: require('./block'), diff --git a/src/transaction_builder.js b/src/transaction_builder.js index 0f6b1ce..55c6e21 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -2,13 +2,13 @@ const Buffer = require('safe-buffer').Buffer const baddress = require('./address') const bcrypto = require('./crypto') const bscript = require('./script') -const btemplates = require('./templates') const networks = require('./networks') const ops = require('bitcoin-ops') const payments = require('./payments') -const SCRIPT_TYPES = btemplates.types const typeforce = require('typeforce') const types = require('./types') +const classify = require('./classify') +const SCRIPT_TYPES = classify.types const ECPair = require('./ecpair') const Transaction = require('./transaction') @@ -16,8 +16,8 @@ const Transaction = require('./transaction') function expandInput (scriptSig, witnessStack, type, scriptPubKey) { if (scriptSig.length === 0 && witnessStack.length === 0) return {} if (!type) { - let ssType = btemplates.classifyInput(scriptSig, true) - let wsType = btemplates.classifyWitness(witnessStack, true) + 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 @@ -76,7 +76,7 @@ function expandInput (scriptSig, witnessStack, type, scriptPubKey) { witness: witnessStack }) - const outputType = btemplates.classifyOutput(redeem.output) + const outputType = classify.output(redeem.output) const expanded = expandInput(redeem.input, redeem.witness, outputType, redeem.output) if (!expanded.prevOutType) return {} @@ -98,7 +98,7 @@ function expandInput (scriptSig, witnessStack, type, scriptPubKey) { input: scriptSig, witness: witnessStack }) - const outputType = btemplates.classifyOutput(redeem.output) + const outputType = classify.output(redeem.output) let expanded if (outputType === SCRIPT_TYPES.P2WPKH) { expanded = expandInput(redeem.input, redeem.witness, outputType) @@ -160,7 +160,7 @@ function fixMultisigOrder (input, transaction, vin) { function expandOutput (script, ourPubKey) { typeforce(types.Buffer, script) - const type = btemplates.classifyOutput(script) + const type = classify.output(script) switch (type) { case SCRIPT_TYPES.P2PKH: { @@ -543,7 +543,7 @@ TransactionBuilder.prototype.__addInputUnsafe = function (txHash, vout, options) } input.prevOutScript = options.prevOutScript - input.prevOutType = prevOutType || btemplates.classifyOutput(options.prevOutScript) + input.prevOutType = prevOutType || classify.output(options.prevOutScript) } const vin = this.__tx.addInput(txHash, vout, options.sequence, options.scriptSig) diff --git a/test/classify.js b/test/classify.js new file mode 100644 index 0000000..f56647e --- /dev/null +++ b/test/classify.js @@ -0,0 +1,157 @@ +/* global describe, it */ + +const assert = require('assert') +const bscript = require('../src/script') +const classify = require('../src/classify') + +const fixtures = require('./fixtures/templates.json') + +const multisig = require('../src/templates/multisig') +const nullData = require('../src/templates/nulldata') +const pubKey = require('../src/templates/pubkey') +const pubKeyHash = require('../src/templates/pubkeyhash') +const scriptHash = require('../src/templates/scripthash') +const witnessPubKeyHash = require('../src/templates/witnesspubkeyhash') +const witnessScriptHash = require('../src/templates/witnessscripthash') +const witnessCommitment = require('../src/templates/witnesscommitment') + +const tmap = { + pubKey, + pubKeyHash, + scriptHash, + witnessPubKeyHash, + witnessScriptHash, + multisig, + nullData, + witnessCommitment +} + +describe('classify', function () { + describe('input', function () { + fixtures.valid.forEach(function (f) { + if (!f.input) return + + it('classifies ' + f.input + ' as ' + f.type, function () { + const input = bscript.fromASM(f.input) + const type = classify.input(input) + + assert.strictEqual(type, f.type) + }) + }) + + fixtures.valid.forEach(function (f) { + if (!f.input) return + if (!f.typeIncomplete) return + + it('classifies incomplete ' + f.input + ' as ' + f.typeIncomplete, function () { + const input = bscript.fromASM(f.input) + const type = classify.input(input, true) + + assert.strictEqual(type, f.typeIncomplete) + }) + }) + }) + + describe('classifyOutput', function () { + fixtures.valid.forEach(function (f) { + if (!f.output) return + + it('classifies ' + f.output + ' as ' + f.type, function () { + 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(function (name) { + const inputType = tmap[name].input + const outputType = tmap[name].output + + describe(name + '.input.check', function () { + fixtures.valid.forEach(function (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, function () { + assert.strictEqual(inputType.check(input), expected) + }) + + if (f.typeIncomplete) { + const expectedIncomplete = name.toLowerCase() === f.typeIncomplete + + it('returns ' + expected + ' for ' + f.input, function () { + assert.strictEqual(inputType.check(input, true), expectedIncomplete) + }) + } + } + }) + + if (!(fixtures.invalid[name])) return + + fixtures.invalid[name].inputs.forEach(function (f) { + if (!f.input && !f.inputHex) return + + it('returns false for ' + f.description + ' (' + (f.input || f.inputHex) + ')', function () { + 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', function () { + fixtures.valid.forEach(function (f) { + const expected = name.toLowerCase() === f.type + + if (outputType && f.output) { + it('returns ' + expected + ' for ' + f.output, function () { + 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[name])) return + + fixtures.invalid[name].outputs.forEach(function (f) { + if (!f.output && !f.outputHex) return + + it('returns false for ' + f.description + ' (' + (f.output || f.outputHex) + ')', function () { + 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/templates.js b/test/templates.js deleted file mode 100644 index 7058c51..0000000 --- a/test/templates.js +++ /dev/null @@ -1,514 +0,0 @@ -/* global describe, it */ - -const assert = require('assert') -const bcrypto = require('../src/crypto') -const bscript = require('../src/script') -const btemplates = require('../src/templates') -const ops = require('bitcoin-ops') - -const fixtures = require('./fixtures/templates.json') - -function fromHex (x) { return Buffer.from(x, 'hex') } -function toHex (x) { return x.toString('hex') } - -describe('script-templates', function () { - describe('classifyInput', function () { - fixtures.valid.forEach(function (f) { - if (!f.input) return - - it('classifies ' + f.input + ' as ' + f.type, function () { - const input = bscript.fromASM(f.input) - const type = btemplates.classifyInput(input) - - assert.strictEqual(type, f.type) - }) - }) - - fixtures.valid.forEach(function (f) { - if (!f.input) return - if (!f.typeIncomplete) return - - it('classifies incomplete ' + f.input + ' as ' + f.typeIncomplete, function () { - const input = bscript.fromASM(f.input) - const type = btemplates.classifyInput(input, true) - - assert.strictEqual(type, f.typeIncomplete) - }) - }) - }) - - describe('classifyOutput', function () { - fixtures.valid.forEach(function (f) { - if (!f.output) return - - it('classifies ' + f.output + ' as ' + f.type, function () { - const output = bscript.fromASM(f.output) - const type = btemplates.classifyOutput(output) - - assert.strictEqual(type, f.type) - }) - }) - }) - - ;[ - 'pubKey', - 'pubKeyHash', - 'scriptHash', - 'witnessPubKeyHash', - 'witnessScriptHash', - 'multisig', - 'nullData', - 'witnessCommitment' - ].forEach(function (name) { - const inputType = btemplates[name].input - const outputType = btemplates[name].output - - describe(name + '.input.check', function () { - fixtures.valid.forEach(function (f) { - if (name.toLowerCase() === btemplates.types.P2WPKH) return - if (name.toLowerCase() === btemplates.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, function () { - assert.strictEqual(inputType.check(input), expected) - }) - - if (f.typeIncomplete) { - const expectedIncomplete = name.toLowerCase() === f.typeIncomplete - - it('returns ' + expected + ' for ' + f.input, function () { - assert.strictEqual(inputType.check(input, true), expectedIncomplete) - }) - } - } - }) - - if (!(fixtures.invalid[name])) return - - fixtures.invalid[name].inputs.forEach(function (f) { - if (!f.input && !f.inputHex) return - - it('returns false for ' + f.description + ' (' + (f.input || f.inputHex) + ')', function () { - 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', function () { - fixtures.valid.forEach(function (f) { - const expected = name.toLowerCase() === f.type - - if (outputType && f.output) { - it('returns ' + expected + ' for ' + f.output, function () { - const output = bscript.fromASM(f.output) - - if (name.toLowerCase() === 'nulldata' && f.type === btemplates.types.WITNESS_COMMITMENT) return - if (name.toLowerCase() === 'witnesscommitment' && f.type === btemplates.types.NULLDATA) return - assert.strictEqual(outputType.check(output), expected) - }) - } - }) - - if (!(fixtures.invalid[name])) return - - fixtures.invalid[name].outputs.forEach(function (f) { - if (!f.output && !f.outputHex) return - - it('returns false for ' + f.description + ' (' + (f.output || f.outputHex) + ')', function () { - let output - - if (f.output) { - output = bscript.fromASM(f.output) - } else { - output = Buffer.from(f.outputHex, 'hex') - } - - assert.strictEqual(outputType.check(output), false) - }) - }) - }) - }) - - describe('pubKey.input', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'pubkey') return - - const signature = Buffer.from(f.signature, 'hex') - const input = btemplates.pubKey.input.encode(signature) - - it('encodes to ' + f.input, function () { - assert.strictEqual(bscript.toASM(input), f.input) - }) - - it('decodes to ' + f.signature, function () { - assert.deepEqual(btemplates.pubKey.input.decode(input), signature) - }) - }) - }) - - describe('pubKey.output', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'pubkey') return - - const pubKey = Buffer.from(f.pubKey, 'hex') - const output = btemplates.pubKey.output.encode(pubKey) - - it('encodes to ' + f.output, function () { - assert.strictEqual(bscript.toASM(output), f.output) - }) - - it('decodes to ' + f.pubKey, function () { - assert.deepEqual(btemplates.pubKey.output.decode(output), pubKey) - }) - }) - }) - - describe('pubKeyHash.input', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'pubkeyhash') return - - const pubKey = Buffer.from(f.pubKey, 'hex') - const signature = Buffer.from(f.signature, 'hex') - const input = btemplates.pubKeyHash.input.encode(signature, pubKey) - - it('encodes to ' + f.input, function () { - assert.strictEqual(bscript.toASM(input), f.input) - }) - - it('decodes to original arguments', function () { - assert.deepEqual(btemplates.pubKeyHash.input.decode(input), { - signature: signature, - pubKey: pubKey - }) - }) - }) - }) - - describe('pubKeyHash.output', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'pubkeyhash') return - - const pubKey = Buffer.from(f.pubKey, 'hex') - const pubKeyHash = bcrypto.hash160(pubKey) - const output = btemplates.pubKeyHash.output.encode(pubKeyHash) - - it('encodes to ' + f.output, function () { - assert.strictEqual(bscript.toASM(output), f.output) - }) - - it('decodes to ' + pubKeyHash.toString('hex'), function () { - assert.deepEqual(btemplates.pubKeyHash.output.decode(output), pubKeyHash) - }) - }) - - fixtures.invalid.pubKeyHash.outputs.forEach(function (f) { - if (!f.hash) return - const hash = Buffer.from(f.hash, 'hex') - - it('throws on ' + f.exception, function () { - assert.throws(function () { - btemplates.pubKeyHash.output.encode(hash) - }, new RegExp(f.exception)) - }) - }) - }) - - describe('multisig.input', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'multisig' && f.typeIncomplete !== 'multisig') return - const allowIncomplete = f.typeIncomplete !== undefined - - const signatures = f.signatures.map(function (signature) { - return signature ? Buffer.from(signature, 'hex') : ops.OP_0 - }) - - const input = btemplates.multisig.input.encode(signatures) - - it('encodes to ' + f.input, function () { - assert.strictEqual(bscript.toASM(input), f.input) - }) - - it('decodes to ' + signatures.map(function (x) { return x === ops.OP_0 ? 'OP_0' : x.toString('hex') }), function () { - assert.deepEqual(btemplates.multisig.input.decode(input, allowIncomplete), signatures) - }) - }) - - fixtures.invalid.multisig.inputs.forEach(function (f) { - if (!f.output) return - const output = bscript.fromASM(f.output) - - it('throws on ' + f.exception, function () { - const signatures = f.signatures.map(function (signature) { - return signature ? Buffer.from(signature, 'hex') : ops.OP_0 - }) - - assert.throws(function () { - btemplates.multisig.input.encode(signatures, output) - }, new RegExp(f.exception)) - }) - }) - }) - - describe('multisig.output', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'multisig') return - - const pubKeys = f.pubKeys.map(function (p) { return Buffer.from(p, 'hex') }) - const m = pubKeys.length - - const output = btemplates.multisig.output.encode(m, pubKeys) - - it('encodes ' + f.output, function () { - assert.strictEqual(bscript.toASM(output), f.output) - }) - - it('decodes to original arguments', function () { - assert.deepEqual(btemplates.multisig.output.decode(output), { - m: m, - pubKeys: pubKeys - }) - }) - }) - - fixtures.invalid.multisig.outputs.forEach(function (f) { - if (!f.pubKeys) return - const pubKeys = f.pubKeys.map(function (p) { - return Buffer.from(p, 'hex') - }) - - it('throws on ' + f.exception, function () { - assert.throws(function () { - btemplates.multisig.output.encode(f.m, pubKeys) - }, new RegExp(f.exception)) - }) - }) - }) - - describe('scriptHash.input', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'scripthash') return - - const redeemScriptSig = bscript.fromASM(f.redeemScriptSig) - const redeemScript = bscript.fromASM(f.redeemScript) - const input = btemplates.scriptHash.input.encode(redeemScriptSig, redeemScript) - - it('encodes to ' + f.output, function () { - if (f.input) { - assert.strictEqual(bscript.toASM(input), f.input) - } else { - assert.strictEqual(input.toString('hex'), f.inputHex) - } - }) - - it('decodes to original arguments', function () { - assert.deepEqual(btemplates.scriptHash.input.decode(input), { - redeemScriptSig: redeemScriptSig, - redeemScript: redeemScript - }) - }) - }) - }) - - describe('scriptHash.output', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'scripthash') return - if (!f.output) return - - const redeemScript = bscript.fromASM(f.redeemScript) - const scriptHash = bcrypto.hash160(redeemScript) - const output = btemplates.scriptHash.output.encode(scriptHash) - - it('encodes to ' + f.output, function () { - assert.strictEqual(bscript.toASM(output), f.output) - }) - - it('decodes to ' + scriptHash.toString('hex'), function () { - assert.deepEqual(btemplates.scriptHash.output.decode(output), scriptHash) - }) - }) - - fixtures.invalid.scriptHash.outputs.forEach(function (f) { - if (!f.hash) return - const hash = Buffer.from(f.hash, 'hex') - - it('throws on ' + f.exception, function () { - assert.throws(function () { - btemplates.scriptHash.output.encode(hash) - }, new RegExp(f.exception)) - }) - }) - }) - - describe('witnessPubKeyHash.input', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'pubkeyhash' && f.type !== 'witnesspubkeyhash') return - if (!f.inputStack) return - - const pubKey = Buffer.from(f.pubKey, 'hex') - const signature = Buffer.from(f.signature, 'hex') - - it('encodes to ' + f.input, function () { - const inputStack = btemplates.witnessPubKeyHash.input.encodeStack(signature, pubKey) - - assert.deepEqual(inputStack.map(toHex), f.inputStack) - }) - - it('decodes to original arguments', function () { - const fInputStack = f.inputStack.map(fromHex) - - assert.deepEqual(btemplates.witnessPubKeyHash.input.decodeStack(fInputStack), { - signature: signature, - pubKey: pubKey - }) - }) - }) - }) - - describe('witnessPubKeyHash.output', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'witnesspubkeyhash') return - if (!f.output) return - - const pubKey = Buffer.from(f.pubKey, 'hex') - const pubKeyHash = bcrypto.hash160(pubKey) - const output = btemplates.witnessPubKeyHash.output.encode(pubKeyHash) - - it('encodes to ' + f.output, function () { - assert.strictEqual(bscript.toASM(output), f.output) - }) - - it('decodes to ' + pubKeyHash.toString('hex'), function () { - assert.deepEqual(btemplates.witnessPubKeyHash.output.decode(output), pubKeyHash) - }) - }) - - fixtures.invalid.witnessPubKeyHash.outputs.forEach(function (f) { - if (!f.hash) return - const hash = Buffer.from(f.hash, 'hex') - - it('throws on ' + f.exception, function () { - assert.throws(function () { - btemplates.witnessPubKeyHash.output.encode(hash) - }, new RegExp(f.exception)) - }) - }) - }) - - describe('witnessScriptHash.input', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'witnessscripthash') return - if (!f.inputStack || !f.witnessData) return - - const witnessData = f.witnessData.map(fromHex) - const witnessScript = bscript.fromASM(f.witnessScript || f.redeemScript) - - it('encodes to ' + f.input, function () { - const inputStack = btemplates.witnessScriptHash.input.encodeStack(witnessData, witnessScript) - - assert.deepEqual(inputStack.map(toHex), f.inputStack) - }) - - it('decodes to original arguments', function () { - const result = btemplates.witnessScriptHash.input.decodeStack(f.inputStack.map(fromHex)) - - assert.deepEqual(result.witnessData.map(toHex), f.witnessData) - assert.strictEqual(bscript.toASM(result.witnessScript), f.witnessScript) - }) - }) - }) - - describe('witnessScriptHash.output', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'witnessscripthash') return - if (!f.output) return - - const witnessScriptPubKey = bscript.fromASM(f.witnessScript) - const scriptHash = bcrypto.hash256(witnessScriptPubKey) - const output = btemplates.witnessScriptHash.output.encode(scriptHash) - - it('encodes to ' + f.output, function () { - assert.strictEqual(bscript.toASM(output), f.output) - }) - - it('decodes to ' + scriptHash.toString('hex'), function () { - assert.deepEqual(btemplates.witnessScriptHash.output.decode(output), scriptHash) - }) - }) - - fixtures.invalid.witnessScriptHash.outputs.forEach(function (f) { - if (!f.hash) return - const hash = Buffer.from(f.hash, 'hex') - - it('throws on ' + f.exception, function () { - assert.throws(function () { - btemplates.witnessScriptHash.output.encode(hash) - }, new RegExp(f.exception)) - }) - }) - }) - - describe('witnessCommitment.output', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'witnesscommitment') return - if (!f.scriptPubKey) return - - const commitment = Buffer.from(f.witnessCommitment, 'hex') - const scriptPubKey = btemplates.witnessCommitment.output.encode(commitment) - - it('encodes to ' + f.scriptPubKey, function () { - assert.strictEqual(bscript.toASM(scriptPubKey), f.scriptPubKey) - }) - - it('decodes to ' + commitment.toString('hex'), function () { - assert.deepEqual(btemplates.witnessCommitment.output.decode(scriptPubKey), commitment) - }) - }) - - fixtures.invalid.witnessCommitment.outputs.forEach(function (f) { - if (f.commitment) { - const hash = Buffer.from(f.commitment, 'hex') - it('throws on bad encode data', function () { - assert.throws(function () { - btemplates.witnessCommitment.output.encode(hash) - }, new RegExp(f.exception)) - }) - } - - if (f.scriptPubKeyHex) { - it('.decode throws on ' + f.description, function () { - assert.throws(function () { - btemplates.witnessCommitment.output.decode(Buffer.from(f.scriptPubKeyHex, 'hex')) - }, new RegExp(f.exception)) - }) - } - }) - }) - - describe('nullData.output', function () { - fixtures.valid.forEach(function (f) { - if (f.type !== 'nulldata') return - - const data = f.data.map(function (x) { return Buffer.from(x, 'hex') }) - const output = btemplates.nullData.output.encode(data) - - it('encodes to ' + f.output, function () { - assert.strictEqual(bscript.toASM(output), f.output) - }) - - it('decodes to ' + f.data, function () { - assert.deepEqual(btemplates.nullData.output.decode(output), data) - }) - }) - }) -})