Tests to arrow functions, use strict asserts, travis uses docker instead of regtest server

This commit is contained in:
junderw 2019-04-09 15:09:50 +09:00
parent 16823e9013
commit dc1ef5958b
No known key found for this signature in database
GPG key ID: B256185D3A971908
24 changed files with 505 additions and 498 deletions

View file

@ -1,5 +1,11 @@
sudo: false sudo: false
language: node_js language: node_js
services:
- docker
before_install:
- docker pull junderw/bitcoinjs-regtest-server
- docker run -d -p 127.0.0.1:8080:8080 junderw/bitcoinjs-regtest-server
- docker ps -a
node_js: node_js:
- "8" - "8"
- "lts/*" - "lts/*"
@ -15,5 +21,5 @@ matrix:
env: TEST_SUITE=coverage env: TEST_SUITE=coverage
env: env:
- TEST_SUITE=unit - TEST_SUITE=unit
- TEST_SUITE=integration - TEST_SUITE=integration APIURL=http://127.0.0.1:8080/1
script: npm run-script $TEST_SUITE script: npm run-script $TEST_SUITE

View file

@ -16,12 +16,12 @@ const NETWORKS = Object.assign({
} }
}, require('../src/networks')) }, require('../src/networks'))
describe('address', function () { describe('address', () => {
describe('fromBase58Check', function () { describe('fromBase58Check', () => {
fixtures.standard.forEach(function (f) { fixtures.standard.forEach(f => {
if (!f.base58check) return if (!f.base58check) return
it('decodes ' + f.base58check, function () { it('decodes ' + f.base58check, () => {
const decode = baddress.fromBase58Check(f.base58check) const decode = baddress.fromBase58Check(f.base58check)
assert.strictEqual(decode.version, f.version) assert.strictEqual(decode.version, f.version)
@ -29,20 +29,20 @@ describe('address', function () {
}) })
}) })
fixtures.invalid.fromBase58Check.forEach(function (f) { fixtures.invalid.fromBase58Check.forEach(f => {
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, () => {
assert.throws(function () { assert.throws(() => {
baddress.fromBase58Check(f.address) baddress.fromBase58Check(f.address)
}, new RegExp(f.address + ' ' + f.exception)) }, new RegExp(f.address + ' ' + f.exception))
}) })
}) })
}) })
describe('fromBech32', function () { describe('fromBech32', () => {
fixtures.standard.forEach((f) => { fixtures.standard.forEach(f => {
if (!f.bech32) return if (!f.bech32) return
it('decodes ' + f.bech32, function () { it('decodes ' + f.bech32, () => {
const actual = baddress.fromBech32(f.bech32) const actual = baddress.fromBech32(f.bech32)
assert.strictEqual(actual.version, f.version) assert.strictEqual(actual.version, f.version)
@ -52,17 +52,17 @@ describe('address', function () {
}) })
fixtures.invalid.bech32.forEach((f, i) => { fixtures.invalid.bech32.forEach((f, i) => {
it('decode fails for ' + f.bech32 + '(' + f.exception + ')', function () { it('decode fails for ' + f.bech32 + '(' + f.exception + ')', () => {
assert.throws(function () { assert.throws(() => {
baddress.fromBech32(f.address) baddress.fromBech32(f.address)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('fromOutputScript', function () { describe('fromOutputScript', () => {
fixtures.standard.forEach(function (f) { fixtures.standard.forEach(f => {
it('encodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', function () { it('encodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', () => {
const script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script)
const address = baddress.fromOutputScript(script, NETWORKS[f.network]) const address = baddress.fromOutputScript(script, NETWORKS[f.network])
@ -70,22 +70,22 @@ describe('address', function () {
}) })
}) })
fixtures.invalid.fromOutputScript.forEach(function (f) { fixtures.invalid.fromOutputScript.forEach(f => {
it('throws when ' + f.script.slice(0, 30) + '... ' + f.exception, function () { it('throws when ' + f.script.slice(0, 30) + '... ' + f.exception, () => {
const script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script)
assert.throws(function () { assert.throws(() => {
baddress.fromOutputScript(script) baddress.fromOutputScript(script)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('toBase58Check', function () { describe('toBase58Check', () => {
fixtures.standard.forEach(function (f) { fixtures.standard.forEach(f => {
if (!f.base58check) return if (!f.base58check) return
it('encodes ' + f.hash + ' (' + f.network + ')', function () { it('encodes ' + f.hash + ' (' + f.network + ')', () => {
const address = baddress.toBase58Check(Buffer.from(f.hash, 'hex'), f.version) const address = baddress.toBase58Check(Buffer.from(f.hash, 'hex'), f.version)
assert.strictEqual(address, f.base58check) assert.strictEqual(address, f.base58check)
@ -93,39 +93,39 @@ describe('address', function () {
}) })
}) })
describe('toBech32', function () { describe('toBech32', () => {
fixtures.bech32.forEach((f, i) => { fixtures.bech32.forEach((f, i) => {
if (!f.bech32) return if (!f.bech32) return
const data = Buffer.from(f.data, 'hex') const data = Buffer.from(f.data, 'hex')
it('encode ' + f.address, function () { it('encode ' + f.address, () => {
assert.deepEqual(baddress.toBech32(data, f.version, f.prefix), f.address) assert.deepStrictEqual(baddress.toBech32(data, f.version, f.prefix), f.address)
}) })
}) })
fixtures.invalid.bech32.forEach((f, i) => { fixtures.invalid.bech32.forEach((f, i) => {
if (!f.prefix || f.version === undefined || f.data === undefined) return if (!f.prefix || f.version === undefined || f.data === undefined) return
it('encode fails (' + f.exception, function () { it('encode fails (' + f.exception, () => {
assert.throws(function () { assert.throws(() => {
baddress.toBech32(Buffer.from(f.data, 'hex'), f.version, f.prefix) baddress.toBech32(Buffer.from(f.data, 'hex'), f.version, f.prefix)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('toOutputScript', function () { describe('toOutputScript', () => {
fixtures.standard.forEach(function (f) { fixtures.standard.forEach(f => {
it('decodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', function () { it('decodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', () => {
const script = baddress.toOutputScript(f.base58check || f.bech32, NETWORKS[f.network]) const script = baddress.toOutputScript(f.base58check || f.bech32, NETWORKS[f.network])
assert.strictEqual(bscript.toASM(script), f.script) assert.strictEqual(bscript.toASM(script), f.script)
}) })
}) })
fixtures.invalid.toOutputScript.forEach(function (f) { fixtures.invalid.toOutputScript.forEach(f => {
it('throws when ' + f.exception, function () { it('throws when ' + f.exception, () => {
assert.throws(function () { assert.throws(() => {
baddress.toOutputScript(f.address, f.network) baddress.toOutputScript(f.address, f.network)
}, new RegExp(f.address + ' ' + f.exception)) }, new RegExp(f.address + ' ' + f.exception))
}) })

View file

@ -12,21 +12,21 @@ const sigHash = require('./fixtures/core/sighash.json')
const sigNoncanonical = require('./fixtures/core/sig_noncanonical.json') const sigNoncanonical = require('./fixtures/core/sig_noncanonical.json')
const txValid = require('./fixtures/core/tx_valid.json') const txValid = require('./fixtures/core/tx_valid.json')
describe('Bitcoin-core', function () { describe('Bitcoin-core', () => {
// base58EncodeDecode // base58EncodeDecode
describe('base58', function () { describe('base58', () => {
base58EncodeDecode.forEach(function (f) { base58EncodeDecode.forEach(f => {
const fhex = f[0] const fhex = f[0]
const fb58 = f[1] const fb58 = f[1]
it('can decode ' + fb58, function () { it('can decode ' + fb58, () => {
const buffer = base58.decode(fb58) const buffer = base58.decode(fb58)
const actual = buffer.toString('hex') const actual = buffer.toString('hex')
assert.strictEqual(actual, fhex) assert.strictEqual(actual, fhex)
}) })
it('can encode ' + fhex, function () { it('can encode ' + fhex, () => {
const buffer = Buffer.from(fhex, 'hex') const buffer = Buffer.from(fhex, 'hex')
const actual = base58.encode(buffer) const actual = base58.encode(buffer)
@ -36,13 +36,13 @@ describe('Bitcoin-core', function () {
}) })
// base58KeysValid // base58KeysValid
describe('address.toBase58Check', function () { describe('address.toBase58Check', () => {
const typeMap = { const typeMap = {
'pubkey': 'pubKeyHash', 'pubkey': 'pubKeyHash',
'script': 'scriptHash' 'script': 'scriptHash'
} }
base58KeysValid.forEach(function (f) { base58KeysValid.forEach(f => {
const expected = f[0] const expected = f[0]
const hash = Buffer.from(f[1], 'hex') const hash = Buffer.from(f[1], 'hex')
const params = f[2] const params = f[2]
@ -52,14 +52,14 @@ describe('Bitcoin-core', function () {
const network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin const network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin
const version = network[typeMap[params.addrType]] const version = network[typeMap[params.addrType]]
it('can export ' + expected, function () { it('can export ' + expected, () => {
assert.strictEqual(bitcoin.address.toBase58Check(hash, version), expected) assert.strictEqual(bitcoin.address.toBase58Check(hash, version), expected)
}) })
}) })
}) })
// base58KeysInvalid // base58KeysInvalid
describe('address.fromBase58Check', function () { describe('address.fromBase58Check', () => {
const allowedNetworks = [ const allowedNetworks = [
bitcoin.networks.bitcoin.pubkeyhash, bitcoin.networks.bitcoin.pubkeyhash,
bitcoin.networks.bitcoin.scripthash, bitcoin.networks.bitcoin.scripthash,
@ -67,22 +67,22 @@ describe('Bitcoin-core', function () {
bitcoin.networks.testnet.scripthash bitcoin.networks.testnet.scripthash
] ]
base58KeysInvalid.forEach(function (f) { base58KeysInvalid.forEach(f => {
const string = f[0] const string = f[0]
it('throws on ' + string, function () { it('throws on ' + string, () => {
assert.throws(function () { assert.throws(() => {
const address = bitcoin.address.fromBase58Check(string) const address = bitcoin.address.fromBase58Check(string)
assert.notEqual(allowedNetworks.indexOf(address.version), -1, 'Invalid network') assert.notStrictEqual(allowedNetworks.indexOf(address.version), -1, 'Invalid network')
}, /(Invalid (checksum|network))|(too (short|long))/) }, /(Invalid (checksum|network))|(too (short|long))/)
}) })
}) })
}) })
// base58KeysValid // base58KeysValid
describe('ECPair', function () { describe('ECPair', () => {
base58KeysValid.forEach(function (f) { base58KeysValid.forEach(f => {
const string = f[0] const string = f[0]
const hex = f[1] const hex = f[1]
const params = f[2] const params = f[2]
@ -92,38 +92,38 @@ describe('Bitcoin-core', function () {
const network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin const network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin
const keyPair = bitcoin.ECPair.fromWIF(string, network) const keyPair = bitcoin.ECPair.fromWIF(string, network)
it('fromWIF imports ' + string, function () { it('fromWIF imports ' + string, () => {
assert.strictEqual(keyPair.privateKey.toString('hex'), hex) assert.strictEqual(keyPair.privateKey.toString('hex'), hex)
assert.strictEqual(keyPair.compressed, params.isCompressed) assert.strictEqual(keyPair.compressed, params.isCompressed)
}) })
it('toWIF exports ' + hex + ' to ' + string, function () { it('toWIF exports ' + hex + ' to ' + string, () => {
assert.strictEqual(keyPair.toWIF(), string) assert.strictEqual(keyPair.toWIF(), string)
}) })
}) })
}) })
// base58KeysInvalid // base58KeysInvalid
describe('ECPair.fromWIF', function () { describe('ECPair.fromWIF', () => {
const allowedNetworks = [ const allowedNetworks = [
bitcoin.networks.bitcoin, bitcoin.networks.bitcoin,
bitcoin.networks.testnet bitcoin.networks.testnet
] ]
base58KeysInvalid.forEach(function (f) { base58KeysInvalid.forEach(f => {
const string = f[0] const string = f[0]
it('throws on ' + string, function () { it('throws on ' + string, () => {
assert.throws(function () { assert.throws(() => {
bitcoin.ECPair.fromWIF(string, allowedNetworks) bitcoin.ECPair.fromWIF(string, allowedNetworks)
}, /(Invalid|Unknown) (checksum|compression flag|network version|WIF length)/) }, /(Invalid|Unknown) (checksum|compression flag|network version|WIF length)/)
}) })
}) })
}) })
describe('Block.fromHex', function () { describe('Block.fromHex', () => {
blocksValid.forEach(function (f) { blocksValid.forEach(f => {
it('can parse ' + f.id, function () { it('can parse ' + f.id, () => {
const block = bitcoin.Block.fromHex(f.hex) const block = bitcoin.Block.fromHex(f.hex)
assert.strictEqual(block.getId(), f.id) assert.strictEqual(block.getId(), f.id)
@ -133,8 +133,8 @@ describe('Bitcoin-core', function () {
}) })
// txValid // txValid
describe('Transaction.fromHex', function () { describe('Transaction.fromHex', () => {
txValid.forEach(function (f) { txValid.forEach(f => {
// Objects that are only a single string are ignored // Objects that are only a single string are ignored
if (f.length === 1) return if (f.length === 1) return
@ -142,17 +142,17 @@ describe('Bitcoin-core', function () {
const fhex = f[1] const fhex = f[1]
// const verifyFlags = f[2] // TODO: do we need to test this? // const verifyFlags = f[2] // TODO: do we need to test this?
it('can decode ' + fhex, function () { it('can decode ' + fhex, () => {
const transaction = bitcoin.Transaction.fromHex(fhex) const transaction = bitcoin.Transaction.fromHex(fhex)
transaction.ins.forEach(function (txIn, i) { transaction.ins.forEach((txIn, i) => {
const input = inputs[i] const input = inputs[i]
// reverse because test data is reversed // reverse because test data is reversed
const prevOutHash = Buffer.from(input[0], 'hex').reverse() const prevOutHash = Buffer.from(input[0], 'hex').reverse()
const prevOutIndex = input[1] const prevOutIndex = input[1]
assert.deepEqual(txIn.hash, prevOutHash) assert.deepStrictEqual(txIn.hash, prevOutHash)
// we read UInt32, not Int32 // we read UInt32, not Int32
assert.strictEqual(txIn.index & 0xffffffff, prevOutIndex) assert.strictEqual(txIn.index & 0xffffffff, prevOutIndex)
@ -162,8 +162,8 @@ describe('Bitcoin-core', function () {
}) })
// sighash // sighash
describe('Transaction', function () { describe('Transaction', () => {
sigHash.forEach(function (f) { sigHash.forEach(f => {
// Objects that are only a single string are ignored // Objects that are only a single string are ignored
if (f.length === 1) return if (f.length === 1) return
@ -181,7 +181,7 @@ describe('Bitcoin-core', function () {
const hashTypeName = hashTypes.join(' | ') const hashTypeName = hashTypes.join(' | ')
it('should hash ' + txHex.slice(0, 40) + '... (' + hashTypeName + ')', function () { it('should hash ' + txHex.slice(0, 40) + '... (' + hashTypeName + ')', () => {
const transaction = bitcoin.Transaction.fromHex(txHex) const transaction = bitcoin.Transaction.fromHex(txHex)
assert.strictEqual(transaction.toHex(), txHex) assert.strictEqual(transaction.toHex(), txHex)
@ -192,16 +192,16 @@ describe('Bitcoin-core', function () {
const hash = transaction.hashForSignature(inIndex, script, hashType) const hash = transaction.hashForSignature(inIndex, script, hashType)
// reverse because test data is reversed // reverse because test data is reversed
assert.equal(hash.reverse().toString('hex'), expectedHash) assert.strictEqual(hash.reverse().toString('hex'), expectedHash)
}) })
}) })
}) })
describe('script.signature.decode', function () { describe('script.signature.decode', () => {
sigCanonical.forEach(function (hex) { sigCanonical.forEach(hex => {
const buffer = Buffer.from(hex, 'hex') const buffer = Buffer.from(hex, 'hex')
it('can parse ' + hex, function () { it('can parse ' + hex, () => {
const parsed = bitcoin.script.signature.decode(buffer) const parsed = bitcoin.script.signature.decode(buffer)
const actual = bitcoin.script.signature.encode(parsed.signature, parsed.hashType) const actual = bitcoin.script.signature.encode(parsed.signature, parsed.hashType)
@ -209,15 +209,15 @@ describe('Bitcoin-core', function () {
}) })
}) })
sigNoncanonical.forEach(function (hex, i) { sigNoncanonical.forEach((hex, i) => {
if (i === 0) return if (i === 0) return
if (i % 2 !== 0) return if (i % 2 !== 0) return
const description = sigNoncanonical[i - 1].slice(0, -1) const description = sigNoncanonical[i - 1].slice(0, -1)
const buffer = Buffer.from(hex, 'hex') const buffer = Buffer.from(hex, 'hex')
it('throws on ' + description, function () { it('throws on ' + description, () => {
assert.throws(function () { assert.throws(() => {
bitcoin.script.signature.decode(buffer) bitcoin.script.signature.decode(buffer)
}, /Expected DER (integer|sequence)|(R|S) value (excessively padded|is negative)|(R|S|DER sequence) length is (zero|too short|too long|invalid)|Invalid hashType/) }, /Expected DER (integer|sequence)|(R|S) value (excessively padded|is negative)|(R|S|DER sequence) length is (zero|too short|too long|invalid)|Invalid hashType/)
}) })

View file

@ -4,29 +4,29 @@ const Block = require('..').Block
const fixtures = require('./fixtures/block') const fixtures = require('./fixtures/block')
describe('Block', function () { describe('Block', () => {
describe('version', function () { describe('version', () => {
it('should be interpreted as an int32le', function () { it('should be interpreted as an int32le', () => {
const blockHex = 'ffffffff0000000000000000000000000000000000000000000000000000000000000000414141414141414141414141414141414141414141414141414141414141414101000000020000000300000000' const blockHex = 'ffffffff0000000000000000000000000000000000000000000000000000000000000000414141414141414141414141414141414141414141414141414141414141414101000000020000000300000000'
const block = Block.fromHex(blockHex) const block = Block.fromHex(blockHex)
assert.equal(-1, block.version) assert.strictEqual(-1, block.version)
assert.equal(1, block.timestamp) assert.strictEqual(1, block.timestamp)
}) })
}) })
describe('calculateTarget', function () { describe('calculateTarget', () => {
fixtures.targets.forEach(function (f) { fixtures.targets.forEach(f => {
it('returns ' + f.expected + ' for 0x' + f.bits, function () { it('returns ' + f.expected + ' for 0x' + f.bits, () => {
const bits = parseInt(f.bits, 16) const bits = parseInt(f.bits, 16)
assert.equal(Block.calculateTarget(bits).toString('hex'), f.expected) assert.strictEqual(Block.calculateTarget(bits).toString('hex'), f.expected)
}) })
}) })
}) })
describe('fromBuffer/fromHex', function () { describe('fromBuffer/fromHex', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('imports ' + f.description, function () { it('imports ' + f.description, () => {
const block = Block.fromHex(f.hex) const block = Block.fromHex(f.hex)
assert.strictEqual(block.version, f.version) assert.strictEqual(block.version, f.version)
@ -42,54 +42,54 @@ describe('Block', function () {
}) })
}) })
fixtures.invalid.forEach(function (f) { fixtures.invalid.forEach(f => {
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, () => {
assert.throws(function () { assert.throws(() => {
Block.fromHex(f.hex) Block.fromHex(f.hex)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('toBuffer/toHex', function () { describe('toBuffer/toHex', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
let block let block
beforeEach(function () { beforeEach(() => {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
}) })
it('exports ' + f.description, function () { it('exports ' + f.description, () => {
assert.strictEqual(block.toHex(true), f.hex.slice(0, 160)) assert.strictEqual(block.toHex(true), f.hex.slice(0, 160))
assert.strictEqual(block.toHex(), f.hex) assert.strictEqual(block.toHex(), f.hex)
}) })
}) })
}) })
describe('getHash/getId', function () { describe('getHash/getId', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
let block let block
beforeEach(function () { beforeEach(() => {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
}) })
it('returns ' + f.id + ' for ' + f.description, function () { it('returns ' + f.id + ' for ' + f.description, () => {
assert.strictEqual(block.getHash().toString('hex'), f.hash) assert.strictEqual(block.getHash().toString('hex'), f.hash)
assert.strictEqual(block.getId(), f.id) assert.strictEqual(block.getId(), f.id)
}) })
}) })
}) })
describe('getUTCDate', function () { describe('getUTCDate', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
let block let block
beforeEach(function () { beforeEach(() => {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
}) })
it('returns UTC date of ' + f.id, function () { it('returns UTC date of ' + f.id, () => {
const utcDate = block.getUTCDate().getTime() const utcDate = block.getUTCDate().getTime()
assert.strictEqual(utcDate, f.timestamp * 1e3) assert.strictEqual(utcDate, f.timestamp * 1e3)
@ -97,59 +97,59 @@ describe('Block', function () {
}) })
}) })
describe('calculateMerkleRoot', function () { describe('calculateMerkleRoot', () => {
it('should throw on zero-length transaction array', function () { it('should throw on zero-length transaction array', () => {
assert.throws(function () { assert.throws(() => {
Block.calculateMerkleRoot([]) Block.calculateMerkleRoot([])
}, /Cannot compute merkle root for zero transactions/) }, /Cannot compute merkle root for zero transactions/)
}) })
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
if (f.hex.length === 160) return if (f.hex.length === 160) return
let block let block
beforeEach(function () { beforeEach(() => {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
}) })
it('returns ' + f.merkleRoot + ' for ' + f.id, function () { it('returns ' + f.merkleRoot + ' for ' + f.id, () => {
assert.strictEqual(Block.calculateMerkleRoot(block.transactions).toString('hex'), f.merkleRoot) assert.strictEqual(Block.calculateMerkleRoot(block.transactions).toString('hex'), f.merkleRoot)
}) })
if (f.witnessCommit) { if (f.witnessCommit) {
it('returns witness commit ' + f.witnessCommit + ' for ' + f.id, function () { it('returns witness commit ' + f.witnessCommit + ' for ' + f.id, () => {
assert.strictEqual(Block.calculateMerkleRoot(block.transactions, true).toString('hex'), f.witnessCommit) assert.strictEqual(Block.calculateMerkleRoot(block.transactions, true).toString('hex'), f.witnessCommit)
}) })
} }
}) })
}) })
describe('checkTxRoots', function () { describe('checkTxRoots', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
if (f.hex.length === 160) return if (f.hex.length === 160) return
let block let block
beforeEach(function () { beforeEach(() => {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
}) })
it('returns ' + f.valid + ' for ' + f.id, function () { it('returns ' + f.valid + ' for ' + f.id, () => {
assert.strictEqual(block.checkTxRoots(), true) assert.strictEqual(block.checkTxRoots(), true)
}) })
}) })
}) })
describe('checkProofOfWork', function () { describe('checkProofOfWork', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
let block let block
beforeEach(function () { beforeEach(() => {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
}) })
it('returns ' + f.valid + ' for ' + f.id, function () { it('returns ' + f.valid + ' for ' + f.id, () => {
assert.strictEqual(block.checkProofOfWork(), f.valid) assert.strictEqual(block.checkProofOfWork(), f.valid)
}) })
}) })

View file

@ -4,10 +4,10 @@ const bufferutils = require('../src/bufferutils')
const fixtures = require('./fixtures/bufferutils.json') const fixtures = require('./fixtures/bufferutils.json')
describe('bufferutils', function () { describe('bufferutils', () => {
describe('readUInt64LE', function () { describe('readUInt64LE', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('decodes ' + f.hex, function () { it('decodes ' + f.hex, () => {
const buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex')
const number = bufferutils.readUInt64LE(buffer, 0) const number = bufferutils.readUInt64LE(buffer, 0)
@ -15,20 +15,20 @@ describe('bufferutils', function () {
}) })
}) })
fixtures.invalid.readUInt64LE.forEach(function (f) { fixtures.invalid.readUInt64LE.forEach(f => {
it('throws on ' + f.description, function () { it('throws on ' + f.description, () => {
const buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex')
assert.throws(function () { assert.throws(() => {
bufferutils.readUInt64LE(buffer, 0) bufferutils.readUInt64LE(buffer, 0)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('writeUInt64LE', function () { describe('writeUInt64LE', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('encodes ' + f.dec, function () { it('encodes ' + f.dec, () => {
const buffer = Buffer.alloc(8, 0) const buffer = Buffer.alloc(8, 0)
bufferutils.writeUInt64LE(buffer, f.dec, 0) bufferutils.writeUInt64LE(buffer, f.dec, 0)
@ -36,11 +36,11 @@ describe('bufferutils', function () {
}) })
}) })
fixtures.invalid.readUInt64LE.forEach(function (f) { fixtures.invalid.readUInt64LE.forEach(f => {
it('throws on ' + f.description, function () { it('throws on ' + f.description, () => {
const buffer = Buffer.alloc(8, 0) const buffer = Buffer.alloc(8, 0)
assert.throws(function () { assert.throws(() => {
bufferutils.writeUInt64LE(buffer, f.dec, 0) bufferutils.writeUInt64LE(buffer, f.dec, 0)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })

View file

@ -25,12 +25,12 @@ const tmap = {
witnessCommitment witnessCommitment
} }
describe('classify', function () { describe('classify', () => {
describe('input', function () { describe('input', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
if (!f.input) return if (!f.input) return
it('classifies ' + f.input + ' as ' + f.type, function () { it('classifies ' + f.input + ' as ' + f.type, () => {
const input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input)
const type = classify.input(input) const type = classify.input(input)
@ -38,11 +38,11 @@ describe('classify', function () {
}) })
}) })
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
if (!f.input) return if (!f.input) return
if (!f.typeIncomplete) return if (!f.typeIncomplete) return
it('classifies incomplete ' + f.input + ' as ' + f.typeIncomplete, function () { it('classifies incomplete ' + f.input + ' as ' + f.typeIncomplete, () => {
const input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input)
const type = classify.input(input, true) const type = classify.input(input, true)
@ -51,11 +51,11 @@ describe('classify', function () {
}) })
}) })
describe('classifyOutput', function () { describe('classifyOutput', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
if (!f.output) return if (!f.output) return
it('classifies ' + f.output + ' as ' + f.type, function () { it('classifies ' + f.output + ' as ' + f.type, () => {
const output = bscript.fromASM(f.output) const output = bscript.fromASM(f.output)
const type = classify.output(output) const type = classify.output(output)
@ -73,12 +73,12 @@ describe('classify', function () {
'multisig', 'multisig',
'nullData', 'nullData',
'witnessCommitment' 'witnessCommitment'
].forEach(function (name) { ].forEach(name => {
const inputType = tmap[name].input const inputType = tmap[name].input
const outputType = tmap[name].output const outputType = tmap[name].output
describe(name + '.input.check', function () { describe(name + '.input.check', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
if (name.toLowerCase() === classify.types.P2WPKH) return if (name.toLowerCase() === classify.types.P2WPKH) return
if (name.toLowerCase() === classify.types.P2WSH) return if (name.toLowerCase() === classify.types.P2WSH) return
const expected = name.toLowerCase() === f.type.toLowerCase() const expected = name.toLowerCase() === f.type.toLowerCase()
@ -86,14 +86,14 @@ describe('classify', function () {
if (inputType && f.input) { if (inputType && f.input) {
const input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input)
it('returns ' + expected + ' for ' + f.input, function () { it('returns ' + expected + ' for ' + f.input, () => {
assert.strictEqual(inputType.check(input), expected) assert.strictEqual(inputType.check(input), expected)
}) })
if (f.typeIncomplete) { if (f.typeIncomplete) {
const expectedIncomplete = name.toLowerCase() === f.typeIncomplete const expectedIncomplete = name.toLowerCase() === f.typeIncomplete
it('returns ' + expected + ' for ' + f.input, function () { it('returns ' + expected + ' for ' + f.input, () => {
assert.strictEqual(inputType.check(input, true), expectedIncomplete) assert.strictEqual(inputType.check(input, true), expectedIncomplete)
}) })
} }
@ -102,10 +102,10 @@ describe('classify', function () {
if (!(fixtures.invalid[name])) return if (!(fixtures.invalid[name])) return
fixtures.invalid[name].inputs.forEach(function (f) { fixtures.invalid[name].inputs.forEach(f => {
if (!f.input && !f.inputHex) return if (!f.input && !f.inputHex) return
it('returns false for ' + f.description + ' (' + (f.input || f.inputHex) + ')', function () { it('returns false for ' + f.description + ' (' + (f.input || f.inputHex) + ')', () => {
let input let input
if (f.input) { if (f.input) {
@ -119,12 +119,12 @@ describe('classify', function () {
}) })
}) })
describe(name + '.output.check', function () { describe(name + '.output.check', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
const expected = name.toLowerCase() === f.type const expected = name.toLowerCase() === f.type
if (outputType && f.output) { if (outputType && f.output) {
it('returns ' + expected + ' for ' + f.output, function () { it('returns ' + expected + ' for ' + f.output, () => {
const output = bscript.fromASM(f.output) const output = bscript.fromASM(f.output)
if (name.toLowerCase() === 'nulldata' && f.type === classify.types.WITNESS_COMMITMENT) return if (name.toLowerCase() === 'nulldata' && f.type === classify.types.WITNESS_COMMITMENT) return
@ -136,10 +136,10 @@ describe('classify', function () {
if (!(fixtures.invalid[name])) return if (!(fixtures.invalid[name])) return
fixtures.invalid[name].outputs.forEach(function (f) { fixtures.invalid[name].outputs.forEach(f => {
if (!f.output && !f.outputHex) return if (!f.output && !f.outputHex) return
it('returns false for ' + f.description + ' (' + (f.output || f.outputHex) + ')', function () { it('returns false for ' + f.description + ' (' + (f.output || f.outputHex) + ')', () => {
let output let output
if (f.output) { if (f.output) {

View file

@ -4,14 +4,14 @@ const bcrypto = require('../src/crypto')
const fixtures = require('./fixtures/crypto') const fixtures = require('./fixtures/crypto')
describe('crypto', function () { describe('crypto', () => {
['hash160', 'hash256', 'ripemd160', 'sha1', 'sha256'].forEach(function (algorithm) { ['hash160', 'hash256', 'ripemd160', 'sha1', 'sha256'].forEach(algorithm => {
describe(algorithm, function () { describe(algorithm, () => {
fixtures.forEach(function (f) { fixtures.forEach(f => {
const fn = bcrypto[algorithm] const fn = bcrypto[algorithm]
const expected = f[algorithm] const expected = f[algorithm]
it('returns ' + expected + ' for ' + f.hex, function () { it('returns ' + expected + ' for ' + f.hex, () => {
const data = Buffer.from(f.hex, 'hex') const data = Buffer.from(f.hex, 'hex')
const actual = fn(data).toString('hex') const actual = fn(data).toString('hex')

View file

@ -19,15 +19,15 @@ const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000
const GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex') const GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex')
const GROUP_ORDER_LESS_1 = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 'hex') const GROUP_ORDER_LESS_1 = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 'hex')
describe('ECPair', function () { describe('ECPair', () => {
describe('getPublicKey', function () { describe('getPublicKey', () => {
let keyPair let keyPair
beforeEach(function () { beforeEach(() => {
keyPair = ECPair.fromPrivateKey(ONE) keyPair = ECPair.fromPrivateKey(ONE)
}) })
it('calls pointFromScalar lazily', hoodwink(function () { it('calls pointFromScalar lazily', hoodwink(() => {
assert.strictEqual(keyPair.__Q, undefined) assert.strictEqual(keyPair.__Q, undefined)
// .publicKey forces the memoization // .publicKey forces the memoization
@ -36,14 +36,14 @@ describe('ECPair', function () {
})) }))
}) })
describe('fromPrivateKey', function () { describe('fromPrivateKey', () => {
it('defaults to compressed', function () { it('defaults to compressed', () => {
const keyPair = ECPair.fromPrivateKey(ONE) const keyPair = ECPair.fromPrivateKey(ONE)
assert.strictEqual(keyPair.compressed, true) assert.strictEqual(keyPair.compressed, true)
}) })
it('supports the uncompressed option', function () { it('supports the uncompressed option', () => {
const keyPair = ECPair.fromPrivateKey(ONE, { const keyPair = ECPair.fromPrivateKey(ONE, {
compressed: false compressed: false
}) })
@ -51,7 +51,7 @@ describe('ECPair', function () {
assert.strictEqual(keyPair.compressed, false) assert.strictEqual(keyPair.compressed, false)
}) })
it('supports the network option', function () { it('supports the network option', () => {
const keyPair = ECPair.fromPrivateKey(ONE, { const keyPair = ECPair.fromPrivateKey(ONE, {
compressed: false, compressed: false,
network: NETWORKS.testnet network: NETWORKS.testnet
@ -60,8 +60,8 @@ describe('ECPair', function () {
assert.strictEqual(keyPair.network, NETWORKS.testnet) assert.strictEqual(keyPair.network, NETWORKS.testnet)
}) })
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('derives public key for ' + f.WIF, function () { it('derives public key for ' + f.WIF, () => {
const d = Buffer.from(f.d, 'hex') const d = Buffer.from(f.d, 'hex')
const keyPair = ECPair.fromPrivateKey(d, { const keyPair = ECPair.fromPrivateKey(d, {
compressed: f.compressed compressed: f.compressed
@ -71,30 +71,30 @@ describe('ECPair', function () {
}) })
}) })
fixtures.invalid.fromPrivateKey.forEach(function (f) { fixtures.invalid.fromPrivateKey.forEach(f => {
it('throws ' + f.exception, function () { it('throws ' + f.exception, () => {
const d = Buffer.from(f.d, 'hex') const d = Buffer.from(f.d, 'hex')
assert.throws(function () { assert.throws(() => {
ECPair.fromPrivateKey(d, f.options) ECPair.fromPrivateKey(d, f.options)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('fromPublicKey', function () { describe('fromPublicKey', () => {
fixtures.invalid.fromPublicKey.forEach(function (f) { fixtures.invalid.fromPublicKey.forEach(f => {
it('throws ' + f.exception, function () { it('throws ' + f.exception, () => {
const Q = Buffer.from(f.Q, 'hex') const Q = Buffer.from(f.Q, 'hex')
assert.throws(function () { assert.throws(() => {
ECPair.fromPublicKey(Q, f.options) ECPair.fromPublicKey(Q, f.options)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('fromWIF', function () { describe('fromWIF', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('imports ' + f.WIF + ' (' + f.network + ')', function () { it('imports ' + f.WIF + ' (' + f.network + ')', () => {
const network = NETWORKS[f.network] const network = NETWORKS[f.network]
const keyPair = ECPair.fromWIF(f.WIF, network) const keyPair = ECPair.fromWIF(f.WIF, network)
@ -104,8 +104,8 @@ describe('ECPair', function () {
}) })
}) })
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('imports ' + f.WIF + ' (via list of networks)', function () { it('imports ' + f.WIF + ' (via list of networks)', () => {
const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST) const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
assert.strictEqual(keyPair.privateKey.toString('hex'), f.d) assert.strictEqual(keyPair.privateKey.toString('hex'), f.d)
@ -114,9 +114,9 @@ describe('ECPair', function () {
}) })
}) })
fixtures.invalid.fromWIF.forEach(function (f) { fixtures.invalid.fromWIF.forEach(f => {
it('throws on ' + f.WIF, function () { it('throws on ' + f.WIF, () => {
assert.throws(function () { assert.throws(() => {
const networks = f.network ? NETWORKS[f.network] : NETWORKS_LIST const networks = f.network ? NETWORKS[f.network] : NETWORKS_LIST
ECPair.fromWIF(f.WIF, networks) ECPair.fromWIF(f.WIF, networks)
@ -125,9 +125,9 @@ describe('ECPair', function () {
}) })
}) })
describe('toWIF', function () { describe('toWIF', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('exports ' + f.WIF, function () { it('exports ' + f.WIF, () => {
const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST) const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
const result = keyPair.toWIF() const result = keyPair.toWIF()
assert.strictEqual(result, f.WIF) assert.strictEqual(result, f.WIF)
@ -135,13 +135,13 @@ describe('ECPair', function () {
}) })
}) })
describe('makeRandom', function () { describe('makeRandom', () => {
const d = Buffer.alloc(32, 4) const d = Buffer.alloc(32, 4)
const exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv' const exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'
describe('uses randombytes RNG', function () { describe('uses randombytes RNG', () => {
it('generates a ECPair', function () { it('generates a ECPair', () => {
const stub = { randombytes: function () { return d } } const stub = { randombytes: () => { return d } }
const ProxiedECPair = proxyquire('../src/ecpair', stub) const ProxiedECPair = proxyquire('../src/ecpair', stub)
const keyPair = ProxiedECPair.makeRandom() const keyPair = ProxiedECPair.makeRandom()
@ -149,22 +149,22 @@ describe('ECPair', function () {
}) })
}) })
it('allows a custom RNG to be used', function () { it('allows a custom RNG to be used', () => {
const keyPair = ECPair.makeRandom({ const keyPair = ECPair.makeRandom({
rng: function (size) { return d.slice(0, size) } rng: size => { return d.slice(0, size) }
}) })
assert.strictEqual(keyPair.toWIF(), exWIF) assert.strictEqual(keyPair.toWIF(), exWIF)
}) })
it('retains the same defaults as ECPair constructor', function () { it('retains the same defaults as ECPair constructor', () => {
const keyPair = ECPair.makeRandom() const keyPair = ECPair.makeRandom()
assert.strictEqual(keyPair.compressed, true) assert.strictEqual(keyPair.compressed, true)
assert.strictEqual(keyPair.network, NETWORKS.bitcoin) assert.strictEqual(keyPair.network, NETWORKS.bitcoin)
}) })
it('supports the options parameter', function () { it('supports the options parameter', () => {
const keyPair = ECPair.makeRandom({ const keyPair = ECPair.makeRandom({
compressed: false, compressed: false,
network: NETWORKS.testnet network: NETWORKS.testnet
@ -174,18 +174,18 @@ describe('ECPair', function () {
assert.strictEqual(keyPair.network, NETWORKS.testnet) assert.strictEqual(keyPair.network, NETWORKS.testnet)
}) })
it('throws if d is bad length', function () { it('throws if d is bad length', () => {
function rng () { function rng () {
return Buffer.alloc(28) return Buffer.alloc(28)
} }
assert.throws(function () { assert.throws(() => {
ECPair.makeRandom({ rng: rng }) ECPair.makeRandom({ rng: rng })
}, /Expected Buffer\(Length: 32\), got Buffer\(Length: 28\)/) }, /Expected Buffer\(Length: 32\), got Buffer\(Length: 28\)/)
}) })
it('loops until d is within interval [1, n) : 1', hoodwink(function () { it('loops until d is within interval [1, n) : 1', hoodwink(function () {
const rng = this.stub(function () { const rng = this.stub(() => {
if (rng.calls === 0) return ZERO // 0 if (rng.calls === 0) return ZERO // 0
return ONE // >0 return ONE // >0
}, 2) }, 2)
@ -194,7 +194,7 @@ describe('ECPair', function () {
})) }))
it('loops until d is within interval [1, n) : n - 1', hoodwink(function () { it('loops until d is within interval [1, n) : n - 1', hoodwink(function () {
const rng = this.stub(function () { const rng = this.stub(() => {
if (rng.calls === 0) return ZERO // <1 if (rng.calls === 0) return ZERO // <1
if (rng.calls === 1) return GROUP_ORDER // >n-1 if (rng.calls === 1) return GROUP_ORDER // >n-1
return GROUP_ORDER_LESS_1 // n-1 return GROUP_ORDER_LESS_1 // n-1
@ -204,9 +204,9 @@ describe('ECPair', function () {
})) }))
}) })
describe('.network', function () { describe('.network', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('returns ' + f.network + ' for ' + f.WIF, function () { it('returns ' + f.network + ' for ' + f.WIF, () => {
const network = NETWORKS[f.network] const network = NETWORKS[f.network]
const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST) const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
@ -215,20 +215,20 @@ describe('ECPair', function () {
}) })
}) })
describe('tinysecp wrappers', function () { describe('tinysecp wrappers', () => {
let keyPair let keyPair
let hash let hash
let signature let signature
beforeEach(function () { beforeEach(() => {
keyPair = ECPair.makeRandom() keyPair = ECPair.makeRandom()
hash = ZERO hash = ZERO
signature = Buffer.alloc(64, 1) signature = Buffer.alloc(64, 1)
}) })
describe('signing', function () { describe('signing', () => {
it('wraps tinysecp.sign', hoodwink(function () { it('wraps tinysecp.sign', hoodwink(function () {
this.mock(tinysecp, 'sign', function (h, d) { this.mock(tinysecp, 'sign', (h, d) => {
assert.strictEqual(h, hash) assert.strictEqual(h, hash)
assert.strictEqual(d, keyPair.privateKey) assert.strictEqual(d, keyPair.privateKey)
return signature return signature
@ -237,18 +237,18 @@ describe('ECPair', function () {
assert.strictEqual(keyPair.sign(hash), signature) assert.strictEqual(keyPair.sign(hash), signature)
})) }))
it('throws if no private key is found', function () { it('throws if no private key is found', () => {
delete keyPair.__D delete keyPair.__D
assert.throws(function () { assert.throws(() => {
keyPair.sign(hash) keyPair.sign(hash)
}, /Missing private key/) }, /Missing private key/)
}) })
}) })
describe('verify', function () { describe('verify', () => {
it('wraps tinysecp.verify', hoodwink(function () { it('wraps tinysecp.verify', hoodwink(function () {
this.mock(tinysecp, 'verify', function (h, q, s) { this.mock(tinysecp, 'verify', (h, q, s) => {
assert.strictEqual(h, hash) assert.strictEqual(h, hash)
assert.strictEqual(q, keyPair.publicKey) assert.strictEqual(q, keyPair.publicKey)
assert.strictEqual(s, signature) assert.strictEqual(s, signature)

View file

@ -47,7 +47,7 @@ async function faucet (address, value) {
let _unspents = [] let _unspents = []
const sleep = ms => new Promise((resolve, reject) => setTimeout(resolve, ms)) const sleep = ms => new Promise((resolve, reject) => setTimeout(resolve, ms))
const randInt = (min, max) => min + Math.floor((max - min + 1) * Math.random()) const randInt = (min, max) => min + Math.floor((max - min + 1) * Math.random())
do { while (_unspents.length === 0) {
if (count > 0) { if (count > 0) {
if (count >= 5) throw new Error('Missing Inputs') if (count >= 5) throw new Error('Missing Inputs')
console.log('Missing Inputs, retry #' + count) console.log('Missing Inputs, retry #' + count)
@ -78,7 +78,7 @@ async function faucet (address, value) {
_unspents = results.filter(x => x.txId === txId) _unspents = results.filter(x => x.txId === txId)
count++ count++
} while (_unspents.length === 0) }
return _unspents.pop() return _unspents.pop()
} }

View file

@ -4,8 +4,8 @@ const bitcoin = require('../../')
const dhttp = require('./_regtest').dhttp const dhttp = require('./_regtest').dhttp
const TESTNET = bitcoin.networks.testnet const TESTNET = bitcoin.networks.testnet
describe('bitcoinjs-lib (addresses)', function () { describe('bitcoinjs-lib (addresses)', () => {
it('can generate a random address [and support the retrieval of transactions for that address (via 3PBP)', async function () { it('can generate a random address [and support the retrieval of transactions for that address (via 3PBP)', async () => {
const keyPair = bitcoin.ECPair.makeRandom() const keyPair = bitcoin.ECPair.makeRandom()
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey }) const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
@ -23,14 +23,14 @@ describe('bitcoinjs-lib (addresses)', function () {
assert.strictEqual(result.total_sent, 0) assert.strictEqual(result.total_sent, 0)
}) })
it('can import an address via WIF', function () { it('can import an address via WIF', () => {
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn') const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn')
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey }) const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
assert.strictEqual(address, '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH') assert.strictEqual(address, '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH')
}) })
it('can generate a P2SH, pay-to-multisig (2-of-3) address', function () { it('can generate a P2SH, pay-to-multisig (2-of-3) address', () => {
const pubkeys = [ const pubkeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9', '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
@ -43,14 +43,14 @@ describe('bitcoinjs-lib (addresses)', function () {
assert.strictEqual(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7') assert.strictEqual(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7')
}) })
it('can generate a SegWit address', function () { it('can generate a SegWit address', () => {
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn') const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn')
const { address } = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey }) const { address } = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey })
assert.strictEqual(address, 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4') assert.strictEqual(address, 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4')
}) })
it('can generate a SegWit address (via P2SH)', function () { it('can generate a SegWit address (via P2SH)', () => {
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn') const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn')
const { address } = bitcoin.payments.p2sh({ const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey }) redeem: bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey })
@ -59,7 +59,7 @@ describe('bitcoinjs-lib (addresses)', function () {
assert.strictEqual(address, '3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN') assert.strictEqual(address, '3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN')
}) })
it('can generate a P2WSH (SegWit), pay-to-multisig (3-of-4) address', function () { it('can generate a P2WSH (SegWit), pay-to-multisig (3-of-4) address', () => {
const pubkeys = [ const pubkeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9', '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
@ -73,7 +73,7 @@ describe('bitcoinjs-lib (addresses)', function () {
assert.strictEqual(address, 'bc1q75f6dv4q8ug7zhujrsp5t0hzf33lllnr3fe7e2pra3v24mzl8rrqtp3qul') assert.strictEqual(address, 'bc1q75f6dv4q8ug7zhujrsp5t0hzf33lllnr3fe7e2pra3v24mzl8rrqtp3qul')
}) })
it('can generate a P2SH(P2WSH(...)), pay-to-multisig (2-of-2) address', function () { it('can generate a P2SH(P2WSH(...)), pay-to-multisig (2-of-2) address', () => {
const pubkeys = [ const pubkeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9' '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9'
@ -88,7 +88,7 @@ describe('bitcoinjs-lib (addresses)', function () {
}) })
// examples using other network information // examples using other network information
it('can generate a Testnet address', function () { it('can generate a Testnet address', () => {
const keyPair = bitcoin.ECPair.makeRandom({ network: TESTNET }) const keyPair = bitcoin.ECPair.makeRandom({ network: TESTNET })
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: TESTNET }) const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: TESTNET })
@ -96,7 +96,7 @@ describe('bitcoinjs-lib (addresses)', function () {
assert.strictEqual(address.startsWith('m') || address.startsWith('n'), true) assert.strictEqual(address.startsWith('m') || address.startsWith('n'), true)
}) })
it('can generate a Litecoin address', function () { it('can generate a Litecoin address', () => {
// WARNING: although possible, bitcoinjs is NOT necessarily compatible with Litecoin // WARNING: although possible, bitcoinjs is NOT necessarily compatible with Litecoin
const LITECOIN = { const LITECOIN = {
messagePrefix: '\x19Litecoin Signed Message:\n', messagePrefix: '\x19Litecoin Signed Message:\n',

View file

@ -8,15 +8,15 @@ function getAddress (node, network) {
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address
} }
describe('bitcoinjs-lib (BIP32)', function () { describe('bitcoinjs-lib (BIP32)', () => {
it('can import a BIP32 testnet xpriv and export to WIF', function () { it('can import a BIP32 testnet xpriv and export to WIF', () => {
const xpriv = 'tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK' const xpriv = 'tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK'
const node = bip32.fromBase58(xpriv, bitcoin.networks.testnet) const node = bip32.fromBase58(xpriv, bitcoin.networks.testnet)
assert.strictEqual(node.toWIF(), 'cQfoY67cetFNunmBUX5wJiw3VNoYx3gG9U9CAofKE6BfiV1fSRw7') assert.strictEqual(node.toWIF(), 'cQfoY67cetFNunmBUX5wJiw3VNoYx3gG9U9CAofKE6BfiV1fSRw7')
}) })
it('can export a BIP32 xpriv, then import it', function () { it('can export a BIP32 xpriv, then import it', () => {
const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost' const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost'
const seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeed(mnemonic)
const node = bip32.fromSeed(seed) const node = bip32.fromSeed(seed)
@ -27,7 +27,7 @@ describe('bitcoinjs-lib (BIP32)', function () {
assert.strictEqual(node.toWIF(), restored.toWIF()) // same private key assert.strictEqual(node.toWIF(), restored.toWIF()) // same private key
}) })
it('can export a BIP32 xpub', function () { it('can export a BIP32 xpub', () => {
const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost' const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost'
const seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeed(mnemonic)
const node = bip32.fromSeed(seed) const node = bip32.fromSeed(seed)
@ -36,7 +36,7 @@ describe('bitcoinjs-lib (BIP32)', function () {
assert.strictEqual(string, 'xpub661MyMwAqRbcGhVeaVfEBA25e3cP9DsJQZoE8iep5fZSxy3TnPBNBgWnMZx56oreNc48ZoTkQfatNJ9VWnQ7ZcLZcVStpaXLTeG8bGrzX3n') assert.strictEqual(string, 'xpub661MyMwAqRbcGhVeaVfEBA25e3cP9DsJQZoE8iep5fZSxy3TnPBNBgWnMZx56oreNc48ZoTkQfatNJ9VWnQ7ZcLZcVStpaXLTeG8bGrzX3n')
}) })
it('can create a BIP32, bitcoin, account 0, external address', function () { it('can create a BIP32, bitcoin, account 0, external address', () => {
const path = "m/0'/0/0" const path = "m/0'/0/0"
const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex')) const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex'))
@ -51,7 +51,7 @@ describe('bitcoinjs-lib (BIP32)', function () {
assert.strictEqual(getAddress(child1b), '1JHyB1oPXufr4FXkfitsjgNB5yRY9jAaa7') assert.strictEqual(getAddress(child1b), '1JHyB1oPXufr4FXkfitsjgNB5yRY9jAaa7')
}) })
it('can create a BIP44, bitcoin, account 0, external address', function () { it('can create a BIP44, bitcoin, account 0, external address', () => {
const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex')) const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex'))
const child1 = root.derivePath("m/44'/0'/0'/0/0") const child1 = root.derivePath("m/44'/0'/0'/0/0")
@ -67,7 +67,7 @@ describe('bitcoinjs-lib (BIP32)', function () {
assert.strictEqual(getAddress(child1b), '12Tyvr1U8A3ped6zwMEU5M8cx3G38sP5Au') assert.strictEqual(getAddress(child1b), '12Tyvr1U8A3ped6zwMEU5M8cx3G38sP5Au')
}) })
it('can create a BIP49, bitcoin testnet, account 0, external address', function () { it('can create a BIP49, bitcoin testnet, account 0, external address', () => {
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about' const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
const seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeed(mnemonic)
const root = bip32.fromSeed(seed) const root = bip32.fromSeed(seed)
@ -82,7 +82,7 @@ describe('bitcoinjs-lib (BIP32)', function () {
assert.strictEqual(address, '2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2') assert.strictEqual(address, '2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2')
}) })
it('can use BIP39 to generate BIP32 addresses', function () { it('can use BIP39 to generate BIP32 addresses', () => {
// var mnemonic = bip39.generateMnemonic() // var mnemonic = bip39.generateMnemonic()
const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost' const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost'
assert(bip39.validateMnemonic(mnemonic)) assert(bip39.validateMnemonic(mnemonic))

View file

@ -4,8 +4,8 @@ const { describe, it } = require('mocha')
const assert = require('assert') const assert = require('assert')
const bitcoin = require('../../') const bitcoin = require('../../')
describe('bitcoinjs-lib (blocks)', function () { describe('bitcoinjs-lib (blocks)', () => {
it('can extract a height from a CoinBase transaction', function () { it('can extract a height from a CoinBase transaction', () => {
// from 00000000000000000097669cdca131f24d40c4cc7d80eaa65967a2d09acf6ce6 // from 00000000000000000097669cdca131f24d40c4cc7d80eaa65967a2d09acf6ce6
const txHex = '010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a2b1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98fd16761d220400000000000000aa340000d49f0000ffffffff02b07fc366000000001976a9148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266a24aa21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12bf1e400120000000000000000000000000000000000000000000000000000000000000000000000000' const txHex = '010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a2b1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98fd16761d220400000000000000aa340000d49f0000ffffffff02b07fc366000000001976a9148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266a24aa21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12bf1e400120000000000000000000000000000000000000000000000000000000000000000000000000'
const tx = bitcoin.Transaction.fromHex(txHex) const tx = bitcoin.Transaction.fromHex(txHex)

View file

@ -8,9 +8,9 @@ const bip65 = require('bip65')
const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest) const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest)
const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest) const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest)
describe('bitcoinjs-lib (transactions w/ CLTV)', function () { describe('bitcoinjs-lib (transactions w/ CLTV)', () => {
// force update MTP // force update MTP
before(async function () { before(async () => {
await regtestUtils.mine(11) await regtestUtils.mine(11)
}) })
@ -38,7 +38,7 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
} }
// expiry past, {Alice's signature} OP_TRUE // expiry past, {Alice's signature} OP_TRUE
it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the past)', async function () { it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the past)', async () => {
// 3 hours ago // 3 hours ago
const lockTime = bip65.encode({ utc: utcNow() - (3600 * 3) }) const lockTime = bip65.encode({ utc: utcNow() - (3600 * 3) })
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime)
@ -77,7 +77,7 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
}) })
// expiry will pass, {Alice's signature} OP_TRUE // expiry will pass, {Alice's signature} OP_TRUE
it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future)', async function () { it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future)', async () => {
const height = await regtestUtils.height() const height = await regtestUtils.height()
// 5 blocks from now // 5 blocks from now
const lockTime = bip65.encode({ blocks: height + 5 }) const lockTime = bip65.encode({ blocks: height + 5 })
@ -120,7 +120,7 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
}) })
// expiry ignored, {Bob's signature} {Alice's signature} OP_FALSE // expiry ignored, {Bob's signature} {Alice's signature} OP_FALSE
it('can create (and broadcast via 3PBP) a Transaction where Alice and Bob can redeem the output at any time', async function () { it('can create (and broadcast via 3PBP) a Transaction where Alice and Bob can redeem the output at any time', async () => {
// two hours ago // two hours ago
const lockTime = bip65.encode({ utc: utcNow() - (3600 * 2) }) const lockTime = bip65.encode({ utc: utcNow() - (3600 * 2) })
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime)
@ -159,7 +159,7 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
}) })
// expiry in the future, {Alice's signature} OP_TRUE // expiry in the future, {Alice's signature} OP_TRUE
it('can create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry', async function () { it('can create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry', async () => {
// two hours from now // two hours from now
const lockTime = bip65.encode({ utc: utcNow() + (3600 * 2) }) const lockTime = bip65.encode({ utc: utcNow() + (3600 * 2) })
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime)
@ -189,7 +189,7 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig)
await regtestUtils.broadcast(tx.toHex()).catch(err => { await regtestUtils.broadcast(tx.toHex()).catch(err => {
assert.throws(function () { assert.throws(() => {
if (err) throw err if (err) throw err
}, /Error: non-final \(code 64\)/) }, /Error: non-final \(code 64\)/)
}) })

View file

@ -8,9 +8,9 @@ const bip68 = require('bip68')
const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest) const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest)
const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest) const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest)
describe('bitcoinjs-lib (transactions w/ CSV)', function () { describe('bitcoinjs-lib (transactions w/ CSV)', () => {
// force update MTP // force update MTP
before(async function () { before(async () => {
await regtestUtils.mine(11) await regtestUtils.mine(11)
}) })
@ -35,7 +35,7 @@ describe('bitcoinjs-lib (transactions w/ CSV)', function () {
} }
// expiry will pass, {Alice's signature} OP_TRUE // expiry will pass, {Alice's signature} OP_TRUE
it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future)', async function () { it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future)', async () => {
// 5 blocks from now // 5 blocks from now
const sequence = bip68.encode({ blocks: 5 }) const sequence = bip68.encode({ blocks: 5 })
const p2sh = bitcoin.payments.p2sh({ const p2sh = bitcoin.payments.p2sh({
@ -84,7 +84,7 @@ describe('bitcoinjs-lib (transactions w/ CSV)', function () {
}) })
// expiry in the future, {Alice's signature} OP_TRUE // expiry in the future, {Alice's signature} OP_TRUE
it('can create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry', async function () { it('can create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry', async () => {
// two hours after confirmation // two hours after confirmation
const sequence = bip68.encode({ seconds: 7168 }) const sequence = bip68.encode({ seconds: 7168 })
const p2sh = bitcoin.payments.p2sh({ const p2sh = bitcoin.payments.p2sh({
@ -119,7 +119,7 @@ describe('bitcoinjs-lib (transactions w/ CSV)', function () {
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig)
await regtestUtils.broadcast(tx.toHex()).catch(err => { await regtestUtils.broadcast(tx.toHex()).catch(err => {
assert.throws(function () { assert.throws(() => {
if (err) throw err if (err) throw err
}, /Error: non-BIP68-final \(code 64\)/) }, /Error: non-BIP68-final \(code 64\)/)
}) })

View file

@ -16,7 +16,7 @@ async function buildAndSign (depends, prevOutput, redeemScript, witnessScript) {
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4)
if (depends.signatures) { if (depends.signatures) {
keyPairs.forEach((keyPair) => { keyPairs.forEach(keyPair => {
txb.sign(0, keyPair, redeemScript, null, unspent.value, witnessScript) txb.sign(0, keyPair, redeemScript, null, unspent.value, witnessScript)
}) })
} else if (depends.signature) { } else if (depends.signature) {
@ -26,7 +26,7 @@ async function buildAndSign (depends, prevOutput, redeemScript, witnessScript) {
return regtestUtils.broadcast(txb.build().toHex()) return regtestUtils.broadcast(txb.build().toHex())
} }
;['p2ms', 'p2pk', 'p2pkh', 'p2wpkh'].forEach((k) => { ;['p2ms', 'p2pk', 'p2pkh', 'p2wpkh'].forEach(k => {
const fixtures = require('../fixtures/' + k) const fixtures = require('../fixtures/' + k)
const { depends } = fixtures.dynamic const { depends } = fixtures.dynamic
const fn = bitcoin.payments[k] const fn = bitcoin.payments[k]
@ -39,7 +39,7 @@ async function buildAndSign (depends, prevOutput, redeemScript, witnessScript) {
const { output } = fn(base) const { output } = fn(base)
if (!output) throw new TypeError('Missing output') if (!output) throw new TypeError('Missing output')
describe('bitcoinjs-lib (payments - ' + k + ')', function () { describe('bitcoinjs-lib (payments - ' + k + ')', () => {
it('can broadcast as an output, and be spent as an input', async () => { it('can broadcast as an output, and be spent as an input', async () => {
await buildAndSign(depends, output, null, null) await buildAndSign(depends, output, null, null)
}) })

View file

@ -8,8 +8,8 @@ function rng () {
return Buffer.from('YT8dAtK4d16A3P1z+TpwB2jJ4aFH3g9M1EioIBkLEV4=', 'base64') return Buffer.from('YT8dAtK4d16A3P1z+TpwB2jJ4aFH3g9M1EioIBkLEV4=', 'base64')
} }
describe('bitcoinjs-lib (transactions)', function () { describe('bitcoinjs-lib (transactions)', () => {
it('can create a 1-to-1 Transaction', function () { it('can create a 1-to-1 Transaction', () => {
const alice = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy') const alice = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy')
const txb = new bitcoin.TransactionBuilder() const txb = new bitcoin.TransactionBuilder()
@ -24,7 +24,7 @@ describe('bitcoinjs-lib (transactions)', function () {
assert.strictEqual(txb.build().toHex(), '01000000019d344070eac3fe6e394a16d06d7704a7d5c0a10eb2a2c16bc98842b7cc20d561000000006b48304502210088828c0bdfcdca68d8ae0caeb6ec62cd3fd5f9b2191848edae33feb533df35d302202e0beadd35e17e7f83a733f5277028a9b453d525553e3f5d2d7a7aa8010a81d60121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b59fffffffff01e02e0000000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00000000') assert.strictEqual(txb.build().toHex(), '01000000019d344070eac3fe6e394a16d06d7704a7d5c0a10eb2a2c16bc98842b7cc20d561000000006b48304502210088828c0bdfcdca68d8ae0caeb6ec62cd3fd5f9b2191848edae33feb533df35d302202e0beadd35e17e7f83a733f5277028a9b453d525553e3f5d2d7a7aa8010a81d60121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b59fffffffff01e02e0000000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00000000')
}) })
it('can create a 2-to-2 Transaction', function () { it('can create a 2-to-2 Transaction', () => {
const alice = bitcoin.ECPair.fromWIF('L1Knwj9W3qK3qMKdTvmg3VfzUs3ij2LETTFhxza9LfD5dngnoLG1') const alice = bitcoin.ECPair.fromWIF('L1Knwj9W3qK3qMKdTvmg3VfzUs3ij2LETTFhxza9LfD5dngnoLG1')
const bob = bitcoin.ECPair.fromWIF('KwcN2pT3wnRAurhy7qMczzbkpY5nXMW2ubh696UBc1bcwctTx26z') const bob = bitcoin.ECPair.fromWIF('KwcN2pT3wnRAurhy7qMczzbkpY5nXMW2ubh696UBc1bcwctTx26z')
@ -232,17 +232,17 @@ describe('bitcoinjs-lib (transactions)', function () {
}) })
}) })
it('can verify Transaction (P2PKH) signatures', function () { it('can verify Transaction (P2PKH) signatures', () => {
const txHex = '010000000321c5f7e7bc98b3feda84aad36a5c99a02bcb8823a2f3eccbcd5da209698b5c20000000006b48304502210099e021772830207cf7c55b69948d3b16b4dcbf1f55a9cd80ebf8221a169735f9022064d33f11d62cd28240b3862afc0b901adc9f231c7124dd19bdb30367b61964c50121032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63dffffffff8a75ce85441ddb3f342708ee33cc8ed418b07d9ba9e0e7c4e1cccfe9f52d8a88000000006946304302207916c23dae212c95a920423902fa44e939fb3d542f4478a7b46e9cde53705800021f0d74e9504146e404c1b8f9cba4dff2d4782e3075491c9ed07ce4a7d1c4461a01210216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2affffffffdfef93f69fe32e944fad79fa8f882b3a155d80383252348caba1a77a5abbf7ef000000006b483045022100faa6e9ca289b46c64764a624c59ac30d9abcf1d4a04c4de9089e67cbe0d300a502206930afa683f6807502de5c2431bf9a1fd333c8a2910a76304df0f3d23d83443f0121039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18fffffffff01ff4b0000000000001976a9146c86476d1d85cd60116cd122a274e6a570a5a35c88acc96d0700' const txHex = '010000000321c5f7e7bc98b3feda84aad36a5c99a02bcb8823a2f3eccbcd5da209698b5c20000000006b48304502210099e021772830207cf7c55b69948d3b16b4dcbf1f55a9cd80ebf8221a169735f9022064d33f11d62cd28240b3862afc0b901adc9f231c7124dd19bdb30367b61964c50121032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63dffffffff8a75ce85441ddb3f342708ee33cc8ed418b07d9ba9e0e7c4e1cccfe9f52d8a88000000006946304302207916c23dae212c95a920423902fa44e939fb3d542f4478a7b46e9cde53705800021f0d74e9504146e404c1b8f9cba4dff2d4782e3075491c9ed07ce4a7d1c4461a01210216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2affffffffdfef93f69fe32e944fad79fa8f882b3a155d80383252348caba1a77a5abbf7ef000000006b483045022100faa6e9ca289b46c64764a624c59ac30d9abcf1d4a04c4de9089e67cbe0d300a502206930afa683f6807502de5c2431bf9a1fd333c8a2910a76304df0f3d23d83443f0121039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18fffffffff01ff4b0000000000001976a9146c86476d1d85cd60116cd122a274e6a570a5a35c88acc96d0700'
const keyPairs = [ const keyPairs = [
'032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d', '032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d',
'0216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2a', '0216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2a',
'039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18f' '039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18f'
].map(function (q) { return bitcoin.ECPair.fromPublicKey(Buffer.from(q, 'hex')) }) ].map(q => { return bitcoin.ECPair.fromPublicKey(Buffer.from(q, 'hex')) })
const tx = bitcoin.Transaction.fromHex(txHex) const tx = bitcoin.Transaction.fromHex(txHex)
tx.ins.forEach(function (input, i) { tx.ins.forEach((input, i) => {
const keyPair = keyPairs[i] const keyPair = keyPairs[i]
const p2pkh = bitcoin.payments.p2pkh({ const p2pkh = bitcoin.payments.p2pkh({
pubkey: keyPair.publicKey, pubkey: keyPair.publicKey,
@ -256,7 +256,7 @@ describe('bitcoinjs-lib (transactions)', function () {
}) })
}) })
it('can verify Transaction (P2SH(P2WPKH)) signatures', function () { it('can verify Transaction (P2SH(P2WPKH)) signatures', () => {
const utxos = { const utxos = {
'f72d1d83ac40fcedd01415751556a905844ab5f44bbb7728565ebb91b1590109:0': { 'f72d1d83ac40fcedd01415751556a905844ab5f44bbb7728565ebb91b1590109:0': {
value: 50000 value: 50000
@ -266,7 +266,7 @@ describe('bitcoinjs-lib (transactions)', function () {
const txHex = '02000000000101090159b191bb5e562877bb4bf4b54a8405a95615751514d0edfc40ac831d2df7000000001716001435a179e5516947a39ae9c8a25e9fe62c0fc598edffffffff01204e0000000000001976a91431d43308d3c886d53e9ae8a45728370571ff456988ac0247304402206ec41f685b997a51f325b07ee852e82a535f6b52ef54485cc133e05168aa052a022070bafa86108acb51c77b2b259ae8fb7fd1efa10fef804fcfe9b13c2db719acf5012103fb03e9d0a9af86cbed94225dbb8bb70f6b82109bce0a61ddcf41dab6cbb4871100000000' const txHex = '02000000000101090159b191bb5e562877bb4bf4b54a8405a95615751514d0edfc40ac831d2df7000000001716001435a179e5516947a39ae9c8a25e9fe62c0fc598edffffffff01204e0000000000001976a91431d43308d3c886d53e9ae8a45728370571ff456988ac0247304402206ec41f685b997a51f325b07ee852e82a535f6b52ef54485cc133e05168aa052a022070bafa86108acb51c77b2b259ae8fb7fd1efa10fef804fcfe9b13c2db719acf5012103fb03e9d0a9af86cbed94225dbb8bb70f6b82109bce0a61ddcf41dab6cbb4871100000000'
const tx = bitcoin.Transaction.fromHex(txHex) const tx = bitcoin.Transaction.fromHex(txHex)
tx.ins.forEach(function (input, i) { tx.ins.forEach((input, i) => {
const txId = Buffer.from(input.hash).reverse().toString('hex') const txId = Buffer.from(input.hash).reverse().toString('hex')
const utxo = utxos[`${txId}:${i}`] const utxo = utxos[`${txId}:${i}`]
if (!utxo) throw new Error('Missing utxo') if (!utxo) throw new Error('Missing utxo')

View file

@ -2,8 +2,8 @@ const { describe, it } = require('mocha')
const assert = require('assert') const assert = require('assert')
const u = require('./payments.utils') const u = require('./payments.utils')
;['embed', 'p2ms', 'p2pk', 'p2pkh', 'p2sh', 'p2wpkh', 'p2wsh'].forEach(function (p) { ;['embed', 'p2ms', 'p2pk', 'p2pkh', 'p2sh', 'p2wpkh', 'p2wsh'].forEach(p => {
describe(p, function () { describe(p, () => {
let fn let fn
let payment = require('../src/payments/' + p) let payment = require('../src/payments/' + p)
if (p === 'embed') { if (p === 'embed') {
@ -13,15 +13,15 @@ const u = require('./payments.utils')
} }
const fixtures = require('./fixtures/' + p) const fixtures = require('./fixtures/' + p)
fixtures.valid.forEach(function (f, i) { fixtures.valid.forEach((f, i) => {
it(f.description + ' as expected', function () { it(f.description + ' as expected', () => {
const args = u.preform(f.arguments) const args = u.preform(f.arguments)
const actual = fn(args, f.options) const actual = fn(args, f.options)
u.equate(actual, f.expected, f.arguments) u.equate(actual, f.expected, f.arguments)
}) })
it(f.description + ' as expected (no validation)', function () { it(f.description + ' as expected (no validation)', () => {
const args = u.preform(f.arguments) const args = u.preform(f.arguments)
const actual = fn(args, Object.assign({}, f.options, { const actual = fn(args, Object.assign({}, f.options, {
validate: false validate: false
@ -31,11 +31,11 @@ const u = require('./payments.utils')
}) })
}) })
fixtures.invalid.forEach(function (f) { fixtures.invalid.forEach(f => {
it('throws ' + f.exception + (f.description ? ('for ' + f.description) : ''), function () { it('throws ' + f.exception + (f.description ? ('for ' + f.description) : ''), () => {
const args = u.preform(f.arguments) const args = u.preform(f.arguments)
assert.throws(function () { assert.throws(() => {
fn(args, f.options) fn(args, f.options)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
@ -45,23 +45,23 @@ const u = require('./payments.utils')
if (!fixtures.dynamic) return if (!fixtures.dynamic) return
const { depends, details } = fixtures.dynamic const { depends, details } = fixtures.dynamic
details.forEach(function (f) { details.forEach(f => {
const detail = u.preform(f) const detail = u.preform(f)
const disabled = {} const disabled = {}
if (f.disabled) f.disabled.forEach(function (k) { disabled[k] = true }) if (f.disabled) f.disabled.forEach(k => { disabled[k] = true })
for (let key in depends) { for (let key in depends) {
if (key in disabled) continue if (key in disabled) continue
const dependencies = depends[key] const dependencies = depends[key]
dependencies.forEach(function (dependency) { dependencies.forEach(dependency => {
if (!Array.isArray(dependency)) dependency = [dependency] if (!Array.isArray(dependency)) dependency = [dependency]
const args = {} const args = {}
dependency.forEach(function (d) { u.from(d, detail, args) }) dependency.forEach(d => { u.from(d, detail, args) })
const expected = u.from(key, detail) const expected = u.from(key, detail)
it(f.description + ', ' + key + ' derives from ' + JSON.stringify(dependency), function () { it(f.description + ', ' + key + ' derives from ' + JSON.stringify(dependency), () => {
u.equate(fn(args), expected) u.equate(fn(args), expected)
}) })
}) })

View file

@ -39,7 +39,7 @@ function carryOver (a, b) {
function equateBase (a, b, context) { function equateBase (a, b, context) {
if ('output' in b) t.strictEqual(tryASM(a.output), tryASM(b.output), `Inequal ${context}output`) if ('output' in b) t.strictEqual(tryASM(a.output), tryASM(b.output), `Inequal ${context}output`)
if ('input' in b) t.strictEqual(tryASM(a.input), tryASM(b.input), `Inequal ${context}input`) if ('input' in b) t.strictEqual(tryASM(a.input), tryASM(b.input), `Inequal ${context}input`)
if ('witness' in b) t.deepEqual(tryHex(a.witness), tryHex(b.witness), `Inequal ${context}witness`) if ('witness' in b) t.deepStrictEqual(tryHex(a.witness), tryHex(b.witness), `Inequal ${context}witness`)
} }
function equate (a, b, args) { function equate (a, b, args) {
@ -58,19 +58,20 @@ function equate (a, b, args) {
equateBase(a, b, '') equateBase(a, b, '')
if (b.redeem) equateBase(a.redeem, b.redeem, 'redeem.') if (b.redeem) equateBase(a.redeem, b.redeem, 'redeem.')
if (b.network) t.deepEqual(a.network, BNETWORKS[b.network], 'Inequal *.network') if (b.network) t.deepStrictEqual(a.network, BNETWORKS[b.network], 'Inequal *.network')
// contextual // contextual
if (b.signature === null) b.signature = undefined if (b.signature === null) b.signature = undefined
if (b.signatures === null) b.signatures = undefined
if ('address' in b) t.strictEqual(a.address, b.address, 'Inequal *.address') if ('address' in b) t.strictEqual(a.address, b.address, 'Inequal *.address')
if ('hash' in b) t.strictEqual(tryHex(a.hash), tryHex(b.hash), 'Inequal *.hash') if ('hash' in b) t.strictEqual(tryHex(a.hash), tryHex(b.hash), 'Inequal *.hash')
if ('pubkey' in b) t.strictEqual(tryHex(a.pubkey), tryHex(b.pubkey), 'Inequal *.pubkey') if ('pubkey' in b) t.strictEqual(tryHex(a.pubkey), tryHex(b.pubkey), 'Inequal *.pubkey')
if ('signature' in b) t.strictEqual(tryHex(a.signature), tryHex(b.signature), 'Inequal signature') if ('signature' in b) t.strictEqual(tryHex(a.signature), tryHex(b.signature), 'Inequal signature')
if ('m' in b) t.strictEqual(a.m, b.m, 'Inequal *.m') if ('m' in b) t.strictEqual(a.m, b.m, 'Inequal *.m')
if ('n' in b) t.strictEqual(a.n, b.n, 'Inequal *.n') if ('n' in b) t.strictEqual(a.n, b.n, 'Inequal *.n')
if ('pubkeys' in b) t.deepEqual(tryHex(a.pubkeys), tryHex(b.pubkeys), 'Inequal *.pubkeys') if ('pubkeys' in b) t.deepStrictEqual(tryHex(a.pubkeys), tryHex(b.pubkeys), 'Inequal *.pubkeys')
if ('signatures' in b) t.deepEqual(tryHex(a.signatures), tryHex(b.signatures), 'Inequal *.signatures') if ('signatures' in b) t.deepStrictEqual(tryHex(a.signatures), tryHex(b.signatures), 'Inequal *.signatures')
if ('data' in b) t.deepEqual(tryHex(a.data), tryHex(b.data), 'Inequal *.data') if ('data' in b) t.deepStrictEqual(tryHex(a.data), tryHex(b.data), 'Inequal *.data')
} }
function preform (x) { function preform (x) {
@ -94,7 +95,7 @@ function preform (x) {
if (x.pubkey) x.pubkey = Buffer.from(x.pubkey, 'hex') if (x.pubkey) x.pubkey = Buffer.from(x.pubkey, 'hex')
if (x.signature) x.signature = Buffer.from(x.signature, 'hex') if (x.signature) x.signature = Buffer.from(x.signature, 'hex')
if (x.pubkeys) x.pubkeys = x.pubkeys.map(fromHex) if (x.pubkeys) x.pubkeys = x.pubkeys.map(fromHex)
if (x.signatures) x.signatures = x.signatures.map(function (y) { return Number.isFinite(y) ? y : Buffer.from(y, 'hex') }) if (x.signatures) x.signatures = x.signatures.map(y => { return Number.isFinite(y) ? y : Buffer.from(y, 'hex') })
if (x.redeem) { if (x.redeem) {
x.redeem = Object.assign({}, x.redeem) x.redeem = Object.assign({}, x.redeem)
if (typeof x.redeem.input === 'string') x.redeem.input = asmToBuffer(x.redeem.input) if (typeof x.redeem.input === 'string') x.redeem.input = asmToBuffer(x.redeem.input)

View file

@ -6,44 +6,44 @@ const minimalData = require('minimaldata')
const fixtures = require('./fixtures/script.json') const fixtures = require('./fixtures/script.json')
const fixtures2 = require('./fixtures/templates.json') const fixtures2 = require('./fixtures/templates.json')
describe('script', function () { describe('script', () => {
// TODO // TODO
describe('isCanonicalPubKey', function () { describe('isCanonicalPubKey', () => {
it('rejects if not provided a Buffer', function () { it('rejects if not provided a Buffer', () => {
assert.strictEqual(false, bscript.isCanonicalPubKey(0)) assert.strictEqual(false, bscript.isCanonicalPubKey(0))
}) })
it('rejects smaller than 33', function () { it('rejects smaller than 33', () => {
for (var i = 0; i < 33; i++) { for (var i = 0; i < 33; i++) {
assert.strictEqual(false, bscript.isCanonicalPubKey(Buffer.from('', i))) assert.strictEqual(false, bscript.isCanonicalPubKey(Buffer.from('', i)))
} }
}) })
}) })
describe.skip('isCanonicalScriptSignature', function () { describe.skip('isCanonicalScriptSignature', () => {
}) })
describe('fromASM/toASM', function () { describe('fromASM/toASM', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('encodes/decodes ' + f.asm, function () { it('encodes/decodes ' + f.asm, () => {
const script = bscript.fromASM(f.asm) const script = bscript.fromASM(f.asm)
assert.strictEqual(bscript.toASM(script), f.asm) assert.strictEqual(bscript.toASM(script), f.asm)
}) })
}) })
fixtures.invalid.fromASM.forEach(function (f) { fixtures.invalid.fromASM.forEach(f => {
it('throws ' + f.description, function () { it('throws ' + f.description, () => {
assert.throws(function () { assert.throws(() => {
bscript.fromASM(f.script) bscript.fromASM(f.script)
}, new RegExp(f.description)) }, new RegExp(f.description))
}) })
}) })
}) })
describe('fromASM/toASM (templates)', function () { describe('fromASM/toASM (templates)', () => {
fixtures2.valid.forEach(function (f) { fixtures2.valid.forEach(f => {
if (f.inputHex) { if (f.inputHex) {
const ih = bscript.toASM(Buffer.from(f.inputHex, 'hex')) const ih = bscript.toASM(Buffer.from(f.inputHex, 'hex'))
it('encodes/decodes ' + ih, function () { it('encodes/decodes ' + ih, () => {
const script = bscript.fromASM(f.input) const script = bscript.fromASM(f.input)
assert.strictEqual(script.toString('hex'), f.inputHex) assert.strictEqual(script.toString('hex'), f.inputHex)
assert.strictEqual(bscript.toASM(script), f.input) assert.strictEqual(bscript.toASM(script), f.input)
@ -51,7 +51,7 @@ describe('script', function () {
} }
if (f.outputHex) { if (f.outputHex) {
it('encodes/decodes ' + f.output, function () { it('encodes/decodes ' + f.output, () => {
const script = bscript.fromASM(f.output) const script = bscript.fromASM(f.output)
assert.strictEqual(script.toString('hex'), f.outputHex) assert.strictEqual(script.toString('hex'), f.outputHex)
assert.strictEqual(bscript.toASM(script), f.output) assert.strictEqual(bscript.toASM(script), f.output)
@ -60,9 +60,9 @@ describe('script', function () {
}) })
}) })
describe('isPushOnly', function () { describe('isPushOnly', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('returns ' + !!f.stack + ' for ' + f.asm, function () { it('returns ' + !!f.stack + ' for ' + f.asm, () => {
const script = bscript.fromASM(f.asm) const script = bscript.fromASM(f.asm)
const chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
@ -71,26 +71,26 @@ describe('script', function () {
}) })
}) })
describe('toStack', function () { describe('toStack', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('returns ' + !!f.stack + ' for ' + f.asm, function () { it('returns ' + !!f.stack + ' for ' + f.asm, () => {
if (!f.stack || !f.asm) return if (!f.stack || !f.asm) return
const script = bscript.fromASM(f.asm) const script = bscript.fromASM(f.asm)
const stack = bscript.toStack(script) const stack = bscript.toStack(script)
assert.deepEqual(stack.map(function (x) { assert.deepStrictEqual(stack.map(x => {
return x.toString('hex') return x.toString('hex')
}), f.stack) }), f.stack)
assert.equal(bscript.toASM(bscript.compile(stack)), f.asm, 'should rebuild same script from stack') assert.strictEqual(bscript.toASM(bscript.compile(stack)), f.asm, 'should rebuild same script from stack')
}) })
}) })
}) })
describe('compile (via fromASM)', function () { describe('compile (via fromASM)', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('(' + f.type + ') compiles ' + f.asm, function () { it('(' + f.type + ') compiles ' + f.asm, () => {
const scriptSig = bscript.fromASM(f.asm) const scriptSig = bscript.fromASM(f.asm)
assert.strictEqual(scriptSig.toString('hex'), f.script) assert.strictEqual(scriptSig.toString('hex'), f.script)
@ -104,9 +104,9 @@ describe('script', function () {
}) })
}) })
describe('decompile', function () { describe('decompile', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('decompiles ' + f.asm, function () { it('decompiles ' + f.asm, () => {
const chunks = bscript.decompile(Buffer.from(f.script, 'hex')) const chunks = bscript.decompile(Buffer.from(f.script, 'hex'))
assert.strictEqual(bscript.compile(chunks).toString('hex'), f.script) assert.strictEqual(bscript.compile(chunks).toString('hex'), f.script)
@ -123,8 +123,8 @@ describe('script', function () {
}) })
}) })
fixtures.invalid.decompile.forEach(function (f) { fixtures.invalid.decompile.forEach(f => {
it('fails to decompile ' + f.script + ', because "' + f.description + '"', function () { it('fails to decompile ' + f.script + ', because "' + f.description + '"', () => {
const chunks = bscript.decompile(Buffer.from(f.script, 'hex')) const chunks = bscript.decompile(Buffer.from(f.script, 'hex'))
assert.strictEqual(chunks, null) assert.strictEqual(chunks, null)
@ -132,9 +132,9 @@ describe('script', function () {
}) })
}) })
describe('SCRIPT_VERIFY_MINIMALDATA policy', function () { describe('SCRIPT_VERIFY_MINIMALDATA policy', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('compliant for ' + f.type + ' scriptSig ' + f.asm, function () { it('compliant for ' + f.type + ' scriptSig ' + f.asm, () => {
const script = Buffer.from(f.script, 'hex') const script = Buffer.from(f.script, 'hex')
assert(minimalData(script)) assert(minimalData(script))
@ -142,7 +142,7 @@ describe('script', function () {
}) })
function testEncodingForSize (i) { function testEncodingForSize (i) {
it('compliant for data PUSH of length ' + i, function () { it('compliant for data PUSH of length ' + i, () => {
const buffer = Buffer.alloc(i) const buffer = Buffer.alloc(i)
const script = bscript.compile([buffer]) const script = bscript.compile([buffer])

View file

@ -3,10 +3,10 @@ const assert = require('assert')
const scriptNumber = require('../src/script_number') const scriptNumber = require('../src/script_number')
const fixtures = require('./fixtures/script_number.json') const fixtures = require('./fixtures/script_number.json')
describe('script-number', function () { describe('script-number', () => {
describe('decode', function () { describe('decode', () => {
fixtures.forEach(function (f) { fixtures.forEach(f => {
it(f.hex + ' returns ' + f.number, function () { it(f.hex + ' returns ' + f.number, () => {
const actual = scriptNumber.decode(Buffer.from(f.hex, 'hex'), f.bytes) const actual = scriptNumber.decode(Buffer.from(f.hex, 'hex'), f.bytes)
assert.strictEqual(actual, f.number) assert.strictEqual(actual, f.number)
@ -14,9 +14,9 @@ describe('script-number', function () {
}) })
}) })
describe('encode', function () { describe('encode', () => {
fixtures.forEach(function (f) { fixtures.forEach(f => {
it(f.number + ' returns ' + f.hex, function () { it(f.number + ' returns ' + f.hex, () => {
const actual = scriptNumber.encode(f.number) const actual = scriptNumber.encode(f.number)
assert.strictEqual(actual.toString('hex'), f.hex) assert.strictEqual(actual.toString('hex'), f.hex)

View file

@ -4,7 +4,7 @@ const bscriptSig = require('../src/script').signature
const Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
const fixtures = require('./fixtures/signature.json') const fixtures = require('./fixtures/signature.json')
describe('Script Signatures', function () { describe('Script Signatures', () => {
function fromRaw (signature) { function fromRaw (signature) {
return Buffer.concat([ return Buffer.concat([
Buffer.from(signature.r, 'hex'), Buffer.from(signature.r, 'hex'),
@ -19,43 +19,43 @@ describe('Script Signatures', function () {
} }
} }
describe('encode', function () { describe('encode', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('encodes ' + f.hex, function () { it('encodes ' + f.hex, () => {
const buffer = bscriptSig.encode(fromRaw(f.raw), f.hashType) const buffer = bscriptSig.encode(fromRaw(f.raw), f.hashType)
assert.strictEqual(buffer.toString('hex'), f.hex) assert.strictEqual(buffer.toString('hex'), f.hex)
}) })
}) })
fixtures.invalid.forEach(function (f) { fixtures.invalid.forEach(f => {
if (!f.raw) return if (!f.raw) return
it('throws ' + f.exception, function () { it('throws ' + f.exception, () => {
const signature = fromRaw(f.raw) const signature = fromRaw(f.raw)
assert.throws(function () { assert.throws(() => {
bscriptSig.encode(signature, f.hashType) bscriptSig.encode(signature, f.hashType)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('decode', function () { describe('decode', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('decodes ' + f.hex, function () { it('decodes ' + f.hex, () => {
const decode = bscriptSig.decode(Buffer.from(f.hex, 'hex')) const decode = bscriptSig.decode(Buffer.from(f.hex, 'hex'))
assert.deepEqual(toRaw(decode.signature), f.raw) assert.deepStrictEqual(toRaw(decode.signature), f.raw)
assert.strictEqual(decode.hashType, f.hashType) assert.strictEqual(decode.hashType, f.hashType)
}) })
}) })
fixtures.invalid.forEach(function (f) { fixtures.invalid.forEach(f => {
it('throws on ' + f.hex, function () { it('throws on ' + f.hex, () => {
const buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex')
assert.throws(function () { assert.throws(() => {
bscriptSig.decode(buffer) bscriptSig.decode(buffer)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })

View file

@ -4,13 +4,13 @@ const bscript = require('../src/script')
const fixtures = require('./fixtures/transaction') const fixtures = require('./fixtures/transaction')
const Transaction = require('..').Transaction const Transaction = require('..').Transaction
describe('Transaction', function () { describe('Transaction', () => {
function fromRaw (raw, noWitness) { function fromRaw (raw, noWitness) {
const tx = new Transaction() const tx = new Transaction()
tx.version = raw.version tx.version = raw.version
tx.locktime = raw.locktime tx.locktime = raw.locktime
raw.ins.forEach(function (txIn, i) { raw.ins.forEach((txIn, i) => {
const txHash = Buffer.from(txIn.hash, 'hex') const txHash = Buffer.from(txIn.hash, 'hex')
let scriptSig let scriptSig
@ -23,7 +23,7 @@ describe('Transaction', function () {
tx.addInput(txHash, txIn.index, txIn.sequence, scriptSig) tx.addInput(txHash, txIn.index, txIn.sequence, scriptSig)
if (!noWitness && txIn.witness) { if (!noWitness && txIn.witness) {
const witness = txIn.witness.map(function (x) { const witness = txIn.witness.map(x => {
return Buffer.from(x, 'hex') return Buffer.from(x, 'hex')
}) })
@ -31,7 +31,7 @@ describe('Transaction', function () {
} }
}) })
raw.outs.forEach(function (txOut) { raw.outs.forEach(txOut => {
let script let script
if (txOut.data) { if (txOut.data) {
@ -46,19 +46,19 @@ describe('Transaction', function () {
return tx return tx
} }
describe('fromBuffer/fromHex', function () { describe('fromBuffer/fromHex', () => {
function importExport (f) { function importExport (f) {
const id = f.id || f.hash const id = f.id || f.hash
const txHex = f.hex || f.txHex const txHex = f.hex || f.txHex
it('imports ' + f.description + ' (' + id + ')', function () { it('imports ' + f.description + ' (' + id + ')', () => {
const actual = Transaction.fromHex(txHex) const actual = Transaction.fromHex(txHex)
assert.strictEqual(actual.toHex(), txHex) assert.strictEqual(actual.toHex(), txHex)
}) })
if (f.whex) { if (f.whex) {
it('imports ' + f.description + ' (' + id + ') as witness', function () { it('imports ' + f.description + ' (' + id + ') as witness', () => {
const actual = Transaction.fromHex(f.whex) const actual = Transaction.fromHex(f.whex)
assert.strictEqual(actual.toHex(), f.whex) assert.strictEqual(actual.toHex(), f.whex)
@ -70,38 +70,38 @@ describe('Transaction', function () {
fixtures.hashForSignature.forEach(importExport) fixtures.hashForSignature.forEach(importExport)
fixtures.hashForWitnessV0.forEach(importExport) fixtures.hashForWitnessV0.forEach(importExport)
fixtures.invalid.fromBuffer.forEach(function (f) { fixtures.invalid.fromBuffer.forEach(f => {
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, () => {
assert.throws(function () { assert.throws(() => {
Transaction.fromHex(f.hex) Transaction.fromHex(f.hex)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
it('.version should be interpreted as an int32le', function () { it('.version should be interpreted as an int32le', () => {
const txHex = 'ffffffff0000ffffffff' const txHex = 'ffffffff0000ffffffff'
const tx = Transaction.fromHex(txHex) const tx = Transaction.fromHex(txHex)
assert.equal(-1, tx.version) assert.strictEqual(-1, tx.version)
assert.equal(0xffffffff, tx.locktime) assert.strictEqual(0xffffffff, tx.locktime)
}) })
}) })
describe('toBuffer/toHex', function () { describe('toBuffer/toHex', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('exports ' + f.description + ' (' + f.id + ')', function () { it('exports ' + f.description + ' (' + f.id + ')', () => {
const actual = fromRaw(f.raw, true) const actual = fromRaw(f.raw, true)
assert.strictEqual(actual.toHex(), f.hex) assert.strictEqual(actual.toHex(), f.hex)
}) })
if (f.whex) { if (f.whex) {
it('exports ' + f.description + ' (' + f.id + ') as witness', function () { it('exports ' + f.description + ' (' + f.id + ') as witness', () => {
const wactual = fromRaw(f.raw) const wactual = fromRaw(f.raw)
assert.strictEqual(wactual.toHex(), f.whex) assert.strictEqual(wactual.toHex(), f.whex)
}) })
} }
}) })
it('accepts target Buffer and offset parameters', function () { it('accepts target Buffer and offset parameters', () => {
const f = fixtures.valid[0] const f = fixtures.valid[0]
const actual = fromRaw(f.raw) const actual = fromRaw(f.raw)
const byteLength = actual.byteLength() const byteLength = actual.byteLength()
@ -114,31 +114,31 @@ describe('Transaction', function () {
assert.strictEqual(b.length, byteLength) assert.strictEqual(b.length, byteLength)
assert.strictEqual(a.toString('hex'), f.hex) assert.strictEqual(a.toString('hex'), f.hex)
assert.strictEqual(b.toString('hex'), f.hex) assert.strictEqual(b.toString('hex'), f.hex)
assert.deepEqual(a, b) assert.deepStrictEqual(a, b)
assert.deepEqual(a, target.slice(0, byteLength)) assert.deepStrictEqual(a, target.slice(0, byteLength))
assert.deepEqual(b, target.slice(byteLength)) assert.deepStrictEqual(b, target.slice(byteLength))
}) })
}) })
describe('hasWitnesses', function () { describe('hasWitnesses', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
it('detects if the transaction has witnesses: ' + (f.whex ? 'true' : 'false'), function () { it('detects if the transaction has witnesses: ' + (f.whex ? 'true' : 'false'), () => {
assert.strictEqual(Transaction.fromHex(f.whex ? f.whex : f.hex).hasWitnesses(), !!f.whex) assert.strictEqual(Transaction.fromHex(f.whex ? f.whex : f.hex).hasWitnesses(), !!f.whex)
}) })
}) })
}) })
describe('weight/virtualSize', function () { describe('weight/virtualSize', () => {
it('computes virtual size', function () { it('computes virtual size', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
const transaction = Transaction.fromHex(f.whex ? f.whex : f.hex) const transaction = Transaction.fromHex(f.whex ? f.whex : f.hex)
assert.strictEqual(transaction.virtualSize(), f.virtualSize) assert.strictEqual(transaction.virtualSize(), f.virtualSize)
}) })
}) })
it('computes weight', function () { it('computes weight', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
const transaction = Transaction.fromHex(f.whex ? f.whex : f.hex) const transaction = Transaction.fromHex(f.whex ? f.whex : f.hex)
assert.strictEqual(transaction.weight(), f.weight) assert.strictEqual(transaction.weight(), f.weight)
@ -146,19 +146,19 @@ describe('Transaction', function () {
}) })
}) })
describe('addInput', function () { describe('addInput', () => {
let prevTxHash let prevTxHash
beforeEach(function () { beforeEach(() => {
prevTxHash = Buffer.from('ffffffff00ffff000000000000000000000000000000000000000000101010ff', 'hex') prevTxHash = Buffer.from('ffffffff00ffff000000000000000000000000000000000000000000101010ff', 'hex')
}) })
it('returns an index', function () { it('returns an index', () => {
const tx = new Transaction() const tx = new Transaction()
assert.strictEqual(tx.addInput(prevTxHash, 0), 0) assert.strictEqual(tx.addInput(prevTxHash, 0), 0)
assert.strictEqual(tx.addInput(prevTxHash, 0), 1) assert.strictEqual(tx.addInput(prevTxHash, 0), 1)
}) })
it('defaults to empty script, witness and 0xffffffff SEQUENCE number', function () { it('defaults to empty script, witness and 0xffffffff SEQUENCE number', () => {
const tx = new Transaction() const tx = new Transaction()
tx.addInput(prevTxHash, 0) tx.addInput(prevTxHash, 0)
@ -167,49 +167,49 @@ describe('Transaction', function () {
assert.strictEqual(tx.ins[0].sequence, 0xffffffff) assert.strictEqual(tx.ins[0].sequence, 0xffffffff)
}) })
fixtures.invalid.addInput.forEach(function (f) { fixtures.invalid.addInput.forEach(f => {
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, () => {
const tx = new Transaction() const tx = new Transaction()
const hash = Buffer.from(f.hash, 'hex') const hash = Buffer.from(f.hash, 'hex')
assert.throws(function () { assert.throws(() => {
tx.addInput(hash, f.index) tx.addInput(hash, f.index)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('addOutput', function () { describe('addOutput', () => {
it('returns an index', function () { it('returns an index', () => {
const tx = new Transaction() const tx = new Transaction()
assert.strictEqual(tx.addOutput(Buffer.alloc(0), 0), 0) assert.strictEqual(tx.addOutput(Buffer.alloc(0), 0), 0)
assert.strictEqual(tx.addOutput(Buffer.alloc(0), 0), 1) assert.strictEqual(tx.addOutput(Buffer.alloc(0), 0), 1)
}) })
}) })
describe('clone', function () { describe('clone', () => {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(f => {
let actual let actual
let expected let expected
beforeEach(function () { beforeEach(() => {
expected = Transaction.fromHex(f.hex) expected = Transaction.fromHex(f.hex)
actual = expected.clone() actual = expected.clone()
}) })
it('should have value equality', function () { it('should have value equality', () => {
assert.deepEqual(actual, expected) assert.deepStrictEqual(actual, expected)
}) })
it('should not have reference equality', function () { it('should not have reference equality', () => {
assert.notEqual(actual, expected) assert.notStrictEqual(actual, expected)
}) })
}) })
}) })
describe('getHash/getId', function () { describe('getHash/getId', () => {
function verify (f) { function verify (f) {
it('should return the id for ' + f.id + '(' + f.description + ')', function () { it('should return the id for ' + f.id + '(' + f.description + ')', () => {
const tx = Transaction.fromHex(f.whex || f.hex) const tx = Transaction.fromHex(f.whex || f.hex)
assert.strictEqual(tx.getHash().toString('hex'), f.hash) assert.strictEqual(tx.getHash().toString('hex'), f.hash)
@ -220,9 +220,9 @@ describe('Transaction', function () {
fixtures.valid.forEach(verify) fixtures.valid.forEach(verify)
}) })
describe('isCoinbase', function () { describe('isCoinbase', () => {
function verify (f) { function verify (f) {
it('should return ' + f.coinbase + ' for ' + f.id + '(' + f.description + ')', function () { it('should return ' + f.coinbase + ' for ' + f.id + '(' + f.description + ')', () => {
const tx = Transaction.fromHex(f.hex) const tx = Transaction.fromHex(f.hex)
assert.strictEqual(tx.isCoinbase(), f.coinbase) assert.strictEqual(tx.isCoinbase(), f.coinbase)
@ -232,8 +232,8 @@ describe('Transaction', function () {
fixtures.valid.forEach(verify) fixtures.valid.forEach(verify)
}) })
describe('hashForSignature', function () { describe('hashForSignature', () => {
it('does not use Witness serialization', function () { it('does not use Witness serialization', () => {
const randScript = Buffer.from('6a', 'hex') const randScript = Buffer.from('6a', 'hex')
const tx = new Transaction() const tx = new Transaction()
@ -241,24 +241,24 @@ describe('Transaction', function () {
tx.addOutput(randScript, 5000000000) tx.addOutput(randScript, 5000000000)
const original = tx.__toBuffer const original = tx.__toBuffer
tx.__toBuffer = function (a, b, c) { tx.__toBuffer = (a, b, c) => {
if (c !== false) throw new Error('hashForSignature MUST pass false') if (c !== false) throw new Error('hashForSignature MUST pass false')
return original.call(this, a, b, c) return original.call(this, a, b, c)
} }
assert.throws(function () { assert.throws(() => {
tx.__toBuffer(undefined, undefined, true) tx.__toBuffer(undefined, undefined, true)
}, /hashForSignature MUST pass false/) }, /hashForSignature MUST pass false/)
// assert hashForSignature does not pass false // assert hashForSignature does not pass false
assert.doesNotThrow(function () { assert.doesNotThrow(() => {
tx.hashForSignature(0, randScript, 1) tx.hashForSignature(0, randScript, 1)
}) })
}) })
fixtures.hashForSignature.forEach(function (f) { fixtures.hashForSignature.forEach(f => {
it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : f.script), function () { it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : f.script), () => {
const tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
const script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script)
@ -267,9 +267,9 @@ describe('Transaction', function () {
}) })
}) })
describe('hashForWitnessV0', function () { describe('hashForWitnessV0', () => {
fixtures.hashForWitnessV0.forEach(function (f) { fixtures.hashForWitnessV0.forEach(f => {
it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : ''), function () { it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : ''), () => {
const tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
const script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script)
@ -278,9 +278,9 @@ describe('Transaction', function () {
}) })
}) })
describe('setWitness', function () { describe('setWitness', () => {
it('only accepts a a witness stack (Array of Buffers)', function () { it('only accepts a a witness stack (Array of Buffers)', () => {
assert.throws(function () { assert.throws(() => {
(new Transaction()).setWitness(0, 'foobar') (new Transaction()).setWitness(0, 'foobar')
}, /Expected property "1" of type \[Buffer], got String "foobar"/) }, /Expected property "1" of type \[Buffer], got String "foobar"/)
}) })

View file

@ -15,9 +15,9 @@ function constructSign (f, txb) {
const network = NETWORKS[f.network] const network = NETWORKS[f.network]
const stages = f.stages && f.stages.concat() const stages = f.stages && f.stages.concat()
f.inputs.forEach(function (input, index) { f.inputs.forEach((input, index) => {
if (!input.signs) return if (!input.signs) return
input.signs.forEach(function (sign) { input.signs.forEach(sign => {
const keyPair = ECPair.fromWIF(sign.keyPair, network) const keyPair = ECPair.fromWIF(sign.keyPair, network)
let redeemScript let redeemScript
let witnessScript let witnessScript
@ -55,7 +55,7 @@ function construct (f, dontSign) {
if (Number.isFinite(f.version)) txb.setVersion(f.version) if (Number.isFinite(f.version)) txb.setVersion(f.version)
if (f.locktime !== undefined) txb.setLockTime(f.locktime) if (f.locktime !== undefined) txb.setLockTime(f.locktime)
f.inputs.forEach(function (input) { f.inputs.forEach(input => {
let prevTx let prevTx
if (input.txRaw) { if (input.txRaw) {
const constructed = construct(input.txRaw) const constructed = construct(input.txRaw)
@ -75,7 +75,7 @@ function construct (f, dontSign) {
txb.addInput(prevTx, input.vout, input.sequence, prevTxScript) txb.addInput(prevTx, input.vout, input.sequence, prevTxScript)
}) })
f.outputs.forEach(function (output) { f.outputs.forEach(output => {
if (output.address) { if (output.address) {
txb.addOutput(output.address, output.value) txb.addOutput(output.address, output.value)
} else { } else {
@ -87,20 +87,20 @@ function construct (f, dontSign) {
return constructSign(f, txb) return constructSign(f, txb)
} }
describe('TransactionBuilder', function () { describe('TransactionBuilder', () => {
// constants // constants
const keyPair = ECPair.fromPrivateKey(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')) const keyPair = ECPair.fromPrivateKey(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex'))
const scripts = [ const scripts = [
'1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH', '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH',
'1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP' '1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP'
].map(function (x) { ].map(x => {
return baddress.toOutputScript(x) return baddress.toOutputScript(x)
}) })
const txHash = Buffer.from('0e7cea811c0be9f73c0aca591034396e7264473fc25c1ca45195d7417b36cbe2', 'hex') const txHash = Buffer.from('0e7cea811c0be9f73c0aca591034396e7264473fc25c1ca45195d7417b36cbe2', 'hex')
describe('fromTransaction', function () { describe('fromTransaction', () => {
fixtures.valid.build.forEach(function (f) { fixtures.valid.build.forEach(f => {
it('returns TransactionBuilder, with ' + f.description, function () { it('returns TransactionBuilder, with ' + f.description, () => {
const network = NETWORKS[f.network || 'bitcoin'] const network = NETWORKS[f.network || 'bitcoin']
const tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
@ -112,82 +112,82 @@ describe('TransactionBuilder', function () {
}) })
}) })
fixtures.valid.fromTransaction.forEach(function (f) { fixtures.valid.fromTransaction.forEach(f => {
it('returns TransactionBuilder, with ' + f.description, function () { it('returns TransactionBuilder, with ' + f.description, () => {
const tx = new Transaction() const tx = new Transaction()
f.inputs.forEach(function (input) { f.inputs.forEach(input => {
const txHash2 = Buffer.from(input.txId, 'hex').reverse() const txHash2 = Buffer.from(input.txId, 'hex').reverse()
tx.addInput(txHash2, input.vout, undefined, bscript.fromASM(input.scriptSig)) tx.addInput(txHash2, input.vout, undefined, bscript.fromASM(input.scriptSig))
}) })
f.outputs.forEach(function (output) { f.outputs.forEach(output => {
tx.addOutput(bscript.fromASM(output.script), output.value) tx.addOutput(bscript.fromASM(output.script), output.value)
}) })
const txb = TransactionBuilder.fromTransaction(tx) const txb = TransactionBuilder.fromTransaction(tx)
const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build() const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build()
txAfter.ins.forEach(function (input, i) { txAfter.ins.forEach((input, i) => {
assert.equal(bscript.toASM(input.script), f.inputs[i].scriptSigAfter) assert.strictEqual(bscript.toASM(input.script), f.inputs[i].scriptSigAfter)
}) })
txAfter.outs.forEach(function (output, i) { txAfter.outs.forEach((output, i) => {
assert.equal(bscript.toASM(output.script), f.outputs[i].script) assert.strictEqual(bscript.toASM(output.script), f.outputs[i].script)
}) })
}) })
}) })
fixtures.valid.fromTransactionSequential.forEach(function (f) { fixtures.valid.fromTransactionSequential.forEach(f => {
it('with ' + f.description, function () { it('with ' + f.description, () => {
const network = NETWORKS[f.network] const network = NETWORKS[f.network]
const tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
const txb = TransactionBuilder.fromTransaction(tx, network) const txb = TransactionBuilder.fromTransaction(tx, network)
tx.ins.forEach(function (input, i) { tx.ins.forEach((input, i) => {
assert.equal(bscript.toASM(input.script), f.inputs[i].scriptSig) assert.strictEqual(bscript.toASM(input.script), f.inputs[i].scriptSig)
}) })
constructSign(f, txb) constructSign(f, txb)
const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build() const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build()
txAfter.ins.forEach(function (input, i) { txAfter.ins.forEach((input, i) => {
assert.equal(bscript.toASM(input.script), f.inputs[i].scriptSigAfter) assert.strictEqual(bscript.toASM(input.script), f.inputs[i].scriptSigAfter)
}) })
assert.equal(txAfter.toHex(), f.txHexAfter) assert.strictEqual(txAfter.toHex(), f.txHexAfter)
}) })
}) })
it('classifies transaction inputs', function () { it('classifies transaction inputs', () => {
const tx = Transaction.fromHex(fixtures.valid.classification.hex) const tx = Transaction.fromHex(fixtures.valid.classification.hex)
const txb = TransactionBuilder.fromTransaction(tx) const txb = TransactionBuilder.fromTransaction(tx)
txb.__INPUTS.forEach(function (i) { txb.__INPUTS.forEach(i => {
assert.strictEqual(i.prevOutType, 'scripthash') assert.strictEqual(i.prevOutType, 'scripthash')
assert.strictEqual(i.redeemScriptType, 'multisig') assert.strictEqual(i.redeemScriptType, 'multisig')
}) })
}) })
fixtures.invalid.fromTransaction.forEach(function (f) { fixtures.invalid.fromTransaction.forEach(f => {
it('throws ' + f.exception, function () { it('throws ' + f.exception, () => {
const tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
assert.throws(function () { assert.throws(() => {
TransactionBuilder.fromTransaction(tx) TransactionBuilder.fromTransaction(tx)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
}) })
}) })
describe('addInput', function () { describe('addInput', () => {
let txb let txb
beforeEach(function () { beforeEach(() => {
txb = new TransactionBuilder() txb = new TransactionBuilder()
}) })
it('accepts a txHash, index [and sequence number]', function () { it('accepts a txHash, index [and sequence number]', () => {
const vin = txb.addInput(txHash, 1, 54) const vin = txb.addInput(txHash, 1, 54)
assert.strictEqual(vin, 0) assert.strictEqual(vin, 0)
@ -198,7 +198,7 @@ describe('TransactionBuilder', function () {
assert.strictEqual(txb.__INPUTS[0].prevOutScript, undefined) assert.strictEqual(txb.__INPUTS[0].prevOutScript, undefined)
}) })
it('accepts a txHash, index [, sequence number and scriptPubKey]', function () { it('accepts a txHash, index [, sequence number and scriptPubKey]', () => {
const vin = txb.addInput(txHash, 1, 54, scripts[1]) const vin = txb.addInput(txHash, 1, 54, scripts[1])
assert.strictEqual(vin, 0) assert.strictEqual(vin, 0)
@ -209,7 +209,7 @@ describe('TransactionBuilder', function () {
assert.strictEqual(txb.__INPUTS[0].prevOutScript, scripts[1]) assert.strictEqual(txb.__INPUTS[0].prevOutScript, scripts[1])
}) })
it('accepts a prevTx, index [and sequence number]', function () { it('accepts a prevTx, index [and sequence number]', () => {
const prevTx = new Transaction() const prevTx = new Transaction()
prevTx.addOutput(scripts[0], 0) prevTx.addOutput(scripts[0], 0)
prevTx.addOutput(scripts[1], 1) prevTx.addOutput(scripts[1], 1)
@ -218,116 +218,116 @@ describe('TransactionBuilder', function () {
assert.strictEqual(vin, 0) assert.strictEqual(vin, 0)
const txIn = txb.__TX.ins[0] const txIn = txb.__TX.ins[0]
assert.deepEqual(txIn.hash, prevTx.getHash()) assert.deepStrictEqual(txIn.hash, prevTx.getHash())
assert.strictEqual(txIn.index, 1) assert.strictEqual(txIn.index, 1)
assert.strictEqual(txIn.sequence, 54) assert.strictEqual(txIn.sequence, 54)
assert.strictEqual(txb.__INPUTS[0].prevOutScript, scripts[1]) assert.strictEqual(txb.__INPUTS[0].prevOutScript, scripts[1])
}) })
it('returns the input index', function () { it('returns the input index', () => {
assert.strictEqual(txb.addInput(txHash, 0), 0) assert.strictEqual(txb.addInput(txHash, 0), 0)
assert.strictEqual(txb.addInput(txHash, 1), 1) assert.strictEqual(txb.addInput(txHash, 1), 1)
}) })
it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', function () { it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', () => {
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
txb.addOutput(scripts[0], 1000) txb.addOutput(scripts[0], 1000)
txb.sign(0, keyPair) txb.sign(0, keyPair)
assert.throws(function () { assert.throws(() => {
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
}, /No, this would invalidate signatures/) }, /No, this would invalidate signatures/)
}) })
}) })
describe('addOutput', function () { describe('addOutput', () => {
let txb let txb
beforeEach(function () { beforeEach(() => {
txb = new TransactionBuilder() txb = new TransactionBuilder()
}) })
it('accepts an address string and value', function () { it('accepts an address string and value', () => {
const { address } = payments.p2pkh({ pubkey: keyPair.publicKey }) const { address } = payments.p2pkh({ pubkey: keyPair.publicKey })
const vout = txb.addOutput(address, 1000) const vout = txb.addOutput(address, 1000)
assert.strictEqual(vout, 0) assert.strictEqual(vout, 0)
const txout = txb.__TX.outs[0] const txout = txb.__TX.outs[0]
assert.deepEqual(txout.script, scripts[0]) assert.deepStrictEqual(txout.script, scripts[0])
assert.strictEqual(txout.value, 1000) assert.strictEqual(txout.value, 1000)
}) })
it('accepts a ScriptPubKey and value', function () { it('accepts a ScriptPubKey and value', () => {
const vout = txb.addOutput(scripts[0], 1000) const vout = txb.addOutput(scripts[0], 1000)
assert.strictEqual(vout, 0) assert.strictEqual(vout, 0)
const txout = txb.__TX.outs[0] const txout = txb.__TX.outs[0]
assert.deepEqual(txout.script, scripts[0]) assert.deepStrictEqual(txout.script, scripts[0])
assert.strictEqual(txout.value, 1000) assert.strictEqual(txout.value, 1000)
}) })
it('throws if address is of the wrong network', function () { it('throws if address is of the wrong network', () => {
assert.throws(function () { assert.throws(() => {
txb.addOutput('2NGHjvjw83pcVFgMcA7QvSMh2c246rxLVz9', 1000) txb.addOutput('2NGHjvjw83pcVFgMcA7QvSMh2c246rxLVz9', 1000)
}, /2NGHjvjw83pcVFgMcA7QvSMh2c246rxLVz9 has no matching Script/) }, /2NGHjvjw83pcVFgMcA7QvSMh2c246rxLVz9 has no matching Script/)
}) })
it('add second output after signed first input with SIGHASH_NONE', function () { it('add second output after signed first input with SIGHASH_NONE', () => {
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
txb.addOutput(scripts[0], 2000) txb.addOutput(scripts[0], 2000)
txb.sign(0, keyPair, undefined, Transaction.SIGHASH_NONE) txb.sign(0, keyPair, undefined, Transaction.SIGHASH_NONE)
assert.equal(txb.addOutput(scripts[1], 9000), 1) assert.strictEqual(txb.addOutput(scripts[1], 9000), 1)
}) })
it('add first output after signed first input with SIGHASH_NONE', function () { it('add first output after signed first input with SIGHASH_NONE', () => {
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
txb.sign(0, keyPair, undefined, Transaction.SIGHASH_NONE) txb.sign(0, keyPair, undefined, Transaction.SIGHASH_NONE)
assert.equal(txb.addOutput(scripts[0], 2000), 0) assert.strictEqual(txb.addOutput(scripts[0], 2000), 0)
}) })
it('add second output after signed first input with SIGHASH_SINGLE', function () { it('add second output after signed first input with SIGHASH_SINGLE', () => {
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
txb.addOutput(scripts[0], 2000) txb.addOutput(scripts[0], 2000)
txb.sign(0, keyPair, undefined, Transaction.SIGHASH_SINGLE) txb.sign(0, keyPair, undefined, Transaction.SIGHASH_SINGLE)
assert.equal(txb.addOutput(scripts[1], 9000), 1) assert.strictEqual(txb.addOutput(scripts[1], 9000), 1)
}) })
it('add first output after signed first input with SIGHASH_SINGLE', function () { it('add first output after signed first input with SIGHASH_SINGLE', () => {
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
txb.sign(0, keyPair, undefined, Transaction.SIGHASH_SINGLE) txb.sign(0, keyPair, undefined, Transaction.SIGHASH_SINGLE)
assert.throws(function () { assert.throws(() => {
txb.addOutput(scripts[0], 2000) txb.addOutput(scripts[0], 2000)
}, /No, this would invalidate signatures/) }, /No, this would invalidate signatures/)
}) })
it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', function () { it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', () => {
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
txb.addOutput(scripts[0], 2000) txb.addOutput(scripts[0], 2000)
txb.sign(0, keyPair) txb.sign(0, keyPair)
assert.throws(function () { assert.throws(() => {
txb.addOutput(scripts[1], 9000) txb.addOutput(scripts[1], 9000)
}, /No, this would invalidate signatures/) }, /No, this would invalidate signatures/)
}) })
}) })
describe('setLockTime', function () { describe('setLockTime', () => {
it('throws if if there exist any scriptSigs', function () { it('throws if if there exist any scriptSigs', () => {
const txb = new TransactionBuilder() const txb = new TransactionBuilder()
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
txb.addOutput(scripts[0], 100) txb.addOutput(scripts[0], 100)
txb.sign(0, keyPair) txb.sign(0, keyPair)
assert.throws(function () { assert.throws(() => {
txb.setLockTime(65535) txb.setLockTime(65535)
}, /No, this would invalidate signatures/) }, /No, this would invalidate signatures/)
}) })
}) })
describe('sign', function () { describe('sign', () => {
it('supports the alternative abstract interface { publicKey, sign }', function () { it('supports the alternative abstract interface { publicKey, sign }', () => {
const keyPair = { const keyPair = {
publicKey: ECPair.makeRandom({ rng: function () { return Buffer.alloc(32, 1) } }).publicKey, publicKey: ECPair.makeRandom({ rng: () => { return Buffer.alloc(32, 1) } }).publicKey,
sign: function (hash) { return Buffer.alloc(64, 0x5f) } sign: hash => { return Buffer.alloc(64, 0x5f) }
} }
const txb = new TransactionBuilder() const txb = new TransactionBuilder()
@ -335,16 +335,16 @@ describe('TransactionBuilder', function () {
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1)
txb.addOutput('1111111111111111111114oLvT2', 100000) txb.addOutput('1111111111111111111114oLvT2', 100000)
txb.sign(0, keyPair) txb.sign(0, keyPair)
assert.equal(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a47304402205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f02205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f0121031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000') assert.strictEqual(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000006a47304402205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f02205f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f0121031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078fffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000')
}) })
fixtures.invalid.sign.forEach(function (f) { fixtures.invalid.sign.forEach(f => {
it('throws ' + f.exception + (f.description ? ' (' + f.description + ')' : ''), function () { it('throws ' + f.exception + (f.description ? ' (' + f.description + ')' : ''), () => {
const txb = construct(f, true) const txb = construct(f, true)
let threw = false let threw = false
f.inputs.forEach(function (input, index) { f.inputs.forEach((input, index) => {
input.signs.forEach(function (sign) { input.signs.forEach(sign => {
const keyPairNetwork = NETWORKS[sign.network || f.network] const keyPairNetwork = NETWORKS[sign.network || f.network]
const keyPair2 = ECPair.fromWIF(sign.keyPair, keyPairNetwork) const keyPair2 = ECPair.fromWIF(sign.keyPair, keyPairNetwork)
let redeemScript let redeemScript
@ -359,7 +359,7 @@ describe('TransactionBuilder', function () {
} }
if (sign.throws) { if (sign.throws) {
assert.throws(function () { assert.throws(() => {
txb.sign(index, keyPair2, redeemScript, sign.hashType, sign.value, witnessScript) txb.sign(index, keyPair2, redeemScript, sign.hashType, sign.value, witnessScript)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
threw = true threw = true
@ -369,14 +369,14 @@ describe('TransactionBuilder', function () {
}) })
}) })
assert.equal(threw, true) assert.strictEqual(threw, true)
}) })
}) })
}) })
describe('build', function () { describe('build', () => {
fixtures.valid.build.forEach(function (f) { fixtures.valid.build.forEach(f => {
it('builds "' + f.description + '"', function () { it('builds "' + f.description + '"', () => {
const txb = construct(f) const txb = construct(f)
const tx = f.incomplete ? txb.buildIncomplete() : txb.build() const tx = f.incomplete ? txb.buildIncomplete() : txb.build()
@ -385,10 +385,10 @@ describe('TransactionBuilder', function () {
}) })
// TODO: remove duplicate test code // TODO: remove duplicate test code
fixtures.invalid.build.forEach(function (f) { fixtures.invalid.build.forEach(f => {
describe('for ' + (f.description || f.exception), function () { describe('for ' + (f.description || f.exception), () => {
it('throws ' + f.exception, function () { it('throws ' + f.exception, () => {
assert.throws(function () { assert.throws(() => {
let txb let txb
if (f.txHex) { if (f.txHex) {
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex))
@ -402,8 +402,8 @@ describe('TransactionBuilder', function () {
// if throws on incomplete too, enforce that // if throws on incomplete too, enforce that
if (f.incomplete) { if (f.incomplete) {
it('throws ' + f.exception, function () { it('throws ' + f.exception, () => {
assert.throws(function () { assert.throws(() => {
let txb let txb
if (f.txHex) { if (f.txHex) {
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex))
@ -415,7 +415,7 @@ describe('TransactionBuilder', function () {
}, new RegExp(f.exception)) }, new RegExp(f.exception))
}) })
} else { } else {
it('does not throw if buildIncomplete', function () { it('does not throw if buildIncomplete', () => {
let txb let txb
if (f.txHex) { if (f.txHex) {
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex))
@ -429,7 +429,7 @@ describe('TransactionBuilder', function () {
}) })
}) })
it('for incomplete with 0 signatures', function () { it('for incomplete with 0 signatures', () => {
const randomTxData = '0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000' const randomTxData = '0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000'
const randomAddress = '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH' const randomAddress = '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'
@ -441,7 +441,7 @@ describe('TransactionBuilder', function () {
assert(tx) assert(tx)
}) })
it('for incomplete P2SH with 0 signatures', function () { it('for incomplete P2SH with 0 signatures', () => {
const inp = Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000017a91471a8ec07ff69c6c4fee489184c462a9b1b9237488700000000', 'hex') // arbitrary P2SH input const inp = Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000017a91471a8ec07ff69c6c4fee489184c462a9b1b9237488700000000', 'hex') // arbitrary P2SH input
const inpTx = Transaction.fromBuffer(inp) const inpTx = Transaction.fromBuffer(inp)
@ -452,7 +452,7 @@ describe('TransactionBuilder', function () {
txb.buildIncomplete() txb.buildIncomplete()
}) })
it('for incomplete P2WPKH with 0 signatures', function () { it('for incomplete P2WPKH with 0 signatures', () => {
const inp = Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a8040000001600141a15805e1f4040c9f68ccc887fca2e63547d794b00000000', 'hex') const inp = Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a8040000001600141a15805e1f4040c9f68ccc887fca2e63547d794b00000000', 'hex')
const inpTx = Transaction.fromBuffer(inp) const inpTx = Transaction.fromBuffer(inp)
@ -463,7 +463,7 @@ describe('TransactionBuilder', function () {
txb.buildIncomplete() txb.buildIncomplete()
}) })
it('for incomplete P2WSH with 0 signatures', function () { it('for incomplete P2WSH with 0 signatures', () => {
const inpTx = Transaction.fromBuffer(Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000022002072df76fcc0b231b94bdf7d8c25d7eef4716597818d211e19ade7813bff7a250200000000', 'hex')) const inpTx = Transaction.fromBuffer(Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000022002072df76fcc0b231b94bdf7d8c25d7eef4716597818d211e19ade7813bff7a250200000000', 'hex'))
const txb = new TransactionBuilder(NETWORKS.testnet) const txb = new TransactionBuilder(NETWORKS.testnet)
@ -474,17 +474,17 @@ describe('TransactionBuilder', function () {
}) })
}) })
describe('multisig', function () { describe('multisig', () => {
fixtures.valid.multisig.forEach(function (f) { fixtures.valid.multisig.forEach(f => {
it(f.description, function () { it(f.description, () => {
const network = NETWORKS[f.network] const network = NETWORKS[f.network]
let txb = construct(f, true) let txb = construct(f, true)
let tx let tx
f.inputs.forEach(function (input, i) { f.inputs.forEach((input, i) => {
const redeemScript = bscript.fromASM(input.redeemScript) const redeemScript = bscript.fromASM(input.redeemScript)
input.signs.forEach(function (sign) { input.signs.forEach(sign => {
// rebuild the transaction each-time after the first // rebuild the transaction each-time after the first
if (tx) { if (tx) {
// manually override the scriptSig? // manually override the scriptSig?
@ -513,10 +513,10 @@ describe('TransactionBuilder', function () {
}) })
}) })
describe('various edge case', function () { describe('various edge case', () => {
const network = NETWORKS.testnet const network = NETWORKS.testnet
it('should warn of high fee for segwit transaction based on VSize, not Size', function () { it('should warn of high fee for segwit transaction based on VSize, not Size', () => {
const rawtx = '01000000000104fdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a' + const rawtx = '01000000000104fdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a' +
'1df90000000000fffffffffdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a1df9' + '1df90000000000fffffffffdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a1df9' +
'0100000000ffffffffa2ef7aaab316a3e5b5b0a78d1d35c774b95a079f9f0c762277a49caf1f26bca40000' + '0100000000ffffffffa2ef7aaab316a3e5b5b0a78d1d35c774b95a079f9f0c762277a49caf1f26bca40000' +
@ -538,12 +538,12 @@ describe('TransactionBuilder', function () {
txb.__INPUTS[2].value = 248920 txb.__INPUTS[2].value = 248920
txb.__INPUTS[3].value = 248920 txb.__INPUTS[3].value = 248920
assert.throws(function () { assert.throws(() => {
txb.build() txb.build()
}, new RegExp('Transaction has absurd fees')) }, new RegExp('Transaction has absurd fees'))
}) })
it('should classify witness inputs with witness = true during multisigning', function () { it('should classify witness inputs with witness = true during multisigning', () => {
const keyPair = ECPair.fromWIF('cRAwuVuVSBZMPu7hdrYvMCZ8eevzmkExjFbaBLhqnDdrezxN3nTS', network) const keyPair = ECPair.fromWIF('cRAwuVuVSBZMPu7hdrYvMCZ8eevzmkExjFbaBLhqnDdrezxN3nTS', network)
const witnessScript = Buffer.from('522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea1952ae', 'hex') const witnessScript = Buffer.from('522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea1952ae', 'hex')
const redeemScript = Buffer.from('002024376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5af', 'hex') const redeemScript = Buffer.from('002024376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5af', 'hex')
@ -558,13 +558,13 @@ describe('TransactionBuilder', function () {
const tx = txb.buildIncomplete() const tx = txb.buildIncomplete()
// Only input is segwit, so txid should be accurate with the final tx // Only input is segwit, so txid should be accurate with the final tx
assert.equal(tx.getId(), 'f15d0a65b21b4471405b21a099f8b18e1ae4d46d55efbd0f4766cf11ad6cb821') assert.strictEqual(tx.getId(), 'f15d0a65b21b4471405b21a099f8b18e1ae4d46d55efbd0f4766cf11ad6cb821')
const txHex = tx.toHex() const txHex = tx.toHex()
TransactionBuilder.fromTransaction(Transaction.fromHex(txHex)) TransactionBuilder.fromTransaction(Transaction.fromHex(txHex))
}) })
it('should handle badly pre-filled OP_0s', function () { it('should handle badly pre-filled OP_0s', () => {
// OP_0 is used where a signature is missing // OP_0 is used where a signature is missing
const redeemScripSig = bscript.fromASM('OP_0 OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae') const redeemScripSig = bscript.fromASM('OP_0 OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae')
const redeemScript = bscript.fromASM('OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG') const redeemScript = bscript.fromASM('OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG')
@ -580,11 +580,11 @@ describe('TransactionBuilder', function () {
txb.sign(0, keyPair2, redeemScript) txb.sign(0, keyPair2, redeemScript)
const tx2 = txb.build() const tx2 = txb.build()
assert.equal(tx2.getId(), 'eab59618a564e361adef6d918bd792903c3d41bcf1220137364fb847880467f9') assert.strictEqual(tx2.getId(), 'eab59618a564e361adef6d918bd792903c3d41bcf1220137364fb847880467f9')
assert.equal(bscript.toASM(tx2.ins[0].script), 'OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae') assert.strictEqual(bscript.toASM(tx2.ins[0].script), 'OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae')
}) })
it('should not classify blank scripts as nonstandard', function () { it('should not classify blank scripts as nonstandard', () => {
let txb = new TransactionBuilder() let txb = new TransactionBuilder()
txb.setVersion(1) txb.setVersion(1)
txb.addInput('aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31', 0) txb.addInput('aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31', 0)
@ -596,14 +596,14 @@ describe('TransactionBuilder', function () {
txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000) txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000)
txb.sign(0, keyPair) txb.sign(0, keyPair)
const txId = txb.build().getId() const txId = txb.build().getId()
assert.equal(txId, '54f097315acbaedb92a95455da3368eb45981cdae5ffbc387a9afc872c0f29b3') assert.strictEqual(txId, '54f097315acbaedb92a95455da3368eb45981cdae5ffbc387a9afc872c0f29b3')
// and, repeat // and, repeat
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(incomplete)) txb = TransactionBuilder.fromTransaction(Transaction.fromHex(incomplete))
txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000) txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000)
txb.sign(0, keyPair) txb.sign(0, keyPair)
const txId2 = txb.build().getId() const txId2 = txb.build().getId()
assert.equal(txId, txId2) assert.strictEqual(txId, txId2)
}) })
}) })
}) })

View file

@ -3,38 +3,38 @@ const assert = require('assert')
const types = require('../src/types') const types = require('../src/types')
const typeforce = require('typeforce') const typeforce = require('typeforce')
describe('types', function () { describe('types', () => {
describe('Buffer Hash160/Hash256', function () { describe('Buffer Hash160/Hash256', () => {
const buffer20byte = Buffer.alloc(20) const buffer20byte = Buffer.alloc(20)
const buffer32byte = Buffer.alloc(32) const buffer32byte = Buffer.alloc(32)
it('return true for valid size', function () { it('return true for valid size', () => {
assert(types.Hash160bit(buffer20byte)) assert(types.Hash160bit(buffer20byte))
assert(types.Hash256bit(buffer32byte)) assert(types.Hash256bit(buffer32byte))
}) })
it('return true for oneOf', function () { it('return true for oneOf', () => {
assert.doesNotThrow(function () { assert.doesNotThrow(() => {
typeforce(types.oneOf(types.Hash160bit, types.Hash256bit), buffer32byte) typeforce(types.oneOf(types.Hash160bit, types.Hash256bit), buffer32byte)
}) })
assert.doesNotThrow(function () { assert.doesNotThrow(() => {
typeforce(types.oneOf(types.Hash256bit, types.Hash160bit), buffer32byte) typeforce(types.oneOf(types.Hash256bit, types.Hash160bit), buffer32byte)
}) })
}) })
it('throws for invalid size', function () { it('throws for invalid size', () => {
assert.throws(function () { assert.throws(() => {
types.Hash160bit(buffer32byte) types.Hash160bit(buffer32byte)
}, /Expected Buffer\(Length: 20\), got Buffer\(Length: 32\)/) }, /Expected Buffer\(Length: 20\), got Buffer\(Length: 32\)/)
assert.throws(function () { assert.throws(() => {
types.Hash256bit(buffer20byte) types.Hash256bit(buffer20byte)
}, /Expected Buffer\(Length: 32\), got Buffer\(Length: 20\)/) }, /Expected Buffer\(Length: 32\), got Buffer\(Length: 20\)/)
}) })
}) })
describe('Satoshi', function () { describe('Satoshi', () => {
[ [
{ value: -1, result: false }, { value: -1, result: false },
{ value: 0, result: true }, { value: 0, result: true },
@ -42,8 +42,8 @@ describe('types', function () {
{ value: 20999999 * 1e8, result: true }, { value: 20999999 * 1e8, result: true },
{ value: 21000000 * 1e8, result: true }, { value: 21000000 * 1e8, result: true },
{ value: 21000001 * 1e8, result: false } { value: 21000001 * 1e8, result: false }
].forEach(function (f) { ].forEach(f => {
it('returns ' + f.result + ' for valid for ' + f.value, function () { it('returns ' + f.result + ' for valid for ' + f.value, () => {
assert.strictEqual(types.Satoshi(f.value), f.result) assert.strictEqual(types.Satoshi(f.value), f.result)
}) })
}) })