From 6cacea6f31aa18cce61bed562d730c55ac3709d3 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
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)
-      })
-    })
-  })
-})