Merge pull request #1111 from bitcoinjs/varlet

s/var/let and s/var/const
This commit is contained in:
Daniel Cousens 2018-06-26 13:13:32 +10:00 committed by GitHub
commit d78bf6a2b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 1048 additions and 1041 deletions

View file

@ -1,28 +1,28 @@
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var bech32 = require('bech32') const bech32 = require('bech32')
var bs58check = require('bs58check') const bs58check = require('bs58check')
var bscript = require('./script') const bscript = require('./script')
var btemplates = require('./templates') const btemplates = require('./templates')
var networks = require('./networks') const networks = require('./networks')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var types = require('./types') const types = require('./types')
function fromBase58Check (address) { function fromBase58Check (address) {
var payload = bs58check.decode(address) const payload = bs58check.decode(address)
// TODO: 4.0.0, move to "toOutputScript" // TODO: 4.0.0, move to "toOutputScript"
if (payload.length < 21) throw new TypeError(address + ' is too short') if (payload.length < 21) throw new TypeError(address + ' is too short')
if (payload.length > 21) throw new TypeError(address + ' is too long') if (payload.length > 21) throw new TypeError(address + ' is too long')
var version = payload.readUInt8(0) const version = payload.readUInt8(0)
var hash = payload.slice(1) const hash = payload.slice(1)
return { version: version, hash: hash } return { version: version, hash: hash }
} }
function fromBech32 (address) { function fromBech32 (address) {
var result = bech32.decode(address) const result = bech32.decode(address)
var data = bech32.fromWords(result.words.slice(1)) const data = bech32.fromWords(result.words.slice(1))
return { return {
version: result.words[0], version: result.words[0],
@ -34,7 +34,7 @@ function fromBech32 (address) {
function toBase58Check (hash, version) { function toBase58Check (hash, version) {
typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments) typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments)
var payload = Buffer.allocUnsafe(21) const payload = Buffer.allocUnsafe(21)
payload.writeUInt8(version, 0) payload.writeUInt8(version, 0)
hash.copy(payload, 1) hash.copy(payload, 1)
@ -42,7 +42,7 @@ function toBase58Check (hash, version) {
} }
function toBech32 (data, version, prefix) { function toBech32 (data, version, prefix) {
var words = bech32.toWords(data) const words = bech32.toWords(data)
words.unshift(version) words.unshift(version)
return bech32.encode(prefix, words) return bech32.encode(prefix, words)
@ -62,7 +62,7 @@ function fromOutputScript (outputScript, network) {
function toOutputScript (address, network) { function toOutputScript (address, network) {
network = network || networks.bitcoin network = network || networks.bitcoin
var decode let decode
try { try {
decode = fromBase58Check(address) decode = fromBase58Check(address)
} catch (e) {} } catch (e) {}

View file

@ -1,11 +1,11 @@
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var bcrypto = require('./crypto') const bcrypto = require('./crypto')
var fastMerkleRoot = require('merkle-lib/fastRoot') const fastMerkleRoot = require('merkle-lib/fastRoot')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var types = require('./types') const types = require('./types')
var varuint = require('varuint-bitcoin') const varuint = require('varuint-bitcoin')
var Transaction = require('./transaction') const Transaction = require('./transaction')
function Block () { function Block () {
this.version = 1 this.version = 1
@ -19,25 +19,25 @@ function Block () {
Block.fromBuffer = function (buffer) { Block.fromBuffer = function (buffer) {
if (buffer.length < 80) throw new Error('Buffer too small (< 80 bytes)') if (buffer.length < 80) throw new Error('Buffer too small (< 80 bytes)')
var offset = 0 let offset = 0
function readSlice (n) { function readSlice (n) {
offset += n offset += n
return buffer.slice(offset - n, offset) return buffer.slice(offset - n, offset)
} }
function readUInt32 () { function readUInt32 () {
var i = buffer.readUInt32LE(offset) const i = buffer.readUInt32LE(offset)
offset += 4 offset += 4
return i return i
} }
function readInt32 () { function readInt32 () {
var i = buffer.readInt32LE(offset) const i = buffer.readInt32LE(offset)
offset += 4 offset += 4
return i return i
} }
var block = new Block() const block = new Block()
block.version = readInt32() block.version = readInt32()
block.prevHash = readSlice(32) block.prevHash = readSlice(32)
block.merkleRoot = readSlice(32) block.merkleRoot = readSlice(32)
@ -48,22 +48,22 @@ Block.fromBuffer = function (buffer) {
if (buffer.length === 80) return block if (buffer.length === 80) return block
function readVarInt () { function readVarInt () {
var vi = varuint.decode(buffer, offset) const vi = varuint.decode(buffer, offset)
offset += varuint.decode.bytes offset += varuint.decode.bytes
return vi return vi
} }
function readTransaction () { function readTransaction () {
var tx = Transaction.fromBuffer(buffer.slice(offset), true) const tx = Transaction.fromBuffer(buffer.slice(offset), true)
offset += tx.byteLength() offset += tx.byteLength()
return tx return tx
} }
var nTransactions = readVarInt() const nTransactions = readVarInt()
block.transactions = [] block.transactions = []
for (var i = 0; i < nTransactions; ++i) { for (var i = 0; i < nTransactions; ++i) {
var tx = readTransaction() const tx = readTransaction()
block.transactions.push(tx) block.transactions.push(tx)
} }
@ -91,7 +91,7 @@ Block.prototype.getId = function () {
} }
Block.prototype.getUTCDate = function () { Block.prototype.getUTCDate = function () {
var date = new Date(0) // epoch const date = new Date(0) // epoch
date.setUTCSeconds(this.timestamp) date.setUTCSeconds(this.timestamp)
return date return date
@ -99,9 +99,9 @@ Block.prototype.getUTCDate = function () {
// TODO: buffer, offset compatibility // TODO: buffer, offset compatibility
Block.prototype.toBuffer = function (headersOnly) { Block.prototype.toBuffer = function (headersOnly) {
var buffer = Buffer.allocUnsafe(this.byteLength(headersOnly)) const buffer = Buffer.allocUnsafe(this.byteLength(headersOnly))
var offset = 0 let offset = 0
function writeSlice (slice) { function writeSlice (slice) {
slice.copy(buffer, offset) slice.copy(buffer, offset)
offset += slice.length offset += slice.length
@ -129,7 +129,7 @@ Block.prototype.toBuffer = function (headersOnly) {
offset += varuint.encode.bytes offset += varuint.encode.bytes
this.transactions.forEach(function (tx) { this.transactions.forEach(function (tx) {
var txSize = tx.byteLength() // TODO: extract from toBuffer? const txSize = tx.byteLength() // TODO: extract from toBuffer?
tx.toBuffer(buffer, offset) tx.toBuffer(buffer, offset)
offset += txSize offset += txSize
}) })
@ -142,9 +142,9 @@ Block.prototype.toHex = function (headersOnly) {
} }
Block.calculateTarget = function (bits) { Block.calculateTarget = function (bits) {
var exponent = ((bits & 0xff000000) >> 24) - 3 const exponent = ((bits & 0xff000000) >> 24) - 3
var mantissa = bits & 0x007fffff const mantissa = bits & 0x007fffff
var target = Buffer.alloc(32, 0) const target = Buffer.alloc(32, 0)
target.writeUInt32BE(mantissa, 28 - exponent) target.writeUInt32BE(mantissa, 28 - exponent)
return target return target
} }
@ -153,7 +153,7 @@ Block.calculateMerkleRoot = function (transactions) {
typeforce([{ getHash: types.Function }], transactions) typeforce([{ getHash: types.Function }], transactions)
if (transactions.length === 0) throw TypeError('Cannot compute merkle root for zero transactions') if (transactions.length === 0) throw TypeError('Cannot compute merkle root for zero transactions')
var hashes = transactions.map(function (transaction) { const hashes = transactions.map(function (transaction) {
return transaction.getHash() return transaction.getHash()
}) })
@ -163,13 +163,13 @@ Block.calculateMerkleRoot = function (transactions) {
Block.prototype.checkMerkleRoot = function () { Block.prototype.checkMerkleRoot = function () {
if (!this.transactions) return false if (!this.transactions) return false
var actualMerkleRoot = Block.calculateMerkleRoot(this.transactions) const actualMerkleRoot = Block.calculateMerkleRoot(this.transactions)
return this.merkleRoot.compare(actualMerkleRoot) === 0 return this.merkleRoot.compare(actualMerkleRoot) === 0
} }
Block.prototype.checkProofOfWork = function () { Block.prototype.checkProofOfWork = function () {
var hash = this.getHash().reverse() const hash = this.getHash().reverse()
var target = Block.calculateTarget(this.bits) const target = Block.calculateTarget(this.bits)
return hash.compare(target) <= 0 return hash.compare(target) <= 0
} }

View file

@ -7,8 +7,8 @@ function verifuint (value, max) {
} }
function readUInt64LE (buffer, offset) { function readUInt64LE (buffer, offset) {
var a = buffer.readUInt32LE(offset) const a = buffer.readUInt32LE(offset)
var b = buffer.readUInt32LE(offset + 4) let b = buffer.readUInt32LE(offset + 4)
b *= 0x100000000 b *= 0x100000000
verifuint(b + a, 0x001fffffffffffff) verifuint(b + a, 0x001fffffffffffff)

View file

@ -1,4 +1,4 @@
var createHash = require('create-hash') const createHash = require('create-hash')
function ripemd160 (buffer) { function ripemd160 (buffer) {
return createHash('rmd160').update(buffer).digest() return createHash('rmd160').update(buffer).digest()

View file

@ -1,14 +1,14 @@
let ecc = require('tiny-secp256k1') const ecc = require('tiny-secp256k1')
let randomBytes = require('randombytes') const randomBytes = require('randombytes')
let typeforce = require('typeforce') const typeforce = require('typeforce')
let types = require('./types') const types = require('./types')
let wif = require('wif') const wif = require('wif')
let NETWORKS = require('./networks') const NETWORKS = require('./networks')
// TODO: why is the function name toJSON weird? // TODO: why is the function name toJSON weird?
function isPoint (x) { return ecc.isPoint(x) } function isPoint (x) { return ecc.isPoint(x) }
let isOptions = typeforce.maybe(typeforce.compile({ const isOptions = typeforce.maybe(typeforce.compile({
compressed: types.maybe(types.Boolean), compressed: types.maybe(types.Boolean),
network: types.maybe(types.Network) network: types.maybe(types.Network)
})) }))
@ -63,8 +63,8 @@ function fromPublicKey (buffer, options) {
} }
function fromWIF (string, network) { function fromWIF (string, network) {
let decoded = wif.decode(string) const decoded = wif.decode(string)
let version = decoded.version const version = decoded.version
// list of networks? // list of networks?
if (types.Array(network)) { if (types.Array(network)) {
@ -90,7 +90,7 @@ function fromWIF (string, network) {
function makeRandom (options) { function makeRandom (options) {
typeforce(isOptions, options) typeforce(isOptions, options)
options = options || {} options = options || {}
let rng = options.rng || randomBytes const rng = options.rng || randomBytes
let d let d
do { do {

View file

@ -1,5 +1,5 @@
let script = require('./script') const script = require('./script')
let templates = require('./templates') const templates = require('./templates')
for (let key in templates) { for (let key in templates) {
script[key] = templates[key] script[key] = templates[key]
} }

View file

@ -1,14 +1,14 @@
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var bip66 = require('bip66') const bip66 = require('bip66')
let ecc = require('tiny-secp256k1') const ecc = require('tiny-secp256k1')
var pushdata = require('pushdata-bitcoin') const pushdata = require('pushdata-bitcoin')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var types = require('./types') const types = require('./types')
var scriptNumber = require('./script_number') const scriptNumber = require('./script_number')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
var REVERSE_OPS = require('bitcoin-ops/map') const REVERSE_OPS = require('bitcoin-ops/map')
var OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1
function isOPInt (value) { function isOPInt (value) {
return types.Number(value) && return types.Number(value) &&
@ -38,7 +38,7 @@ function compile (chunks) {
typeforce(types.Array, chunks) typeforce(types.Array, chunks)
var bufferSize = chunks.reduce(function (accum, chunk) { const bufferSize = chunks.reduce(function (accum, chunk) {
// data chunk // data chunk
if (Buffer.isBuffer(chunk)) { if (Buffer.isBuffer(chunk)) {
// adhere to BIP62.3, minimal push policy // adhere to BIP62.3, minimal push policy
@ -53,14 +53,14 @@ function compile (chunks) {
return accum + 1 return accum + 1
}, 0.0) }, 0.0)
var buffer = Buffer.allocUnsafe(bufferSize) const buffer = Buffer.allocUnsafe(bufferSize)
var offset = 0 let offset = 0
chunks.forEach(function (chunk) { chunks.forEach(function (chunk) {
// data chunk // data chunk
if (Buffer.isBuffer(chunk)) { if (Buffer.isBuffer(chunk)) {
// adhere to BIP62.3, minimal push policy // adhere to BIP62.3, minimal push policy
var opcode = asMinimalOP(chunk) const opcode = asMinimalOP(chunk)
if (opcode !== undefined) { if (opcode !== undefined) {
buffer.writeUInt8(opcode, offset) buffer.writeUInt8(opcode, offset)
offset += 1 offset += 1
@ -88,15 +88,15 @@ function decompile (buffer) {
typeforce(types.Buffer, buffer) typeforce(types.Buffer, buffer)
var chunks = [] const chunks = []
var i = 0 let i = 0
while (i < buffer.length) { while (i < buffer.length) {
var opcode = buffer[i] const opcode = buffer[i]
// data chunk // data chunk
if ((opcode > OPS.OP_0) && (opcode <= OPS.OP_PUSHDATA4)) { if ((opcode > OPS.OP_0) && (opcode <= OPS.OP_PUSHDATA4)) {
var d = pushdata.decode(buffer, i) const d = pushdata.decode(buffer, i)
// did reading a pushDataInt fail? empty script // did reading a pushDataInt fail? empty script
if (d === null) return null if (d === null) return null
@ -105,11 +105,11 @@ function decompile (buffer) {
// attempt to read too much data? empty script // attempt to read too much data? empty script
if (i + d.number > buffer.length) return null if (i + d.number > buffer.length) return null
var data = buffer.slice(i, i + d.number) const data = buffer.slice(i, i + d.number)
i += d.number i += d.number
// decompile minimally // decompile minimally
var op = asMinimalOP(data) const op = asMinimalOP(data)
if (op !== undefined) { if (op !== undefined) {
chunks.push(op) chunks.push(op)
} else { } else {
@ -135,7 +135,7 @@ function toASM (chunks) {
return chunks.map(function (chunk) { return chunks.map(function (chunk) {
// data? // data?
if (Buffer.isBuffer(chunk)) { if (Buffer.isBuffer(chunk)) {
var op = asMinimalOP(chunk) const op = asMinimalOP(chunk)
if (op === undefined) return chunk.toString('hex') if (op === undefined) return chunk.toString('hex')
chunk = op chunk = op
} }
@ -175,7 +175,7 @@ function isCanonicalPubKey (buffer) {
} }
function isDefinedHashType (hashType) { function isDefinedHashType (hashType) {
var hashTypeMod = hashType & ~0x80 const hashTypeMod = hashType & ~0x80
// return hashTypeMod > SIGHASH_ALL && hashTypeMod < SIGHASH_SINGLE // return hashTypeMod > SIGHASH_ALL && hashTypeMod < SIGHASH_SINGLE
return hashTypeMod > 0x00 && hashTypeMod < 0x04 return hashTypeMod > 0x00 && hashTypeMod < 0x04

View file

@ -1,10 +1,10 @@
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
function decode (buffer, maxLength, minimal) { function decode (buffer, maxLength, minimal) {
maxLength = maxLength || 4 maxLength = maxLength || 4
minimal = minimal === undefined ? true : minimal minimal = minimal === undefined ? true : minimal
var length = buffer.length const length = buffer.length
if (length === 0) return 0 if (length === 0) return 0
if (length > maxLength) throw new TypeError('Script number overflow') if (length > maxLength) throw new TypeError('Script number overflow')
if (minimal) { if (minimal) {
@ -15,16 +15,15 @@ function decode (buffer, maxLength, minimal) {
// 40-bit // 40-bit
if (length === 5) { if (length === 5) {
var a = buffer.readUInt32LE(0) const a = buffer.readUInt32LE(0)
var b = buffer.readUInt8(4) const b = buffer.readUInt8(4)
if (b & 0x80) return -(((b & ~0x80) * 0x100000000) + a) if (b & 0x80) return -(((b & ~0x80) * 0x100000000) + a)
return (b * 0x100000000) + a return (b * 0x100000000) + a
} }
var result = 0
// 32-bit / 24-bit / 16-bit / 8-bit // 32-bit / 24-bit / 16-bit / 8-bit
let result = 0
for (var i = 0; i < length; ++i) { for (var i = 0; i < length; ++i) {
result |= buffer[i] << (8 * i) result |= buffer[i] << (8 * i)
} }
@ -43,10 +42,10 @@ function scriptNumSize (i) {
} }
function encode (number) { function encode (number) {
var value = Math.abs(number) let value = Math.abs(number)
var size = scriptNumSize(value) const size = scriptNumSize(value)
var buffer = Buffer.allocUnsafe(size) const buffer = Buffer.allocUnsafe(size)
var negative = number < 0 const negative = number < 0
for (var i = 0; i < size; ++i) { for (var i = 0; i < size; ++i) {
buffer.writeUInt8(value & 0xff, i) buffer.writeUInt8(value & 0xff, i)

View file

@ -1,9 +1,9 @@
let bip66 = require('bip66') const bip66 = require('bip66')
let Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
let typeforce = require('typeforce') const typeforce = require('typeforce')
let types = require('./types') const types = require('./types')
let ZERO = Buffer.alloc(1, 0) const ZERO = Buffer.alloc(1, 0)
function toDER (x) { function toDER (x) {
let i = 0 let i = 0
while (x[i] === 0) ++i while (x[i] === 0) ++i
@ -15,21 +15,21 @@ function toDER (x) {
function fromDER (x) { function fromDER (x) {
if (x[0] === 0x00) x = x.slice(1) if (x[0] === 0x00) x = x.slice(1)
let buffer = Buffer.alloc(32, 0) const buffer = Buffer.alloc(32, 0)
let bstart = Math.max(0, 32 - x.length) const bstart = Math.max(0, 32 - x.length)
x.copy(buffer, bstart) x.copy(buffer, bstart)
return buffer return buffer
} }
// BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed) // BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed)
function decode (buffer) { function decode (buffer) {
let hashType = buffer.readUInt8(buffer.length - 1) const hashType = buffer.readUInt8(buffer.length - 1)
let hashTypeMod = hashType & ~0x80 const hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType) if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
let decode = bip66.decode(buffer.slice(0, -1)) const decode = bip66.decode(buffer.slice(0, -1))
let r = fromDER(decode.r) const r = fromDER(decode.r)
let s = fromDER(decode.s) const s = fromDER(decode.s)
return { return {
signature: Buffer.concat([r, s], 64), signature: Buffer.concat([r, s], 64),
@ -43,14 +43,14 @@ function encode (signature, hashType) {
hashType: types.UInt8 hashType: types.UInt8
}, { signature, hashType }) }, { signature, hashType })
let hashTypeMod = hashType & ~0x80 const hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType) if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
let hashTypeBuffer = Buffer.allocUnsafe(1) const hashTypeBuffer = Buffer.allocUnsafe(1)
hashTypeBuffer.writeUInt8(hashType, 0) hashTypeBuffer.writeUInt8(hashType, 0)
let r = toDER(signature.slice(0, 32)) const r = toDER(signature.slice(0, 32))
let s = toDER(signature.slice(32, 64)) const s = toDER(signature.slice(32, 64))
return Buffer.concat([ return Buffer.concat([
bip66.encode(r, s), bip66.encode(r, s),

View file

@ -1,14 +1,14 @@
var decompile = require('../script').decompile const decompile = require('../script').decompile
var multisig = require('./multisig') const multisig = require('./multisig')
var nullData = require('./nulldata') const nullData = require('./nulldata')
var pubKey = require('./pubkey') const pubKey = require('./pubkey')
var pubKeyHash = require('./pubkeyhash') const pubKeyHash = require('./pubkeyhash')
var scriptHash = require('./scripthash') const scriptHash = require('./scripthash')
var witnessPubKeyHash = require('./witnesspubkeyhash') const witnessPubKeyHash = require('./witnesspubkeyhash')
var witnessScriptHash = require('./witnessscripthash') const witnessScriptHash = require('./witnessscripthash')
var witnessCommitment = require('./witnesscommitment') const witnessCommitment = require('./witnesscommitment')
var types = { const types = {
MULTISIG: 'multisig', MULTISIG: 'multisig',
NONSTANDARD: 'nonstandard', NONSTANDARD: 'nonstandard',
NULLDATA: 'nulldata', NULLDATA: 'nulldata',
@ -27,7 +27,7 @@ function classifyOutput (script) {
if (scriptHash.output.check(script)) return types.P2SH if (scriptHash.output.check(script)) return types.P2SH
// XXX: optimization, below functions .decompile before use // XXX: optimization, below functions .decompile before use
var chunks = decompile(script) const chunks = decompile(script)
if (!chunks) throw new TypeError('Invalid script') if (!chunks) throw new TypeError('Invalid script')
if (multisig.output.check(chunks)) return types.MULTISIG if (multisig.output.check(chunks)) return types.MULTISIG
@ -40,7 +40,7 @@ function classifyOutput (script) {
function classifyInput (script, allowIncomplete) { function classifyInput (script, allowIncomplete) {
// XXX: optimization, below functions .decompile before use // XXX: optimization, below functions .decompile before use
var chunks = decompile(script) const chunks = decompile(script)
if (!chunks) throw new TypeError('Invalid script') if (!chunks) throw new TypeError('Invalid script')
if (pubKeyHash.input.check(chunks)) return types.P2PKH if (pubKeyHash.input.check(chunks)) return types.P2PKH
@ -53,7 +53,7 @@ function classifyInput (script, allowIncomplete) {
function classifyWitness (script, allowIncomplete) { function classifyWitness (script, allowIncomplete) {
// XXX: optimization, below functions .decompile before use // XXX: optimization, below functions .decompile before use
var chunks = decompile(script) const chunks = decompile(script)
if (!chunks) throw new TypeError('Invalid script') if (!chunks) throw new TypeError('Invalid script')
if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH

View file

@ -1,17 +1,17 @@
// OP_0 [signatures ...] // OP_0 [signatures ...]
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var bscript = require('../../script') const bscript = require('../../script')
var p2mso = require('./output') const p2mso = require('./output')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
function partialSignature (value) { function partialSignature (value) {
return value === OPS.OP_0 || bscript.isCanonicalScriptSignature(value) return value === OPS.OP_0 || bscript.isCanonicalScriptSignature(value)
} }
function check (script, allowIncomplete) { function check (script, allowIncomplete) {
var chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
if (chunks.length < 2) return false if (chunks.length < 2) return false
if (chunks[0] !== OPS.OP_0) return false if (chunks[0] !== OPS.OP_0) return false
@ -23,13 +23,13 @@ function check (script, allowIncomplete) {
} }
check.toJSON = function () { return 'multisig input' } check.toJSON = function () { return 'multisig input' }
var EMPTY_BUFFER = Buffer.allocUnsafe(0) const EMPTY_BUFFER = Buffer.allocUnsafe(0)
function encodeStack (signatures, scriptPubKey) { function encodeStack (signatures, scriptPubKey) {
typeforce([partialSignature], signatures) typeforce([partialSignature], signatures)
if (scriptPubKey) { if (scriptPubKey) {
var scriptData = p2mso.decode(scriptPubKey) const scriptData = p2mso.decode(scriptPubKey)
if (signatures.length < scriptData.m) { if (signatures.length < scriptData.m) {
throw new TypeError('Not enough signatures provided') throw new TypeError('Not enough signatures provided')
@ -59,7 +59,7 @@ function decodeStack (stack, allowIncomplete) {
} }
function decode (buffer, allowIncomplete) { function decode (buffer, allowIncomplete) {
var stack = bscript.decompile(buffer) const stack = bscript.decompile(buffer)
return decodeStack(stack, allowIncomplete) return decodeStack(stack, allowIncomplete)
} }

View file

@ -1,20 +1,20 @@
// m [pubKeys ...] n OP_CHECKMULTISIG // m [pubKeys ...] n OP_CHECKMULTISIG
var bscript = require('../../script') const bscript = require('../../script')
var types = require('../../types') const types = require('../../types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
var OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1
function check (script, allowIncomplete) { function check (script, allowIncomplete) {
var chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
if (chunks.length < 4) return false if (chunks.length < 4) return false
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false
if (!types.Number(chunks[0])) return false if (!types.Number(chunks[0])) return false
if (!types.Number(chunks[chunks.length - 2])) return false if (!types.Number(chunks[chunks.length - 2])) return false
var m = chunks[0] - OP_INT_BASE const m = chunks[0] - OP_INT_BASE
var n = chunks[chunks.length - 2] - OP_INT_BASE const n = chunks[chunks.length - 2] - OP_INT_BASE
if (m <= 0) return false if (m <= 0) return false
if (n > 16) return false if (n > 16) return false
@ -22,7 +22,7 @@ function check (script, allowIncomplete) {
if (n !== chunks.length - 3) return false if (n !== chunks.length - 3) return false
if (allowIncomplete) return true if (allowIncomplete) return true
var keys = chunks.slice(1, -2) const keys = chunks.slice(1, -2)
return keys.every(bscript.isCanonicalPubKey) return keys.every(bscript.isCanonicalPubKey)
} }
check.toJSON = function () { return 'multi-sig output' } check.toJSON = function () { return 'multi-sig output' }
@ -36,7 +36,7 @@ function encode (m, pubKeys) {
pubKeys: pubKeys pubKeys: pubKeys
}) })
var n = pubKeys.length const n = pubKeys.length
if (n < m) throw new TypeError('Not enough pubKeys provided') if (n < m) throw new TypeError('Not enough pubKeys provided')
return bscript.compile([].concat( return bscript.compile([].concat(
@ -48,7 +48,7 @@ function encode (m, pubKeys) {
} }
function decode (buffer, allowIncomplete) { function decode (buffer, allowIncomplete) {
var chunks = bscript.decompile(buffer) const chunks = bscript.decompile(buffer)
typeforce(check, chunks, allowIncomplete) typeforce(check, chunks, allowIncomplete)
return { return {

View file

@ -1,12 +1,12 @@
// OP_RETURN {data} // OP_RETURN {data}
var bscript = require('../script') const bscript = require('../script')
var types = require('../types') const types = require('../types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
function check (script) { function check (script) {
var buffer = bscript.compile(script) const buffer = bscript.compile(script)
return buffer.length > 1 && return buffer.length > 1 &&
buffer[0] === OPS.OP_RETURN buffer[0] === OPS.OP_RETURN

View file

@ -1,10 +1,10 @@
// {signature} // {signature}
var bscript = require('../../script') const bscript = require('../../script')
var typeforce = require('typeforce') const typeforce = require('typeforce')
function check (script) { function check (script) {
var chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
return chunks.length === 1 && return chunks.length === 1 &&
bscript.isCanonicalScriptSignature(chunks[0]) bscript.isCanonicalScriptSignature(chunks[0])
@ -27,7 +27,7 @@ function decodeStack (stack) {
} }
function decode (buffer) { function decode (buffer) {
var stack = bscript.decompile(buffer) const stack = bscript.decompile(buffer)
return decodeStack(stack) return decodeStack(stack)
} }

View file

@ -1,11 +1,11 @@
// {pubKey} OP_CHECKSIG // {pubKey} OP_CHECKSIG
var bscript = require('../../script') const bscript = require('../../script')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
function check (script) { function check (script) {
var chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
return chunks.length === 2 && return chunks.length === 2 &&
bscript.isCanonicalPubKey(chunks[0]) && bscript.isCanonicalPubKey(chunks[0]) &&
@ -20,7 +20,7 @@ function encode (pubKey) {
} }
function decode (buffer) { function decode (buffer) {
var chunks = bscript.decompile(buffer) const chunks = bscript.decompile(buffer)
typeforce(check, chunks) typeforce(check, chunks)
return chunks[0] return chunks[0]

View file

@ -1,10 +1,10 @@
// {signature} {pubKey} // {signature} {pubKey}
var bscript = require('../../script') const bscript = require('../../script')
var typeforce = require('typeforce') const typeforce = require('typeforce')
function check (script) { function check (script) {
var chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
return chunks.length === 2 && return chunks.length === 2 &&
bscript.isCanonicalScriptSignature(chunks[0]) && bscript.isCanonicalScriptSignature(chunks[0]) &&
@ -39,7 +39,7 @@ function decodeStack (stack) {
} }
function decode (buffer) { function decode (buffer) {
var stack = bscript.decompile(buffer) const stack = bscript.decompile(buffer)
return decodeStack(stack) return decodeStack(stack)
} }

View file

@ -1,12 +1,12 @@
// OP_DUP OP_HASH160 {pubKeyHash} OP_EQUALVERIFY OP_CHECKSIG // OP_DUP OP_HASH160 {pubKeyHash} OP_EQUALVERIFY OP_CHECKSIG
var bscript = require('../../script') const bscript = require('../../script')
var types = require('../../types') const types = require('../../types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
function check (script) { function check (script) {
var buffer = bscript.compile(script) const buffer = bscript.compile(script)
return buffer.length === 25 && return buffer.length === 25 &&
buffer[0] === OPS.OP_DUP && buffer[0] === OPS.OP_DUP &&

View file

@ -1,24 +1,24 @@
// <scriptSig> {serialized scriptPubKey script} // <scriptSig> {serialized scriptPubKey script}
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var bscript = require('../../script') const bscript = require('../../script')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var p2ms = require('../multisig/') const p2ms = require('../multisig/')
var p2pk = require('../pubkey/') const p2pk = require('../pubkey/')
var p2pkh = require('../pubkeyhash/') const p2pkh = require('../pubkeyhash/')
var p2wpkho = require('../witnesspubkeyhash/output') const p2wpkho = require('../witnesspubkeyhash/output')
var p2wsho = require('../witnessscripthash/output') const p2wsho = require('../witnessscripthash/output')
function check (script, allowIncomplete) { function check (script, allowIncomplete) {
var chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
if (chunks.length < 1) return false if (chunks.length < 1) return false
var lastChunk = chunks[chunks.length - 1] const lastChunk = chunks[chunks.length - 1]
if (!Buffer.isBuffer(lastChunk)) return false if (!Buffer.isBuffer(lastChunk)) return false
var scriptSigChunks = bscript.decompile(bscript.compile(chunks.slice(0, -1))) const scriptSigChunks = bscript.decompile(bscript.compile(chunks.slice(0, -1)))
var redeemScriptChunks = bscript.decompile(lastChunk) const redeemScriptChunks = bscript.decompile(lastChunk)
// is redeemScript a valid script? // is redeemScript a valid script?
if (!redeemScriptChunks) return false if (!redeemScriptChunks) return false
@ -47,13 +47,13 @@ function check (script, allowIncomplete) {
check.toJSON = function () { return 'scriptHash input' } check.toJSON = function () { return 'scriptHash input' }
function encodeStack (redeemScriptStack, redeemScript) { function encodeStack (redeemScriptStack, redeemScript) {
var serializedScriptPubKey = bscript.compile(redeemScript) const serializedScriptPubKey = bscript.compile(redeemScript)
return [].concat(redeemScriptStack, serializedScriptPubKey) return [].concat(redeemScriptStack, serializedScriptPubKey)
} }
function encode (redeemScriptSig, redeemScript) { function encode (redeemScriptSig, redeemScript) {
var redeemScriptStack = bscript.decompile(redeemScriptSig) const redeemScriptStack = bscript.decompile(redeemScriptSig)
return bscript.compile(encodeStack(redeemScriptStack, redeemScript)) return bscript.compile(encodeStack(redeemScriptStack, redeemScript))
} }
@ -69,8 +69,8 @@ function decodeStack (stack) {
} }
function decode (buffer) { function decode (buffer) {
var stack = bscript.decompile(buffer) const stack = bscript.decompile(buffer)
var result = decodeStack(stack) const result = decodeStack(stack)
result.redeemScriptSig = bscript.compile(result.redeemScriptStack) result.redeemScriptSig = bscript.compile(result.redeemScriptStack)
delete result.redeemScriptStack delete result.redeemScriptStack
return result return result

View file

@ -1,12 +1,12 @@
// OP_HASH160 {scriptHash} OP_EQUAL // OP_HASH160 {scriptHash} OP_EQUAL
var bscript = require('../../script') const bscript = require('../../script')
var types = require('../../types') const types = require('../../types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
function check (script) { function check (script) {
var buffer = bscript.compile(script) const buffer = bscript.compile(script)
return buffer.length === 23 && return buffer.length === 23 &&
buffer[0] === OPS.OP_HASH160 && buffer[0] === OPS.OP_HASH160 &&

View file

@ -1,15 +1,15 @@
// OP_RETURN {aa21a9ed} {commitment} // OP_RETURN {aa21a9ed} {commitment}
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var bscript = require('../../script') const bscript = require('../../script')
var types = require('../../types') const types = require('../../types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
var HEADER = Buffer.from('aa21a9ed', 'hex') const HEADER = Buffer.from('aa21a9ed', 'hex')
function check (script) { function check (script) {
var buffer = bscript.compile(script) const buffer = bscript.compile(script)
return buffer.length > 37 && return buffer.length > 37 &&
buffer[0] === OPS.OP_RETURN && buffer[0] === OPS.OP_RETURN &&
@ -22,7 +22,7 @@ check.toJSON = function () { return 'Witness commitment output' }
function encode (commitment) { function encode (commitment) {
typeforce(types.Hash256bit, commitment) typeforce(types.Hash256bit, commitment)
var buffer = Buffer.allocUnsafe(36) const buffer = Buffer.allocUnsafe(36)
HEADER.copy(buffer, 0) HEADER.copy(buffer, 0)
commitment.copy(buffer, 4) commitment.copy(buffer, 4)

View file

@ -1,14 +1,14 @@
// {signature} {pubKey} // {signature} {pubKey}
var bscript = require('../../script') const bscript = require('../../script')
var typeforce = require('typeforce') const typeforce = require('typeforce')
function isCompressedCanonicalPubKey (pubKey) { function isCompressedCanonicalPubKey (pubKey) {
return bscript.isCanonicalPubKey(pubKey) && pubKey.length === 33 return bscript.isCanonicalPubKey(pubKey) && pubKey.length === 33
} }
function check (script) { function check (script) {
var chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
return chunks.length === 2 && return chunks.length === 2 &&
bscript.isCanonicalScriptSignature(chunks[0]) && bscript.isCanonicalScriptSignature(chunks[0]) &&

View file

@ -1,12 +1,12 @@
// OP_0 {pubKeyHash} // OP_0 {pubKeyHash}
var bscript = require('../../script') const bscript = require('../../script')
var types = require('../../types') const types = require('../../types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
function check (script) { function check (script) {
var buffer = bscript.compile(script) const buffer = bscript.compile(script)
return buffer.length === 22 && return buffer.length === 22 &&
buffer[0] === OPS.OP_0 && buffer[0] === OPS.OP_0 &&

View file

@ -1,26 +1,26 @@
// <scriptSig> {serialized scriptPubKey script} // <scriptSig> {serialized scriptPubKey script}
var bscript = require('../../script') const bscript = require('../../script')
var types = require('../../types') const types = require('../../types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var p2ms = require('../multisig/') const p2ms = require('../multisig/')
var p2pk = require('../pubkey/') const p2pk = require('../pubkey/')
var p2pkh = require('../pubkeyhash/') const p2pkh = require('../pubkeyhash/')
function check (chunks, allowIncomplete) { function check (chunks, allowIncomplete) {
typeforce(types.Array, chunks) typeforce(types.Array, chunks)
if (chunks.length < 1) return false if (chunks.length < 1) return false
var witnessScript = chunks[chunks.length - 1] const witnessScript = chunks[chunks.length - 1]
if (!Buffer.isBuffer(witnessScript)) return false if (!Buffer.isBuffer(witnessScript)) return false
var witnessScriptChunks = bscript.decompile(witnessScript) const witnessScriptChunks = bscript.decompile(witnessScript)
// is witnessScript a valid script? // is witnessScript a valid script?
if (witnessScriptChunks.length === 0) return false if (witnessScriptChunks.length === 0) return false
var witnessRawScriptSig = bscript.compile(chunks.slice(0, -1)) const witnessRawScriptSig = bscript.compile(chunks.slice(0, -1))
// match types // match types
if (p2pkh.input.check(witnessRawScriptSig) && if (p2pkh.input.check(witnessRawScriptSig) &&

View file

@ -1,12 +1,12 @@
// OP_0 {scriptHash} // OP_0 {scriptHash}
var bscript = require('../../script') const bscript = require('../../script')
var types = require('../../types') const types = require('../../types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var OPS = require('bitcoin-ops') const OPS = require('bitcoin-ops')
function check (script) { function check (script) {
var buffer = bscript.compile(script) const buffer = bscript.compile(script)
return buffer.length === 34 && return buffer.length === 34 &&
buffer[0] === OPS.OP_0 && buffer[0] === OPS.OP_0 &&

View file

@ -1,20 +1,20 @@
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var bcrypto = require('./crypto') const bcrypto = require('./crypto')
var bscript = require('./script') const bscript = require('./script')
var bufferutils = require('./bufferutils') const bufferutils = require('./bufferutils')
var opcodes = require('bitcoin-ops') const opcodes = require('bitcoin-ops')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var types = require('./types') const types = require('./types')
var varuint = require('varuint-bitcoin') const varuint = require('varuint-bitcoin')
function varSliceSize (someScript) { function varSliceSize (someScript) {
var length = someScript.length const length = someScript.length
return varuint.encodingLength(length) + length return varuint.encodingLength(length) + length
} }
function vectorSize (someVector) { function vectorSize (someVector) {
var length = someVector.length const length = someVector.length
return varuint.encodingLength(length) + someVector.reduce(function (sum, witness) { return varuint.encodingLength(length) + someVector.reduce(function (sum, witness) {
return sum + varSliceSize(witness) return sum + varSliceSize(witness)
@ -36,43 +36,43 @@ Transaction.SIGHASH_ANYONECANPAY = 0x80
Transaction.ADVANCED_TRANSACTION_MARKER = 0x00 Transaction.ADVANCED_TRANSACTION_MARKER = 0x00
Transaction.ADVANCED_TRANSACTION_FLAG = 0x01 Transaction.ADVANCED_TRANSACTION_FLAG = 0x01
var EMPTY_SCRIPT = Buffer.allocUnsafe(0) const EMPTY_SCRIPT = Buffer.allocUnsafe(0)
var EMPTY_WITNESS = [] const EMPTY_WITNESS = []
var ZERO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex') const ZERO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
var ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex') const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
var VALUE_UINT64_MAX = Buffer.from('ffffffffffffffff', 'hex') const VALUE_UINT64_MAX = Buffer.from('ffffffffffffffff', 'hex')
var BLANK_OUTPUT = { const BLANK_OUTPUT = {
script: EMPTY_SCRIPT, script: EMPTY_SCRIPT,
valueBuffer: VALUE_UINT64_MAX valueBuffer: VALUE_UINT64_MAX
} }
Transaction.fromBuffer = function (buffer, __noStrict) { Transaction.fromBuffer = function (buffer, __noStrict) {
var offset = 0 let offset = 0
function readSlice (n) { function readSlice (n) {
offset += n offset += n
return buffer.slice(offset - n, offset) return buffer.slice(offset - n, offset)
} }
function readUInt32 () { function readUInt32 () {
var i = buffer.readUInt32LE(offset) const i = buffer.readUInt32LE(offset)
offset += 4 offset += 4
return i return i
} }
function readInt32 () { function readInt32 () {
var i = buffer.readInt32LE(offset) const i = buffer.readInt32LE(offset)
offset += 4 offset += 4
return i return i
} }
function readUInt64 () { function readUInt64 () {
var i = bufferutils.readUInt64LE(buffer, offset) const i = bufferutils.readUInt64LE(buffer, offset)
offset += 8 offset += 8
return i return i
} }
function readVarInt () { function readVarInt () {
var vi = varuint.decode(buffer, offset) const vi = varuint.decode(buffer, offset)
offset += varuint.decode.bytes offset += varuint.decode.bytes
return vi return vi
} }
@ -82,26 +82,26 @@ Transaction.fromBuffer = function (buffer, __noStrict) {
} }
function readVector () { function readVector () {
var count = readVarInt() const count = readVarInt()
var vector = [] const vector = []
for (var i = 0; i < count; i++) vector.push(readVarSlice()) for (var i = 0; i < count; i++) vector.push(readVarSlice())
return vector return vector
} }
var tx = new Transaction() const tx = new Transaction()
tx.version = readInt32() tx.version = readInt32()
var marker = buffer.readUInt8(offset) const marker = buffer.readUInt8(offset)
var flag = buffer.readUInt8(offset + 1) const flag = buffer.readUInt8(offset + 1)
var hasWitnesses = false let hasWitnesses = false
if (marker === Transaction.ADVANCED_TRANSACTION_MARKER && if (marker === Transaction.ADVANCED_TRANSACTION_MARKER &&
flag === Transaction.ADVANCED_TRANSACTION_FLAG) { flag === Transaction.ADVANCED_TRANSACTION_FLAG) {
offset += 2 offset += 2
hasWitnesses = true hasWitnesses = true
} }
var vinLen = readVarInt() const vinLen = readVarInt()
for (var i = 0; i < vinLen; ++i) { for (var i = 0; i < vinLen; ++i) {
tx.ins.push({ tx.ins.push({
hash: readSlice(32), hash: readSlice(32),
@ -112,7 +112,7 @@ Transaction.fromBuffer = function (buffer, __noStrict) {
}) })
} }
var voutLen = readVarInt() const voutLen = readVarInt()
for (i = 0; i < voutLen; ++i) { for (i = 0; i < voutLen; ++i) {
tx.outs.push({ tx.outs.push({
value: readUInt64(), value: readUInt64(),
@ -192,8 +192,8 @@ Transaction.prototype.hasWitnesses = function () {
} }
Transaction.prototype.weight = function () { Transaction.prototype.weight = function () {
var base = this.__byteLength(false) const base = this.__byteLength(false)
var total = this.__byteLength(true) const total = this.__byteLength(true)
return base * 3 + total return base * 3 + total
} }
@ -206,7 +206,7 @@ Transaction.prototype.byteLength = function () {
} }
Transaction.prototype.__byteLength = function (__allowWitness) { Transaction.prototype.__byteLength = function (__allowWitness) {
var hasWitnesses = __allowWitness && this.hasWitnesses() const hasWitnesses = __allowWitness && this.hasWitnesses()
return ( return (
(hasWitnesses ? 10 : 8) + (hasWitnesses ? 10 : 8) +
@ -219,7 +219,7 @@ Transaction.prototype.__byteLength = function (__allowWitness) {
} }
Transaction.prototype.clone = function () { Transaction.prototype.clone = function () {
var newTx = new Transaction() const newTx = new Transaction()
newTx.version = this.version newTx.version = this.version
newTx.locktime = this.locktime newTx.locktime = this.locktime
@ -258,11 +258,11 @@ Transaction.prototype.hashForSignature = function (inIndex, prevOutScript, hashT
if (inIndex >= this.ins.length) return ONE if (inIndex >= this.ins.length) return ONE
// ignore OP_CODESEPARATOR // ignore OP_CODESEPARATOR
var ourScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) { const ourScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) {
return x !== opcodes.OP_CODESEPARATOR return x !== opcodes.OP_CODESEPARATOR
})) }))
var txTmp = this.clone() const txTmp = this.clone()
// SIGHASH_NONE: ignore all outputs? (wildcard payee) // SIGHASH_NONE: ignore all outputs? (wildcard payee)
if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) { if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) {
@ -309,7 +309,7 @@ Transaction.prototype.hashForSignature = function (inIndex, prevOutScript, hashT
} }
// serialize and hash // serialize and hash
var buffer = Buffer.allocUnsafe(txTmp.__byteLength(false) + 4) const buffer = Buffer.allocUnsafe(txTmp.__byteLength(false) + 4)
buffer.writeInt32LE(hashType, buffer.length - 4) buffer.writeInt32LE(hashType, buffer.length - 4)
txTmp.__toBuffer(buffer, 0, false) txTmp.__toBuffer(buffer, 0, false)
@ -319,7 +319,7 @@ Transaction.prototype.hashForSignature = function (inIndex, prevOutScript, hashT
Transaction.prototype.hashForWitnessV0 = function (inIndex, prevOutScript, value, hashType) { Transaction.prototype.hashForWitnessV0 = function (inIndex, prevOutScript, value, hashType) {
typeforce(types.tuple(types.UInt32, types.Buffer, types.Satoshi, types.UInt32), arguments) typeforce(types.tuple(types.UInt32, types.Buffer, types.Satoshi, types.UInt32), arguments)
var tbuffer, toffset let tbuffer, toffset
function writeSlice (slice) { toffset += slice.copy(tbuffer, toffset) } function writeSlice (slice) { toffset += slice.copy(tbuffer, toffset) }
function writeUInt32 (i) { toffset = tbuffer.writeUInt32LE(i, toffset) } function writeUInt32 (i) { toffset = tbuffer.writeUInt32LE(i, toffset) }
function writeUInt64 (i) { toffset = bufferutils.writeUInt64LE(tbuffer, i, toffset) } function writeUInt64 (i) { toffset = bufferutils.writeUInt64LE(tbuffer, i, toffset) }
@ -329,9 +329,9 @@ Transaction.prototype.hashForWitnessV0 = function (inIndex, prevOutScript, value
} }
function writeVarSlice (slice) { writeVarInt(slice.length); writeSlice(slice) } function writeVarSlice (slice) { writeVarInt(slice.length); writeSlice(slice) }
var hashOutputs = ZERO let hashOutputs = ZERO
var hashPrevouts = ZERO let hashPrevouts = ZERO
var hashSequence = ZERO let hashSequence = ZERO
if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) { if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) {
tbuffer = Buffer.allocUnsafe(36 * this.ins.length) tbuffer = Buffer.allocUnsafe(36 * this.ins.length)
@ -360,7 +360,7 @@ Transaction.prototype.hashForWitnessV0 = function (inIndex, prevOutScript, value
if ((hashType & 0x1f) !== Transaction.SIGHASH_SINGLE && if ((hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
(hashType & 0x1f) !== Transaction.SIGHASH_NONE) { (hashType & 0x1f) !== Transaction.SIGHASH_NONE) {
var txOutsSize = this.outs.reduce(function (sum, output) { const txOutsSize = this.outs.reduce(function (sum, output) {
return sum + 8 + varSliceSize(output.script) return sum + 8 + varSliceSize(output.script)
}, 0) }, 0)
@ -374,7 +374,7 @@ Transaction.prototype.hashForWitnessV0 = function (inIndex, prevOutScript, value
hashOutputs = bcrypto.hash256(tbuffer) hashOutputs = bcrypto.hash256(tbuffer)
} else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) { } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) {
var output = this.outs[inIndex] const output = this.outs[inIndex]
tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script)) tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script))
toffset = 0 toffset = 0
@ -387,7 +387,7 @@ Transaction.prototype.hashForWitnessV0 = function (inIndex, prevOutScript, value
tbuffer = Buffer.allocUnsafe(156 + varSliceSize(prevOutScript)) tbuffer = Buffer.allocUnsafe(156 + varSliceSize(prevOutScript))
toffset = 0 toffset = 0
var input = this.ins[inIndex] const input = this.ins[inIndex]
writeUInt32(this.version) writeUInt32(this.version)
writeSlice(hashPrevouts) writeSlice(hashPrevouts)
writeSlice(hashSequence) writeSlice(hashSequence)
@ -418,7 +418,7 @@ Transaction.prototype.toBuffer = function (buffer, initialOffset) {
Transaction.prototype.__toBuffer = function (buffer, initialOffset, __allowWitness) { Transaction.prototype.__toBuffer = function (buffer, initialOffset, __allowWitness) {
if (!buffer) buffer = Buffer.allocUnsafe(this.__byteLength(__allowWitness)) if (!buffer) buffer = Buffer.allocUnsafe(this.__byteLength(__allowWitness))
var offset = initialOffset || 0 let offset = initialOffset || 0
function writeSlice (slice) { offset += slice.copy(buffer, offset) } function writeSlice (slice) { offset += slice.copy(buffer, offset) }
function writeUInt8 (i) { offset = buffer.writeUInt8(i, offset) } function writeUInt8 (i) { offset = buffer.writeUInt8(i, offset) }
function writeUInt32 (i) { offset = buffer.writeUInt32LE(i, offset) } function writeUInt32 (i) { offset = buffer.writeUInt32LE(i, offset) }
@ -433,7 +433,7 @@ Transaction.prototype.__toBuffer = function (buffer, initialOffset, __allowWitne
writeInt32(this.version) writeInt32(this.version)
var hasWitnesses = __allowWitness && this.hasWitnesses() const hasWitnesses = __allowWitness && this.hasWitnesses()
if (hasWitnesses) { if (hasWitnesses) {
writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER) writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER)

View file

@ -1,18 +1,18 @@
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var baddress = require('./address') const baddress = require('./address')
var bcrypto = require('./crypto') const bcrypto = require('./crypto')
var bscript = require('./script') const bscript = require('./script')
var btemplates = require('./templates') const btemplates = require('./templates')
var networks = require('./networks') const networks = require('./networks')
var ops = require('bitcoin-ops') const ops = require('bitcoin-ops')
var typeforce = require('typeforce') const typeforce = require('typeforce')
var types = require('./types') const types = require('./types')
var scriptTypes = btemplates.types const scriptTypes = btemplates.types
var SIGNABLE = [btemplates.types.P2PKH, btemplates.types.P2PK, btemplates.types.MULTISIG] const SIGNABLE = [btemplates.types.P2PKH, btemplates.types.P2PK, btemplates.types.MULTISIG]
var P2SH = SIGNABLE.concat([btemplates.types.P2WPKH, btemplates.types.P2WSH]) const P2SH = SIGNABLE.concat([btemplates.types.P2WPKH, btemplates.types.P2WSH])
var ECPair = require('./ecpair') const ECPair = require('./ecpair')
var Transaction = require('./transaction') const Transaction = require('./transaction')
function supportedType (type) { function supportedType (type) {
return SIGNABLE.indexOf(type) !== -1 return SIGNABLE.indexOf(type) !== -1
@ -23,8 +23,8 @@ function supportedP2SHType (type) {
} }
function extractChunks (type, chunks, script) { function extractChunks (type, chunks, script) {
var pubKeys = [] let pubKeys = []
var signatures = [] let signatures = []
switch (type) { switch (type) {
case scriptTypes.P2PKH: case scriptTypes.P2PKH:
// if (redeemScript) throw new Error('Nonstandard... P2SH(P2PKH)') // if (redeemScript) throw new Error('Nonstandard... P2SH(P2PKH)')
@ -39,7 +39,7 @@ function extractChunks (type, chunks, script) {
case scriptTypes.MULTISIG: case scriptTypes.MULTISIG:
if (script) { if (script) {
var multisig = btemplates.multisig.output.decode(script) const multisig = btemplates.multisig.output.decode(script)
pubKeys = multisig.pubKeys pubKeys = multisig.pubKeys
} }
@ -57,22 +57,22 @@ function extractChunks (type, chunks, script) {
function expandInput (scriptSig, witnessStack) { function expandInput (scriptSig, witnessStack) {
if (scriptSig.length === 0 && witnessStack.length === 0) return {} if (scriptSig.length === 0 && witnessStack.length === 0) return {}
var prevOutScript let prevOutScript
var prevOutType let prevOutType
var scriptType let scriptType
var script let script
var redeemScript let redeemScript
var witnessScript let witnessScript
var witnessScriptType let witnessScriptType
var redeemScriptType let redeemScriptType
var witness = false let witness = false
var p2wsh = false let p2wsh = false
var p2sh = false let p2sh = false
var witnessProgram let witnessProgram
var chunks let chunks
var scriptSigChunks = bscript.decompile(scriptSig) || [] const scriptSigChunks = bscript.decompile(scriptSig) || []
var sigType = btemplates.classifyInput(scriptSigChunks, true) const sigType = btemplates.classifyInput(scriptSigChunks, true)
if (sigType === scriptTypes.P2SH) { if (sigType === scriptTypes.P2SH) {
p2sh = true p2sh = true
redeemScript = scriptSigChunks[scriptSigChunks.length - 1] redeemScript = scriptSigChunks[scriptSigChunks.length - 1]
@ -82,7 +82,7 @@ function expandInput (scriptSig, witnessStack) {
script = redeemScript script = redeemScript
} }
var classifyWitness = btemplates.classifyWitness(witnessStack, true) const classifyWitness = btemplates.classifyWitness(witnessStack, true)
if (classifyWitness === scriptTypes.P2WSH) { if (classifyWitness === scriptTypes.P2WSH) {
witnessScript = witnessStack[witnessStack.length - 1] witnessScript = witnessStack[witnessStack.length - 1]
witnessScriptType = btemplates.classifyOutput(witnessScript) witnessScriptType = btemplates.classifyOutput(witnessScript)
@ -114,8 +114,8 @@ function expandInput (scriptSig, witnessStack) {
chunks = witnessStack.slice(0, -1) chunks = witnessStack.slice(0, -1)
} else if (classifyWitness === scriptTypes.P2WPKH) { } else if (classifyWitness === scriptTypes.P2WPKH) {
witness = true witness = true
var key = witnessStack[witnessStack.length - 1] const key = witnessStack[witnessStack.length - 1]
var keyHash = bcrypto.hash160(key) const keyHash = bcrypto.hash160(key)
if (scriptSig.length === 0) { if (scriptSig.length === 0) {
prevOutScript = btemplates.witnessPubKeyHash.output.encode(keyHash) prevOutScript = btemplates.witnessPubKeyHash.output.encode(keyHash)
prevOutType = scriptTypes.P2WPKH prevOutType = scriptTypes.P2WPKH
@ -147,9 +147,9 @@ function expandInput (scriptSig, witnessStack) {
chunks = scriptSigChunks chunks = scriptSigChunks
} }
var expanded = extractChunks(scriptType, chunks, script) const expanded = extractChunks(scriptType, chunks, script)
var result = { const result = {
pubKeys: expanded.pubKeys, pubKeys: expanded.pubKeys,
signatures: expanded.signatures, signatures: expanded.signatures,
prevOutScript: prevOutScript, prevOutScript: prevOutScript,
@ -177,11 +177,11 @@ function fixMultisigOrder (input, transaction, vin) {
if (input.redeemScriptType !== scriptTypes.MULTISIG || !input.redeemScript) return if (input.redeemScriptType !== scriptTypes.MULTISIG || !input.redeemScript) return
if (input.pubKeys.length === input.signatures.length) return if (input.pubKeys.length === input.signatures.length) return
var unmatched = input.signatures.concat() const unmatched = input.signatures.concat()
input.signatures = input.pubKeys.map(function (pubKey) { input.signatures = input.pubKeys.map(function (pubKey) {
var keyPair = ECPair.fromPublicKey(pubKey) const keyPair = ECPair.fromPublicKey(pubKey)
var match let match
// check for a signature // check for a signature
unmatched.some(function (signature, i) { unmatched.some(function (signature, i) {
@ -189,8 +189,8 @@ function fixMultisigOrder (input, transaction, vin) {
if (!signature) return false if (!signature) return false
// TODO: avoid O(n) hashForSignature // TODO: avoid O(n) hashForSignature
var parsed = bscript.signature.decode(signature) const parsed = bscript.signature.decode(signature)
var hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType) const hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType)
// skip if signature does not match pubKey // skip if signature does not match pubKey
if (!keyPair.verify(hash, parsed.signature)) return false if (!keyPair.verify(hash, parsed.signature)) return false
@ -209,20 +209,20 @@ function fixMultisigOrder (input, transaction, vin) {
function expandOutput (script, scriptType, ourPubKey) { function expandOutput (script, scriptType, ourPubKey) {
typeforce(types.Buffer, script) typeforce(types.Buffer, script)
var scriptChunks = bscript.decompile(script) || [] const scriptChunks = bscript.decompile(script) || []
if (!scriptType) { if (!scriptType) {
scriptType = btemplates.classifyOutput(script) scriptType = btemplates.classifyOutput(script)
} }
var pubKeys = [] let pubKeys = []
switch (scriptType) { switch (scriptType) {
// does our hash160(pubKey) match the output scripts? // does our hash160(pubKey) match the output scripts?
case scriptTypes.P2PKH: case scriptTypes.P2PKH:
if (!ourPubKey) break if (!ourPubKey) break
var pkh1 = scriptChunks[2] const pkh1 = scriptChunks[2]
var pkh2 = bcrypto.hash160(ourPubKey) const pkh2 = bcrypto.hash160(ourPubKey)
if (pkh1.equals(pkh2)) pubKeys = [ourPubKey] if (pkh1.equals(pkh2)) pubKeys = [ourPubKey]
break break
@ -230,8 +230,8 @@ function expandOutput (script, scriptType, ourPubKey) {
case scriptTypes.P2WPKH: case scriptTypes.P2WPKH:
if (!ourPubKey) break if (!ourPubKey) break
var wpkh1 = scriptChunks[1] const wpkh1 = scriptChunks[1]
var wpkh2 = bcrypto.hash160(ourPubKey) const wpkh2 = bcrypto.hash160(ourPubKey)
if (wpkh1.equals(wpkh2)) pubKeys = [ourPubKey] if (wpkh1.equals(wpkh2)) pubKeys = [ourPubKey]
break break
@ -257,7 +257,7 @@ function checkP2SHInput (input, redeemScriptHash) {
if (input.prevOutType) { if (input.prevOutType) {
if (input.prevOutType !== scriptTypes.P2SH) throw new Error('PrevOutScript must be P2SH') if (input.prevOutType !== scriptTypes.P2SH) throw new Error('PrevOutScript must be P2SH')
var chunks = bscript.decompile(input.prevOutScript) const chunks = bscript.decompile(input.prevOutScript)
if (!chunks) throw new Error('Invalid prevOutScript') if (!chunks) throw new Error('Invalid prevOutScript')
if (!chunks[1].equals(redeemScriptHash)) throw new Error('Inconsistent hash160(redeemScript)') if (!chunks[1].equals(redeemScriptHash)) throw new Error('Inconsistent hash160(redeemScript)')
} }
@ -267,28 +267,28 @@ function checkP2WSHInput (input, witnessScriptHash) {
if (input.prevOutType) { if (input.prevOutType) {
if (input.prevOutType !== scriptTypes.P2WSH) throw new Error('PrevOutScript must be P2WSH') if (input.prevOutType !== scriptTypes.P2WSH) throw new Error('PrevOutScript must be P2WSH')
var chunks = bscript.decompile(input.prevOutScript) const chunks = bscript.decompile(input.prevOutScript)
if (!chunks) throw new Error('Invalid witnessScript') if (!chunks) throw new Error('Invalid witnessScript')
if (!chunks[1].equals(witnessScriptHash)) throw new Error('Inconsistent sha256(witnessScript)') if (!chunks[1].equals(witnessScriptHash)) throw new Error('Inconsistent sha256(witnessScript)')
} }
} }
function prepareInput (input, kpPubKey, redeemScript, witnessValue, witnessScript) { function prepareInput (input, kpPubKey, redeemScript, witnessValue, witnessScript) {
var expanded let expanded
var prevOutType let prevOutType
var prevOutScript let prevOutScript
var p2sh = false let p2sh = false
var p2shType let p2shType
var redeemScriptHash let redeemScriptHash
var witness = false let witness = false
var p2wsh = false let p2wsh = false
var witnessType let witnessType
var witnessScriptHash let witnessScriptHash
var signType let signType
var signScript let signScript
if (redeemScript && witnessScript) { if (redeemScript && witnessScript) {
redeemScriptHash = bcrypto.hash160(redeemScript) redeemScriptHash = bcrypto.hash160(redeemScript)
@ -408,15 +408,15 @@ function buildStack (type, signatures, pubKeys, allowIncomplete) {
} }
function buildInput (input, allowIncomplete) { function buildInput (input, allowIncomplete) {
var scriptType = input.prevOutType let scriptType = input.prevOutType
var sig = [] let sig = []
var witness = [] let witness = []
if (supportedType(scriptType)) { if (supportedType(scriptType)) {
sig = buildStack(scriptType, input.signatures, input.pubKeys, allowIncomplete) sig = buildStack(scriptType, input.signatures, input.pubKeys, allowIncomplete)
} }
var p2sh = false let p2sh = false
if (scriptType === btemplates.types.P2SH) { if (scriptType === btemplates.types.P2SH) {
// We can remove this error later when we have a guarantee prepareInput // We can remove this error later when we have a guarantee prepareInput
// rejects unsignable scripts - it MUST be signable at this point. // rejects unsignable scripts - it MUST be signable at this point.
@ -503,7 +503,7 @@ TransactionBuilder.prototype.setVersion = function (version) {
} }
TransactionBuilder.fromTransaction = function (transaction, network) { TransactionBuilder.fromTransaction = function (transaction, network) {
var txb = new TransactionBuilder(network) const txb = new TransactionBuilder(network)
// Copy transaction fields // Copy transaction fields
txb.setVersion(transaction.version) txb.setVersion(transaction.version)
@ -536,7 +536,7 @@ TransactionBuilder.prototype.addInput = function (txHash, vout, sequence, prevOu
throw new Error('No, this would invalidate signatures') throw new Error('No, this would invalidate signatures')
} }
var value let value
// is it a hex string? // is it a hex string?
if (typeof txHash === 'string') { if (typeof txHash === 'string') {
@ -545,7 +545,7 @@ TransactionBuilder.prototype.addInput = function (txHash, vout, sequence, prevOu
// is it a Transaction object? // is it a Transaction object?
} else if (txHash instanceof Transaction) { } else if (txHash instanceof Transaction) {
var txOut = txHash.outs[vout] const txOut = txHash.outs[vout]
prevOutScript = txOut.script prevOutScript = txOut.script
value = txOut.value value = txOut.value
@ -564,10 +564,10 @@ TransactionBuilder.prototype.__addInputUnsafe = function (txHash, vout, options)
throw new Error('coinbase inputs not supported') throw new Error('coinbase inputs not supported')
} }
var prevTxOut = txHash.toString('hex') + ':' + vout const prevTxOut = txHash.toString('hex') + ':' + vout
if (this.__prevTxSet[prevTxOut] !== undefined) throw new Error('Duplicate TxOut: ' + prevTxOut) if (this.__prevTxSet[prevTxOut] !== undefined) throw new Error('Duplicate TxOut: ' + prevTxOut)
var input = {} let input = {}
// derive what we can from the scriptSig // derive what we can from the scriptSig
if (options.script !== undefined) { if (options.script !== undefined) {
@ -581,10 +581,10 @@ TransactionBuilder.prototype.__addInputUnsafe = function (txHash, vout, options)
// derive what we can from the previous transactions output script // derive what we can from the previous transactions output script
if (!input.prevOutScript && options.prevOutScript) { if (!input.prevOutScript && options.prevOutScript) {
var prevOutType let prevOutType
if (!input.pubKeys && !input.signatures) { if (!input.pubKeys && !input.signatures) {
var expanded = expandOutput(options.prevOutScript) const expanded = expandOutput(options.prevOutScript)
if (expanded.pubKeys) { if (expanded.pubKeys) {
input.pubKeys = expanded.pubKeys input.pubKeys = expanded.pubKeys
@ -598,7 +598,7 @@ TransactionBuilder.prototype.__addInputUnsafe = function (txHash, vout, options)
input.prevOutType = prevOutType || btemplates.classifyOutput(options.prevOutScript) input.prevOutType = prevOutType || btemplates.classifyOutput(options.prevOutScript)
} }
var vin = this.__tx.addInput(txHash, vout, options.sequence, options.scriptSig) const vin = this.__tx.addInput(txHash, vout, options.sequence, options.scriptSig)
this.__inputs[vin] = input this.__inputs[vin] = input
this.__prevTxSet[prevTxOut] = true this.__prevTxSet[prevTxOut] = true
return vin return vin
@ -630,12 +630,12 @@ TransactionBuilder.prototype.__build = function (allowIncomplete) {
if (!this.__tx.outs.length) throw new Error('Transaction has no outputs') if (!this.__tx.outs.length) throw new Error('Transaction has no outputs')
} }
var tx = this.__tx.clone() const tx = this.__tx.clone()
// Create script signatures from inputs // Create script signatures from inputs
this.__inputs.forEach(function (input, i) { this.__inputs.forEach(function (input, i) {
var scriptType = input.witnessScriptType || input.redeemScriptType || input.prevOutType const scriptType = input.witnessScriptType || input.redeemScriptType || input.prevOutType
if (!scriptType && !allowIncomplete) throw new Error('Transaction is not complete') if (!scriptType && !allowIncomplete) throw new Error('Transaction is not complete')
var result = buildInput(input, allowIncomplete) const result = buildInput(input, allowIncomplete)
// skip if no result // skip if no result
if (!allowIncomplete) { if (!allowIncomplete) {
@ -677,7 +677,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
if (!this.__inputs[vin]) throw new Error('No input at index: ' + vin) if (!this.__inputs[vin]) throw new Error('No input at index: ' + vin)
hashType = hashType || Transaction.SIGHASH_ALL hashType = hashType || Transaction.SIGHASH_ALL
var input = this.__inputs[vin] const input = this.__inputs[vin]
// if redeemScript was previously provided, enforce consistency // if redeemScript was previously provided, enforce consistency
if (input.redeemScript !== undefined && if (input.redeemScript !== undefined &&
@ -686,7 +686,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
throw new Error('Inconsistent redeemScript') throw new Error('Inconsistent redeemScript')
} }
var kpPubKey = keyPair.publicKey || keyPair.getPublicKey() const kpPubKey = keyPair.publicKey || keyPair.getPublicKey()
if (!canSign(input)) { if (!canSign(input)) {
if (witnessValue !== undefined) { if (witnessValue !== undefined) {
if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue') if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue')
@ -699,7 +699,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
} }
// ready to sign // ready to sign
var signatureHash let signatureHash
if (input.witness) { if (input.witness) {
signatureHash = this.__tx.hashForWitnessV0(vin, input.signScript, input.value, hashType) signatureHash = this.__tx.hashForWitnessV0(vin, input.signScript, input.value, hashType)
} else { } else {
@ -707,7 +707,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
} }
// enforce in order signing of public keys // enforce in order signing of public keys
var signed = input.pubKeys.some(function (pubKey, i) { const signed = input.pubKeys.some(function (pubKey, i) {
if (!kpPubKey.equals(pubKey)) return false if (!kpPubKey.equals(pubKey)) return false
if (input.signatures[i]) throw new Error('Signature already exists') if (input.signatures[i]) throw new Error('Signature already exists')
@ -717,7 +717,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
input.prevOutType === scriptTypes.P2WSH input.prevOutType === scriptTypes.P2WSH
)) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH') )) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH')
let signature = keyPair.sign(signatureHash) const signature = keyPair.sign(signatureHash)
input.signatures[i] = bscript.signature.encode(signature, hashType) input.signatures[i] = bscript.signature.encode(signature, hashType)
return true return true
}) })
@ -736,7 +736,7 @@ TransactionBuilder.prototype.__canModifyInputs = function () {
return input.signatures.every(function (signature) { return input.signatures.every(function (signature) {
if (!signature) return true if (!signature) return true
var hashType = signatureHashType(signature) const hashType = signatureHashType(signature)
// if SIGHASH_ANYONECANPAY is set, signatures would not // if SIGHASH_ANYONECANPAY is set, signatures would not
// be invalidated by more inputs // be invalidated by more inputs
@ -746,17 +746,17 @@ TransactionBuilder.prototype.__canModifyInputs = function () {
} }
TransactionBuilder.prototype.__canModifyOutputs = function () { TransactionBuilder.prototype.__canModifyOutputs = function () {
var nInputs = this.__tx.ins.length const nInputs = this.__tx.ins.length
var nOutputs = this.__tx.outs.length const nOutputs = this.__tx.outs.length
return this.__inputs.every(function (input) { return this.__inputs.every(function (input) {
if (input.signatures === undefined) return true if (input.signatures === undefined) return true
return input.signatures.every(function (signature) { return input.signatures.every(function (signature) {
if (!signature) return true if (!signature) return true
var hashType = signatureHashType(signature) const hashType = signatureHashType(signature)
var hashTypeMod = hashType & 0x1f const hashTypeMod = hashType & 0x1f
if (hashTypeMod === Transaction.SIGHASH_NONE) return true if (hashTypeMod === Transaction.SIGHASH_NONE) return true
if (hashTypeMod === Transaction.SIGHASH_SINGLE) { if (hashTypeMod === Transaction.SIGHASH_SINGLE) {
// if SIGHASH_SINGLE is set, and nInputs > nOutputs // if SIGHASH_SINGLE is set, and nInputs > nOutputs
@ -770,13 +770,13 @@ TransactionBuilder.prototype.__canModifyOutputs = function () {
TransactionBuilder.prototype.__overMaximumFees = function (bytes) { TransactionBuilder.prototype.__overMaximumFees = function (bytes) {
// not all inputs will have .value defined // not all inputs will have .value defined
var incoming = this.__inputs.reduce(function (a, x) { return a + (x.value >>> 0) }, 0) const incoming = this.__inputs.reduce(function (a, x) { return a + (x.value >>> 0) }, 0)
// but all outputs do, and if we have any input value // but all outputs do, and if we have any input value
// we can immediately determine if the outputs are too small // we can immediately determine if the outputs are too small
var outgoing = this.__tx.outs.reduce(function (a, x) { return a + x.value }, 0) const outgoing = this.__tx.outs.reduce(function (a, x) { return a + x.value }, 0)
var fee = incoming - outgoing const fee = incoming - outgoing
var feeRate = fee / bytes const feeRate = fee / bytes
return feeRate > this.maximumFeeRate return feeRate > this.maximumFeeRate
} }

View file

@ -1,6 +1,6 @@
var typeforce = require('typeforce') const typeforce = require('typeforce')
var UINT31_MAX = Math.pow(2, 31) - 1 const UINT31_MAX = Math.pow(2, 31) - 1
function UInt31 (value) { function UInt31 (value) {
return typeforce.UInt32(value) && value <= UINT31_MAX return typeforce.UInt32(value) && value <= UINT31_MAX
} }
@ -10,16 +10,16 @@ function BIP32Path (value) {
} }
BIP32Path.toJSON = function () { return 'BIP32 derivation path' } BIP32Path.toJSON = function () { return 'BIP32 derivation path' }
var SATOSHI_MAX = 21 * 1e14 const SATOSHI_MAX = 21 * 1e14
function Satoshi (value) { function Satoshi (value) {
return typeforce.UInt53(value) && value <= SATOSHI_MAX return typeforce.UInt53(value) && value <= SATOSHI_MAX
} }
// external dependent types // external dependent types
var ECPoint = typeforce.quacksLike('Point') const ECPoint = typeforce.quacksLike('Point')
// exposed, external API // exposed, external API
var Network = typeforce.compile({ const Network = typeforce.compile({
messagePrefix: typeforce.oneOf(typeforce.Buffer, typeforce.String), messagePrefix: typeforce.oneOf(typeforce.Buffer, typeforce.String),
bip32: { bip32: {
public: typeforce.UInt32, public: typeforce.UInt32,
@ -31,7 +31,7 @@ var Network = typeforce.compile({
}) })
// extend typeforce types with ours // extend typeforce types with ours
var types = { const types = {
BIP32Path: BIP32Path, BIP32Path: BIP32Path,
Buffer256bit: typeforce.BufferN(32), Buffer256bit: typeforce.BufferN(32),
ECPoint: ECPoint, ECPoint: ECPoint,

View file

@ -1,10 +1,10 @@
/* global describe, it */ /* global describe, it */
let assert = require('assert') const assert = require('assert')
let baddress = require('../src/address') const baddress = require('../src/address')
let bscript = require('../src/script') const bscript = require('../src/script')
let fixtures = require('./fixtures/address.json') const fixtures = require('./fixtures/address.json')
let NETWORKS = Object.assign({ const NETWORKS = Object.assign({
litecoin: { litecoin: {
messagePrefix: '\x19Litecoin Signed Message:\n', messagePrefix: '\x19Litecoin Signed Message:\n',
bip32: { bip32: {
@ -23,7 +23,7 @@ describe('address', function () {
if (!f.base58check) return if (!f.base58check) return
it('decodes ' + f.base58check, function () { it('decodes ' + f.base58check, function () {
var decode = baddress.fromBase58Check(f.base58check) const decode = baddress.fromBase58Check(f.base58check)
assert.strictEqual(decode.version, f.version) assert.strictEqual(decode.version, f.version)
assert.strictEqual(decode.hash.toString('hex'), f.hash) assert.strictEqual(decode.hash.toString('hex'), f.hash)
@ -44,7 +44,7 @@ describe('address', function () {
if (!f.bech32) return if (!f.bech32) return
it('decodes ' + f.bech32, function () { it('decodes ' + f.bech32, function () {
var actual = baddress.fromBech32(f.bech32) const actual = baddress.fromBech32(f.bech32)
assert.strictEqual(actual.version, f.version) assert.strictEqual(actual.version, f.version)
assert.strictEqual(actual.prefix, NETWORKS[f.network].bech32) assert.strictEqual(actual.prefix, NETWORKS[f.network].bech32)
@ -64,8 +64,8 @@ describe('address', function () {
describe('fromOutputScript', function () { describe('fromOutputScript', function () {
fixtures.standard.forEach(function (f) { fixtures.standard.forEach(function (f) {
it('encodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', function () { it('encodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', function () {
var script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script)
var address = baddress.fromOutputScript(script, NETWORKS[f.network]) const address = baddress.fromOutputScript(script, NETWORKS[f.network])
assert.strictEqual(address, f.base58check || f.bech32.toLowerCase()) assert.strictEqual(address, f.base58check || f.bech32.toLowerCase())
}) })
@ -73,7 +73,7 @@ describe('address', function () {
fixtures.invalid.fromOutputScript.forEach(function (f) { fixtures.invalid.fromOutputScript.forEach(function (f) {
it('throws when ' + f.script.slice(0, 30) + '... ' + f.exception, function () { it('throws when ' + f.script.slice(0, 30) + '... ' + f.exception, function () {
var script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script)
assert.throws(function () { assert.throws(function () {
baddress.fromOutputScript(script) baddress.fromOutputScript(script)
@ -87,7 +87,7 @@ describe('address', function () {
if (!f.base58check) return if (!f.base58check) return
it('encodes ' + f.hash + ' (' + f.network + ')', function () { it('encodes ' + f.hash + ' (' + f.network + ')', function () {
var 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)
}) })
@ -97,7 +97,7 @@ describe('address', function () {
describe('toBech32', function () { describe('toBech32', function () {
fixtures.bech32.forEach((f, i) => { fixtures.bech32.forEach((f, i) => {
if (!f.bech32) return if (!f.bech32) return
var data = Buffer.from(f.data, 'hex') const data = Buffer.from(f.data, 'hex')
it('encode ' + f.address, function () { it('encode ' + f.address, function () {
assert.deepEqual(baddress.toBech32(data, f.version, f.prefix), f.address) assert.deepEqual(baddress.toBech32(data, f.version, f.prefix), f.address)
@ -118,7 +118,7 @@ describe('address', function () {
describe('toOutputScript', function () { describe('toOutputScript', function () {
fixtures.standard.forEach(function (f) { fixtures.standard.forEach(function (f) {
it('decodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', function () { it('decodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', function () {
var 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)
}) })

View file

@ -1,35 +1,35 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var base58 = require('bs58') const base58 = require('bs58')
var bitcoin = require('../') const bitcoin = require('../')
var base58EncodeDecode = require('./fixtures/core/base58_encode_decode.json') const base58EncodeDecode = require('./fixtures/core/base58_encode_decode.json')
var base58KeysInvalid = require('./fixtures/core/base58_keys_invalid.json') const base58KeysInvalid = require('./fixtures/core/base58_keys_invalid.json')
var base58KeysValid = require('./fixtures/core/base58_keys_valid.json') const base58KeysValid = require('./fixtures/core/base58_keys_valid.json')
var blocksValid = require('./fixtures/core/blocks.json') const blocksValid = require('./fixtures/core/blocks.json')
var sigCanonical = require('./fixtures/core/sig_canonical.json') const sigCanonical = require('./fixtures/core/sig_canonical.json')
var sigHash = require('./fixtures/core/sighash.json') const sigHash = require('./fixtures/core/sighash.json')
var sigNoncanonical = require('./fixtures/core/sig_noncanonical.json') const sigNoncanonical = require('./fixtures/core/sig_noncanonical.json')
var txValid = require('./fixtures/core/tx_valid.json') const txValid = require('./fixtures/core/tx_valid.json')
describe('Bitcoin-core', function () { describe('Bitcoin-core', function () {
// base58EncodeDecode // base58EncodeDecode
describe('base58', function () { describe('base58', function () {
base58EncodeDecode.forEach(function (f) { base58EncodeDecode.forEach(function (f) {
var fhex = f[0] const fhex = f[0]
var fb58 = f[1] const fb58 = f[1]
it('can decode ' + fb58, function () { it('can decode ' + fb58, function () {
var buffer = base58.decode(fb58) const buffer = base58.decode(fb58)
var 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, function () {
var buffer = Buffer.from(fhex, 'hex') const buffer = Buffer.from(fhex, 'hex')
var actual = base58.encode(buffer) const actual = base58.encode(buffer)
assert.strictEqual(actual, fb58) assert.strictEqual(actual, fb58)
}) })
@ -38,20 +38,20 @@ describe('Bitcoin-core', function () {
// base58KeysValid // base58KeysValid
describe('address.toBase58Check', function () { describe('address.toBase58Check', function () {
var typeMap = { const typeMap = {
'pubkey': 'pubKeyHash', 'pubkey': 'pubKeyHash',
'script': 'scriptHash' 'script': 'scriptHash'
} }
base58KeysValid.forEach(function (f) { base58KeysValid.forEach(function (f) {
var expected = f[0] const expected = f[0]
var hash = Buffer.from(f[1], 'hex') const hash = Buffer.from(f[1], 'hex')
var params = f[2] const params = f[2]
if (params.isPrivkey) return if (params.isPrivkey) return
var network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin const network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin
var version = network[typeMap[params.addrType]] const version = network[typeMap[params.addrType]]
it('can export ' + expected, function () { it('can export ' + expected, function () {
assert.strictEqual(bitcoin.address.toBase58Check(hash, version), expected) assert.strictEqual(bitcoin.address.toBase58Check(hash, version), expected)
@ -61,7 +61,7 @@ describe('Bitcoin-core', function () {
// base58KeysInvalid // base58KeysInvalid
describe('address.fromBase58Check', function () { describe('address.fromBase58Check', function () {
var allowedNetworks = [ const allowedNetworks = [
bitcoin.networks.bitcoin.pubkeyhash, bitcoin.networks.bitcoin.pubkeyhash,
bitcoin.networks.bitcoin.scripthash, bitcoin.networks.bitcoin.scripthash,
bitcoin.networks.testnet.pubkeyhash, bitcoin.networks.testnet.pubkeyhash,
@ -69,11 +69,11 @@ describe('Bitcoin-core', function () {
] ]
base58KeysInvalid.forEach(function (f) { base58KeysInvalid.forEach(function (f) {
var string = f[0] const string = f[0]
it('throws on ' + string, function () { it('throws on ' + string, function () {
assert.throws(function () { assert.throws(function () {
var address = bitcoin.address.fromBase58Check(string) const address = bitcoin.address.fromBase58Check(string)
assert.notEqual(allowedNetworks.indexOf(address.version), -1, 'Invalid network') assert.notEqual(allowedNetworks.indexOf(address.version), -1, 'Invalid network')
}, /(Invalid (checksum|network))|(too (short|long))/) }, /(Invalid (checksum|network))|(too (short|long))/)
@ -84,14 +84,14 @@ describe('Bitcoin-core', function () {
// base58KeysValid // base58KeysValid
describe('ECPair', function () { describe('ECPair', function () {
base58KeysValid.forEach(function (f) { base58KeysValid.forEach(function (f) {
var string = f[0] const string = f[0]
var hex = f[1] const hex = f[1]
var params = f[2] const params = f[2]
if (!params.isPrivkey) return if (!params.isPrivkey) return
var network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin const network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin
var keyPair = bitcoin.ECPair.fromWIF(string, network) const keyPair = bitcoin.ECPair.fromWIF(string, network)
it('fromWIF imports ' + string, function () { it('fromWIF imports ' + string, function () {
assert.strictEqual(keyPair.privateKey.toString('hex'), hex) assert.strictEqual(keyPair.privateKey.toString('hex'), hex)
@ -106,13 +106,13 @@ describe('Bitcoin-core', function () {
// base58KeysInvalid // base58KeysInvalid
describe('ECPair.fromWIF', function () { describe('ECPair.fromWIF', function () {
var allowedNetworks = [ const allowedNetworks = [
bitcoin.networks.bitcoin, bitcoin.networks.bitcoin,
bitcoin.networks.testnet bitcoin.networks.testnet
] ]
base58KeysInvalid.forEach(function (f) { base58KeysInvalid.forEach(function (f) {
var string = f[0] const string = f[0]
it('throws on ' + string, function () { it('throws on ' + string, function () {
assert.throws(function () { assert.throws(function () {
@ -125,7 +125,7 @@ describe('Bitcoin-core', function () {
describe('Block.fromHex', function () { describe('Block.fromHex', function () {
blocksValid.forEach(function (f) { blocksValid.forEach(function (f) {
it('can parse ' + f.id, function () { it('can parse ' + f.id, function () {
var 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)
assert.strictEqual(block.transactions.length, f.transactions) assert.strictEqual(block.transactions.length, f.transactions)
@ -139,19 +139,19 @@ describe('Bitcoin-core', function () {
// 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
var inputs = f[0] const inputs = f[0]
var fhex = f[1] const fhex = f[1]
// var 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, function () {
var transaction = bitcoin.Transaction.fromHex(fhex) const transaction = bitcoin.Transaction.fromHex(fhex)
transaction.ins.forEach(function (txIn, i) { transaction.ins.forEach(function (txIn, i) {
var input = inputs[i] const input = inputs[i]
// reverse because test data is reversed // reverse because test data is reversed
var prevOutHash = Buffer.from(input[0], 'hex').reverse() const prevOutHash = Buffer.from(input[0], 'hex').reverse()
var prevOutIndex = input[1] const prevOutIndex = input[1]
assert.deepEqual(txIn.hash, prevOutHash) assert.deepEqual(txIn.hash, prevOutHash)
@ -168,29 +168,29 @@ describe('Bitcoin-core', function () {
// 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
var txHex = f[0] const txHex = f[0]
var scriptHex = f[1] const scriptHex = f[1]
var inIndex = f[2] const inIndex = f[2]
var hashType = f[3] const hashType = f[3]
var expectedHash = f[4] const expectedHash = f[4]
var hashTypes = [] const hashTypes = []
if ((hashType & 0x1f) === bitcoin.Transaction.SIGHASH_NONE) hashTypes.push('SIGHASH_NONE') if ((hashType & 0x1f) === bitcoin.Transaction.SIGHASH_NONE) hashTypes.push('SIGHASH_NONE')
else if ((hashType & 0x1f) === bitcoin.Transaction.SIGHASH_SINGLE) hashTypes.push('SIGHASH_SINGLE') else if ((hashType & 0x1f) === bitcoin.Transaction.SIGHASH_SINGLE) hashTypes.push('SIGHASH_SINGLE')
else hashTypes.push('SIGHASH_ALL') else hashTypes.push('SIGHASH_ALL')
if (hashType & bitcoin.Transaction.SIGHASH_ANYONECANPAY) hashTypes.push('SIGHASH_ANYONECANPAY') if (hashType & bitcoin.Transaction.SIGHASH_ANYONECANPAY) hashTypes.push('SIGHASH_ANYONECANPAY')
var hashTypeName = hashTypes.join(' | ') const hashTypeName = hashTypes.join(' | ')
it('should hash ' + txHex.slice(0, 40) + '... (' + hashTypeName + ')', function () { it('should hash ' + txHex.slice(0, 40) + '... (' + hashTypeName + ')', function () {
var transaction = bitcoin.Transaction.fromHex(txHex) const transaction = bitcoin.Transaction.fromHex(txHex)
assert.strictEqual(transaction.toHex(), txHex) assert.strictEqual(transaction.toHex(), txHex)
var script = Buffer.from(scriptHex, 'hex') const script = Buffer.from(scriptHex, 'hex')
var scriptChunks = bitcoin.script.decompile(script) const scriptChunks = bitcoin.script.decompile(script)
assert.strictEqual(bitcoin.script.compile(scriptChunks).toString('hex'), scriptHex) assert.strictEqual(bitcoin.script.compile(scriptChunks).toString('hex'), scriptHex)
var 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.equal(hash.reverse().toString('hex'), expectedHash)
@ -200,11 +200,11 @@ describe('Bitcoin-core', function () {
describe('script.signature.decode', function () { describe('script.signature.decode', function () {
sigCanonical.forEach(function (hex) { sigCanonical.forEach(function (hex) {
var buffer = Buffer.from(hex, 'hex') const buffer = Buffer.from(hex, 'hex')
it('can parse ' + hex, function () { it('can parse ' + hex, function () {
var parsed = bitcoin.script.signature.decode(buffer) const parsed = bitcoin.script.signature.decode(buffer)
var actual = bitcoin.script.signature.encode(parsed.signature, parsed.hashType) const actual = bitcoin.script.signature.encode(parsed.signature, parsed.hashType)
assert.strictEqual(actual.toString('hex'), hex) assert.strictEqual(actual.toString('hex'), hex)
}) })
@ -214,8 +214,8 @@ describe('Bitcoin-core', function () {
if (i === 0) return if (i === 0) return
if (i % 2 !== 0) return if (i % 2 !== 0) return
var description = sigNoncanonical[i - 1].slice(0, -1) const description = sigNoncanonical[i - 1].slice(0, -1)
var buffer = Buffer.from(hex, 'hex') const buffer = Buffer.from(hex, 'hex')
it('throws on ' + description, function () { it('throws on ' + description, function () {
assert.throws(function () { assert.throws(function () {

View file

@ -1,15 +1,15 @@
/* global describe, it, beforeEach */ /* global describe, it, beforeEach */
var assert = require('assert') const assert = require('assert')
var Block = require('../src/block') const Block = require('../src/block')
var fixtures = require('./fixtures/block') const fixtures = require('./fixtures/block')
describe('Block', function () { describe('Block', function () {
describe('version', function () { describe('version', function () {
it('should be interpreted as an int32le', function () { it('should be interpreted as an int32le', function () {
var blockHex = 'ffffffff0000000000000000000000000000000000000000000000000000000000000000414141414141414141414141414141414141414141414141414141414141414101000000020000000300000000' const blockHex = 'ffffffff0000000000000000000000000000000000000000000000000000000000000000414141414141414141414141414141414141414141414141414141414141414101000000020000000300000000'
var block = Block.fromHex(blockHex) const block = Block.fromHex(blockHex)
assert.equal(-1, block.version) assert.equal(-1, block.version)
assert.equal(1, block.timestamp) assert.equal(1, block.timestamp)
}) })
@ -18,7 +18,7 @@ describe('Block', function () {
describe('calculateTarget', function () { describe('calculateTarget', function () {
fixtures.targets.forEach(function (f) { fixtures.targets.forEach(function (f) {
it('returns ' + f.expected + ' for 0x' + f.bits, function () { it('returns ' + f.expected + ' for 0x' + f.bits, function () {
var bits = parseInt(f.bits, 16) const bits = parseInt(f.bits, 16)
assert.equal(Block.calculateTarget(bits).toString('hex'), f.expected) assert.equal(Block.calculateTarget(bits).toString('hex'), f.expected)
}) })
@ -28,7 +28,7 @@ describe('Block', function () {
describe('fromBuffer/fromHex', function () { describe('fromBuffer/fromHex', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('imports ' + f.description, function () { it('imports ' + f.description, function () {
var block = Block.fromHex(f.hex) const block = Block.fromHex(f.hex)
assert.strictEqual(block.version, f.version) assert.strictEqual(block.version, f.version)
assert.strictEqual(block.prevHash.toString('hex'), f.prevHash) assert.strictEqual(block.prevHash.toString('hex'), f.prevHash)
@ -51,7 +51,7 @@ describe('Block', function () {
describe('toBuffer/toHex', function () { describe('toBuffer/toHex', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
var block let block
beforeEach(function () { beforeEach(function () {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
@ -66,7 +66,7 @@ describe('Block', function () {
describe('getHash/getId', function () { describe('getHash/getId', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
var block let block
beforeEach(function () { beforeEach(function () {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
@ -81,14 +81,14 @@ describe('Block', function () {
describe('getUTCDate', function () { describe('getUTCDate', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
var block let block
beforeEach(function () { beforeEach(function () {
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, function () {
var utcDate = block.getUTCDate().getTime() const utcDate = block.getUTCDate().getTime()
assert.strictEqual(utcDate, f.timestamp * 1e3) assert.strictEqual(utcDate, f.timestamp * 1e3)
}) })
@ -105,7 +105,7 @@ describe('Block', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.hex.length === 160) return if (f.hex.length === 160) return
var block let block
beforeEach(function () { beforeEach(function () {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
@ -121,7 +121,7 @@ describe('Block', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.hex.length === 160) return if (f.hex.length === 160) return
var block let block
beforeEach(function () { beforeEach(function () {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)
@ -135,7 +135,7 @@ describe('Block', function () {
describe('checkProofOfWork', function () { describe('checkProofOfWork', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
var block let block
beforeEach(function () { beforeEach(function () {
block = Block.fromHex(f.hex) block = Block.fromHex(f.hex)

View file

@ -1,16 +1,16 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var bufferutils = require('../src/bufferutils') const bufferutils = require('../src/bufferutils')
var fixtures = require('./fixtures/bufferutils.json') const fixtures = require('./fixtures/bufferutils.json')
describe('bufferutils', function () { describe('bufferutils', function () {
describe('readUInt64LE', function () { describe('readUInt64LE', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('decodes ' + f.hex, function () { it('decodes ' + f.hex, function () {
var buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex')
var number = bufferutils.readUInt64LE(buffer, 0) const number = bufferutils.readUInt64LE(buffer, 0)
assert.strictEqual(number, f.dec) assert.strictEqual(number, f.dec)
}) })
@ -18,7 +18,7 @@ describe('bufferutils', function () {
fixtures.invalid.readUInt64LE.forEach(function (f) { fixtures.invalid.readUInt64LE.forEach(function (f) {
it('throws on ' + f.description, function () { it('throws on ' + f.description, function () {
var buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex')
assert.throws(function () { assert.throws(function () {
bufferutils.readUInt64LE(buffer, 0) bufferutils.readUInt64LE(buffer, 0)
@ -30,7 +30,7 @@ describe('bufferutils', function () {
describe('writeUInt64LE', function () { describe('writeUInt64LE', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('encodes ' + f.dec, function () { it('encodes ' + f.dec, function () {
var buffer = Buffer.alloc(8, 0) const buffer = Buffer.alloc(8, 0)
bufferutils.writeUInt64LE(buffer, f.dec, 0) bufferutils.writeUInt64LE(buffer, f.dec, 0)
assert.strictEqual(buffer.toString('hex'), f.hex) assert.strictEqual(buffer.toString('hex'), f.hex)
@ -39,7 +39,7 @@ describe('bufferutils', function () {
fixtures.invalid.readUInt64LE.forEach(function (f) { fixtures.invalid.readUInt64LE.forEach(function (f) {
it('throws on ' + f.description, function () { it('throws on ' + f.description, function () {
var buffer = Buffer.alloc(8, 0) const buffer = Buffer.alloc(8, 0)
assert.throws(function () { assert.throws(function () {
bufferutils.writeUInt64LE(buffer, f.dec, 0) bufferutils.writeUInt64LE(buffer, f.dec, 0)

View file

@ -1,20 +1,20 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var bcrypto = require('../src/crypto') const bcrypto = require('../src/crypto')
var fixtures = require('./fixtures/crypto') const fixtures = require('./fixtures/crypto')
describe('crypto', function () { describe('crypto', function () {
['hash160', 'hash256', 'ripemd160', 'sha1', 'sha256'].forEach(function (algorithm) { ['hash160', 'hash256', 'ripemd160', 'sha1', 'sha256'].forEach(function (algorithm) {
describe(algorithm, function () { describe(algorithm, function () {
fixtures.forEach(function (f) { fixtures.forEach(function (f) {
var fn = bcrypto[algorithm] const fn = bcrypto[algorithm]
var expected = f[algorithm] const expected = f[algorithm]
it('returns ' + expected + ' for ' + f.hex, function () { it('returns ' + expected + ' for ' + f.hex, function () {
var data = Buffer.from(f.hex, 'hex') const data = Buffer.from(f.hex, 'hex')
var actual = fn(data).toString('hex') const actual = fn(data).toString('hex')
assert.strictEqual(actual, expected) assert.strictEqual(actual, expected)
}) })

View file

@ -1,36 +1,36 @@
/* global describe, it, beforeEach */ /* global describe, it, beforeEach */
/* eslint-disable no-new */ /* eslint-disable no-new */
let assert = require('assert') const assert = require('assert')
let proxyquire = require('proxyquire') const proxyquire = require('proxyquire')
let hoodwink = require('hoodwink') const hoodwink = require('hoodwink')
let ECPair = require('../src/ecpair') const ECPair = require('../src/ecpair')
let tinysecp = require('tiny-secp256k1') const tinysecp = require('tiny-secp256k1')
let fixtures = require('./fixtures/ecpair.json') const fixtures = require('./fixtures/ecpair.json')
let NETWORKS = require('../src/networks') const NETWORKS = require('../src/networks')
let NETWORKS_LIST = [] // Object.values(NETWORKS) const NETWORKS_LIST = [] // Object.values(NETWORKS)
for (let networkName in NETWORKS) { for (let networkName in NETWORKS) {
NETWORKS_LIST.push(NETWORKS[networkName]) NETWORKS_LIST.push(NETWORKS[networkName])
} }
let ZERO = Buffer.alloc(32, 0) const ZERO = Buffer.alloc(32, 0)
let ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex') const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
let GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex') const GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex')
let GROUP_ORDER_LESS_1 = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 'hex') const GROUP_ORDER_LESS_1 = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 'hex')
describe('ECPair', function () { describe('ECPair', function () {
describe('constructor', function () { describe('constructor', function () {
it('defaults to compressed', function () { it('defaults to compressed', function () {
let 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', function () {
let keyPair = ECPair.fromPrivateKey(ONE, { const keyPair = ECPair.fromPrivateKey(ONE, {
compressed: false compressed: false
}) })
@ -38,7 +38,7 @@ describe('ECPair', function () {
}) })
it('supports the network option', function () { it('supports the network option', function () {
let keyPair = ECPair.fromPrivateKey(ONE, { const keyPair = ECPair.fromPrivateKey(ONE, {
compressed: false, compressed: false,
network: NETWORKS.testnet network: NETWORKS.testnet
}) })
@ -48,10 +48,10 @@ describe('ECPair', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('derives public key for ' + f.WIF, function () { it('derives public key for ' + f.WIF, function () {
let d = Buffer.from(f.d, 'hex') const d = Buffer.from(f.d, 'hex')
console.log(d) console.log(d)
let keyPair = ECPair.fromPrivateKey(d, { const keyPair = ECPair.fromPrivateKey(d, {
compressed: f.compressed compressed: f.compressed
}) })
@ -62,12 +62,12 @@ describe('ECPair', function () {
fixtures.invalid.constructor.forEach(function (f) { fixtures.invalid.constructor.forEach(function (f) {
it('throws ' + f.exception, function () { it('throws ' + f.exception, function () {
if (f.d) { if (f.d) {
let d = Buffer.from(f.d, 'hex') const d = Buffer.from(f.d, 'hex')
assert.throws(function () { assert.throws(function () {
ECPair.fromPrivateKey(d, f.options) ECPair.fromPrivateKey(d, f.options)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
} else { } else {
let Q = Buffer.from(f.Q, 'hex') const Q = Buffer.from(f.Q, 'hex')
assert.throws(function () { assert.throws(function () {
ECPair.fromPublicKey(Q, f.options) ECPair.fromPublicKey(Q, f.options)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
@ -95,8 +95,8 @@ describe('ECPair', function () {
describe('fromWIF', function () { describe('fromWIF', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('imports ' + f.WIF + ' (' + f.network + ')', function () { it('imports ' + f.WIF + ' (' + f.network + ')', function () {
let network = NETWORKS[f.network] const network = NETWORKS[f.network]
let keyPair = ECPair.fromWIF(f.WIF, network) const keyPair = ECPair.fromWIF(f.WIF, network)
assert.strictEqual(keyPair.privateKey.toString('hex'), f.d) assert.strictEqual(keyPair.privateKey.toString('hex'), f.d)
assert.strictEqual(keyPair.compressed, f.compressed) assert.strictEqual(keyPair.compressed, f.compressed)
@ -106,7 +106,7 @@ describe('ECPair', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('imports ' + f.WIF + ' (via list of networks)', function () { it('imports ' + f.WIF + ' (via list of networks)', function () {
let 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)
assert.strictEqual(keyPair.compressed, f.compressed) assert.strictEqual(keyPair.compressed, f.compressed)
@ -117,7 +117,7 @@ describe('ECPair', function () {
fixtures.invalid.fromWIF.forEach(function (f) { fixtures.invalid.fromWIF.forEach(function (f) {
it('throws on ' + f.WIF, function () { it('throws on ' + f.WIF, function () {
assert.throws(function () { assert.throws(function () {
let 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)
}, new RegExp(f.exception)) }, new RegExp(f.exception))
@ -128,29 +128,29 @@ describe('ECPair', function () {
describe('toWIF', function () { describe('toWIF', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('exports ' + f.WIF, function () { it('exports ' + f.WIF, function () {
let keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST) const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
let result = keyPair.toWIF() const result = keyPair.toWIF()
assert.strictEqual(result, f.WIF) assert.strictEqual(result, f.WIF)
}) })
}) })
}) })
describe('makeRandom', function () { describe('makeRandom', function () {
let d = Buffer.alloc(32, 4) const d = Buffer.alloc(32, 4)
let exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv' const exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'
describe('uses randombytes RNG', function () { describe('uses randombytes RNG', function () {
it('generates a ECPair', function () { it('generates a ECPair', function () {
let stub = { randombytes: function () { return d } } const stub = { randombytes: function () { return d } }
let ProxiedECPair = proxyquire('../src/ecpair', stub) const ProxiedECPair = proxyquire('../src/ecpair', stub)
let keyPair = ProxiedECPair.makeRandom() const keyPair = ProxiedECPair.makeRandom()
assert.strictEqual(keyPair.toWIF(), exWIF) assert.strictEqual(keyPair.toWIF(), exWIF)
}) })
}) })
it('allows a custom RNG to be used', function () { it('allows a custom RNG to be used', function () {
let keyPair = ECPair.makeRandom({ const keyPair = ECPair.makeRandom({
rng: function (size) { return d.slice(0, size) } rng: function (size) { return d.slice(0, size) }
}) })
@ -158,14 +158,14 @@ describe('ECPair', function () {
}) })
it('retains the same defaults as ECPair constructor', function () { it('retains the same defaults as ECPair constructor', function () {
let 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', function () {
let keyPair = ECPair.makeRandom({ const keyPair = ECPair.makeRandom({
compressed: false, compressed: false,
network: NETWORKS.testnet network: NETWORKS.testnet
}) })
@ -185,7 +185,7 @@ describe('ECPair', function () {
}) })
it('loops until d is within interval [1, n) : 1', hoodwink(function () { it('loops until d is within interval [1, n) : 1', hoodwink(function () {
let rng = this.stub(function f () { const rng = this.stub(function f () {
if (f.calls === 0) return ZERO // 0 if (f.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 () {
let rng = this.stub(function f () { const rng = this.stub(function f () {
if (f.calls === 0) return ZERO // <1 if (f.calls === 0) return ZERO // <1
if (f.calls === 1) return GROUP_ORDER // >n-1 if (f.calls === 1) return GROUP_ORDER // >n-1
return GROUP_ORDER_LESS_1 // n-1 return GROUP_ORDER_LESS_1 // n-1
@ -207,8 +207,8 @@ describe('ECPair', function () {
describe('.network', function () { describe('.network', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('returns ' + f.network + ' for ' + f.WIF, function () { it('returns ' + f.network + ' for ' + f.WIF, function () {
let network = NETWORKS[f.network] const network = NETWORKS[f.network]
let keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST) const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
assert.strictEqual(keyPair.network, network) assert.strictEqual(keyPair.network, network)
}) })
@ -216,7 +216,9 @@ describe('ECPair', function () {
}) })
describe('tinysecp wrappers', function () { describe('tinysecp wrappers', function () {
let keyPair, hash, signature let keyPair
let hash
let signature
beforeEach(function () { beforeEach(function () {
keyPair = ECPair.makeRandom() keyPair = ECPair.makeRandom()

View file

@ -1,9 +1,9 @@
var assert = require('assert') const assert = require('assert')
var bitcoin = require('../../') const bitcoin = require('../../')
var dhttp = require('dhttp/200') const dhttp = require('dhttp/200')
var APIPASS = process.env.APIPASS || 'satoshi' const APIPASS = process.env.APIPASS || 'satoshi'
var APIURL = 'https://api.dcousens.cloud/1' const APIURL = 'https://api.dcousens.cloud/1'
function broadcast (txHex, callback) { function broadcast (txHex, callback) {
dhttp({ dhttp({
@ -60,7 +60,7 @@ function verify (txo, callback) {
fetch(txo.txId, function (err, tx) { fetch(txo.txId, function (err, tx) {
if (err) return callback(err) if (err) return callback(err)
var txoActual = tx.outs[txo.vout] const txoActual = tx.outs[txo.vout]
if (txo.address) assert.strictEqual(txoActual.address, txo.address) if (txo.address) assert.strictEqual(txoActual.address, txo.address)
if (txo.value) assert.strictEqual(txoActual.value, txo.value) if (txo.value) assert.strictEqual(txoActual.value, txo.value)
callback() callback()
@ -68,8 +68,8 @@ function verify (txo, callback) {
} }
// TODO: remove // TODO: remove
let baddress = bitcoin.address const baddress = bitcoin.address
let bcrypto = bitcoin.crypto const bcrypto = bitcoin.crypto
function getAddress (node, network) { function getAddress (node, network) {
network = network || bitcoin.networks.bitcoin network = network || bitcoin.networks.bitcoin
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash) return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)

View file

@ -1,10 +1,10 @@
/* global describe, it */ /* global describe, it */
let assert = require('assert') const assert = require('assert')
let bitcoin = require('../../') const bitcoin = require('../../')
let dhttp = require('dhttp/200') const dhttp = require('dhttp/200')
let LITECOIN = { const LITECOIN = {
messagePrefix: '\x19Litecoin Signed Message:\n', messagePrefix: '\x19Litecoin Signed Message:\n',
bip32: { bip32: {
public: 0x019da462, public: 0x019da462,
@ -19,8 +19,8 @@ let LITECOIN = {
function rng () { return Buffer.from('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') } function rng () { return Buffer.from('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') }
// TODO: remove // TODO: remove
let baddress = bitcoin.address const baddress = bitcoin.address
let bcrypto = bitcoin.crypto const bcrypto = bitcoin.crypto
function getAddress (node, network) { function getAddress (node, network) {
network = network || bitcoin.networks.bitcoin network = network || bitcoin.networks.bitcoin
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash) return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
@ -28,17 +28,17 @@ function getAddress (node, network) {
describe('bitcoinjs-lib (addresses)', function () { describe('bitcoinjs-lib (addresses)', function () {
it('can generate a random address', function () { it('can generate a random address', function () {
var keyPair = bitcoin.ECPair.makeRandom({ rng: rng }) const keyPair = bitcoin.ECPair.makeRandom({ rng: rng })
var address = getAddress(keyPair) const address = getAddress(keyPair)
assert.strictEqual(address, '1F5VhMHukdnUES9kfXqzPzMeF1GPHKiF64') assert.strictEqual(address, '1F5VhMHukdnUES9kfXqzPzMeF1GPHKiF64')
}) })
it('can generate an address from a SHA256 hash', function () { it('can generate an address from a SHA256 hash', function () {
var hash = bitcoin.crypto.sha256(Buffer.from('correct horse battery staple')) const hash = bitcoin.crypto.sha256(Buffer.from('correct horse battery staple'))
var keyPair = bitcoin.ECPair.fromPrivateKey(hash) const keyPair = bitcoin.ECPair.fromPrivateKey(hash)
var address = getAddress(keyPair) const address = getAddress(keyPair)
// Generating addresses from SHA256 hashes is not secure if the input to the hash function is predictable // Generating addresses from SHA256 hashes is not secure if the input to the hash function is predictable
// Do not use with predictable inputs // Do not use with predictable inputs
@ -46,70 +46,70 @@ describe('bitcoinjs-lib (addresses)', function () {
}) })
it('can import an address via WIF', function () { it('can import an address via WIF', function () {
var keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct') const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
var address = getAddress(keyPair) const address = getAddress(keyPair)
assert.strictEqual(address, '19AAjaTUbRjQCMuVczepkoPswiZRhjtg31') assert.strictEqual(address, '19AAjaTUbRjQCMuVczepkoPswiZRhjtg31')
}) })
it('can generate a 2-of-3 multisig P2SH address', function () { it('can generate a 2-of-3 multisig P2SH address', function () {
var pubKeys = [ const pubKeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9', '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
'03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9' '03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9'
].map(function (hex) { return Buffer.from(hex, 'hex') }) ].map(function (hex) { return Buffer.from(hex, 'hex') })
var redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys) // 2 of 3 const redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys) // 2 of 3
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey) const address = bitcoin.address.fromOutputScript(scriptPubKey)
assert.strictEqual(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7') assert.strictEqual(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7')
}) })
it('can generate a SegWit address', function () { it('can generate a SegWit address', function () {
var keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct') const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
var scriptPubKey = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(keyPair.publicKey)) const scriptPubKey = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(keyPair.publicKey))
var address = bitcoin.address.fromOutputScript(scriptPubKey) const address = bitcoin.address.fromOutputScript(scriptPubKey)
assert.strictEqual(address, 'bc1qt97wqg464zrhnx23upykca5annqvwkwujjglky') assert.strictEqual(address, 'bc1qt97wqg464zrhnx23upykca5annqvwkwujjglky')
}) })
it('can generate a SegWit address (via P2SH)', function () { it('can generate a SegWit address (via P2SH)', function () {
var keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct') const keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
var redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(keyPair.publicKey)) const redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(keyPair.publicKey))
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey) const address = bitcoin.address.fromOutputScript(scriptPubKey)
assert.strictEqual(address, '34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53') assert.strictEqual(address, '34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53')
}) })
it('can generate a SegWit 3-of-4 multisig address', function () { it('can generate a SegWit 3-of-4 multisig address', function () {
var pubKeys = [ const pubKeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9', '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
'023e4740d0ba639e28963f3476157b7cf2fb7c6fdf4254f97099cf8670b505ea59', '023e4740d0ba639e28963f3476157b7cf2fb7c6fdf4254f97099cf8670b505ea59',
'03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9' '03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9'
].map(function (hex) { return Buffer.from(hex, 'hex') }) ].map(function (hex) { return Buffer.from(hex, 'hex') })
var witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys) // 3 of 4 const witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys) // 3 of 4
var scriptPubKey = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript)) const scriptPubKey = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey) const address = bitcoin.address.fromOutputScript(scriptPubKey)
assert.strictEqual(address, 'bc1q75f6dv4q8ug7zhujrsp5t0hzf33lllnr3fe7e2pra3v24mzl8rrqtp3qul') assert.strictEqual(address, 'bc1q75f6dv4q8ug7zhujrsp5t0hzf33lllnr3fe7e2pra3v24mzl8rrqtp3qul')
}) })
it('can generate a SegWit 2-of-2 multisig address (via P2SH)', function () { it('can generate a SegWit 2-of-2 multisig address (via P2SH)', function () {
var pubKeys = [ const pubKeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9' '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9'
].map(function (hex) { return Buffer.from(hex, 'hex') }) ].map(function (hex) { return Buffer.from(hex, 'hex') })
var witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys) // 2 of 2 const witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys) // 2 of 2
var redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript)) const redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey) const address = bitcoin.address.fromOutputScript(scriptPubKey)
assert.strictEqual(address, '3P4mrxQfmExfhxqjLnR2Ah4WES5EB1KBrN') assert.strictEqual(address, '3P4mrxQfmExfhxqjLnR2Ah4WES5EB1KBrN')
}) })
@ -134,19 +134,19 @@ describe('bitcoinjs-lib (addresses)', function () {
// other networks // other networks
it('can generate a Testnet address', function () { it('can generate a Testnet address', function () {
let testnet = bitcoin.networks.testnet const testnet = bitcoin.networks.testnet
let keyPair = bitcoin.ECPair.makeRandom({ network: testnet, rng: rng }) const keyPair = bitcoin.ECPair.makeRandom({ network: testnet, rng: rng })
let wif = keyPair.toWIF() const wif = keyPair.toWIF()
let address = getAddress(keyPair, testnet) const address = getAddress(keyPair, testnet)
assert.strictEqual(address, 'mubSzQNtZfDj1YdNP6pNDuZy6zs6GDn61L') assert.strictEqual(address, 'mubSzQNtZfDj1YdNP6pNDuZy6zs6GDn61L')
assert.strictEqual(wif, 'cRgnQe9MUu1JznntrLaoQpB476M8PURvXVQB5R2eqms5tXnzNsrr') assert.strictEqual(wif, 'cRgnQe9MUu1JznntrLaoQpB476M8PURvXVQB5R2eqms5tXnzNsrr')
}) })
it('can generate a Litecoin address', function () { it('can generate a Litecoin address', function () {
let keyPair = bitcoin.ECPair.makeRandom({ network: LITECOIN, rng: rng }) const keyPair = bitcoin.ECPair.makeRandom({ network: LITECOIN, rng: rng })
let wif = keyPair.toWIF() const wif = keyPair.toWIF()
let address = getAddress(keyPair, LITECOIN) const address = getAddress(keyPair, LITECOIN)
assert.strictEqual(address, 'LZJSxZbjqJ2XVEquqfqHg1RQTDdfST5PTn') assert.strictEqual(address, 'LZJSxZbjqJ2XVEquqfqHg1RQTDdfST5PTn')
assert.strictEqual(wif, 'T7A4PUSgTDHecBxW1ZiYFrDNRih2o7M8Gf9xpoCgudPF9gDiNvuS') assert.strictEqual(wif, 'T7A4PUSgTDHecBxW1ZiYFrDNRih2o7M8Gf9xpoCgudPF9gDiNvuS')

View file

@ -1,13 +1,13 @@
/* global describe, it */ /* global describe, it */
let assert = require('assert') const assert = require('assert')
let bip32 = require('bip32') const bip32 = require('bip32')
let bip39 = require('bip39') const bip39 = require('bip39')
let bitcoin = require('../../') const bitcoin = require('../../')
// TODO: remove // TODO: remove
let baddress = bitcoin.address const baddress = bitcoin.address
let bcrypto = bitcoin.crypto const bcrypto = bitcoin.crypto
function getAddress (node, network) { function getAddress (node, network) {
network = network || bitcoin.networks.bitcoin network = network || bitcoin.networks.bitcoin
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash) return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
@ -15,40 +15,40 @@ function getAddress (node, network) {
describe('bitcoinjs-lib (BIP32)', function () { describe('bitcoinjs-lib (BIP32)', function () {
it('can import a BIP32 testnet xpriv and export to WIF', function () { it('can import a BIP32 testnet xpriv and export to WIF', function () {
var xpriv = 'tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK' const xpriv = 'tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK'
var node = bip32.fromBase58(xpriv, bitcoin.networks.testnet) const node = bip32.fromBase58(xpriv, bitcoin.networks.testnet)
assert.equal(node.toWIF(), 'cQfoY67cetFNunmBUX5wJiw3VNoYx3gG9U9CAofKE6BfiV1fSRw7') assert.equal(node.toWIF(), 'cQfoY67cetFNunmBUX5wJiw3VNoYx3gG9U9CAofKE6BfiV1fSRw7')
}) })
it('can export a BIP32 xpriv, then import it', function () { it('can export a BIP32 xpriv, then import it', function () {
var 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'
var seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeed(mnemonic)
var node = bip32.fromSeed(seed) const node = bip32.fromSeed(seed)
var string = node.toBase58() const string = node.toBase58()
var restored = bip32.fromBase58(string) const restored = bip32.fromBase58(string)
assert.equal(getAddress(node), getAddress(restored)) // same public key assert.equal(getAddress(node), getAddress(restored)) // same public key
assert.equal(node.toWIF(), restored.toWIF()) // same private key assert.equal(node.toWIF(), restored.toWIF()) // same private key
}) })
it('can export a BIP32 xpub', function () { it('can export a BIP32 xpub', function () {
var 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'
var seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeed(mnemonic)
var node = bip32.fromSeed(seed) const node = bip32.fromSeed(seed)
var string = node.neutered().toBase58() const string = node.neutered().toBase58()
assert.equal(string, 'xpub661MyMwAqRbcGhVeaVfEBA25e3cP9DsJQZoE8iep5fZSxy3TnPBNBgWnMZx56oreNc48ZoTkQfatNJ9VWnQ7ZcLZcVStpaXLTeG8bGrzX3n') assert.equal(string, 'xpub661MyMwAqRbcGhVeaVfEBA25e3cP9DsJQZoE8iep5fZSxy3TnPBNBgWnMZx56oreNc48ZoTkQfatNJ9VWnQ7ZcLZcVStpaXLTeG8bGrzX3n')
}) })
it('can create a BIP32, bitcoin, account 0, external address', function () { it('can create a BIP32, bitcoin, account 0, external address', function () {
var path = "m/0'/0/0" const path = "m/0'/0/0"
var root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex')) const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex'))
var child1 = root.derivePath(path) const child1 = root.derivePath(path)
// option 2, manually // option 2, manually
var child1b = root.deriveHardened(0) const child1b = root.deriveHardened(0)
.derive(0) .derive(0)
.derive(0) .derive(0)
@ -57,12 +57,12 @@ describe('bitcoinjs-lib (BIP32)', function () {
}) })
it('can create a BIP44, bitcoin, account 0, external address', function () { it('can create a BIP44, bitcoin, account 0, external address', function () {
var root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex')) const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex'))
var child1 = root.derivePath("m/44'/0'/0'/0/0") const child1 = root.derivePath("m/44'/0'/0'/0/0")
// option 2, manually // option 2, manually
var child1b = root.deriveHardened(44) const child1b = root.deriveHardened(44)
.deriveHardened(0) .deriveHardened(0)
.deriveHardened(0) .deriveHardened(0)
.derive(0) .derive(0)
@ -73,29 +73,29 @@ describe('bitcoinjs-lib (BIP32)', function () {
}) })
it('can create a BIP49, bitcoin testnet, account 0, external address', function () { it('can create a BIP49, bitcoin testnet, account 0, external address', function () {
var 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'
var seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeed(mnemonic)
var root = bip32.fromSeed(seed) const root = bip32.fromSeed(seed)
var path = "m/49'/1'/0'/0/0" const path = "m/49'/1'/0'/0/0"
var child = root.derivePath(path) const child = root.derivePath(path)
var keyhash = bitcoin.crypto.hash160(child.publicKey) const keyhash = bitcoin.crypto.hash160(child.publicKey)
var scriptSig = bitcoin.script.witnessPubKeyHash.output.encode(keyhash) const scriptSig = bitcoin.script.witnessPubKeyHash.output.encode(keyhash)
var addressBytes = bitcoin.crypto.hash160(scriptSig) const addressBytes = bitcoin.crypto.hash160(scriptSig)
var outputScript = bitcoin.script.scriptHash.output.encode(addressBytes) const outputScript = bitcoin.script.scriptHash.output.encode(addressBytes)
var address = bitcoin.address.fromOutputScript(outputScript, bitcoin.networks.testnet) const address = bitcoin.address.fromOutputScript(outputScript, bitcoin.networks.testnet)
assert.equal(address, '2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2') assert.equal(address, '2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2')
}) })
it('can use BIP39 to generate BIP32 addresses', function () { it('can use BIP39 to generate BIP32 addresses', function () {
// var mnemonic = bip39.generateMnemonic() // var mnemonic = bip39.generateMnemonic()
var 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))
var seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeed(mnemonic)
var root = bip32.fromSeed(seed) const root = bip32.fromSeed(seed)
// receive addresses // receive addresses
assert.strictEqual(getAddress(root.derivePath("m/0'/0/0")), '1AVQHbGuES57wD68AJi7Gcobc3RZrfYWTC') assert.strictEqual(getAddress(root.derivePath("m/0'/0/0")), '1AVQHbGuES57wD68AJi7Gcobc3RZrfYWTC')

View file

@ -1,22 +1,22 @@
/* global describe, it */ /* global describe, it */
'use strict' 'use strict'
var assert = require('assert') const assert = require('assert')
var bitcoin = require('../../') const bitcoin = require('../../')
describe('bitcoinjs-lib (blocks)', function () { describe('bitcoinjs-lib (blocks)', function () {
it('can extract a height from a CoinBase transaction', function () { it('can extract a height from a CoinBase transaction', function () {
// from 00000000000000000097669cdca131f24d40c4cc7d80eaa65967a2d09acf6ce6 // from 00000000000000000097669cdca131f24d40c4cc7d80eaa65967a2d09acf6ce6
let txHex = '010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a2b1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98fd16761d220400000000000000aa340000d49f0000ffffffff02b07fc366000000001976a9148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266a24aa21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12bf1e400120000000000000000000000000000000000000000000000000000000000000000000000000' const txHex = '010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a2b1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98fd16761d220400000000000000aa340000d49f0000ffffffff02b07fc366000000001976a9148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266a24aa21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12bf1e400120000000000000000000000000000000000000000000000000000000000000000000000000'
let tx = bitcoin.Transaction.fromHex(txHex) const tx = bitcoin.Transaction.fromHex(txHex)
assert.strictEqual(tx.ins.length, 1) assert.strictEqual(tx.ins.length, 1)
let script = tx.ins[0].script const script = tx.ins[0].script
// bitcoin.script.decompile(script) // returns [] :( // bitcoin.script.decompile(script) // returns [] :(
assert.strictEqual(script[0], 0x03) assert.strictEqual(script[0], 0x03)
let heightBuffer = script.slice(1, 4) const heightBuffer = script.slice(1, 4)
let height = bitcoin.script.number.decode(heightBuffer) const height = bitcoin.script.number.decode(heightBuffer)
assert.strictEqual(height, 498303) assert.strictEqual(height, 498303)
}) })
}) })

View file

@ -1,13 +1,13 @@
/* global describe, it, before */ /* global describe, it, before */
var assert = require('assert') const assert = require('assert')
var bitcoin = require('../../') const bitcoin = require('../../')
var regtestUtils = require('./_regtest') const regtestUtils = require('./_regtest')
var regtest = regtestUtils.network const regtest = regtestUtils.network
var bip65 = require('bip65') const bip65 = require('bip65')
var alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest) const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest)
var 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)', function () {
// force update MTP // force update MTP
@ -15,7 +15,7 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
regtestUtils.mine(11, done) regtestUtils.mine(11, done)
}) })
let hashType = bitcoin.Transaction.SIGHASH_ALL const hashType = bitcoin.Transaction.SIGHASH_ALL
function cltvCheckSigOutput (aQ, bQ, lockTime) { function cltvCheckSigOutput (aQ, bQ, lockTime) {
return bitcoin.script.compile([ return bitcoin.script.compile([
@ -43,24 +43,24 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
this.timeout(30000) this.timeout(30000)
// 3 hours ago // 3 hours ago
let lockTime = bip65.encode({ utc: utcNow() - (3600 * 3) }) const lockTime = bip65.encode({ utc: utcNow() - (3600 * 3) })
let redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime)
let scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
let address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
// fund the P2SH(CLTV) address // fund the P2SH(CLTV) address
regtestUtils.faucet(address, 1e5, function (err, unspent) { regtestUtils.faucet(address, 1e5, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.setLockTime(lockTime) txb.setLockTime(lockTime)
txb.addInput(unspent.txId, unspent.vout, 0xfffffffe) txb.addInput(unspent.txId, unspent.vout, 0xfffffffe)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4)
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
var tx = txb.buildIncomplete() const tx = txb.buildIncomplete()
var signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType)
var redeemScriptSig = bitcoin.script.scriptHash.input.encode([ const redeemScriptSig = bitcoin.script.scriptHash.input.encode([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE
], redeemScript) ], redeemScript)
@ -87,24 +87,24 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
if (err) return done(err) if (err) return done(err)
// 5 blocks from now // 5 blocks from now
var lockTime = bip65.encode({ blocks: height + 5 }) const lockTime = bip65.encode({ blocks: height + 5 })
var redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime)
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
// fund the P2SH(CLTV) address // fund the P2SH(CLTV) address
regtestUtils.faucet(address, 1e5, function (err, unspent) { regtestUtils.faucet(address, 1e5, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.setLockTime(lockTime) txb.setLockTime(lockTime)
txb.addInput(unspent.txId, unspent.vout, 0xfffffffe) txb.addInput(unspent.txId, unspent.vout, 0xfffffffe)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4)
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
var tx = txb.buildIncomplete() const tx = txb.buildIncomplete()
var signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType)
var redeemScriptSig = bitcoin.script.scriptHash.input.encode([ const redeemScriptSig = bitcoin.script.scriptHash.input.encode([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE
], redeemScript) ], redeemScript)
@ -136,24 +136,24 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
this.timeout(30000) this.timeout(30000)
// two hours ago // two hours ago
var lockTime = bip65.encode({ utc: utcNow() - (3600 * 2) }) const lockTime = bip65.encode({ utc: utcNow() - (3600 * 2) })
var redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime)
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
// fund the P2SH(CLTV) address // fund the P2SH(CLTV) address
regtestUtils.faucet(address, 2e5, function (err, unspent) { regtestUtils.faucet(address, 2e5, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.setLockTime(lockTime) txb.setLockTime(lockTime)
txb.addInput(unspent.txId, unspent.vout, 0xfffffffe) txb.addInput(unspent.txId, unspent.vout, 0xfffffffe)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 8e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 8e4)
// {Alice's signature} {Bob's signature} OP_FALSE // {Alice's signature} {Bob's signature} OP_FALSE
var tx = txb.buildIncomplete() const tx = txb.buildIncomplete()
var signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType)
var redeemScriptSig = bitcoin.script.scriptHash.input.encode([ const redeemScriptSig = bitcoin.script.scriptHash.input.encode([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType), bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
bitcoin.opcodes.OP_FALSE bitcoin.opcodes.OP_FALSE
@ -178,24 +178,24 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
this.timeout(30000) this.timeout(30000)
// two hours from now // two hours from now
var lockTime = bip65.encode({ utc: utcNow() + (3600 * 2) }) const lockTime = bip65.encode({ utc: utcNow() + (3600 * 2) })
var redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime)
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
// fund the P2SH(CLTV) address // fund the P2SH(CLTV) address
regtestUtils.faucet(address, 2e4, function (err, unspent) { regtestUtils.faucet(address, 2e4, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.setLockTime(lockTime) txb.setLockTime(lockTime)
txb.addInput(unspent.txId, unspent.vout, 0xfffffffe) txb.addInput(unspent.txId, unspent.vout, 0xfffffffe)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4)
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
var tx = txb.buildIncomplete() const tx = txb.buildIncomplete()
var signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType)
var redeemScriptSig = bitcoin.script.scriptHash.input.encode([ const redeemScriptSig = bitcoin.script.scriptHash.input.encode([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType), bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE

View file

@ -1,32 +1,32 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var bigi = require('bigi') const bigi = require('bigi')
var bitcoin = require('../../') const bitcoin = require('../../')
var bip32 = require('bip32') const bip32 = require('bip32')
var crypto = require('crypto') const crypto = require('crypto')
var tinysecp = require('tiny-secp256k1') const tinysecp = require('tiny-secp256k1')
var ecurve = require('ecurve') const ecurve = require('ecurve')
var secp256k1 = ecurve.getCurveByName('secp256k1') const secp256k1 = ecurve.getCurveByName('secp256k1')
describe('bitcoinjs-lib (crypto)', function () { describe('bitcoinjs-lib (crypto)', function () {
it('can recover a private key from duplicate R values', function () { it('can recover a private key from duplicate R values', function () {
this.timeout(30000) this.timeout(30000)
// https://blockchain.info/tx/f4c16475f2a6e9c602e4a287f9db3040e319eb9ece74761a4b84bc820fbeef50 // https://blockchain.info/tx/f4c16475f2a6e9c602e4a287f9db3040e319eb9ece74761a4b84bc820fbeef50
var tx = bitcoin.Transaction.fromHex('01000000020b668015b32a6178d8524cfef6dc6fc0a4751915c2e9b2ed2d2eab02424341c8000000006a47304402205e00298dc5265b7a914974c9d0298aa0e69a0ca932cb52a360436d6a622e5cd7022024bf5f506968f5f23f1835574d5afe0e9021b4a5b65cf9742332d5e4acb68f41012103fd089f73735129f3d798a657aaaa4aa62a00fa15c76b61fc7f1b27ed1d0f35b8ffffffffa95fa69f11dc1cbb77ef64f25a95d4b12ebda57d19d843333819d95c9172ff89000000006b48304502205e00298dc5265b7a914974c9d0298aa0e69a0ca932cb52a360436d6a622e5cd7022100832176b59e8f50c56631acbc824bcba936c9476c559c42a4468be98975d07562012103fd089f73735129f3d798a657aaaa4aa62a00fa15c76b61fc7f1b27ed1d0f35b8ffffffff02b000eb04000000001976a91472956eed9a8ecb19ae7e3ebd7b06cae4668696a788ac303db000000000001976a9146c0bd55dd2592287cd9992ce3ba3fc1208fb76da88ac00000000') const tx = bitcoin.Transaction.fromHex('01000000020b668015b32a6178d8524cfef6dc6fc0a4751915c2e9b2ed2d2eab02424341c8000000006a47304402205e00298dc5265b7a914974c9d0298aa0e69a0ca932cb52a360436d6a622e5cd7022024bf5f506968f5f23f1835574d5afe0e9021b4a5b65cf9742332d5e4acb68f41012103fd089f73735129f3d798a657aaaa4aa62a00fa15c76b61fc7f1b27ed1d0f35b8ffffffffa95fa69f11dc1cbb77ef64f25a95d4b12ebda57d19d843333819d95c9172ff89000000006b48304502205e00298dc5265b7a914974c9d0298aa0e69a0ca932cb52a360436d6a622e5cd7022100832176b59e8f50c56631acbc824bcba936c9476c559c42a4468be98975d07562012103fd089f73735129f3d798a657aaaa4aa62a00fa15c76b61fc7f1b27ed1d0f35b8ffffffff02b000eb04000000001976a91472956eed9a8ecb19ae7e3ebd7b06cae4668696a788ac303db000000000001976a9146c0bd55dd2592287cd9992ce3ba3fc1208fb76da88ac00000000')
tx.ins.forEach(function (input, vin) { tx.ins.forEach(function (input, vin) {
var script = input.script const script = input.script
var scriptChunks = bitcoin.script.decompile(script) const scriptChunks = bitcoin.script.decompile(script)
assert(bitcoin.script.pubKeyHash.input.check(scriptChunks), 'Expected pubKeyHash script') assert(bitcoin.script.pubKeyHash.input.check(scriptChunks), 'Expected pubKeyHash script')
var prevOutScript = bitcoin.address.toOutputScript('1ArJ9vRaQcoQ29mTWZH768AmRwzb6Zif1z') const prevOutScript = bitcoin.address.toOutputScript('1ArJ9vRaQcoQ29mTWZH768AmRwzb6Zif1z')
var scriptSignature = bitcoin.script.signature.decode(scriptChunks[0]) const scriptSignature = bitcoin.script.signature.decode(scriptChunks[0])
var publicKey = bitcoin.ECPair.fromPublicKey(scriptChunks[1]) const publicKey = bitcoin.ECPair.fromPublicKey(scriptChunks[1])
var m = tx.hashForSignature(vin, prevOutScript, scriptSignature.hashType) const m = tx.hashForSignature(vin, prevOutScript, scriptSignature.hashType)
assert(publicKey.verify(m, scriptSignature.signature), 'Invalid m') assert(publicKey.verify(m, scriptSignature.signature), 'Invalid m')
// store the required information // store the required information
@ -35,34 +35,34 @@ describe('bitcoinjs-lib (crypto)', function () {
}) })
// finally, run the tasks, then on to the math // finally, run the tasks, then on to the math
var n = secp256k1.n const n = secp256k1.n
for (var i = 0; i < tx.ins.length; ++i) { for (var i = 0; i < tx.ins.length; ++i) {
for (var j = i + 1; j < tx.ins.length; ++j) { for (var j = i + 1; j < tx.ins.length; ++j) {
var inputA = tx.ins[i] const inputA = tx.ins[i]
var inputB = tx.ins[j] const inputB = tx.ins[j]
// enforce matching r values // enforce matching r values
let r = inputA.signature.slice(0, 32) const r = inputA.signature.slice(0, 32)
let rB = inputB.signature.slice(0, 32) const rB = inputB.signature.slice(0, 32)
assert.strictEqual(r.toString('hex'), rB.toString('hex')) assert.strictEqual(r.toString('hex'), rB.toString('hex'))
var rInv = bigi.fromBuffer(r).modInverse(n) const rInv = bigi.fromBuffer(r).modInverse(n)
var s1 = bigi.fromBuffer(inputA.signature.slice(32, 64)) const s1 = bigi.fromBuffer(inputA.signature.slice(32, 64))
var s2 = bigi.fromBuffer(inputB.signature.slice(32, 64)) const s2 = bigi.fromBuffer(inputB.signature.slice(32, 64))
var z1 = inputA.z const z1 = inputA.z
var z2 = inputB.z const z2 = inputB.z
var zz = z1.subtract(z2).mod(n) const zz = z1.subtract(z2).mod(n)
var ss = s1.subtract(s2).mod(n) const ss = s1.subtract(s2).mod(n)
// k = (z1 - z2) / (s1 - s2) // k = (z1 - z2) / (s1 - s2)
// d1 = (s1 * k - z1) / r // d1 = (s1 * k - z1) / r
// d2 = (s2 * k - z2) / r // d2 = (s2 * k - z2) / r
var k = zz.multiply(ss.modInverse(n)).mod(n) const k = zz.multiply(ss.modInverse(n)).mod(n)
var d1 = ((s1.multiply(k).mod(n)).subtract(z1).mod(n)).multiply(rInv).mod(n) const d1 = ((s1.multiply(k).mod(n)).subtract(z1).mod(n)).multiply(rInv).mod(n)
var d2 = ((s2.multiply(k).mod(n)).subtract(z2).mod(n)).multiply(rInv).mod(n) const d2 = ((s2.multiply(k).mod(n)).subtract(z2).mod(n)).multiply(rInv).mod(n)
// enforce matching private keys // enforce matching private keys
assert.strictEqual(d1.toString(), d2.toString()) assert.strictEqual(d1.toString(), d2.toString())
@ -75,41 +75,41 @@ describe('bitcoinjs-lib (crypto)', function () {
assert(master.isNeutered(), 'You already have the parent private key') assert(master.isNeutered(), 'You already have the parent private key')
assert(!child.isNeutered(), 'Missing child private key') assert(!child.isNeutered(), 'Missing child private key')
var serQP = master.publicKey const serQP = master.publicKey
var d1 = child.privateKey const d1 = child.privateKey
var d2 const data = Buffer.alloc(37)
var data = Buffer.alloc(37)
serQP.copy(data, 0) serQP.copy(data, 0)
// search index space until we find it // search index space until we find it
let d2
for (var i = 0; i < 0x80000000; ++i) { for (var i = 0; i < 0x80000000; ++i) {
data.writeUInt32BE(i, 33) data.writeUInt32BE(i, 33)
// calculate I // calculate I
var I = crypto.createHmac('sha512', master.chainCode).update(data).digest() const I = crypto.createHmac('sha512', master.chainCode).update(data).digest()
var IL = I.slice(0, 32) const IL = I.slice(0, 32)
// See bip32.js:273 to understand // See bip32.js:273 to understand
d2 = tinysecp.privateSub(d1, IL) d2 = tinysecp.privateSub(d1, IL)
var Qp = bip32.fromPrivateKey(d2, Buffer.alloc(32, 0)).publicKey const Qp = bip32.fromPrivateKey(d2, Buffer.alloc(32, 0)).publicKey
if (Qp.equals(serQP)) break if (Qp.equals(serQP)) break
} }
var node = bip32.fromPrivateKey(d2, master.chainCode, master.network) const node = bip32.fromPrivateKey(d2, master.chainCode, master.network)
node.depth = master.depth node.depth = master.depth
node.index = master.index node.index = master.index
node.masterFingerprint = master.masterFingerprint node.masterFingerprint = master.masterFingerprint
return node return node
} }
var seed = crypto.randomBytes(32) const seed = crypto.randomBytes(32)
var master = bip32.fromSeed(seed) const master = bip32.fromSeed(seed)
var child = master.derive(6) // m/6 const child = master.derive(6) // m/6
// now for the recovery // now for the recovery
var neuteredMaster = master.neutered() const neuteredMaster = master.neutered()
var recovered = recoverParent(neuteredMaster, child) const recovered = recoverParent(neuteredMaster, child)
assert.strictEqual(recovered.toBase58(), master.toBase58()) assert.strictEqual(recovered.toBase58(), master.toBase58())
}) })
}) })

View file

@ -1,13 +1,13 @@
/* global describe, it, before */ /* global describe, it, before */
let assert = require('assert') const assert = require('assert')
let bitcoin = require('../../') const bitcoin = require('../../')
let regtestUtils = require('./_regtest') const regtestUtils = require('./_regtest')
let regtest = regtestUtils.network const regtest = regtestUtils.network
let bip68 = require('bip68') const bip68 = require('bip68')
let alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest) const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest)
let 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)', function () {
// force update MTP // force update MTP
@ -15,7 +15,7 @@ describe('bitcoinjs-lib (transactions w/ CSV)', function () {
regtestUtils.mine(11, done) regtestUtils.mine(11, done)
}) })
let hashType = bitcoin.Transaction.SIGHASH_ALL const hashType = bitcoin.Transaction.SIGHASH_ALL
// IF MTP (from when confirmed) > seconds, aQ can redeem // IF MTP (from when confirmed) > seconds, aQ can redeem
function csvCheckSigOutput (aQ, bQ, sequence) { function csvCheckSigOutput (aQ, bQ, sequence) {
@ -43,23 +43,23 @@ describe('bitcoinjs-lib (transactions w/ CSV)', function () {
if (err) return done(err) if (err) return done(err)
// 5 blocks from now // 5 blocks from now
let sequence = bip68.encode({ blocks: 5 }) const sequence = bip68.encode({ blocks: 5 })
let redeemScript = csvCheckSigOutput(alice, bob, sequence) const redeemScript = csvCheckSigOutput(alice, bob, sequence)
let scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
let address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
// fund the P2SH(CSV) address // fund the P2SH(CSV) address
regtestUtils.faucet(address, 1e5, function (err, unspent) { regtestUtils.faucet(address, 1e5, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
let txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.addInput(unspent.txId, unspent.vout, sequence) txb.addInput(unspent.txId, unspent.vout, sequence)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4)
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
let tx = txb.buildIncomplete() const tx = txb.buildIncomplete()
let signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType)
let redeemScriptSig = bitcoin.script.scriptHash.input.encode([ const redeemScriptSig = bitcoin.script.scriptHash.input.encode([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE
], redeemScript) ], redeemScript)
@ -91,23 +91,23 @@ describe('bitcoinjs-lib (transactions w/ CSV)', function () {
this.timeout(30000) this.timeout(30000)
// two hours after confirmation // two hours after confirmation
let sequence = bip68.encode({ seconds: 7168 }) const sequence = bip68.encode({ seconds: 7168 })
let redeemScript = csvCheckSigOutput(alice, bob, sequence) const redeemScript = csvCheckSigOutput(alice, bob, sequence)
let scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
let address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
// fund the P2SH(CSV) address // fund the P2SH(CSV) address
regtestUtils.faucet(address, 2e4, function (err, unspent) { regtestUtils.faucet(address, 2e4, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
let txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.addInput(unspent.txId, unspent.vout, sequence) txb.addInput(unspent.txId, unspent.vout, sequence)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4)
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
let tx = txb.buildIncomplete() const tx = txb.buildIncomplete()
let signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType)
let redeemScriptSig = bitcoin.script.scriptHash.input.encode([ const redeemScriptSig = bitcoin.script.scriptHash.input.encode([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType), bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE

View file

@ -1,72 +1,72 @@
/* global describe, it */ /* global describe, it */
let assert = require('assert') const assert = require('assert')
let bitcoin = require('../../') const bitcoin = require('../../')
let ecc = require('tiny-secp256k1') const ecc = require('tiny-secp256k1')
// TODO: remove // TODO: remove
let baddress = bitcoin.address const baddress = bitcoin.address
let bcrypto = bitcoin.crypto const bcrypto = bitcoin.crypto
function getAddress (node) { function getAddress (node) {
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), bitcoin.networks.bitcoin.pubKeyHash) return baddress.toBase58Check(bcrypto.hash160(node.publicKey), bitcoin.networks.bitcoin.pubKeyHash)
} }
// vG = (dG \+ sha256(e * dG)G) // vG = (dG \+ sha256(e * dG)G)
function stealthSend (e, Q) { function stealthSend (e, Q) {
var eQ = ecc.pointMultiply(Q, e, true) // shared secret const eQ = ecc.pointMultiply(Q, e, true) // shared secret
var c = bitcoin.crypto.sha256(eQ) const c = bitcoin.crypto.sha256(eQ)
var Qc = ecc.pointAddScalar(Q, c) const Qc = ecc.pointAddScalar(Q, c)
var vG = bitcoin.ECPair.fromPublicKey(Qc) const vG = bitcoin.ECPair.fromPublicKey(Qc)
return vG return vG
} }
// v = (d + sha256(eG * d)) // v = (d + sha256(eG * d))
function stealthReceive (d, eG) { function stealthReceive (d, eG) {
var eQ = ecc.pointMultiply(eG, d) // shared secret const eQ = ecc.pointMultiply(eG, d) // shared secret
var c = bitcoin.crypto.sha256(eQ) const c = bitcoin.crypto.sha256(eQ)
var dc = ecc.privateAdd(d, c) const dc = ecc.privateAdd(d, c)
var v = bitcoin.ECPair.fromPrivateKey(dc) const v = bitcoin.ECPair.fromPrivateKey(dc)
return v return v
} }
// d = (v - sha256(e * dG)) // d = (v - sha256(e * dG))
function stealthRecoverLeaked (v, e, Q) { function stealthRecoverLeaked (v, e, Q) {
var eQ = ecc.pointMultiply(Q, e) // shared secret const eQ = ecc.pointMultiply(Q, e) // shared secret
var c = bitcoin.crypto.sha256(eQ) const c = bitcoin.crypto.sha256(eQ)
var vc = ecc.privateSub(v, c) const vc = ecc.privateSub(v, c)
var d = bitcoin.ECPair.fromPrivateKey(vc) const d = bitcoin.ECPair.fromPrivateKey(vc)
return d return d
} }
// vG = (rG \+ sha256(e * dG)G) // vG = (rG \+ sha256(e * dG)G)
function stealthDualSend (e, R, Q) { function stealthDualSend (e, R, Q) {
var eQ = ecc.pointMultiply(Q, e) // shared secret const eQ = ecc.pointMultiply(Q, e) // shared secret
var c = bitcoin.crypto.sha256(eQ) const c = bitcoin.crypto.sha256(eQ)
var Rc = ecc.pointAddScalar(R, c) const Rc = ecc.pointAddScalar(R, c)
var vG = bitcoin.ECPair.fromPublicKey(Rc) const vG = bitcoin.ECPair.fromPublicKey(Rc)
return vG return vG
} }
// vG = (rG \+ sha256(eG * d)G) // vG = (rG \+ sha256(eG * d)G)
function stealthDualScan (d, R, eG) { function stealthDualScan (d, R, eG) {
var eQ = ecc.pointMultiply(eG, d) // shared secret const eQ = ecc.pointMultiply(eG, d) // shared secret
var c = bitcoin.crypto.sha256(eQ) const c = bitcoin.crypto.sha256(eQ)
var Rc = ecc.pointAddScalar(R, c) const Rc = ecc.pointAddScalar(R, c)
var vG = bitcoin.ECPair.fromPublicKey(Rc) const vG = bitcoin.ECPair.fromPublicKey(Rc)
return vG return vG
} }
// v = (r + sha256(eG * d)) // v = (r + sha256(eG * d))
function stealthDualReceive (d, r, eG) { function stealthDualReceive (d, r, eG) {
var eQ = ecc.pointMultiply(eG, d) // shared secret const eQ = ecc.pointMultiply(eG, d) // shared secret
var c = bitcoin.crypto.sha256(eQ) const c = bitcoin.crypto.sha256(eQ)
var rc = ecc.privateAdd(r, c) const rc = ecc.privateAdd(r, c)
var v = bitcoin.ECPair.fromPrivateKey(rc) const v = bitcoin.ECPair.fromPrivateKey(rc)
return v return v
} }
@ -74,16 +74,16 @@ function stealthDualReceive (d, r, eG) {
describe('bitcoinjs-lib (crypto)', function () { describe('bitcoinjs-lib (crypto)', function () {
it('can generate a single-key stealth address', function () { it('can generate a single-key stealth address', function () {
// XXX: should be randomly generated, see next test for example // XXX: should be randomly generated, see next test for example
var recipient = bitcoin.ECPair.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss') // private to recipient const recipient = bitcoin.ECPair.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss') // private to recipient
var nonce = bitcoin.ECPair.fromWIF('KxVqB96pxbw1pokzQrZkQbLfVBjjHFfp2mFfEp8wuEyGenLFJhM9') // private to sender const nonce = bitcoin.ECPair.fromWIF('KxVqB96pxbw1pokzQrZkQbLfVBjjHFfp2mFfEp8wuEyGenLFJhM9') // private to sender
// ... recipient reveals public key (recipient.Q) to sender // ... recipient reveals public key (recipient.Q) to sender
var forSender = stealthSend(nonce.privateKey, recipient.publicKey) const forSender = stealthSend(nonce.privateKey, recipient.publicKey)
assert.equal(getAddress(forSender), '1CcZWwCpACJL3AxqoDbwEt4JgDFuTHUspE') assert.equal(getAddress(forSender), '1CcZWwCpACJL3AxqoDbwEt4JgDFuTHUspE')
assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/) assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
// ... sender reveals nonce public key (nonce.Q) to recipient // ... sender reveals nonce public key (nonce.Q) to recipient
var forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey) const forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey)
assert.equal(getAddress(forRecipient), '1CcZWwCpACJL3AxqoDbwEt4JgDFuTHUspE') assert.equal(getAddress(forRecipient), '1CcZWwCpACJL3AxqoDbwEt4JgDFuTHUspE')
assert.equal(forRecipient.toWIF(), 'L1yjUN3oYyCXV3LcsBrmxCNTa62bZKWCybxVJMvqjMmmfDE8yk7n') assert.equal(forRecipient.toWIF(), 'L1yjUN3oYyCXV3LcsBrmxCNTa62bZKWCybxVJMvqjMmmfDE8yk7n')
@ -92,15 +92,15 @@ describe('bitcoinjs-lib (crypto)', function () {
}) })
it('can generate a single-key stealth address (randomly)', function () { it('can generate a single-key stealth address (randomly)', function () {
var recipient = bitcoin.ECPair.makeRandom() // private to recipient const recipient = bitcoin.ECPair.makeRandom() // private to recipient
var nonce = bitcoin.ECPair.makeRandom() // private to sender const nonce = bitcoin.ECPair.makeRandom() // private to sender
// ... recipient reveals public key (recipient.Q) to sender // ... recipient reveals public key (recipient.Q) to sender
var forSender = stealthSend(nonce.privateKey, recipient.publicKey) const forSender = stealthSend(nonce.privateKey, recipient.publicKey)
assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/) assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
// ... sender reveals nonce public key (nonce.Q) to recipient // ... sender reveals nonce public key (nonce.Q) to recipient
var forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey) const forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey)
assert.doesNotThrow(function () { forRecipient.toWIF() }) assert.doesNotThrow(function () { forRecipient.toWIF() })
// sender and recipient, both derived same address // sender and recipient, both derived same address
@ -108,38 +108,38 @@ describe('bitcoinjs-lib (crypto)', function () {
}) })
it('can recover parent recipient.d, if a derived private key is leaked [and nonce was revealed]', function () { it('can recover parent recipient.d, if a derived private key is leaked [and nonce was revealed]', function () {
var recipient = bitcoin.ECPair.makeRandom() // private to recipient const recipient = bitcoin.ECPair.makeRandom() // private to recipient
var nonce = bitcoin.ECPair.makeRandom() // private to sender const nonce = bitcoin.ECPair.makeRandom() // private to sender
// ... recipient reveals public key (recipient.Q) to sender // ... recipient reveals public key (recipient.Q) to sender
var forSender = stealthSend(nonce.privateKey, recipient.publicKey) const forSender = stealthSend(nonce.privateKey, recipient.publicKey)
assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/) assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
// ... sender reveals nonce public key (nonce.Q) to recipient // ... sender reveals nonce public key (nonce.Q) to recipient
var forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey) const forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey)
assert.doesNotThrow(function () { forRecipient.toWIF() }) assert.doesNotThrow(function () { forRecipient.toWIF() })
// ... recipient accidentally leaks forRecipient.d on the blockchain // ... recipient accidentally leaks forRecipient.d on the blockchain
var leaked = stealthRecoverLeaked(forRecipient.privateKey, nonce.privateKey, recipient.publicKey) const leaked = stealthRecoverLeaked(forRecipient.privateKey, nonce.privateKey, recipient.publicKey)
assert.equal(leaked.toWIF(), recipient.toWIF()) assert.equal(leaked.toWIF(), recipient.toWIF())
}) })
it('can generate a dual-key stealth address', function () { it('can generate a dual-key stealth address', function () {
// XXX: should be randomly generated, see next test for example // XXX: should be randomly generated, see next test for example
var recipient = bitcoin.ECPair.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss') // private to recipient const recipient = bitcoin.ECPair.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss') // private to recipient
var scan = bitcoin.ECPair.fromWIF('L5DkCk3xLLoGKncqKsWQTdaPSR4V8gzc14WVghysQGkdryRudjBM') // private to scanner/recipient const scan = bitcoin.ECPair.fromWIF('L5DkCk3xLLoGKncqKsWQTdaPSR4V8gzc14WVghysQGkdryRudjBM') // private to scanner/recipient
var nonce = bitcoin.ECPair.fromWIF('KxVqB96pxbw1pokzQrZkQbLfVBjjHFfp2mFfEp8wuEyGenLFJhM9') // private to sender const nonce = bitcoin.ECPair.fromWIF('KxVqB96pxbw1pokzQrZkQbLfVBjjHFfp2mFfEp8wuEyGenLFJhM9') // private to sender
// ... recipient reveals public key(s) (recipient.Q, scan.Q) to sender // ... recipient reveals public key(s) (recipient.Q, scan.Q) to sender
var forSender = stealthDualSend(nonce.privateKey, recipient.publicKey, scan.publicKey) const forSender = stealthDualSend(nonce.privateKey, recipient.publicKey, scan.publicKey)
assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/) assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
// ... sender reveals nonce public key (nonce.Q) to scanner // ... sender reveals nonce public key (nonce.Q) to scanner
var forScanner = stealthDualScan(scan.privateKey, recipient.publicKey, nonce.publicKey) const forScanner = stealthDualScan(scan.privateKey, recipient.publicKey, nonce.publicKey)
assert.throws(function () { forScanner.toWIF() }, /Error: Missing private key/) assert.throws(function () { forScanner.toWIF() }, /Error: Missing private key/)
// ... scanner reveals relevant transaction + nonce public key (nonce.Q) to recipient // ... scanner reveals relevant transaction + nonce public key (nonce.Q) to recipient
var forRecipient = stealthDualReceive(scan.privateKey, recipient.privateKey, nonce.publicKey) const forRecipient = stealthDualReceive(scan.privateKey, recipient.privateKey, nonce.publicKey)
assert.doesNotThrow(function () { forRecipient.toWIF() }) assert.doesNotThrow(function () { forRecipient.toWIF() })
// scanner, sender and recipient, all derived same address // scanner, sender and recipient, all derived same address
@ -148,20 +148,20 @@ describe('bitcoinjs-lib (crypto)', function () {
}) })
it('can generate a dual-key stealth address (randomly)', function () { it('can generate a dual-key stealth address (randomly)', function () {
var recipient = bitcoin.ECPair.makeRandom() // private to recipient const recipient = bitcoin.ECPair.makeRandom() // private to recipient
var scan = bitcoin.ECPair.makeRandom() // private to scanner/recipient const scan = bitcoin.ECPair.makeRandom() // private to scanner/recipient
var nonce = bitcoin.ECPair.makeRandom() // private to sender const nonce = bitcoin.ECPair.makeRandom() // private to sender
// ... recipient reveals public key(s) (recipient.Q, scan.Q) to sender // ... recipient reveals public key(s) (recipient.Q, scan.Q) to sender
var forSender = stealthDualSend(nonce.privateKey, recipient.publicKey, scan.publicKey) const forSender = stealthDualSend(nonce.privateKey, recipient.publicKey, scan.publicKey)
assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/) assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
// ... sender reveals nonce public key (nonce.Q) to scanner // ... sender reveals nonce public key (nonce.Q) to scanner
var forScanner = stealthDualScan(scan.privateKey, recipient.publicKey, nonce.publicKey) const forScanner = stealthDualScan(scan.privateKey, recipient.publicKey, nonce.publicKey)
assert.throws(function () { forScanner.toWIF() }, /Error: Missing private key/) assert.throws(function () { forScanner.toWIF() }, /Error: Missing private key/)
// ... scanner reveals relevant transaction + nonce public key (nonce.Q) to recipient // ... scanner reveals relevant transaction + nonce public key (nonce.Q) to recipient
var forRecipient = stealthDualReceive(scan.privateKey, recipient.privateKey, nonce.publicKey) const forRecipient = stealthDualReceive(scan.privateKey, recipient.privateKey, nonce.publicKey)
assert.doesNotThrow(function () { forRecipient.toWIF() }) assert.doesNotThrow(function () { forRecipient.toWIF() })
// scanner, sender and recipient, all derived same address // scanner, sender and recipient, all derived same address

View file

@ -1,13 +1,13 @@
/* global describe, it */ /* global describe, it */
let assert = require('assert') const assert = require('assert')
let bitcoin = require('../../') const bitcoin = require('../../')
let regtestUtils = require('./_regtest') const regtestUtils = require('./_regtest')
let regtest = regtestUtils.network const regtest = regtestUtils.network
// TODO: remove // TODO: remove
let baddress = bitcoin.address const baddress = bitcoin.address
let bcrypto = bitcoin.crypto const bcrypto = bitcoin.crypto
function getAddress (node, network) { function getAddress (node, network) {
network = network || bitcoin.networks.bitcoin network = network || bitcoin.networks.bitcoin
return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash) return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
@ -19,8 +19,8 @@ function rng () {
describe('bitcoinjs-lib (transactions)', function () { describe('bitcoinjs-lib (transactions)', function () {
it('can create a 1-to-1 Transaction', function () { it('can create a 1-to-1 Transaction', function () {
var alice = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy') const alice = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy')
var txb = new bitcoin.TransactionBuilder() const txb = new bitcoin.TransactionBuilder()
txb.setVersion(1) txb.setVersion(1)
txb.addInput('61d520ccb74288c96bc1a2b20ea1c0d5a704776dd0164a396efec3ea7040349d', 0) // Alice's previous transaction output, has 15000 satoshis txb.addInput('61d520ccb74288c96bc1a2b20ea1c0d5a704776dd0164a396efec3ea7040349d', 0) // Alice's previous transaction output, has 15000 satoshis
@ -34,10 +34,10 @@ describe('bitcoinjs-lib (transactions)', function () {
}) })
it('can create a 2-to-2 Transaction', function () { it('can create a 2-to-2 Transaction', function () {
var alice = bitcoin.ECPair.fromWIF('L1Knwj9W3qK3qMKdTvmg3VfzUs3ij2LETTFhxza9LfD5dngnoLG1') const alice = bitcoin.ECPair.fromWIF('L1Knwj9W3qK3qMKdTvmg3VfzUs3ij2LETTFhxza9LfD5dngnoLG1')
var bob = bitcoin.ECPair.fromWIF('KwcN2pT3wnRAurhy7qMczzbkpY5nXMW2ubh696UBc1bcwctTx26z') const bob = bitcoin.ECPair.fromWIF('KwcN2pT3wnRAurhy7qMczzbkpY5nXMW2ubh696UBc1bcwctTx26z')
var txb = new bitcoin.TransactionBuilder() const txb = new bitcoin.TransactionBuilder()
txb.setVersion(1) txb.setVersion(1)
txb.addInput('b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c', 6) // Alice's previous transaction output, has 200000 satoshis txb.addInput('b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c', 6) // Alice's previous transaction output, has 200000 satoshis
txb.addInput('7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730', 0) // Bob's previous transaction output, has 300000 satoshis txb.addInput('7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730', 0) // Bob's previous transaction output, has 300000 satoshis
@ -55,9 +55,9 @@ describe('bitcoinjs-lib (transactions)', function () {
it('can create (and broadcast via 3PBP) a typical Transaction', function (done) { it('can create (and broadcast via 3PBP) a typical Transaction', function (done) {
this.timeout(30000) this.timeout(30000)
var alice1 = bitcoin.ECPair.makeRandom({ network: regtest }) const alice1 = bitcoin.ECPair.makeRandom({ network: regtest })
var alice2 = bitcoin.ECPair.makeRandom({ network: regtest }) const alice2 = bitcoin.ECPair.makeRandom({ network: regtest })
var aliceChange = bitcoin.ECPair.makeRandom({ network: regtest, rng: rng }) const aliceChange = bitcoin.ECPair.makeRandom({ network: regtest, rng: rng })
// give Alice 2 unspent outputs // give Alice 2 unspent outputs
regtestUtils.faucet(getAddress(alice1, regtest), 5e4, function (err, unspent0) { regtestUtils.faucet(getAddress(alice1, regtest), 5e4, function (err, unspent0) {
@ -66,7 +66,7 @@ describe('bitcoinjs-lib (transactions)', function () {
regtestUtils.faucet(getAddress(alice2, regtest), 7e4, function (err, unspent1) { regtestUtils.faucet(getAddress(alice2, regtest), 7e4, function (err, unspent1) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.addInput(unspent0.txId, unspent0.vout) // alice1 unspent txb.addInput(unspent0.txId, unspent0.vout) // alice1 unspent
txb.addInput(unspent1.txId, unspent1.vout) // alice2 unspent txb.addInput(unspent1.txId, unspent1.vout) // alice2 unspent
txb.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4) // the actual "spend" txb.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4) // the actual "spend"
@ -87,14 +87,14 @@ describe('bitcoinjs-lib (transactions)', function () {
it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', function (done) { it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', function (done) {
this.timeout(30000) this.timeout(30000)
var keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) const keyPair = bitcoin.ECPair.makeRandom({ network: regtest })
regtestUtils.faucet(getAddress(keyPair, regtest), 2e5, function (err, unspent) { regtestUtils.faucet(getAddress(keyPair, regtest), 2e5, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
var data = Buffer.from('bitcoinjs-lib', 'utf8') const data = Buffer.from('bitcoinjs-lib', 'utf8')
var dataScript = bitcoin.script.nullData.output.encode([data]) const dataScript = bitcoin.script.nullData.output.encode([data])
txb.addInput(unspent.txId, unspent.vout) txb.addInput(unspent.txId, unspent.vout)
txb.addOutput(dataScript, 1000) txb.addOutput(dataScript, 1000)
@ -117,20 +117,20 @@ describe('bitcoinjs-lib (transactions)', function () {
] ]
const pubKeys = keyPairs.map(function (x) { return x.publicKey }) const pubKeys = keyPairs.map(function (x) { return x.publicKey })
var redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys) const redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys)
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
regtestUtils.faucet(address, 2e4, function (err, unspent) { regtestUtils.faucet(address, 2e4, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.addInput(unspent.txId, unspent.vout) txb.addInput(unspent.txId, unspent.vout)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4)
txb.sign(0, keyPairs[0], redeemScript) txb.sign(0, keyPairs[0], redeemScript)
txb.sign(0, keyPairs[2], redeemScript) txb.sign(0, keyPairs[2], redeemScript)
var tx = txb.build() const tx = txb.build()
// build and broadcast to the Bitcoin RegTest network // build and broadcast to the Bitcoin RegTest network
regtestUtils.broadcast(tx.toHex(), function (err) { regtestUtils.broadcast(tx.toHex(), function (err) {
@ -152,20 +152,20 @@ describe('bitcoinjs-lib (transactions)', function () {
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) const keyPair = bitcoin.ECPair.makeRandom({ network: regtest })
const pubKeyHash = bitcoin.crypto.hash160(keyPair.publicKey) const pubKeyHash = bitcoin.crypto.hash160(keyPair.publicKey)
var redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(pubKeyHash) const redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(pubKeyHash)
var redeemScriptHash = bitcoin.crypto.hash160(redeemScript) const redeemScriptHash = bitcoin.crypto.hash160(redeemScript)
var scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash) const scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
var address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
regtestUtils.faucet(address, 5e4, function (err, unspent) { regtestUtils.faucet(address, 5e4, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.addInput(unspent.txId, unspent.vout) txb.addInput(unspent.txId, unspent.vout)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4)
txb.sign(0, keyPair, redeemScript, null, unspent.value) txb.sign(0, keyPair, redeemScript, null, unspent.value)
var tx = txb.build() const tx = txb.build()
// build and broadcast to the Bitcoin RegTest network // build and broadcast to the Bitcoin RegTest network
regtestUtils.broadcast(tx.toHex(), function (err) { regtestUtils.broadcast(tx.toHex(), function (err) {
@ -192,22 +192,22 @@ describe('bitcoinjs-lib (transactions)', function () {
] ]
const pubKeys = keyPairs.map(function (x) { return x.publicKey }) const pubKeys = keyPairs.map(function (x) { return x.publicKey })
var witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys) const witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys)
var redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript)) const redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript)) const scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
var address = bitcoin.address.fromOutputScript(scriptPubKey, regtest) const address = bitcoin.address.fromOutputScript(scriptPubKey, regtest)
regtestUtils.faucet(address, 6e4, function (err, unspent) { regtestUtils.faucet(address, 6e4, function (err, unspent) {
if (err) return done(err) if (err) return done(err)
var txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(regtest)
txb.addInput(unspent.txId, unspent.vout) txb.addInput(unspent.txId, unspent.vout)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 3e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 3e4)
txb.sign(0, keyPairs[0], redeemScript, null, unspent.value, witnessScript) txb.sign(0, keyPairs[0], redeemScript, null, unspent.value, witnessScript)
txb.sign(0, keyPairs[2], redeemScript, null, unspent.value, witnessScript) txb.sign(0, keyPairs[2], redeemScript, null, unspent.value, witnessScript)
txb.sign(0, keyPairs[3], redeemScript, null, unspent.value, witnessScript) txb.sign(0, keyPairs[3], redeemScript, null, unspent.value, witnessScript)
var tx = txb.build() const tx = txb.build()
// build and broadcast to the Bitcoin RegTest network // build and broadcast to the Bitcoin RegTest network
regtestUtils.broadcast(tx.toHex(), function (err) { regtestUtils.broadcast(tx.toHex(), function (err) {
@ -224,21 +224,21 @@ describe('bitcoinjs-lib (transactions)', function () {
}) })
it('can verify Transaction signatures', function () { it('can verify Transaction signatures', function () {
var txHex = '010000000321c5f7e7bc98b3feda84aad36a5c99a02bcb8823a2f3eccbcd5da209698b5c20000000006b48304502210099e021772830207cf7c55b69948d3b16b4dcbf1f55a9cd80ebf8221a169735f9022064d33f11d62cd28240b3862afc0b901adc9f231c7124dd19bdb30367b61964c50121032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63dffffffff8a75ce85441ddb3f342708ee33cc8ed418b07d9ba9e0e7c4e1cccfe9f52d8a88000000006946304302207916c23dae212c95a920423902fa44e939fb3d542f4478a7b46e9cde53705800021f0d74e9504146e404c1b8f9cba4dff2d4782e3075491c9ed07ce4a7d1c4461a01210216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2affffffffdfef93f69fe32e944fad79fa8f882b3a155d80383252348caba1a77a5abbf7ef000000006b483045022100faa6e9ca289b46c64764a624c59ac30d9abcf1d4a04c4de9089e67cbe0d300a502206930afa683f6807502de5c2431bf9a1fd333c8a2910a76304df0f3d23d83443f0121039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18fffffffff01ff4b0000000000001976a9146c86476d1d85cd60116cd122a274e6a570a5a35c88acc96d0700' const txHex = '010000000321c5f7e7bc98b3feda84aad36a5c99a02bcb8823a2f3eccbcd5da209698b5c20000000006b48304502210099e021772830207cf7c55b69948d3b16b4dcbf1f55a9cd80ebf8221a169735f9022064d33f11d62cd28240b3862afc0b901adc9f231c7124dd19bdb30367b61964c50121032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63dffffffff8a75ce85441ddb3f342708ee33cc8ed418b07d9ba9e0e7c4e1cccfe9f52d8a88000000006946304302207916c23dae212c95a920423902fa44e939fb3d542f4478a7b46e9cde53705800021f0d74e9504146e404c1b8f9cba4dff2d4782e3075491c9ed07ce4a7d1c4461a01210216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2affffffffdfef93f69fe32e944fad79fa8f882b3a155d80383252348caba1a77a5abbf7ef000000006b483045022100faa6e9ca289b46c64764a624c59ac30d9abcf1d4a04c4de9089e67cbe0d300a502206930afa683f6807502de5c2431bf9a1fd333c8a2910a76304df0f3d23d83443f0121039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18fffffffff01ff4b0000000000001976a9146c86476d1d85cd60116cd122a274e6a570a5a35c88acc96d0700'
var keyPairs = [ const keyPairs = [
'032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d', '032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d',
'0216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2a', '0216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2a',
'039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18f' '039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18f'
].map(function (q) { return bitcoin.ECPair.fromPublicKey(Buffer.from(q, 'hex')) }) ].map(function (q) { return bitcoin.ECPair.fromPublicKey(Buffer.from(q, 'hex')) })
var tx = bitcoin.Transaction.fromHex(txHex) const tx = bitcoin.Transaction.fromHex(txHex)
tx.ins.forEach(function (input, i) { tx.ins.forEach(function (input, i) {
var keyPair = keyPairs[i] const keyPair = keyPairs[i]
var prevOutScript = bitcoin.address.toOutputScript(getAddress(keyPair)) const prevOutScript = bitcoin.address.toOutputScript(getAddress(keyPair))
var scriptSig = bitcoin.script.pubKeyHash.input.decode(input.script) const scriptSig = bitcoin.script.pubKeyHash.input.decode(input.script)
var ss = bitcoin.script.signature.decode(scriptSig.signature) const ss = bitcoin.script.signature.decode(scriptSig.signature)
var hash = tx.hashForSignature(i, prevOutScript, ss.hashType) const hash = tx.hashForSignature(i, prevOutScript, ss.hashType)
assert.strictEqual(scriptSig.pubKey.toString('hex'), keyPair.publicKey.toString('hex')) assert.strictEqual(scriptSig.pubKey.toString('hex'), keyPair.publicKey.toString('hex'))
assert.strictEqual(keyPair.verify(hash, ss.signature), true) assert.strictEqual(keyPair.verify(hash, ss.signature), true)

View file

@ -1,11 +1,11 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var bscript = require('../src/script') const bscript = require('../src/script')
var minimalData = require('minimaldata') const minimalData = require('minimaldata')
var fixtures = require('./fixtures/script.json') const fixtures = require('./fixtures/script.json')
var fixtures2 = require('./fixtures/templates.json') const fixtures2 = require('./fixtures/templates.json')
describe('script', function () { describe('script', function () {
// TODO // TODO
@ -25,7 +25,7 @@ describe('script', function () {
describe('fromASM/toASM', function () { describe('fromASM/toASM', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('encodes/decodes ' + f.asm, function () { it('encodes/decodes ' + f.asm, function () {
var 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)
}) })
}) })
@ -42,10 +42,10 @@ describe('script', function () {
describe('fromASM/toASM (templates)', function () { describe('fromASM/toASM (templates)', function () {
fixtures2.valid.forEach(function (f) { fixtures2.valid.forEach(function (f) {
if (f.inputHex) { if (f.inputHex) {
var 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, function () {
var 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)
}) })
@ -53,7 +53,7 @@ describe('script', function () {
if (f.outputHex) { if (f.outputHex) {
it('encodes/decodes ' + f.output, function () { it('encodes/decodes ' + f.output, function () {
var 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)
}) })
@ -64,8 +64,8 @@ describe('script', function () {
describe('isPushOnly', function () { describe('isPushOnly', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('returns ' + !!f.stack + ' for ' + f.asm, function () { it('returns ' + !!f.stack + ' for ' + f.asm, function () {
var script = bscript.fromASM(f.asm) const script = bscript.fromASM(f.asm)
var chunks = bscript.decompile(script) const chunks = bscript.decompile(script)
assert.strictEqual(bscript.isPushOnly(chunks), !!f.stack) assert.strictEqual(bscript.isPushOnly(chunks), !!f.stack)
}) })
@ -77,9 +77,9 @@ describe('script', function () {
it('returns ' + !!f.stack + ' for ' + f.asm, function () { it('returns ' + !!f.stack + ' for ' + f.asm, function () {
if (!f.stack || !f.asm) return if (!f.stack || !f.asm) return
var script = bscript.fromASM(f.asm) const script = bscript.fromASM(f.asm)
var stack = bscript.toStack(script) const stack = bscript.toStack(script)
assert.deepEqual(stack.map(function (x) { assert.deepEqual(stack.map(function (x) {
return x.toString('hex') return x.toString('hex')
}), f.stack) }), f.stack)
@ -92,12 +92,12 @@ describe('script', function () {
describe('compile (via fromASM)', function () { describe('compile (via fromASM)', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('(' + f.type + ') compiles ' + f.asm, function () { it('(' + f.type + ') compiles ' + f.asm, function () {
var 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)
if (f.nonstandard) { if (f.nonstandard) {
var scriptSigNS = bscript.fromASM(f.nonstandard.scriptSig) const scriptSigNS = bscript.fromASM(f.nonstandard.scriptSig)
assert.strictEqual(scriptSigNS.toString('hex'), f.script) assert.strictEqual(scriptSigNS.toString('hex'), f.script)
} }
@ -108,13 +108,13 @@ describe('script', function () {
describe('decompile', function () { describe('decompile', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('decompiles ' + f.asm, function () { it('decompiles ' + f.asm, function () {
var 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)
assert.strictEqual(bscript.toASM(chunks), f.asm) assert.strictEqual(bscript.toASM(chunks), f.asm)
if (f.nonstandard) { if (f.nonstandard) {
var chunksNS = bscript.decompile(Buffer.from(f.nonstandard.scriptSigHex, 'hex')) const chunksNS = bscript.decompile(Buffer.from(f.nonstandard.scriptSigHex, 'hex'))
assert.strictEqual(bscript.compile(chunksNS).toString('hex'), f.script) assert.strictEqual(bscript.compile(chunksNS).toString('hex'), f.script)
@ -126,7 +126,7 @@ describe('script', function () {
fixtures.invalid.decompile.forEach(function (f) { fixtures.invalid.decompile.forEach(function (f) {
it('fails to decompile ' + f.script + ', because "' + f.description + '"', function () { it('fails to decompile ' + f.script + ', because "' + f.description + '"', function () {
var 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)
}) })
@ -136,7 +136,7 @@ describe('script', function () {
describe('SCRIPT_VERIFY_MINIMALDATA policy', function () { describe('SCRIPT_VERIFY_MINIMALDATA policy', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('compliant for ' + f.type + ' scriptSig ' + f.asm, function () { it('compliant for ' + f.type + ' scriptSig ' + f.asm, function () {
var script = Buffer.from(f.script, 'hex') const script = Buffer.from(f.script, 'hex')
assert(minimalData(script)) assert(minimalData(script))
}) })
@ -144,8 +144,8 @@ 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, function () {
var buffer = Buffer.alloc(i) const buffer = Buffer.alloc(i)
var script = bscript.compile([buffer]) const script = bscript.compile([buffer])
assert(minimalData(script), 'Failed for ' + i + ' length script: ' + script.toString('hex')) assert(minimalData(script), 'Failed for ' + i + ' length script: ' + script.toString('hex'))
}) })

View file

@ -1,14 +1,14 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var scriptNumber = require('../src/script_number') const scriptNumber = require('../src/script_number')
var fixtures = require('./fixtures/script_number.json') const fixtures = require('./fixtures/script_number.json')
describe('script-number', function () { describe('script-number', function () {
describe('decode', function () { describe('decode', function () {
fixtures.forEach(function (f) { fixtures.forEach(function (f) {
it(f.hex + ' returns ' + f.number, function () { it(f.hex + ' returns ' + f.number, function () {
var 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)
}) })
@ -18,7 +18,7 @@ describe('script-number', function () {
describe('encode', function () { describe('encode', function () {
fixtures.forEach(function (f) { fixtures.forEach(function (f) {
it(f.number + ' returns ' + f.hex, function () { it(f.number + ' returns ' + f.hex, function () {
var 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

@ -1,9 +1,9 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var bscriptSig = require('../src/script').signature const bscriptSig = require('../src/script').signature
var Buffer = require('safe-buffer').Buffer const Buffer = require('safe-buffer').Buffer
var fixtures = require('./fixtures/signature.json') const fixtures = require('./fixtures/signature.json')
describe('Script Signatures', function () { describe('Script Signatures', function () {
function fromRaw (signature) { function fromRaw (signature) {
@ -23,7 +23,7 @@ describe('Script Signatures', function () {
describe('encode', function () { describe('encode', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('encodes ' + f.hex, function () { it('encodes ' + f.hex, function () {
var 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)
}) })
@ -33,7 +33,7 @@ describe('Script Signatures', function () {
if (!f.raw) return if (!f.raw) return
it('throws ' + f.exception, function () { it('throws ' + f.exception, function () {
var signature = fromRaw(f.raw) const signature = fromRaw(f.raw)
assert.throws(function () { assert.throws(function () {
bscriptSig.encode(signature, f.hashType) bscriptSig.encode(signature, f.hashType)
@ -45,7 +45,7 @@ describe('Script Signatures', function () {
describe('decode', function () { describe('decode', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('decodes ' + f.hex, function () { it('decodes ' + f.hex, function () {
var 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.deepEqual(toRaw(decode.signature), f.raw)
assert.strictEqual(decode.hashType, f.hashType) assert.strictEqual(decode.hashType, f.hashType)
@ -54,7 +54,7 @@ describe('Script Signatures', function () {
fixtures.invalid.forEach(function (f) { fixtures.invalid.forEach(function (f) {
it('throws on ' + f.hex, function () { it('throws on ' + f.hex, function () {
var buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex')
assert.throws(function () { assert.throws(function () {
bscriptSig.decode(buffer) bscriptSig.decode(buffer)

View file

@ -1,12 +1,12 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var bcrypto = require('../src/crypto') const bcrypto = require('../src/crypto')
var bscript = require('../src/script') const bscript = require('../src/script')
var btemplates = require('../src/templates') const btemplates = require('../src/templates')
var ops = require('bitcoin-ops') const ops = require('bitcoin-ops')
var fixtures = require('./fixtures/templates.json') const fixtures = require('./fixtures/templates.json')
function fromHex (x) { return Buffer.from(x, 'hex') } function fromHex (x) { return Buffer.from(x, 'hex') }
function toHex (x) { return x.toString('hex') } function toHex (x) { return x.toString('hex') }
@ -17,8 +17,8 @@ describe('script-templates', function () {
if (!f.input) return if (!f.input) return
it('classifies ' + f.input + ' as ' + f.type, function () { it('classifies ' + f.input + ' as ' + f.type, function () {
var input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input)
var type = btemplates.classifyInput(input) const type = btemplates.classifyInput(input)
assert.strictEqual(type, f.type) assert.strictEqual(type, f.type)
}) })
@ -29,8 +29,8 @@ describe('script-templates', function () {
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, function () {
var input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input)
var type = btemplates.classifyInput(input, true) const type = btemplates.classifyInput(input, true)
assert.strictEqual(type, f.typeIncomplete) assert.strictEqual(type, f.typeIncomplete)
}) })
@ -42,8 +42,8 @@ describe('script-templates', function () {
if (!f.output) return if (!f.output) return
it('classifies ' + f.output + ' as ' + f.type, function () { it('classifies ' + f.output + ' as ' + f.type, function () {
var output = bscript.fromASM(f.output) const output = bscript.fromASM(f.output)
var type = btemplates.classifyOutput(output) const type = btemplates.classifyOutput(output)
assert.strictEqual(type, f.type) assert.strictEqual(type, f.type)
}) })
@ -60,24 +60,24 @@ describe('script-templates', function () {
'nullData', 'nullData',
'witnessCommitment' 'witnessCommitment'
].forEach(function (name) { ].forEach(function (name) {
var inputType = btemplates[name].input const inputType = btemplates[name].input
var outputType = btemplates[name].output const outputType = btemplates[name].output
describe(name + '.input.check', function () { describe(name + '.input.check', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (name.toLowerCase() === btemplates.types.P2WPKH) return if (name.toLowerCase() === btemplates.types.P2WPKH) return
if (name.toLowerCase() === btemplates.types.P2WSH) return if (name.toLowerCase() === btemplates.types.P2WSH) return
var expected = name.toLowerCase() === f.type.toLowerCase() const expected = name.toLowerCase() === f.type.toLowerCase()
if (inputType && f.input) { if (inputType && f.input) {
var input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input)
it('returns ' + expected + ' for ' + f.input, function () { it('returns ' + expected + ' for ' + f.input, function () {
assert.strictEqual(inputType.check(input), expected) assert.strictEqual(inputType.check(input), expected)
}) })
if (f.typeIncomplete) { if (f.typeIncomplete) {
var expectedIncomplete = name.toLowerCase() === f.typeIncomplete const expectedIncomplete = name.toLowerCase() === f.typeIncomplete
it('returns ' + expected + ' for ' + f.input, function () { it('returns ' + expected + ' for ' + f.input, function () {
assert.strictEqual(inputType.check(input, true), expectedIncomplete) assert.strictEqual(inputType.check(input, true), expectedIncomplete)
@ -92,7 +92,7 @@ describe('script-templates', function () {
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) + ')', function () {
var input let input
if (f.input) { if (f.input) {
input = bscript.fromASM(f.input) input = bscript.fromASM(f.input)
@ -107,11 +107,11 @@ describe('script-templates', function () {
describe(name + '.output.check', function () { describe(name + '.output.check', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
var 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, function () {
var output = bscript.fromASM(f.output) const output = bscript.fromASM(f.output)
if (name.toLowerCase() === 'nulldata' && f.type === btemplates.types.WITNESS_COMMITMENT) return if (name.toLowerCase() === 'nulldata' && f.type === btemplates.types.WITNESS_COMMITMENT) return
if (name.toLowerCase() === 'witnesscommitment' && f.type === btemplates.types.NULLDATA) return if (name.toLowerCase() === 'witnesscommitment' && f.type === btemplates.types.NULLDATA) return
@ -126,7 +126,7 @@ describe('script-templates', function () {
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) + ')', function () {
var output let output
if (f.output) { if (f.output) {
output = bscript.fromASM(f.output) output = bscript.fromASM(f.output)
@ -144,8 +144,8 @@ describe('script-templates', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.type !== 'pubkey') return if (f.type !== 'pubkey') return
var signature = Buffer.from(f.signature, 'hex') const signature = Buffer.from(f.signature, 'hex')
var input = btemplates.pubKey.input.encode(signature) const input = btemplates.pubKey.input.encode(signature)
it('encodes to ' + f.input, function () { it('encodes to ' + f.input, function () {
assert.strictEqual(bscript.toASM(input), f.input) assert.strictEqual(bscript.toASM(input), f.input)
@ -161,8 +161,8 @@ describe('script-templates', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.type !== 'pubkey') return if (f.type !== 'pubkey') return
var pubKey = Buffer.from(f.pubKey, 'hex') const pubKey = Buffer.from(f.pubKey, 'hex')
var output = btemplates.pubKey.output.encode(pubKey) const output = btemplates.pubKey.output.encode(pubKey)
it('encodes to ' + f.output, function () { it('encodes to ' + f.output, function () {
assert.strictEqual(bscript.toASM(output), f.output) assert.strictEqual(bscript.toASM(output), f.output)
@ -178,9 +178,9 @@ describe('script-templates', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.type !== 'pubkeyhash') return if (f.type !== 'pubkeyhash') return
var pubKey = Buffer.from(f.pubKey, 'hex') const pubKey = Buffer.from(f.pubKey, 'hex')
var signature = Buffer.from(f.signature, 'hex') const signature = Buffer.from(f.signature, 'hex')
var input = btemplates.pubKeyHash.input.encode(signature, pubKey) const input = btemplates.pubKeyHash.input.encode(signature, pubKey)
it('encodes to ' + f.input, function () { it('encodes to ' + f.input, function () {
assert.strictEqual(bscript.toASM(input), f.input) assert.strictEqual(bscript.toASM(input), f.input)
@ -199,9 +199,9 @@ describe('script-templates', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.type !== 'pubkeyhash') return if (f.type !== 'pubkeyhash') return
var pubKey = Buffer.from(f.pubKey, 'hex') const pubKey = Buffer.from(f.pubKey, 'hex')
var pubKeyHash = bcrypto.hash160(pubKey) const pubKeyHash = bcrypto.hash160(pubKey)
var output = btemplates.pubKeyHash.output.encode(pubKeyHash) const output = btemplates.pubKeyHash.output.encode(pubKeyHash)
it('encodes to ' + f.output, function () { it('encodes to ' + f.output, function () {
assert.strictEqual(bscript.toASM(output), f.output) assert.strictEqual(bscript.toASM(output), f.output)
@ -214,7 +214,7 @@ describe('script-templates', function () {
fixtures.invalid.pubKeyHash.outputs.forEach(function (f) { fixtures.invalid.pubKeyHash.outputs.forEach(function (f) {
if (!f.hash) return if (!f.hash) return
var hash = Buffer.from(f.hash, 'hex') const hash = Buffer.from(f.hash, 'hex')
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, function () {
assert.throws(function () { assert.throws(function () {
@ -227,13 +227,13 @@ describe('script-templates', function () {
describe('multisig.input', function () { describe('multisig.input', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.type !== 'multisig' && f.typeIncomplete !== 'multisig') return if (f.type !== 'multisig' && f.typeIncomplete !== 'multisig') return
var allowIncomplete = f.typeIncomplete !== undefined const allowIncomplete = f.typeIncomplete !== undefined
var signatures = f.signatures.map(function (signature) { const signatures = f.signatures.map(function (signature) {
return signature ? Buffer.from(signature, 'hex') : ops.OP_0 return signature ? Buffer.from(signature, 'hex') : ops.OP_0
}) })
var input = btemplates.multisig.input.encode(signatures) const input = btemplates.multisig.input.encode(signatures)
it('encodes to ' + f.input, function () { it('encodes to ' + f.input, function () {
assert.strictEqual(bscript.toASM(input), f.input) assert.strictEqual(bscript.toASM(input), f.input)
@ -246,10 +246,10 @@ describe('script-templates', function () {
fixtures.invalid.multisig.inputs.forEach(function (f) { fixtures.invalid.multisig.inputs.forEach(function (f) {
if (!f.output) return if (!f.output) return
var output = bscript.fromASM(f.output) const output = bscript.fromASM(f.output)
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, function () {
var signatures = f.signatures.map(function (signature) { const signatures = f.signatures.map(function (signature) {
return signature ? Buffer.from(signature, 'hex') : ops.OP_0 return signature ? Buffer.from(signature, 'hex') : ops.OP_0
}) })
@ -264,10 +264,10 @@ describe('script-templates', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.type !== 'multisig') return if (f.type !== 'multisig') return
var pubKeys = f.pubKeys.map(function (p) { return Buffer.from(p, 'hex') }) const pubKeys = f.pubKeys.map(function (p) { return Buffer.from(p, 'hex') })
var m = pubKeys.length const m = pubKeys.length
var output = btemplates.multisig.output.encode(m, pubKeys) const output = btemplates.multisig.output.encode(m, pubKeys)
it('encodes ' + f.output, function () { it('encodes ' + f.output, function () {
assert.strictEqual(bscript.toASM(output), f.output) assert.strictEqual(bscript.toASM(output), f.output)
@ -283,7 +283,7 @@ describe('script-templates', function () {
fixtures.invalid.multisig.outputs.forEach(function (f) { fixtures.invalid.multisig.outputs.forEach(function (f) {
if (!f.pubKeys) return if (!f.pubKeys) return
var pubKeys = f.pubKeys.map(function (p) { const pubKeys = f.pubKeys.map(function (p) {
return Buffer.from(p, 'hex') return Buffer.from(p, 'hex')
}) })
@ -299,9 +299,9 @@ describe('script-templates', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.type !== 'scripthash') return if (f.type !== 'scripthash') return
var redeemScriptSig = bscript.fromASM(f.redeemScriptSig) const redeemScriptSig = bscript.fromASM(f.redeemScriptSig)
var redeemScript = bscript.fromASM(f.redeemScript) const redeemScript = bscript.fromASM(f.redeemScript)
var input = btemplates.scriptHash.input.encode(redeemScriptSig, redeemScript) const input = btemplates.scriptHash.input.encode(redeemScriptSig, redeemScript)
it('encodes to ' + f.output, function () { it('encodes to ' + f.output, function () {
if (f.input) { if (f.input) {
@ -325,9 +325,9 @@ describe('script-templates', function () {
if (f.type !== 'scripthash') return if (f.type !== 'scripthash') return
if (!f.output) return if (!f.output) return
var redeemScript = bscript.fromASM(f.redeemScript) const redeemScript = bscript.fromASM(f.redeemScript)
var scriptHash = bcrypto.hash160(redeemScript) const scriptHash = bcrypto.hash160(redeemScript)
var output = btemplates.scriptHash.output.encode(scriptHash) const output = btemplates.scriptHash.output.encode(scriptHash)
it('encodes to ' + f.output, function () { it('encodes to ' + f.output, function () {
assert.strictEqual(bscript.toASM(output), f.output) assert.strictEqual(bscript.toASM(output), f.output)
@ -340,7 +340,7 @@ describe('script-templates', function () {
fixtures.invalid.scriptHash.outputs.forEach(function (f) { fixtures.invalid.scriptHash.outputs.forEach(function (f) {
if (!f.hash) return if (!f.hash) return
var hash = Buffer.from(f.hash, 'hex') const hash = Buffer.from(f.hash, 'hex')
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, function () {
assert.throws(function () { assert.throws(function () {
@ -355,17 +355,17 @@ describe('script-templates', function () {
if (f.type !== 'pubkeyhash' && f.type !== 'witnesspubkeyhash') return if (f.type !== 'pubkeyhash' && f.type !== 'witnesspubkeyhash') return
if (!f.inputStack) return if (!f.inputStack) return
var pubKey = Buffer.from(f.pubKey, 'hex') const pubKey = Buffer.from(f.pubKey, 'hex')
var signature = Buffer.from(f.signature, 'hex') const signature = Buffer.from(f.signature, 'hex')
it('encodes to ' + f.input, function () { it('encodes to ' + f.input, function () {
var inputStack = btemplates.witnessPubKeyHash.input.encodeStack(signature, pubKey) const inputStack = btemplates.witnessPubKeyHash.input.encodeStack(signature, pubKey)
assert.deepEqual(inputStack.map(toHex), f.inputStack) assert.deepEqual(inputStack.map(toHex), f.inputStack)
}) })
it('decodes to original arguments', function () { it('decodes to original arguments', function () {
var fInputStack = f.inputStack.map(fromHex) const fInputStack = f.inputStack.map(fromHex)
assert.deepEqual(btemplates.witnessPubKeyHash.input.decodeStack(fInputStack), { assert.deepEqual(btemplates.witnessPubKeyHash.input.decodeStack(fInputStack), {
signature: signature, signature: signature,
@ -380,9 +380,9 @@ describe('script-templates', function () {
if (f.type !== 'witnesspubkeyhash') return if (f.type !== 'witnesspubkeyhash') return
if (!f.output) return if (!f.output) return
var pubKey = Buffer.from(f.pubKey, 'hex') const pubKey = Buffer.from(f.pubKey, 'hex')
var pubKeyHash = bcrypto.hash160(pubKey) const pubKeyHash = bcrypto.hash160(pubKey)
var output = btemplates.witnessPubKeyHash.output.encode(pubKeyHash) const output = btemplates.witnessPubKeyHash.output.encode(pubKeyHash)
it('encodes to ' + f.output, function () { it('encodes to ' + f.output, function () {
assert.strictEqual(bscript.toASM(output), f.output) assert.strictEqual(bscript.toASM(output), f.output)
@ -395,7 +395,7 @@ describe('script-templates', function () {
fixtures.invalid.witnessPubKeyHash.outputs.forEach(function (f) { fixtures.invalid.witnessPubKeyHash.outputs.forEach(function (f) {
if (!f.hash) return if (!f.hash) return
var hash = Buffer.from(f.hash, 'hex') const hash = Buffer.from(f.hash, 'hex')
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, function () {
assert.throws(function () { assert.throws(function () {
@ -410,17 +410,17 @@ describe('script-templates', function () {
if (f.type !== 'witnessscripthash') return if (f.type !== 'witnessscripthash') return
if (!f.inputStack || !f.witnessData) return if (!f.inputStack || !f.witnessData) return
var witnessData = f.witnessData.map(fromHex) const witnessData = f.witnessData.map(fromHex)
var witnessScript = bscript.fromASM(f.witnessScript || f.redeemScript) const witnessScript = bscript.fromASM(f.witnessScript || f.redeemScript)
it('encodes to ' + f.input, function () { it('encodes to ' + f.input, function () {
var inputStack = btemplates.witnessScriptHash.input.encodeStack(witnessData, witnessScript) const inputStack = btemplates.witnessScriptHash.input.encodeStack(witnessData, witnessScript)
assert.deepEqual(inputStack.map(toHex), f.inputStack) assert.deepEqual(inputStack.map(toHex), f.inputStack)
}) })
it('decodes to original arguments', function () { it('decodes to original arguments', function () {
var result = btemplates.witnessScriptHash.input.decodeStack(f.inputStack.map(fromHex)) const result = btemplates.witnessScriptHash.input.decodeStack(f.inputStack.map(fromHex))
assert.deepEqual(result.witnessData.map(toHex), f.witnessData) assert.deepEqual(result.witnessData.map(toHex), f.witnessData)
assert.strictEqual(bscript.toASM(result.witnessScript), f.witnessScript) assert.strictEqual(bscript.toASM(result.witnessScript), f.witnessScript)
@ -433,9 +433,9 @@ describe('script-templates', function () {
if (f.type !== 'witnessscripthash') return if (f.type !== 'witnessscripthash') return
if (!f.output) return if (!f.output) return
var witnessScriptPubKey = bscript.fromASM(f.witnessScript) const witnessScriptPubKey = bscript.fromASM(f.witnessScript)
var scriptHash = bcrypto.hash256(witnessScriptPubKey) const scriptHash = bcrypto.hash256(witnessScriptPubKey)
var output = btemplates.witnessScriptHash.output.encode(scriptHash) const output = btemplates.witnessScriptHash.output.encode(scriptHash)
it('encodes to ' + f.output, function () { it('encodes to ' + f.output, function () {
assert.strictEqual(bscript.toASM(output), f.output) assert.strictEqual(bscript.toASM(output), f.output)
@ -448,7 +448,7 @@ describe('script-templates', function () {
fixtures.invalid.witnessScriptHash.outputs.forEach(function (f) { fixtures.invalid.witnessScriptHash.outputs.forEach(function (f) {
if (!f.hash) return if (!f.hash) return
var hash = Buffer.from(f.hash, 'hex') const hash = Buffer.from(f.hash, 'hex')
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, function () {
assert.throws(function () { assert.throws(function () {
@ -463,8 +463,8 @@ describe('script-templates', function () {
if (f.type !== 'witnesscommitment') return if (f.type !== 'witnesscommitment') return
if (!f.scriptPubKey) return if (!f.scriptPubKey) return
var commitment = Buffer.from(f.witnessCommitment, 'hex') const commitment = Buffer.from(f.witnessCommitment, 'hex')
var scriptPubKey = btemplates.witnessCommitment.output.encode(commitment) const scriptPubKey = btemplates.witnessCommitment.output.encode(commitment)
it('encodes to ' + f.scriptPubKey, function () { it('encodes to ' + f.scriptPubKey, function () {
assert.strictEqual(bscript.toASM(scriptPubKey), f.scriptPubKey) assert.strictEqual(bscript.toASM(scriptPubKey), f.scriptPubKey)
@ -477,7 +477,7 @@ describe('script-templates', function () {
fixtures.invalid.witnessCommitment.outputs.forEach(function (f) { fixtures.invalid.witnessCommitment.outputs.forEach(function (f) {
if (f.commitment) { if (f.commitment) {
var hash = Buffer.from(f.commitment, 'hex') const hash = Buffer.from(f.commitment, 'hex')
it('throws on bad encode data', function () { it('throws on bad encode data', function () {
assert.throws(function () { assert.throws(function () {
btemplates.witnessCommitment.output.encode(hash) btemplates.witnessCommitment.output.encode(hash)
@ -499,8 +499,8 @@ describe('script-templates', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
if (f.type !== 'nulldata') return if (f.type !== 'nulldata') return
var data = f.data.map(function (x) { return Buffer.from(x, 'hex') }) const data = f.data.map(function (x) { return Buffer.from(x, 'hex') })
var output = btemplates.nullData.output.encode(data) const output = btemplates.nullData.output.encode(data)
it('encodes to ' + f.output, function () { it('encodes to ' + f.output, function () {
assert.strictEqual(bscript.toASM(output), f.output) assert.strictEqual(bscript.toASM(output), f.output)

View file

@ -1,19 +1,19 @@
/* global describe, it, beforeEach */ /* global describe, it, beforeEach */
var assert = require('assert') const assert = require('assert')
var bscript = require('../src/script') const bscript = require('../src/script')
var fixtures = require('./fixtures/transaction') const fixtures = require('./fixtures/transaction')
var Transaction = require('../src/transaction') const Transaction = require('../src/transaction')
describe('Transaction', function () { describe('Transaction', function () {
function fromRaw (raw, noWitness) { function fromRaw (raw, noWitness) {
var 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(function (txIn, i) {
var txHash = Buffer.from(txIn.hash, 'hex') const txHash = Buffer.from(txIn.hash, 'hex')
var scriptSig let scriptSig
if (txIn.data) { if (txIn.data) {
scriptSig = Buffer.from(txIn.data, 'hex') scriptSig = Buffer.from(txIn.data, 'hex')
@ -24,7 +24,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) {
var witness = txIn.witness.map(function (x) { const witness = txIn.witness.map(function (x) {
return Buffer.from(x, 'hex') return Buffer.from(x, 'hex')
}) })
@ -33,7 +33,7 @@ describe('Transaction', function () {
}) })
raw.outs.forEach(function (txOut) { raw.outs.forEach(function (txOut) {
var script let script
if (txOut.data) { if (txOut.data) {
script = Buffer.from(txOut.data, 'hex') script = Buffer.from(txOut.data, 'hex')
@ -49,18 +49,18 @@ describe('Transaction', function () {
describe('fromBuffer/fromHex', function () { describe('fromBuffer/fromHex', function () {
function importExport (f) { function importExport (f) {
var id = f.id || f.hash const id = f.id || f.hash
var txHex = f.hex || f.txHex const txHex = f.hex || f.txHex
it('imports ' + f.description + ' (' + id + ')', function () { it('imports ' + f.description + ' (' + id + ')', function () {
var 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', function () {
var actual = Transaction.fromHex(f.whex) const actual = Transaction.fromHex(f.whex)
assert.strictEqual(actual.toHex(), f.whex) assert.strictEqual(actual.toHex(), f.whex)
}) })
@ -80,8 +80,8 @@ describe('Transaction', function () {
}) })
it('.version should be interpreted as an int32le', function () { it('.version should be interpreted as an int32le', function () {
var txHex = 'ffffffff0000ffffffff' const txHex = 'ffffffff0000ffffffff'
var tx = Transaction.fromHex(txHex) const tx = Transaction.fromHex(txHex)
assert.equal(-1, tx.version) assert.equal(-1, tx.version)
assert.equal(0xffffffff, tx.locktime) assert.equal(0xffffffff, tx.locktime)
}) })
@ -90,26 +90,26 @@ describe('Transaction', function () {
describe('toBuffer/toHex', function () { describe('toBuffer/toHex', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
it('exports ' + f.description + ' (' + f.id + ')', function () { it('exports ' + f.description + ' (' + f.id + ')', function () {
var 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', function () {
var 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', function () {
var f = fixtures.valid[0] const f = fixtures.valid[0]
var actual = fromRaw(f.raw) const actual = fromRaw(f.raw)
var byteLength = actual.byteLength() const byteLength = actual.byteLength()
var target = Buffer.alloc(byteLength * 2) const target = Buffer.alloc(byteLength * 2)
var a = actual.toBuffer(target, 0) const a = actual.toBuffer(target, 0)
var b = actual.toBuffer(target, byteLength) const b = actual.toBuffer(target, byteLength)
assert.strictEqual(a.length, byteLength) assert.strictEqual(a.length, byteLength)
assert.strictEqual(b.length, byteLength) assert.strictEqual(b.length, byteLength)
@ -132,7 +132,7 @@ describe('Transaction', function () {
describe('weight/virtualSize', function () { describe('weight/virtualSize', function () {
it('computes virtual size', function () { it('computes virtual size', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
var 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)
}) })
@ -140,7 +140,7 @@ describe('Transaction', function () {
it('computes weight', function () { it('computes weight', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
var 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)
}) })
@ -148,19 +148,19 @@ describe('Transaction', function () {
}) })
describe('addInput', function () { describe('addInput', function () {
var prevTxHash let prevTxHash
beforeEach(function () { beforeEach(function () {
prevTxHash = Buffer.from('ffffffff00ffff000000000000000000000000000000000000000000101010ff', 'hex') prevTxHash = Buffer.from('ffffffff00ffff000000000000000000000000000000000000000000101010ff', 'hex')
}) })
it('returns an index', function () { it('returns an index', function () {
var 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', function () {
var tx = new Transaction() const tx = new Transaction()
tx.addInput(prevTxHash, 0) tx.addInput(prevTxHash, 0)
assert.strictEqual(tx.ins[0].script.length, 0) assert.strictEqual(tx.ins[0].script.length, 0)
@ -170,8 +170,8 @@ describe('Transaction', function () {
fixtures.invalid.addInput.forEach(function (f) { fixtures.invalid.addInput.forEach(function (f) {
it('throws on ' + f.exception, function () { it('throws on ' + f.exception, function () {
var tx = new Transaction() const tx = new Transaction()
var hash = Buffer.from(f.hash, 'hex') const hash = Buffer.from(f.hash, 'hex')
assert.throws(function () { assert.throws(function () {
tx.addInput(hash, f.index) tx.addInput(hash, f.index)
@ -182,7 +182,7 @@ describe('Transaction', function () {
describe('addOutput', function () { describe('addOutput', function () {
it('returns an index', function () { it('returns an index', function () {
var 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)
}) })
@ -190,7 +190,8 @@ describe('Transaction', function () {
describe('clone', function () { describe('clone', function () {
fixtures.valid.forEach(function (f) { fixtures.valid.forEach(function (f) {
var actual, expected let actual
let expected
beforeEach(function () { beforeEach(function () {
expected = Transaction.fromHex(f.hex) expected = Transaction.fromHex(f.hex)
@ -210,7 +211,7 @@ describe('Transaction', function () {
describe('getHash/getId', function () { describe('getHash/getId', function () {
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 + ')', function () {
var 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)
assert.strictEqual(tx.getId(), f.id) assert.strictEqual(tx.getId(), f.id)
@ -223,7 +224,7 @@ describe('Transaction', function () {
describe('isCoinbase', function () { describe('isCoinbase', function () {
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 + ')', function () {
var tx = Transaction.fromHex(f.hex) const tx = Transaction.fromHex(f.hex)
assert.strictEqual(tx.isCoinbase(), f.coinbase) assert.strictEqual(tx.isCoinbase(), f.coinbase)
}) })
@ -234,13 +235,13 @@ describe('Transaction', function () {
describe('hashForSignature', function () { describe('hashForSignature', function () {
it('does not use Witness serialization', function () { it('does not use Witness serialization', function () {
var randScript = Buffer.from('6a', 'hex') const randScript = Buffer.from('6a', 'hex')
var tx = new Transaction() const tx = new Transaction()
tx.addInput(Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'), 0) tx.addInput(Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'), 0)
tx.addOutput(randScript, 5000000000) tx.addOutput(randScript, 5000000000)
var original = tx.__toBuffer const original = tx.__toBuffer
tx.__toBuffer = function (a, b, c) { tx.__toBuffer = function (a, b, c) {
if (c !== false) throw new Error('hashForSignature MUST pass false') if (c !== false) throw new Error('hashForSignature MUST pass false')
@ -259,8 +260,8 @@ describe('Transaction', function () {
fixtures.hashForSignature.forEach(function (f) { fixtures.hashForSignature.forEach(function (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), function () {
var tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
var script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script)
assert.strictEqual(tx.hashForSignature(f.inIndex, script, f.type).toString('hex'), f.hash) assert.strictEqual(tx.hashForSignature(f.inIndex, script, f.type).toString('hex'), f.hash)
}) })
@ -270,8 +271,8 @@ describe('Transaction', function () {
describe('hashForWitnessV0', function () { describe('hashForWitnessV0', function () {
fixtures.hashForWitnessV0.forEach(function (f) { fixtures.hashForWitnessV0.forEach(function (f) {
it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : ''), function () { it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : ''), function () {
var tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
var script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script)
assert.strictEqual(tx.hashForWitnessV0(f.inIndex, script, f.value, f.type).toString('hex'), f.hash) assert.strictEqual(tx.hashForWitnessV0(f.inIndex, script, f.value, f.type).toString('hex'), f.hash)
}) })

View file

@ -1,18 +1,18 @@
/* global describe, it, beforeEach */ /* global describe, it, beforeEach */
let assert = require('assert') const assert = require('assert')
let baddress = require('../src/address') const baddress = require('../src/address')
let bcrypto = require('../src/crypto') const bcrypto = require('../src/crypto')
let bscript = require('../src/script') const bscript = require('../src/script')
let btemplates = require('../src/templates') const btemplates = require('../src/templates')
let ops = require('bitcoin-ops') const ops = require('bitcoin-ops')
let ECPair = require('../src/ecpair') const ECPair = require('../src/ecpair')
let Transaction = require('../src/transaction') const Transaction = require('../src/transaction')
let TransactionBuilder = require('../src/transaction_builder') const TransactionBuilder = require('../src/transaction_builder')
let NETWORKS = require('../src/networks') const NETWORKS = require('../src/networks')
let fixtures = require('./fixtures/transaction_builder') const fixtures = require('./fixtures/transaction_builder')
// TODO: remove // TODO: remove
function getAddress (node) { function getAddress (node) {
@ -20,16 +20,16 @@ function getAddress (node) {
} }
function construct (f, dontSign) { function construct (f, dontSign) {
var network = NETWORKS[f.network] const network = NETWORKS[f.network]
var txb = new TransactionBuilder(network) let txb = new TransactionBuilder(network)
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(function (input) {
var prevTx let prevTx
if (input.txRaw) { if (input.txRaw) {
var constructed = construct(input.txRaw) const constructed = construct(input.txRaw)
if (input.txRaw.incomplete) prevTx = constructed.buildIncomplete() if (input.txRaw.incomplete) prevTx = constructed.buildIncomplete()
else prevTx = constructed.build() else prevTx = constructed.build()
} else if (input.txHex) { } else if (input.txHex) {
@ -38,7 +38,7 @@ function construct (f, dontSign) {
prevTx = input.txId prevTx = input.txId
} }
var prevTxScript let prevTxScript
if (input.prevTxScript) { if (input.prevTxScript) {
prevTxScript = bscript.fromASM(input.prevTxScript) prevTxScript = bscript.fromASM(input.prevTxScript)
} }
@ -56,27 +56,31 @@ function construct (f, dontSign) {
if (dontSign) return txb if (dontSign) return txb
var stages = f.stages && f.stages.concat() const stages = f.stages && f.stages.concat()
f.inputs.forEach(function (input, index) { f.inputs.forEach(function (input, index) {
if (!input.signs) return if (!input.signs) return
input.signs.forEach(function (sign) { input.signs.forEach(function (sign) {
var keyPair = ECPair.fromWIF(sign.keyPair, network) const keyPair = ECPair.fromWIF(sign.keyPair, network)
var redeemScript let redeemScript
var witnessScript let witnessScript
var value let value
if (sign.redeemScript) { if (sign.redeemScript) {
redeemScript = bscript.fromASM(sign.redeemScript) redeemScript = bscript.fromASM(sign.redeemScript)
} }
if (sign.value) { if (sign.value) {
value = sign.value value = sign.value
} }
if (sign.witnessScript) { if (sign.witnessScript) {
witnessScript = bscript.fromASM(sign.witnessScript) witnessScript = bscript.fromASM(sign.witnessScript)
} }
txb.sign(index, keyPair, redeemScript, sign.hashType, value, witnessScript) txb.sign(index, keyPair, redeemScript, sign.hashType, value, witnessScript)
if (sign.stage) { if (sign.stage) {
var tx = txb.buildIncomplete() const tx = txb.buildIncomplete()
assert.strictEqual(tx.toHex(), stages.shift()) assert.strictEqual(tx.toHex(), stages.shift())
txb = TransactionBuilder.fromTransaction(tx, network) txb = TransactionBuilder.fromTransaction(tx, network)
} }
@ -88,23 +92,23 @@ function construct (f, dontSign) {
describe('TransactionBuilder', function () { describe('TransactionBuilder', function () {
// constants // constants
var keyPair = ECPair.fromPrivateKey(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')) const keyPair = ECPair.fromPrivateKey(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex'))
var scripts = [ const scripts = [
'1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH', '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH',
'1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP' '1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP'
].map(function (x) { ].map(function (x) {
return baddress.toOutputScript(x) return baddress.toOutputScript(x)
}) })
var txHash = Buffer.from('0e7cea811c0be9f73c0aca591034396e7264473fc25c1ca45195d7417b36cbe2', 'hex') const txHash = Buffer.from('0e7cea811c0be9f73c0aca591034396e7264473fc25c1ca45195d7417b36cbe2', 'hex')
describe('fromTransaction', function () { describe('fromTransaction', function () {
fixtures.valid.build.forEach(function (f) { fixtures.valid.build.forEach(function (f) {
it('returns TransactionBuilder, with ' + f.description, function () { it('returns TransactionBuilder, with ' + f.description, function () {
var network = NETWORKS[f.network || 'bitcoin'] const network = NETWORKS[f.network || 'bitcoin']
var tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
var txb = TransactionBuilder.fromTransaction(tx, network) const txb = TransactionBuilder.fromTransaction(tx, network)
var txAfter = f.incomplete ? txb.buildIncomplete() : txb.build() const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build()
assert.strictEqual(txAfter.toHex(), f.txHex) assert.strictEqual(txAfter.toHex(), f.txHex)
assert.strictEqual(txb.network, network) assert.strictEqual(txb.network, network)
@ -113,10 +117,10 @@ describe('TransactionBuilder', function () {
fixtures.valid.fromTransaction.forEach(function (f) { fixtures.valid.fromTransaction.forEach(function (f) {
it('returns TransactionBuilder, with ' + f.description, function () { it('returns TransactionBuilder, with ' + f.description, function () {
var tx = new Transaction() const tx = new Transaction()
f.inputs.forEach(function (input) { f.inputs.forEach(function (input) {
var 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))
}) })
@ -125,8 +129,8 @@ describe('TransactionBuilder', function () {
tx.addOutput(bscript.fromASM(output.script), output.value) tx.addOutput(bscript.fromASM(output.script), output.value)
}) })
var txb = TransactionBuilder.fromTransaction(tx) const txb = TransactionBuilder.fromTransaction(tx)
var txAfter = f.incomplete ? txb.buildIncomplete() : txb.build() const txAfter = f.incomplete ? txb.buildIncomplete() : txb.build()
txAfter.ins.forEach(function (input, i) { txAfter.ins.forEach(function (input, i) {
assert.equal(bscript.toASM(input.script), f.inputs[i].scriptSigAfter) assert.equal(bscript.toASM(input.script), f.inputs[i].scriptSigAfter)
@ -139,8 +143,8 @@ describe('TransactionBuilder', function () {
}) })
it('classifies transaction inputs', function () { it('classifies transaction inputs', function () {
var tx = Transaction.fromHex(fixtures.valid.classification.hex) const tx = Transaction.fromHex(fixtures.valid.classification.hex)
var txb = TransactionBuilder.fromTransaction(tx) const txb = TransactionBuilder.fromTransaction(tx)
txb.__inputs.forEach(function (i) { txb.__inputs.forEach(function (i) {
assert.strictEqual(i.prevOutType, 'scripthash') assert.strictEqual(i.prevOutType, 'scripthash')
@ -151,7 +155,7 @@ describe('TransactionBuilder', function () {
fixtures.invalid.fromTransaction.forEach(function (f) { fixtures.invalid.fromTransaction.forEach(function (f) {
it('throws ' + f.exception, function () { it('throws ' + f.exception, function () {
var tx = Transaction.fromHex(f.txHex) const tx = Transaction.fromHex(f.txHex)
assert.throws(function () { assert.throws(function () {
TransactionBuilder.fromTransaction(tx) TransactionBuilder.fromTransaction(tx)
@ -161,16 +165,16 @@ describe('TransactionBuilder', function () {
}) })
describe('addInput', function () { describe('addInput', function () {
var txb let txb
beforeEach(function () { beforeEach(function () {
txb = new TransactionBuilder() txb = new TransactionBuilder()
}) })
it('accepts a txHash, index [and sequence number]', function () { it('accepts a txHash, index [and sequence number]', function () {
var vin = txb.addInput(txHash, 1, 54) const vin = txb.addInput(txHash, 1, 54)
assert.strictEqual(vin, 0) assert.strictEqual(vin, 0)
var txIn = txb.__tx.ins[0] const txIn = txb.__tx.ins[0]
assert.strictEqual(txIn.hash, txHash) assert.strictEqual(txIn.hash, txHash)
assert.strictEqual(txIn.index, 1) assert.strictEqual(txIn.index, 1)
assert.strictEqual(txIn.sequence, 54) assert.strictEqual(txIn.sequence, 54)
@ -178,10 +182,10 @@ describe('TransactionBuilder', function () {
}) })
it('accepts a txHash, index [, sequence number and scriptPubKey]', function () { it('accepts a txHash, index [, sequence number and scriptPubKey]', function () {
var 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)
var txIn = txb.__tx.ins[0] const txIn = txb.__tx.ins[0]
assert.strictEqual(txIn.hash, txHash) assert.strictEqual(txIn.hash, txHash)
assert.strictEqual(txIn.index, 1) assert.strictEqual(txIn.index, 1)
assert.strictEqual(txIn.sequence, 54) assert.strictEqual(txIn.sequence, 54)
@ -189,14 +193,14 @@ describe('TransactionBuilder', function () {
}) })
it('accepts a prevTx, index [and sequence number]', function () { it('accepts a prevTx, index [and sequence number]', function () {
var 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)
var vin = txb.addInput(prevTx, 1, 54) const vin = txb.addInput(prevTx, 1, 54)
assert.strictEqual(vin, 0) assert.strictEqual(vin, 0)
var txIn = txb.__tx.ins[0] const txIn = txb.__tx.ins[0]
assert.deepEqual(txIn.hash, prevTx.getHash()) assert.deepEqual(txIn.hash, prevTx.getHash())
assert.strictEqual(txIn.index, 1) assert.strictEqual(txIn.index, 1)
assert.strictEqual(txIn.sequence, 54) assert.strictEqual(txIn.sequence, 54)
@ -219,26 +223,26 @@ describe('TransactionBuilder', function () {
}) })
describe('addOutput', function () { describe('addOutput', function () {
var txb let txb
beforeEach(function () { beforeEach(function () {
txb = new TransactionBuilder() txb = new TransactionBuilder()
}) })
it('accepts an address string and value', function () { it('accepts an address string and value', function () {
let address = getAddress(keyPair) const address = getAddress(keyPair)
var vout = txb.addOutput(address, 1000) const vout = txb.addOutput(address, 1000)
assert.strictEqual(vout, 0) assert.strictEqual(vout, 0)
var txout = txb.__tx.outs[0] const txout = txb.__tx.outs[0]
assert.deepEqual(txout.script, scripts[0]) assert.deepEqual(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', function () {
var vout = txb.addOutput(scripts[0], 1000) const vout = txb.addOutput(scripts[0], 1000)
assert.strictEqual(vout, 0) assert.strictEqual(vout, 0)
var txout = txb.__tx.outs[0] const txout = txb.__tx.outs[0]
assert.deepEqual(txout.script, scripts[0]) assert.deepEqual(txout.script, scripts[0])
assert.strictEqual(txout.value, 1000) assert.strictEqual(txout.value, 1000)
}) })
@ -290,7 +294,7 @@ describe('TransactionBuilder', function () {
describe('setLockTime', function () { describe('setLockTime', function () {
it('throws if if there exist any scriptSigs', function () { it('throws if if there exist any scriptSigs', function () {
var txb = new TransactionBuilder() const txb = new TransactionBuilder()
txb.addInput(txHash, 0) txb.addInput(txHash, 0)
txb.sign(0, keyPair) txb.sign(0, keyPair)
@ -302,12 +306,12 @@ describe('TransactionBuilder', function () {
describe('sign', function () { describe('sign', function () {
it('supports the alternative abstract interface { publicKey, sign }', function () { it('supports the alternative abstract interface { publicKey, sign }', function () {
var keyPair = { const keyPair = {
publicKey: ECPair.makeRandom({ rng: function () { return Buffer.alloc(32, 1) } }).publicKey, publicKey: ECPair.makeRandom({ rng: function () { return Buffer.alloc(32, 1) } }).publicKey,
sign: function (hash) { return Buffer.alloc(64, 0x5f) } sign: function (hash) { return Buffer.alloc(64, 0x5f) }
} }
var txb = new TransactionBuilder() const txb = new TransactionBuilder()
txb.setVersion(1) txb.setVersion(1)
txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1)
txb.addOutput('1111111111111111111114oLvT2', 100000) txb.addOutput('1111111111111111111114oLvT2', 100000)
@ -317,13 +321,14 @@ describe('TransactionBuilder', function () {
fixtures.invalid.sign.forEach(function (f) { fixtures.invalid.sign.forEach(function (f) {
it('throws ' + f.exception + (f.description ? ' (' + f.description + ')' : ''), function () { it('throws ' + f.exception + (f.description ? ' (' + f.description + ')' : ''), function () {
var txb = construct(f, true) const txb = construct(f, true)
f.inputs.forEach(function (input, index) { f.inputs.forEach(function (input, index) {
input.signs.forEach(function (sign) { input.signs.forEach(function (sign) {
var keyPairNetwork = NETWORKS[sign.network || f.network] const keyPairNetwork = NETWORKS[sign.network || f.network]
var keyPair2 = ECPair.fromWIF(sign.keyPair, keyPairNetwork) const keyPair2 = ECPair.fromWIF(sign.keyPair, keyPairNetwork)
var redeemScript, witnessScript let redeemScript
let witnessScript
if (sign.redeemScript) { if (sign.redeemScript) {
redeemScript = bscript.fromASM(sign.redeemScript) redeemScript = bscript.fromASM(sign.redeemScript)
@ -349,8 +354,8 @@ describe('TransactionBuilder', function () {
describe('build', function () { describe('build', function () {
fixtures.valid.build.forEach(function (f) { fixtures.valid.build.forEach(function (f) {
it('builds "' + f.description + '"', function () { it('builds "' + f.description + '"', function () {
var txb = construct(f) const txb = construct(f)
var tx = f.incomplete ? txb.buildIncomplete() : txb.build() const tx = f.incomplete ? txb.buildIncomplete() : txb.build()
assert.strictEqual(tx.toHex(), f.txHex) assert.strictEqual(tx.toHex(), f.txHex)
}) })
@ -361,7 +366,7 @@ describe('TransactionBuilder', function () {
describe('for ' + (f.description || f.exception), function () { describe('for ' + (f.description || f.exception), function () {
it('throws ' + f.exception, function () { it('throws ' + f.exception, function () {
assert.throws(function () { assert.throws(function () {
var txb let txb
if (f.txHex) { if (f.txHex) {
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex))
} else { } else {
@ -376,7 +381,7 @@ describe('TransactionBuilder', function () {
if (f.incomplete) { if (f.incomplete) {
it('throws ' + f.exception, function () { it('throws ' + f.exception, function () {
assert.throws(function () { assert.throws(function () {
var txb let txb
if (f.txHex) { if (f.txHex) {
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex))
} else { } else {
@ -388,7 +393,7 @@ describe('TransactionBuilder', function () {
}) })
} else { } else {
it('does not throw if buildIncomplete', function () { it('does not throw if buildIncomplete', function () {
var txb let txb
if (f.txHex) { if (f.txHex) {
txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex)) txb = TransactionBuilder.fromTransaction(Transaction.fromHex(f.txHex))
} else { } else {
@ -402,11 +407,11 @@ describe('TransactionBuilder', function () {
}) })
it('for incomplete with 0 signatures', function () { it('for incomplete with 0 signatures', function () {
var randomTxData = '0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000' const randomTxData = '0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000'
var randomAddress = '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH' const randomAddress = '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH'
var randomTx = Transaction.fromHex(randomTxData) const randomTx = Transaction.fromHex(randomTxData)
var tx = new TransactionBuilder() let tx = new TransactionBuilder()
tx.addInput(randomTx, 0) tx.addInput(randomTx, 0)
tx.addOutput(randomAddress, 1000) tx.addOutput(randomAddress, 1000)
tx = tx.buildIncomplete() tx = tx.buildIncomplete()
@ -414,10 +419,10 @@ describe('TransactionBuilder', function () {
}) })
it('for incomplete P2SH with 0 signatures', function () { it('for incomplete P2SH with 0 signatures', function () {
var inp = Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000017a91471a8ec07ff69c6c4fee489184c462a9b1b9237488700000000', 'hex') // arbitrary P2SH input const inp = Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000017a91471a8ec07ff69c6c4fee489184c462a9b1b9237488700000000', 'hex') // arbitrary P2SH input
var inpTx = Transaction.fromBuffer(inp) const inpTx = Transaction.fromBuffer(inp)
var txb = new TransactionBuilder(NETWORKS.testnet) const txb = new TransactionBuilder(NETWORKS.testnet)
txb.addInput(inpTx, 0) txb.addInput(inpTx, 0)
txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8) // arbitrary output txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8) // arbitrary output
@ -425,10 +430,10 @@ describe('TransactionBuilder', function () {
}) })
it('for incomplete P2WPKH with 0 signatures', function () { it('for incomplete P2WPKH with 0 signatures', function () {
var inp = Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a8040000001600141a15805e1f4040c9f68ccc887fca2e63547d794b00000000', 'hex') const inp = Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a8040000001600141a15805e1f4040c9f68ccc887fca2e63547d794b00000000', 'hex')
var inpTx = Transaction.fromBuffer(inp) const inpTx = Transaction.fromBuffer(inp)
var txb = new TransactionBuilder(NETWORKS.testnet) const txb = new TransactionBuilder(NETWORKS.testnet)
txb.addInput(inpTx, 0) txb.addInput(inpTx, 0)
txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8) // arbitrary output txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8) // arbitrary output
@ -436,9 +441,9 @@ describe('TransactionBuilder', function () {
}) })
it('for incomplete P2WSH with 0 signatures', function () { it('for incomplete P2WSH with 0 signatures', function () {
var inpTx = Transaction.fromBuffer(Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000022002072df76fcc0b231b94bdf7d8c25d7eef4716597818d211e19ade7813bff7a250200000000', 'hex')) const inpTx = Transaction.fromBuffer(Buffer.from('010000000173120703f67318aef51f7251272a6816d3f7523bb25e34b136d80be959391c100000000000ffffffff0100c817a80400000022002072df76fcc0b231b94bdf7d8c25d7eef4716597818d211e19ade7813bff7a250200000000', 'hex'))
var txb = new TransactionBuilder(NETWORKS.testnet) const txb = new TransactionBuilder(NETWORKS.testnet)
txb.addInput(inpTx, 0) txb.addInput(inpTx, 0)
txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8) // arbitrary output txb.addOutput('2NAkqp5xffoomp5RLBcakuGpZ12GU4twdz4', 1e8) // arbitrary output
@ -449,25 +454,25 @@ describe('TransactionBuilder', function () {
describe('multisig', function () { describe('multisig', function () {
fixtures.valid.multisig.forEach(function (f) { fixtures.valid.multisig.forEach(function (f) {
it(f.description, function () { it(f.description, function () {
var txb = construct(f, true) const network = NETWORKS[f.network]
var tx let txb = construct(f, true)
var network = NETWORKS[f.network] let tx
f.inputs.forEach(function (input, i) { f.inputs.forEach(function (input, i) {
var redeemScript = bscript.fromASM(input.redeemScript) const redeemScript = bscript.fromASM(input.redeemScript)
input.signs.forEach(function (sign) { input.signs.forEach(function (sign) {
// rebuild the transaction each-time after the first // rebuild the transaction each-time after the first
if (tx) { if (tx) {
// do we filter OP_0's beforehand? // do we filter OP_0's beforehand?
if (sign.filterOP_0) { if (sign.filterOP_0) {
var scriptSig = tx.ins[i].script const scriptSig = tx.ins[i].script
// ignore OP_0 on the front, ignore redeemScript // ignore OP_0 on the front, ignore redeemScript
var signatures = bscript.decompile(scriptSig).slice(1, -1).filter(function (x) { return x !== ops.OP_0 }) const signatures = bscript.decompile(scriptSig).slice(1, -1).filter(function (x) { return x !== ops.OP_0 })
// rebuild/replace the scriptSig without them // rebuild/replace the scriptSig without them
var replacement = btemplates.scriptHash.input.encode(btemplates.multisig.input.encode(signatures), redeemScript) const replacement = btemplates.scriptHash.input.encode(btemplates.multisig.input.encode(signatures), redeemScript)
assert.strictEqual(bscript.toASM(replacement), sign.scriptSigFiltered) assert.strictEqual(bscript.toASM(replacement), sign.scriptSigFiltered)
tx.ins[i].script = replacement tx.ins[i].script = replacement
@ -476,7 +481,7 @@ describe('TransactionBuilder', function () {
txb = TransactionBuilder.fromTransaction(tx, network) txb = TransactionBuilder.fromTransaction(tx, network)
} }
var keyPair2 = ECPair.fromWIF(sign.keyPair, network) const keyPair2 = ECPair.fromWIF(sign.keyPair, network)
txb.sign(i, keyPair2, redeemScript, sign.hashType) txb.sign(i, keyPair2, redeemScript, sign.hashType)
// update the tx // update the tx
@ -493,10 +498,10 @@ describe('TransactionBuilder', function () {
}) })
describe('various edge case', function () { describe('various edge case', function () {
var 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', function () {
var rawtx = '01000000000104fdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a' + const rawtx = '01000000000104fdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a' +
'1df90000000000fffffffffdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a1df9' + '1df90000000000fffffffffdaac89627208b4733484ca56bc291f4cf4fa8d7c5f29893c52b46788a0a1df9' +
'0100000000ffffffffa2ef7aaab316a3e5b5b0a78d1d35c774b95a079f9f0c762277a49caf1f26bca40000' + '0100000000ffffffffa2ef7aaab316a3e5b5b0a78d1d35c774b95a079f9f0c762277a49caf1f26bca40000' +
'000000ffffffffa2ef7aaab316a3e5b5b0a78d1d35c774b95a079f9f0c762277a49caf1f26bca401000000' + '000000ffffffffa2ef7aaab316a3e5b5b0a78d1d35c774b95a079f9f0c762277a49caf1f26bca401000000' +
@ -511,7 +516,7 @@ describe('TransactionBuilder', function () {
'd561abaac86c37a353b52895a5e6c196d6f44802473044022007be81ffd4297441ab10e740fc9bab9545a2' + 'd561abaac86c37a353b52895a5e6c196d6f44802473044022007be81ffd4297441ab10e740fc9bab9545a2' +
'194a565cd6aa4cc38b8eaffa343402201c5b4b61d73fa38e49c1ee68cc0e6dfd2f5dae453dd86eb142e87a' + '194a565cd6aa4cc38b8eaffa343402201c5b4b61d73fa38e49c1ee68cc0e6dfd2f5dae453dd86eb142e87a' +
'0bafb1bc8401210283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f44800000000' '0bafb1bc8401210283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f44800000000'
var txb = TransactionBuilder.fromTransaction(Transaction.fromHex(rawtx)) const txb = TransactionBuilder.fromTransaction(Transaction.fromHex(rawtx))
txb.__inputs[0].value = 241530 txb.__inputs[0].value = 241530
txb.__inputs[1].value = 241530 txb.__inputs[1].value = 241530
txb.__inputs[2].value = 248920 txb.__inputs[2].value = 248920
@ -523,64 +528,64 @@ describe('TransactionBuilder', function () {
}) })
it('should classify witness inputs with witness = true during multisigning', function () { it('should classify witness inputs with witness = true during multisigning', function () {
var keyPair = ECPair.fromWIF('cRAwuVuVSBZMPu7hdrYvMCZ8eevzmkExjFbaBLhqnDdrezxN3nTS', network) const keyPair = ECPair.fromWIF('cRAwuVuVSBZMPu7hdrYvMCZ8eevzmkExjFbaBLhqnDdrezxN3nTS', network)
var witnessScript = Buffer.from('522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea1952ae', 'hex') const witnessScript = Buffer.from('522102bbbd6eb01efcbe4bd9664b886f26f69de5afcb2e479d72596c8bf21929e352e22102d9c3f7180ef13ec5267723c9c2ffab56a4215241f837502ea8977c8532b9ea1952ae', 'hex')
var redeemScript = Buffer.from('002024376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5af', 'hex') const redeemScript = Buffer.from('002024376a0a9abab599d0e028248d48ebe817bc899efcffa1cd2984d67289daf5af', 'hex')
var scriptPubKey = Buffer.from('a914b64f1a3eacc1c8515592a6f10457e8ff90e4db6a87', 'hex') const scriptPubKey = Buffer.from('a914b64f1a3eacc1c8515592a6f10457e8ff90e4db6a87', 'hex')
var txb = new TransactionBuilder(network) const txb = new TransactionBuilder(network)
txb.setVersion(1) txb.setVersion(1)
txb.addInput('a4696c4b0cd27ec2e173ab1fa7d1cc639a98ee237cec95a77ca7ff4145791529', 1, 0xffffffff, scriptPubKey) txb.addInput('a4696c4b0cd27ec2e173ab1fa7d1cc639a98ee237cec95a77ca7ff4145791529', 1, 0xffffffff, scriptPubKey)
txb.addOutput(scriptPubKey, 99000) txb.addOutput(scriptPubKey, 99000)
txb.sign(0, keyPair, redeemScript, null, 100000, witnessScript) txb.sign(0, keyPair, redeemScript, null, 100000, witnessScript)
// 2-of-2 signed only once // 2-of-2 signed only once
var 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.equal(tx.getId(), 'f15d0a65b21b4471405b21a099f8b18e1ae4d46d55efbd0f4766cf11ad6cb821')
var txHex = tx.toHex() const txHex = tx.toHex()
var newTxb = TransactionBuilder.fromTransaction(Transaction.fromHex(txHex)) const newTxb = TransactionBuilder.fromTransaction(Transaction.fromHex(txHex))
// input should have the key 'witness' set to true // input should have the key 'witness' set to true
assert.equal(newTxb.__inputs[0].witness, true) assert.equal(newTxb.__inputs[0].witness, true)
}) })
it('should handle badly pre-filled OP_0s', function () { it('should handle badly pre-filled OP_0s', function () {
// OP_0 is used where a signature is missing // OP_0 is used where a signature is missing
var redeemScripSig = bscript.fromASM('OP_0 OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae') const redeemScripSig = bscript.fromASM('OP_0 OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae')
var 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')
var tx = new Transaction() const tx = new Transaction()
tx.addInput(Buffer.from('cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f07149', 'hex'), 0, undefined, redeemScripSig) tx.addInput(Buffer.from('cff58855426469d0ef16442ee9c644c4fb13832467bcbc3173168a7916f07149', 'hex'), 0, undefined, redeemScripSig)
tx.addOutput(Buffer.from('76a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac', 'hex'), 1000) tx.addOutput(Buffer.from('76a914aa4d7985c57e011a8b3dd8e0e5a73aaef41629c588ac', 'hex'), 1000)
// now import the Transaction // now import the Transaction
var txb = TransactionBuilder.fromTransaction(tx, NETWORKS.testnet) const txb = TransactionBuilder.fromTransaction(tx, NETWORKS.testnet)
var keyPair2 = ECPair.fromWIF('91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe', network) const keyPair2 = ECPair.fromWIF('91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe', network)
txb.sign(0, keyPair2, redeemScript) txb.sign(0, keyPair2, redeemScript)
var tx2 = txb.build() const tx2 = txb.build()
assert.equal(tx2.getId(), 'eab59618a564e361adef6d918bd792903c3d41bcf1220137364fb847880467f9') assert.equal(tx2.getId(), 'eab59618a564e361adef6d918bd792903c3d41bcf1220137364fb847880467f9')
assert.equal(bscript.toASM(tx2.ins[0].script), 'OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae') assert.equal(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', function () {
var txb = new TransactionBuilder() let txb = new TransactionBuilder()
txb.setVersion(1) txb.setVersion(1)
txb.addInput('aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31', 0) txb.addInput('aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31', 0)
var incomplete = txb.buildIncomplete().toHex() const incomplete = txb.buildIncomplete().toHex()
var keyPair = ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy') const keyPair = ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy')
// sign, as expected // sign, as expected
txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000) txb.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000)
txb.sign(0, keyPair) txb.sign(0, keyPair)
var txId = txb.build().getId() const txId = txb.build().getId()
assert.equal(txId, '54f097315acbaedb92a95455da3368eb45981cdae5ffbc387a9afc872c0f29b3') assert.equal(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)
var txId2 = txb.build().getId() const txId2 = txb.build().getId()
assert.equal(txId, txId2) assert.equal(txId, txId2)
}) })
}) })

View file

@ -1,13 +1,13 @@
/* global describe, it */ /* global describe, it */
var assert = require('assert') const assert = require('assert')
var types = require('../src/types') const types = require('../src/types')
var typeforce = require('typeforce') const typeforce = require('typeforce')
describe('types', function () { describe('types', function () {
describe('Buffer Hash160/Hash256', function () { describe('Buffer Hash160/Hash256', function () {
var buffer20byte = Buffer.alloc(20) const buffer20byte = Buffer.alloc(20)
var buffer32byte = Buffer.alloc(32) const buffer32byte = Buffer.alloc(32)
it('return true for valid size', function () { it('return true for valid size', function () {
assert(types.Hash160bit(buffer20byte)) assert(types.Hash160bit(buffer20byte))