function Block() { this.version = 1 this.prevHash = null this.merkleRoot = null this.timestamp = 0 this.bits = 0 this.nonce = 0 }
n/a
function ECPair(d, Q, options) { if (options) { typeforce({ compressed: types.maybe(types.Boolean), network: types.maybe(types.Network) }, options) } options = options || {} if (d) { if (d.signum() <= 0) throw new Error('Private key must be greater than 0') if (d.compareTo(secp256k1.n) >= 0) throw new Error('Private key must be less than the curve order') if (Q) throw new TypeError('Unexpected publicKey parameter') this.d = d } else { typeforce(types.ECPoint, Q) this.__Q = Q } this.compressed = options.compressed === undefined ? true : options.compressed this.network = options.network || NETWORKS.bitcoin }
n/a
function ECSignature(r, s) { typeforce(types.tuple(types.BigInt, types.BigInt), arguments) this.r = r this.s = s }
n/a
function HDNode(keyPair, chainCode) { typeforce(types.tuple('ECPair', types.Buffer256bit), arguments) if (!keyPair.compressed) throw new TypeError('BIP32 only allows compressed keyPairs') this.keyPair = keyPair this.chainCode = chainCode this.depth = 0 this.index = 0 this.parentFingerprint = 0x00000000 }
n/a
function Transaction() { this.version = 1 this.locktime = 0 this.ins = [] this.outs = [] }
n/a
function TransactionBuilder(network, maximumFeeRate) { this.prevTxMap = {} this.network = network || networks.bitcoin // WARNING: This is __NOT__ to be relied on, its just another potential safety mechanism (safety in-depth) this.maximumFeeRate = maximumFeeRate || 1000 this.inputs = [] this.tx = new Transaction() }
n/a
function Block() { this.version = 1 this.prevHash = null this.merkleRoot = null this.timestamp = 0 this.bits = 0 this.nonce = 0 }
n/a
calculateMerkleRoot = function (transactions) { typeforce([{ getHash: types.Function }], transactions) if (transactions.length === 0) throw TypeError('Cannot compute merkle root for zero transactions') var hashes = transactions.map(function (transaction) { return transaction.getHash() }) return fastMerkleRoot(hashes, bcrypto.hash256) }
n/a
calculateTarget = function (bits) { var exponent = ((bits & 0xff000000) >> 24) - 3 var mantissa = bits & 0x007fffff var target = new Buffer(32) target.fill(0) target.writeUInt32BE(mantissa, 28 - exponent) return target }
n/a
fromBuffer = function (buffer) { if (buffer.length < 80) throw new Error('Buffer too small (< 80 bytes)') var offset = 0 function readSlice (n) { offset += n return buffer.slice(offset - n, offset) } function readUInt32 () { var i = buffer.readUInt32LE(offset) offset += 4 return i } function readInt32 () { var i = buffer.readInt32LE(offset) offset += 4 return i } var block = new Block() block.version = readInt32() block.prevHash = readSlice(32) block.merkleRoot = readSlice(32) block.timestamp = readUInt32() block.bits = readUInt32() block.nonce = readUInt32() if (buffer.length === 80) return block function readVarInt () { var vi = varuint.decode(buffer, offset) offset += varuint.decode.bytes return vi } function readTransaction () { var tx = Transaction.fromBuffer(buffer.slice(offset), true) offset += tx.byteLength() return tx } var nTransactions = readVarInt() block.transactions = [] for (var i = 0; i < nTransactions; ++i) { var tx = readTransaction() block.transactions.push(tx) } return block }
...
// Step G
v = createHmac('sha256', k).update(v).digest()
// Step H1/H2a, ignored as tlen === qlen (256 bit)
// Step H2b
v = createHmac('sha256', k).update(v).digest()
var T = BigInteger.fromBuffer(v)
// Step H3, repeat until T is within the interval [1, n - 1] and is suitable for ECDSA
while (T.signum() <= 0 || T.compareTo(secp256k1.n) >= 0 || !checkSig(T)) {
k = createHmac('sha256', k)
.update(v)
.update(ZERO)
.digest()
...
fromHex = function (hex) { return Block.fromBuffer(new Buffer(hex, 'hex')) }
n/a
byteLength = function (headersOnly) { if (headersOnly || !this.transactions) return 80 return 80 + varuint.encodingLength(this.transactions.length) + this.transactions.reduce(function (a, x) { return a + x.byteLength() }, 0) }
n/a
checkMerkleRoot = function () { if (!this.transactions) return false var actualMerkleRoot = Block.calculateMerkleRoot(this.transactions) return this.merkleRoot.compare(actualMerkleRoot) === 0 }
n/a
checkProofOfWork = function () { var hash = this.getHash().reverse() var target = Block.calculateTarget(this.bits) return hash.compare(target) <= 0 }
n/a
getHash = function () { return bcrypto.hash256(this.toBuffer(true)) }
n/a
getId = function () { return this.getHash().reverse().toString('hex') }
n/a
getUTCDate = function () { var date = new Date(0) // epoch date.setUTCSeconds(this.timestamp) return date }
n/a
toBuffer = function (headersOnly) { var buffer = new Buffer(this.byteLength(headersOnly)) var offset = 0 function writeSlice (slice) { slice.copy(buffer, offset) offset += slice.length } function writeInt32 (i) { buffer.writeInt32LE(i, offset) offset += 4 } function writeUInt32 (i) { buffer.writeUInt32LE(i, offset) offset += 4 } writeInt32(this.version) writeSlice(this.prevHash) writeSlice(this.merkleRoot) writeUInt32(this.timestamp) writeUInt32(this.bits) writeUInt32(this.nonce) if (headersOnly || !this.transactions) return buffer varuint.encode(this.transactions.length, buffer, offset) offset += varuint.encode.bytes this.transactions.forEach(function (tx) { var txSize = tx.byteLength() // TODO: extract from toBuffer? tx.toBuffer(buffer, offset) offset += txSize }) return buffer }
...
}
var N_OVER_TWO = secp256k1.n.shiftRight(1)
function sign (hash, d) {
typeforce(types.tuple(types.Hash256bit, types.BigInt), arguments)
var x = d.toBuffer(32)
var e = BigInteger.fromBuffer(hash)
var n = secp256k1.n
var G = secp256k1.G
var r, s
deterministicGenerateK(hash, x, function (k) {
var Q = G.multiply(k)
...
toHex = function (headersOnly) { return this.toBuffer(headersOnly).toString('hex') }
n/a
function ECPair(d, Q, options) { if (options) { typeforce({ compressed: types.maybe(types.Boolean), network: types.maybe(types.Network) }, options) } options = options || {} if (d) { if (d.signum() <= 0) throw new Error('Private key must be greater than 0') if (d.compareTo(secp256k1.n) >= 0) throw new Error('Private key must be less than the curve order') if (Q) throw new TypeError('Unexpected publicKey parameter') this.d = d } else { typeforce(types.ECPoint, Q) this.__Q = Q } this.compressed = options.compressed === undefined ? true : options.compressed this.network = options.network || NETWORKS.bitcoin }
n/a
fromPublicKeyBuffer = function (buffer, network) { var Q = ecurve.Point.decodeFrom(secp256k1, buffer) return new ECPair(null, Q, { compressed: Q.compressed, network: network }) }
n/a
fromWIF = function (string, network) { var decoded = wif.decode(string) var version = decoded.version // list of networks? if (types.Array(network)) { network = network.filter(function (x) { return version === x.wif }).pop() if (!network) throw new Error('Unknown network version') // otherwise, assume a network object (or default to bitcoin) } else { network = network || NETWORKS.bitcoin if (version !== network.wif) throw new Error('Invalid network version') } var d = BigInteger.fromBuffer(decoded.privateKey) return new ECPair(d, null, { compressed: decoded.compressed, network: network }) }
n/a
makeRandom = function (options) { options = options || {} var rng = options.rng || randomBytes var d do { var buffer = rng(32) typeforce(types.Buffer256bit, buffer) d = BigInteger.fromBuffer(buffer) } while (d.signum() <= 0 || d.compareTo(secp256k1.n) >= 0) return new ECPair(d, null, options) }
n/a
getAddress = function () { return baddress.toBase58Check(bcrypto.hash160(this.getPublicKeyBuffer()), this.getNetwork().pubKeyHash) }
n/a
getNetwork = function () { return this.network }
n/a
getPublicKeyBuffer = function () { return this.Q.getEncoded(this.compressed) }
n/a
sign = function (hash) { if (!this.d) throw new Error('Missing private key') return ecdsa.sign(hash, this.d) }
n/a
toWIF = function () { if (!this.d) throw new Error('Missing private key') return wif.encode(this.network.wif, this.d.toBuffer(32), this.compressed) }
n/a
verify = function (hash, signature) { return ecdsa.verify(hash, signature, this.Q) }
n/a
function ECSignature(r, s) { typeforce(types.tuple(types.BigInt, types.BigInt), arguments) this.r = r this.s = s }
n/a
fromDER = function (buffer) { var decode = bip66.decode(buffer) var r = BigInteger.fromDERInteger(decode.r) var s = BigInteger.fromDERInteger(decode.s) return new ECSignature(r, s) }
n/a
parseCompact = function (buffer) { if (buffer.length !== 65) throw new Error('Invalid signature length') var flagByte = buffer.readUInt8(0) - 27 if (flagByte !== (flagByte & 7)) throw new Error('Invalid signature parameter') var compressed = !!(flagByte & 4) var recoveryParam = flagByte & 3 var r = BigInteger.fromBuffer(buffer.slice(1, 33)) var s = BigInteger.fromBuffer(buffer.slice(33)) return { compressed: compressed, i: recoveryParam, signature: new ECSignature(r, s) } }
n/a
parseScriptSignature = function (buffer) { var hashType = buffer.readUInt8(buffer.length - 1) var hashTypeMod = hashType & ~0x80 if (hashTypeMod <= 0x00 || hashTypeMod >= 0x04) throw new Error('Invalid hashType ' + hashType) return { signature: ECSignature.fromDER(buffer.slice(0, -1)), hashType: hashType } }
n/a
toCompact = function (i, compressed) { if (compressed) { i += 4 } i += 27 var buffer = new Buffer(65) buffer.writeUInt8(i, 0) this.r.toBuffer(32).copy(buffer, 1) this.s.toBuffer(32).copy(buffer, 33) return buffer }
n/a
toDER = function () { var r = new Buffer(this.r.toDERInteger()) var s = new Buffer(this.s.toDERInteger()) return bip66.encode(r, s) }
n/a
toScriptSignature = function (hashType) { var hashTypeMod = hashType & ~0x80 if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType) var hashTypeBuffer = new Buffer(1) hashTypeBuffer.writeUInt8(hashType, 0) return Buffer.concat([this.toDER(), hashTypeBuffer]) }
n/a
function HDNode(keyPair, chainCode) { typeforce(types.tuple('ECPair', types.Buffer256bit), arguments) if (!keyPair.compressed) throw new TypeError('BIP32 only allows compressed keyPairs') this.keyPair = keyPair this.chainCode = chainCode this.depth = 0 this.index = 0 this.parentFingerprint = 0x00000000 }
n/a
fromBase58 = function (string, networks) { var buffer = base58check.decode(string) if (buffer.length !== 78) throw new Error('Invalid buffer length') // 4 bytes: version bytes var version = buffer.readUInt32BE(0) var network // list of networks? if (Array.isArray(networks)) { network = networks.filter(function (x) { return version === x.bip32.private || version === x.bip32.public }).pop() if (!network) throw new Error('Unknown network version') // otherwise, assume a network object (or default to bitcoin) } else { network = networks || NETWORKS.bitcoin } if (version !== network.bip32.private && version !== network.bip32.public) throw new Error('Invalid network version') // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ... var depth = buffer[4] // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key) var parentFingerprint = buffer.readUInt32BE(5) if (depth === 0) { if (parentFingerprint !== 0x00000000) throw new Error('Invalid parent fingerprint') } // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized. // This is encoded in MSB order. (0x00000000 if master key) var index = buffer.readUInt32BE(9) if (depth === 0 && index !== 0) throw new Error('Invalid index') // 32 bytes: the chain code var chainCode = buffer.slice(13, 45) var keyPair // 33 bytes: private key data (0x00 + k) if (version === network.bip32.private) { if (buffer.readUInt8(45) !== 0x00) throw new Error('Invalid private key') var d = BigInteger.fromBuffer(buffer.slice(46, 78)) keyPair = new ECPair(d, null, { network: network }) // 33 bytes: public key data (0x02 + X or 0x03 + X) } else { var Q = ecurve.Point.decodeFrom(curve, buffer.slice(45, 78)) // Q.compressed is assumed, if somehow this assumption is broken, `new HDNode` will throw // Verify that the X coordinate in the public point corresponds to a point on the curve. // If not, the extended public key is invalid. curve.validate(Q) keyPair = new ECPair(null, Q, { network: network }) } var hd = new HDNode(keyPair, chainCode) hd.depth = depth hd.index = index hd.parentFingerprint = parentFingerprint return hd }
n/a
fromSeedBuffer = function (seed, network) { typeforce(types.tuple(types.Buffer, types.maybe(types.Network)), arguments) if (seed.length < 16) throw new TypeError('Seed should be at least 128 bits') if (seed.length > 64) throw new TypeError('Seed should be at most 512 bits') var I = createHmac('sha512', HDNode.MASTER_SECRET).update(seed).digest() var IL = I.slice(0, 32) var IR = I.slice(32) // In case IL is 0 or >= n, the master key is invalid // This is handled by the ECPair constructor var pIL = BigInteger.fromBuffer(IL) var keyPair = new ECPair(pIL, null, { network: network }) return new HDNode(keyPair, IR) }
n/a
fromSeedHex = function (hex, network) { return HDNode.fromSeedBuffer(new Buffer(hex, 'hex'), network) }
n/a
derive = function (index) { typeforce(types.UInt32, index) var isHardened = index >= HDNode.HIGHEST_BIT var data = new Buffer(37) // Hardened child if (isHardened) { if (this.isNeutered()) throw new TypeError('Could not derive hardened child key') // data = 0x00 || ser256(kpar) || ser32(index) data[0] = 0x00 this.keyPair.d.toBuffer(32).copy(data, 1) data.writeUInt32BE(index, 33) // Normal child } else { // data = serP(point(kpar)) || ser32(index) // = serP(Kpar) || ser32(index) this.keyPair.getPublicKeyBuffer().copy(data, 0) data.writeUInt32BE(index, 33) } var I = createHmac('sha512', this.chainCode).update(data).digest() var IL = I.slice(0, 32) var IR = I.slice(32) var pIL = BigInteger.fromBuffer(IL) // In case parse256(IL) >= n, proceed with the next value for i if (pIL.compareTo(curve.n) >= 0) { return this.derive(index + 1) } // Private parent key -> private child key var derivedKeyPair if (!this.isNeutered()) { // ki = parse256(IL) + kpar (mod n) var ki = pIL.add(this.keyPair.d).mod(curve.n) // In case ki == 0, proceed with the next value for i if (ki.signum() === 0) { return this.derive(index + 1) } derivedKeyPair = new ECPair(ki, null, { network: this.keyPair.network }) // Public parent key -> public child key } else { // Ki = point(parse256(IL)) + Kpar // = G*IL + Kpar var Ki = curve.G.multiply(pIL).add(this.keyPair.Q) // In case Ki is the point at infinity, proceed with the next value for i if (curve.isInfinity(Ki)) { return this.derive(index + 1) } derivedKeyPair = new ECPair(null, Ki, { network: this.keyPair.network }) } var hd = new HDNode(derivedKeyPair, IR) hd.depth = this.depth + 1 hd.index = index hd.parentFingerprint = this.getFingerprint().readUInt32BE(0) return hd }
n/a
deriveHardened = function (index) { typeforce(types.UInt31, index) // Only derives hardened private keys by default return this.derive(index + HDNode.HIGHEST_BIT) }
n/a
derivePath = function (path) { typeforce(types.BIP32Path, path) var splitPath = path.split('/') if (splitPath[0] === 'm') { if (this.parentFingerprint) { throw new Error('Not a master node') } splitPath = splitPath.slice(1) } return splitPath.reduce(function (prevHd, indexStr) { var index if (indexStr.slice(-1) === "'") { index = parseInt(indexStr.slice(0, -1), 10) return prevHd.deriveHardened(index) } else { index = parseInt(indexStr, 10) return prevHd.derive(index) } }, this) }
n/a
getAddress = function () { return this.keyPair.getAddress() }
n/a
getFingerprint = function () { return this.getIdentifier().slice(0, 4) }
n/a
getIdentifier = function () { return bcrypto.hash160(this.keyPair.getPublicKeyBuffer()) }
n/a
getNetwork = function () { return this.keyPair.getNetwork() }
n/a
getPublicKeyBuffer = function () { return this.keyPair.getPublicKeyBuffer() }
n/a
isNeutered = function () { return !(this.keyPair.d) }
n/a
neutered = function () { var neuteredKeyPair = new ECPair(null, this.keyPair.Q, { network: this.keyPair.network }) var neutered = new HDNode(neuteredKeyPair, this.chainCode) neutered.depth = this.depth neutered.index = this.index neutered.parentFingerprint = this.parentFingerprint return neutered }
n/a
sign = function (hash) { return this.keyPair.sign(hash) }
n/a
toBase58 = function (__isPrivate) { if (__isPrivate !== undefined) throw new TypeError('Unsupported argument in 2.0.0') // Version var network = this.keyPair.network var version = (!this.isNeutered()) ? network.bip32.private : network.bip32.public var buffer = new Buffer(78) // 4 bytes: version bytes buffer.writeUInt32BE(version, 0) // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, .... buffer.writeUInt8(this.depth, 4) // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key) buffer.writeUInt32BE(this.parentFingerprint, 5) // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized. // This is encoded in big endian. (0x00000000 if master key) buffer.writeUInt32BE(this.index, 9) // 32 bytes: the chain code this.chainCode.copy(buffer, 13) // 33 bytes: the public key or private key data if (!this.isNeutered()) { // 0x00 + k for private keys buffer.writeUInt8(0, 45) this.keyPair.d.toBuffer(32).copy(buffer, 46) // 33 bytes: the public key } else { // X9.62 encoding for public keys this.keyPair.getPublicKeyBuffer().copy(buffer, 45) } return base58check.encode(buffer) }
n/a
verify = function (hash, signature) { return this.keyPair.verify(hash, signature) }
n/a
function Transaction() { this.version = 1 this.locktime = 0 this.ins = [] this.outs = [] }
n/a
fromBuffer = function (buffer, __noStrict) { var offset = 0 function readSlice (n) { offset += n return buffer.slice(offset - n, offset) } function readUInt32 () { var i = buffer.readUInt32LE(offset) offset += 4 return i } function readInt32 () { var i = buffer.readInt32LE(offset) offset += 4 return i } function readUInt64 () { var i = bufferutils.readUInt64LE(buffer, offset) offset += 8 return i } function readVarInt () { var vi = varuint.decode(buffer, offset) offset += varuint.decode.bytes return vi } function readVarSlice () { return readSlice(readVarInt()) } function readVector () { var count = readVarInt() var vector = [] for (var i = 0; i < count; i++) vector.push(readVarSlice()) return vector } var tx = new Transaction() tx.version = readInt32() var marker = buffer.readUInt8(offset) var flag = buffer.readUInt8(offset + 1) var hasWitnesses = false if (marker === Transaction.ADVANCED_TRANSACTION_MARKER && flag === Transaction.ADVANCED_TRANSACTION_FLAG) { offset += 2 hasWitnesses = true } var vinLen = readVarInt() for (var i = 0; i < vinLen; ++i) { tx.ins.push({ hash: readSlice(32), index: readUInt32(), script: readVarSlice(), sequence: readUInt32(), witness: EMPTY_WITNESS }) } var voutLen = readVarInt() for (i = 0; i < voutLen; ++i) { tx.outs.push({ value: readUInt64(), script: readVarSlice() }) } if (hasWitnesses) { for (i = 0; i < vinLen; ++i) { tx.ins[i].witness = readVector() } // was this pointless? if (!tx.hasWitnesses()) throw new Error('Transaction has superfluous witness data') } tx.locktime = readUInt32() if (__noStrict) return tx if (offset !== buffer.length) throw new Error('Transaction has unexpected data') return tx }
...
// Step G
v = createHmac('sha256', k).update(v).digest()
// Step H1/H2a, ignored as tlen === qlen (256 bit)
// Step H2b
v = createHmac('sha256', k).update(v).digest()
var T = BigInteger.fromBuffer(v)
// Step H3, repeat until T is within the interval [1, n - 1] and is suitable for ECDSA
while (T.signum() <= 0 || T.compareTo(secp256k1.n) >= 0 || !checkSig(T)) {
k = createHmac('sha256', k)
.update(v)
.update(ZERO)
.digest()
...
fromHex = function (hex) { return Transaction.fromBuffer(Buffer.from(hex, 'hex')) }
n/a
isCoinbaseHash = function (buffer) { typeforce(types.Hash256bit, buffer) for (var i = 0; i < 32; ++i) { if (buffer[i] !== 0) return false } return true }
n/a
__byteLength = function (__allowWitness) { var hasWitnesses = __allowWitness && this.hasWitnesses() return ( (hasWitnesses ? 10 : 8) + varuint.encodingLength(this.ins.length) + varuint.encodingLength(this.outs.length) + this.ins.reduce(function (sum, input) { return sum + 40 + varSliceSize(input.script) }, 0) + this.outs.reduce(function (sum, output) { return sum + 8 + varSliceSize(output.script) }, 0) + (hasWitnesses ? this.ins.reduce(function (sum, input) { return sum + vectorSize(input.witness) }, 0) : 0) ) }
n/a
__toBuffer = function (buffer, initialOffset, __allowWitness) { if (!buffer) buffer = new Buffer(this.__byteLength(__allowWitness)) var offset = initialOffset || 0 function writeSlice (slice) { offset += slice.copy(buffer, offset) } function writeUInt8 (i) { offset = buffer.writeUInt8(i, offset) } function writeUInt32 (i) { offset = buffer.writeUInt32LE(i, offset) } function writeInt32 (i) { offset = buffer.writeInt32LE(i, offset) } function writeUInt64 (i) { offset = bufferutils.writeUInt64LE(buffer, i, offset) } function writeVarInt (i) { varuint.encode(i, buffer, offset) offset += varuint.encode.bytes } function writeVarSlice (slice) { writeVarInt(slice.length); writeSlice(slice) } function writeVector (vector) { writeVarInt(vector.length); vector.forEach(writeVarSlice) } writeInt32(this.version) var hasWitnesses = __allowWitness && this.hasWitnesses() if (hasWitnesses) { writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER) writeUInt8(Transaction.ADVANCED_TRANSACTION_FLAG) } writeVarInt(this.ins.length) this.ins.forEach(function (txIn) { writeSlice(txIn.hash) writeUInt32(txIn.index) writeVarSlice(txIn.script) writeUInt32(txIn.sequence) }) writeVarInt(this.outs.length) this.outs.forEach(function (txOut) { if (!txOut.valueBuffer) { writeUInt64(txOut.value) } else { writeSlice(txOut.valueBuffer) } writeVarSlice(txOut.script) }) if (hasWitnesses) { this.ins.forEach(function (input) { writeVector(input.witness) }) } writeUInt32(this.locktime) // avoid slicing unless necessary if (initialOffset !== undefined) return buffer.slice(initialOffset, offset) return buffer }
n/a
addInput = function (hash, index, sequence, scriptSig) { typeforce(types.tuple( types.Hash256bit, types.UInt32, types.maybe(types.UInt32), types.maybe(types.Buffer) ), arguments) if (types.Null(sequence)) { sequence = Transaction.DEFAULT_SEQUENCE } // Add the input and return the input's index return (this.ins.push({ hash: hash, index: index, script: scriptSig || EMPTY_SCRIPT, sequence: sequence, witness: EMPTY_WITNESS }) - 1) }
n/a
addOutput = function (scriptPubKey, value) { typeforce(types.tuple(types.Buffer, types.Satoshi), arguments) // Add the output and return the output's index return (this.outs.push({ script: scriptPubKey, value: value }) - 1) }
n/a
byteLength = function () { return this.__byteLength(true) }
n/a
clone = function () { var newTx = new Transaction() newTx.version = this.version newTx.locktime = this.locktime newTx.ins = this.ins.map(function (txIn) { return { hash: txIn.hash, index: txIn.index, script: txIn.script, sequence: txIn.sequence, witness: txIn.witness } }) newTx.outs = this.outs.map(function (txOut) { return { script: txOut.script, value: txOut.value } }) return newTx }
n/a
getHash = function () { return bcrypto.hash256(this.__toBuffer(undefined, undefined, false)) }
n/a
getId = function () { // transaction hash's are displayed in reverse order return this.getHash().reverse().toString('hex') }
n/a
hasWitnesses = function () { return this.ins.some(function (x) { return x.witness.length !== 0 }) }
n/a
hashForSignature = function (inIndex, prevOutScript, hashType) { typeforce(types.tuple(types.UInt32, types.Buffer, /* types.UInt8 */ types.Number), arguments) // https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L29 if (inIndex >= this.ins.length) return ONE // ignore OP_CODESEPARATOR var ourScript = bscript.compile(bscript.decompile(prevOutScript).filter(function (x) { return x !== opcodes.OP_CODESEPARATOR })) var txTmp = this.clone() // SIGHASH_NONE: ignore all outputs? (wildcard payee) if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) { txTmp.outs = [] // ignore sequence numbers (except at inIndex) txTmp.ins.forEach(function (input, i) { if (i === inIndex) return input.sequence = 0 }) // SIGHASH_SINGLE: ignore all outputs, except at the same index? } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE) { // https://github.com/bitcoin/bitcoin/blob/master/src/test/sighash_tests.cpp#L60 if (inIndex >= this.outs.length) return ONE // truncate outputs after txTmp.outs.length = inIndex + 1 // "blank" outputs before for (var i = 0; i < inIndex; i++) { txTmp.outs[i] = BLANK_OUTPUT } // ignore sequence numbers (except at inIndex) txTmp.ins.forEach(function (input, y) { if (y === inIndex) return input.sequence = 0 }) } // SIGHASH_ANYONECANPAY: ignore inputs entirely? if (hashType & Transaction.SIGHASH_ANYONECANPAY) { txTmp.ins = [txTmp.ins[inIndex]] txTmp.ins[0].script = ourScript // SIGHASH_ALL: only ignore input scripts } else { // "blank" others input scripts txTmp.ins.forEach(function (input) { input.script = EMPTY_SCRIPT }) txTmp.ins[inIndex].script = ourScript } // serialize and hash var buffer = new Buffer(txTmp.__byteLength(false) + 4) buffer.writeInt32LE(hashType, buffer.length - 4) txTmp.__toBuffer(buffer, 0, false) return bcrypto.hash256(buffer) }
n/a
hashForWitnessV0 = function (inIndex, prevOutScript, value, hashType) { typeforce(types.tuple(types.UInt32, types.Buffer, types.Satoshi, types.UInt32), arguments) var tbuffer, toffset function writeSlice (slice) { toffset += slice.copy(tbuffer, toffset) } function writeUInt32 (i) { toffset = tbuffer.writeUInt32LE(i, toffset) } function writeUInt64 (i) { toffset = bufferutils.writeUInt64LE(tbuffer, i, toffset) } function writeVarInt (i) { varuint.encode(i, tbuffer, toffset) toffset += varuint.encode.bytes } function writeVarSlice (slice) { writeVarInt(slice.length); writeSlice(slice) } var hashOutputs = ZERO var hashPrevouts = ZERO var hashSequence = ZERO if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) { tbuffer = new Buffer(36 * this.ins.length) toffset = 0 this.ins.forEach(function (txIn) { writeSlice(txIn.hash) writeUInt32(txIn.index) }) hashPrevouts = bcrypto.hash256(tbuffer) } if (!(hashType & Transaction.SIGHASH_ANYONECANPAY) && (hashType & 0x1f) !== Transaction.SIGHASH_SINGLE && (hashType & 0x1f) !== Transaction.SIGHASH_NONE) { tbuffer = new Buffer(4 * this.ins.length) toffset = 0 this.ins.forEach(function (txIn) { writeUInt32(txIn.sequence) }) hashSequence = bcrypto.hash256(tbuffer) } if ((hashType & 0x1f) !== Transaction.SIGHASH_SINGLE && (hashType & 0x1f) !== Transaction.SIGHASH_NONE) { var txOutsSize = this.outs.reduce(function (sum, output) { return sum + 8 + varSliceSize(output.script) }, 0) tbuffer = new Buffer(txOutsSize) toffset = 0 this.outs.forEach(function (out) { writeUInt64(out.value) writeVarSlice(out.script) }) hashOutputs = bcrypto.hash256(tbuffer) } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) { var output = this.outs[inIndex] tbuffer = new Buffer(8 + varSliceSize(output.script)) toffset = 0 writeUInt64(output.value) writeVarSlice(output.script) hashOutputs = bcrypto.hash256(tbuffer) } tbuffer = new Buffer(156 + varSliceSize(prevOutScript)) toffset = 0 var input = this.ins[inIndex] writeUInt32(this.version) writeSlice(hashPrevouts) writeSlice(hashSequence) writeSlice(input.hash) writeUInt32(input.index) writeVarSlice(prevOutScript) writeUInt64(value) writeUInt32(input.sequence) writeSlice(hashOutputs) writeUInt32(this.locktime) writeUInt32(hashType) return bcrypto.hash256(tbuffer) }
n/a
isCoinbase = function () { return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash) }
n/a
setInputScript = function (index, scriptSig) { typeforce(types.tuple(types.Number, types.Buffer), arguments) this.ins[index].script = scriptSig }
n/a
setWitness = function (index, witness) { typeforce(types.tuple(types.Number, [types.Buffer]), arguments) this.ins[index].witness = witness }
n/a
toBuffer = function (buffer, initialOffset) { return this.__toBuffer(buffer, initialOffset, true) }
...
}
var N_OVER_TWO = secp256k1.n.shiftRight(1)
function sign (hash, d) {
typeforce(types.tuple(types.Hash256bit, types.BigInt), arguments)
var x = d.toBuffer(32)
var e = BigInteger.fromBuffer(hash)
var n = secp256k1.n
var G = secp256k1.G
var r, s
deterministicGenerateK(hash, x, function (k) {
var Q = G.multiply(k)
...
toHex = function () { return this.toBuffer().toString('hex') }
n/a
function TransactionBuilder(network, maximumFeeRate) { this.prevTxMap = {} this.network = network || networks.bitcoin // WARNING: This is __NOT__ to be relied on, its just another potential safety mechanism (safety in-depth) this.maximumFeeRate = maximumFeeRate || 1000 this.inputs = [] this.tx = new Transaction() }
n/a
fromTransaction = function (transaction, network) { var txb = new TransactionBuilder(network) // Copy transaction fields txb.setVersion(transaction.version) txb.setLockTime(transaction.locktime) // Copy outputs (done first to avoid signature invalidation) transaction.outs.forEach(function (txOut) { txb.addOutput(txOut.script, txOut.value) }) // Copy inputs transaction.ins.forEach(function (txIn) { txb.__addInputUnsafe(txIn.hash, txIn.index, { sequence: txIn.sequence, script: txIn.script, witness: txIn.witness }) }) // fix some things not possible through the public API txb.inputs.forEach(function (input, i) { fixMultisigOrder(input, transaction, i) }) return txb }
n/a
__addInputUnsafe = function (txHash, vout, options) { if (Transaction.isCoinbaseHash(txHash)) { throw new Error('coinbase inputs not supported') } var prevTxOut = txHash.toString('hex') + ':' + vout if (this.prevTxMap[prevTxOut] !== undefined) throw new Error('Duplicate TxOut: ' + prevTxOut) var input = {} // derive what we can from the scriptSig if (options.script !== undefined) { input = expandInput(options.script, options.witness) } // if an input value was given, retain it if (options.value !== undefined) { input.value = options.value } // derive what we can from the previous transactions output script if (!input.prevOutScript && options.prevOutScript) { var prevOutType if (!input.pubKeys && !input.signatures) { var expanded = expandOutput(options.prevOutScript) if (expanded.pubKeys) { input.pubKeys = expanded.pubKeys input.signatures = expanded.signatures } prevOutType = expanded.scriptType } input.prevOutScript = options.prevOutScript input.prevOutType = prevOutType || bscript.classifyOutput(options.prevOutScript) } var vin = this.tx.addInput(txHash, vout, options.sequence, options.scriptSig) this.inputs[vin] = input this.prevTxMap[prevTxOut] = vin return vin }
n/a
__build = function (allowIncomplete) { if (!allowIncomplete) { if (!this.tx.ins.length) throw new Error('Transaction has no inputs') if (!this.tx.outs.length) throw new Error('Transaction has no outputs') } var tx = this.tx.clone() // Create script signatures from inputs this.inputs.forEach(function (input, i) { var scriptType = input.witnessScriptType || input.redeemScriptType || input.prevOutType if (!scriptType && !allowIncomplete) throw new Error('Transaction is not complete') var result = buildInput(input, allowIncomplete) // skip if no result if (!allowIncomplete) { if (SIGNABLE.indexOf(result.type) === -1 && result.type !== bscript.types.P2WPKH) { throw new Error(result.type + ' not supported') } } tx.setInputScript(i, result.script) tx.setWitness(i, result.witness) }) if (!allowIncomplete) { // do not rely on this, its merely a last resort if (this.__overMaximumFees(tx.byteLength())) { throw new Error('Transaction has absurd fees') } } return tx }
n/a
__canModifyInputs = function () { return this.inputs.every(function (input) { // any signatures? if (input.signatures === undefined) return true return input.signatures.every(function (signature) { if (!signature) return true var hashType = signatureHashType(signature) // if SIGHASH_ANYONECANPAY is set, signatures would not // be invalidated by more inputs return hashType & Transaction.SIGHASH_ANYONECANPAY }) }) }
n/a
__canModifyOutputs = function () { var nInputs = this.tx.ins.length var nOutputs = this.tx.outs.length return this.inputs.every(function (input) { if (input.signatures === undefined) return true return input.signatures.every(function (signature) { if (!signature) return true var hashType = signatureHashType(signature) var hashTypeMod = hashType & 0x1f if (hashTypeMod === Transaction.SIGHASH_NONE) return true if (hashTypeMod === Transaction.SIGHASH_SINGLE) { // if SIGHASH_SINGLE is set, and nInputs > nOutputs // some signatures would be invalidated by the addition // of more outputs return nInputs <= nOutputs } }) }) }
n/a
__overMaximumFees = function (bytes) { // not all inputs will have .value defined var incoming = this.inputs.reduce(function (a, x) { return a + (x.value >>> 0) }, 0) // but all outputs do, and if we have any input value // we can immediately determine if the outputs are too small var outgoing = this.tx.outs.reduce(function (a, x) { return a + x.value }, 0) var fee = incoming - outgoing var feeRate = fee / bytes return feeRate > this.maximumFeeRate }
n/a
addInput = function (txHash, vout, sequence, prevOutScript) { if (!this.__canModifyInputs()) { throw new Error('No, this would invalidate signatures') } var value // is it a hex string? if (typeof txHash === 'string') { // transaction hashs's are displayed in reverse order, un-reverse it txHash = new Buffer(txHash, 'hex').reverse() // is it a Transaction object? } else if (txHash instanceof Transaction) { var txOut = txHash.outs[vout] prevOutScript = txOut.script value = txOut.value txHash = txHash.getHash() } return this.__addInputUnsafe(txHash, vout, { sequence: sequence, prevOutScript: prevOutScript, value: value }) }
n/a
addOutput = function (scriptPubKey, value) { if (!this.__canModifyOutputs()) { throw new Error('No, this would invalidate signatures') } // Attempt to get a script if it's a base58 address string if (typeof scriptPubKey === 'string') { scriptPubKey = baddress.toOutputScript(scriptPubKey, this.network) } return this.tx.addOutput(scriptPubKey, value) }
n/a
build = function () { return this.__build(false) }
n/a
buildIncomplete = function () { return this.__build(true) }
n/a
setLockTime = function (locktime) { typeforce(types.UInt32, locktime) // if any signatures exist, throw if (this.inputs.some(function (input) { if (!input.signatures) return false return input.signatures.some(function (s) { return s }) })) { throw new Error('No, this would invalidate signatures') } this.tx.locktime = locktime }
n/a
setVersion = function (version) { typeforce(types.UInt32, version) // XXX: this might eventually become more complex depending on what the versions represent this.tx.version = version }
n/a
sign = function (vin, keyPair, redeemScript, hashType, witnessValue, witnessScript) { if (keyPair.network !== this.network) throw new Error('Inconsistent network') if (!this.inputs[vin]) throw new Error('No input at index: ' + vin) hashType = hashType || Transaction.SIGHASH_ALL var input = this.inputs[vin] // if redeemScript was previously provided, enforce consistency if (input.redeemScript !== undefined && redeemScript && !input.redeemScript.equals(redeemScript)) { throw new Error('Inconsistent redeemScript') } var kpPubKey = keyPair.getPublicKeyBuffer() if (!canSign(input)) { prepareInput(input, kpPubKey, redeemScript, witnessValue, witnessScript) if (!canSign(input)) throw Error(input.prevOutType + ' not supported') } // ready to sign var signatureHash if (input.witness) { signatureHash = this.tx.hashForWitnessV0(vin, input.signScript, witnessValue, hashType) } else { signatureHash = this.tx.hashForSignature(vin, input.signScript, hashType) } // enforce in order signing of public keys var signed = input.pubKeys.some(function (pubKey, i) { if (!kpPubKey.equals(pubKey)) return false if (input.signatures[i]) throw new Error('Signature already exists') input.signatures[i] = keyPair.sign(signatureHash).toScriptSignature(hashType) return true }) if (!signed) throw new Error('Key pair cannot sign for this input') }
n/a
function fromBase58Check(address) { var payload = bs58check.decode(address) if (payload.length < 21) throw new TypeError(address + ' is too short') if (payload.length > 21) throw new TypeError(address + ' is too long') var version = payload[0] var hash = payload.slice(1) return { hash: hash, version: version } }
n/a
function fromOutputScript(outputScript, network) { network = network || networks.bitcoin if (bscript.pubKeyHash.output.check(outputScript)) return toBase58Check(bscript.compile(outputScript).slice(3, 23), network.pubKeyHash ) if (bscript.scriptHash.output.check(outputScript)) return toBase58Check(bscript.compile(outputScript).slice(2, 22), network.scriptHash ) throw new Error(bscript.toASM(outputScript) + ' has no matching Address') }
n/a
function toBase58Check(hash, version) { typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments) var payload = new Buffer(21) payload.writeUInt8(version, 0) hash.copy(payload, 1) return bs58check.encode(payload) }
n/a
function toOutputScript(address, network) { network = network || networks.bitcoin var decode = fromBase58Check(address) if (decode.version === network.pubKeyHash) return bscript.pubKeyHash.output.encode(decode.hash) if (decode.version === network.scriptHash) return bscript.scriptHash.output.encode(decode.hash) throw new Error(address + ' has no matching Script') }
n/a
function encodingLength(i) { return i < OPS.OP_PUSHDATA1 ? 1 : i <= 0xff ? 2 : i <= 0xffff ? 3 : 5 }
n/a
function decode(buffer, offset) { var opcode = buffer.readUInt8(offset) var number, size // ~6 bit if (opcode < OPS.OP_PUSHDATA1) { number = opcode size = 1 // 8 bit } else if (opcode === OPS.OP_PUSHDATA1) { if (offset + 2 > buffer.length) return null number = buffer.readUInt8(offset + 1) size = 2 // 16 bit } else if (opcode === OPS.OP_PUSHDATA2) { if (offset + 3 > buffer.length) return null number = buffer.readUInt16LE(offset + 1) size = 3 // 32 bit } else { if (offset + 5 > buffer.length) return null if (opcode !== OPS.OP_PUSHDATA4) throw new Error('Unexpected opcode') number = buffer.readUInt32LE(offset + 1) size = 5 } return { opcode: opcode, number: number, size: size } }
n/a
function readUInt64LE(buffer, offset) { var a = buffer.readUInt32LE(offset) var b = buffer.readUInt32LE(offset + 4) b *= 0x100000000 verifuint(b + a, 0x001fffffffffffff) return b + a }
n/a
function readVarInt(buffer, offset) { var result = varuint.decode(buffer, offset) return { number: result, size: varuint.decode.bytes } }
n/a
function encode(number, buffer, offset) { checkUInt53(number) if (!buffer) buffer = new Buffer(encodingLength(number)) if (!Buffer.isBuffer(buffer)) throw new TypeError('buffer must be a Buffer instance') if (!offset) offset = 0 // 8 bit if (number < 0xfd) { buffer.writeUInt8(number, offset) encode.bytes = 1 // 16 bit } else if (number <= 0xffff) { buffer.writeUInt8(0xfd, offset) buffer.writeUInt16LE(number, offset + 1) encode.bytes = 3 // 32 bit } else if (number <= 0xffffffff) { buffer.writeUInt8(0xfe, offset) buffer.writeUInt32LE(number, offset + 1) encode.bytes = 5 // 64 bit } else { buffer.writeUInt8(0xff, offset) buffer.writeUInt32LE(number >>> 0, offset + 1) buffer.writeUInt32LE((number / 0x100000000) | 0, offset + 5) encode.bytes = 9 } return buffer }
n/a
function encodingLength(number) { checkUInt53(number) return ( number < 0xfd ? 1 : number <= 0xffff ? 3 : number <= 0xffffffff ? 5 : 9 ) }
n/a
function encode(buffer, number, offset) { var size = encodingLength(number) // ~6 bit if (size === 1) { buffer.writeUInt8(number, offset) // 8 bit } else if (size === 2) { buffer.writeUInt8(OPS.OP_PUSHDATA1, offset) buffer.writeUInt8(number, offset + 1) // 16 bit } else if (size === 3) { buffer.writeUInt8(OPS.OP_PUSHDATA2, offset) buffer.writeUInt16LE(number, offset + 1) // 32 bit } else { buffer.writeUInt8(OPS.OP_PUSHDATA4, offset) buffer.writeUInt32LE(number, offset + 1) } return size }
n/a
function writeUInt64LE(buffer, value, offset) { verifuint(value, 0x001fffffffffffff) buffer.writeInt32LE(value & -1, offset) buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4) return offset + 8 }
n/a
function writeVarInt(buffer, number, offset) { varuint.encode(number, buffer, offset) return varuint.encode.bytes }
n/a
function hash160(buffer) { return ripemd160(sha256(buffer)) }
n/a
function hash256(buffer) { return sha256(sha256(buffer)) }
n/a
function ripemd160(buffer) { return createHash('rmd160').update(buffer).digest() }
n/a
function sha1(buffer) { return createHash('sha1').update(buffer).digest() }
n/a
function sha256(buffer) { return createHash('sha256').update(buffer).digest() }
n/a
function deterministicGenerateK(hash, x, checkSig) { typeforce(types.tuple( types.Hash256bit, types.Buffer256bit, types.Function ), arguments) var k = new Buffer(32) var v = new Buffer(32) // Step A, ignored as hash already provided // Step B v.fill(1) // Step C k.fill(0) // Step D k = createHmac('sha256', k) .update(v) .update(ZERO) .update(x) .update(hash) .digest() // Step E v = createHmac('sha256', k).update(v).digest() // Step F k = createHmac('sha256', k) .update(v) .update(ONE) .update(x) .update(hash) .digest() // Step G v = createHmac('sha256', k).update(v).digest() // Step H1/H2a, ignored as tlen === qlen (256 bit) // Step H2b v = createHmac('sha256', k).update(v).digest() var T = BigInteger.fromBuffer(v) // Step H3, repeat until T is within the interval [1, n - 1] and is suitable for ECDSA while (T.signum() <= 0 || T.compareTo(secp256k1.n) >= 0 || !checkSig(T)) { k = createHmac('sha256', k) .update(v) .update(ZERO) .digest() v = createHmac('sha256', k).update(v).digest() // Step H1/H2a, again, ignored as tlen === qlen (256 bit) // Step H2b again v = createHmac('sha256', k).update(v).digest() T = BigInteger.fromBuffer(v) } return T }
n/a
function sign(hash, d) { typeforce(types.tuple(types.Hash256bit, types.BigInt), arguments) var x = d.toBuffer(32) var e = BigInteger.fromBuffer(hash) var n = secp256k1.n var G = secp256k1.G var r, s deterministicGenerateK(hash, x, function (k) { var Q = G.multiply(k) if (secp256k1.isInfinity(Q)) return false r = Q.affineX.mod(n) if (r.signum() === 0) return false s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n) if (s.signum() === 0) return false return true }) // enforce low S values, see bip62: 'low s values in signatures' if (s.compareTo(N_OVER_TWO) > 0) { s = n.subtract(s) } return new ECSignature(r, s) }
n/a
function verify(hash, signature, Q) { typeforce(types.tuple( types.Hash256bit, types.ECSignature, types.ECPoint ), arguments) var n = secp256k1.n var G = secp256k1.G var r = signature.r var s = signature.s // 1.4.1 Enforce r and s are both integers in the interval [1, n − 1] if (r.signum() <= 0 || r.compareTo(n) >= 0) return false if (s.signum() <= 0 || s.compareTo(n) >= 0) return false // 1.4.2 H = Hash(M), already done by the user // 1.4.3 e = H var e = BigInteger.fromBuffer(hash) // Compute s^-1 var sInv = s.modInverse(n) // 1.4.4 Compute u1 = es^−1 mod n // u2 = rs^−1 mod n var u1 = e.multiply(sInv).mod(n) var u2 = r.multiply(sInv).mod(n) // 1.4.5 Compute R = (xR, yR) // R = u1G + u2Q var R = G.multiplyTwo(u1, Q, u2) // 1.4.5 (cont.) Enforce R is not at infinity if (secp256k1.isInfinity(R)) return false // 1.4.6 Convert the field element R.x to an integer var xR = R.affineX // 1.4.7 Set v = xR mod n var v = xR.mod(n) // 1.4.8 If v = r, output "valid", and if v != r, output "invalid" return v.equals(r) }
n/a
function classifyInput(script, allowIncomplete) { // XXX: optimization, below functions .decompile before use var chunks = decompile(script) if (pubKeyHash.input.check(chunks)) return types.P2PKH if (scriptHash.input.check(chunks, allowIncomplete)) return types.P2SH if (multisig.input.check(chunks, allowIncomplete)) return types.MULTISIG if (pubKey.input.check(chunks)) return types.P2PK return types.NONSTANDARD }
n/a
function classifyOutput(script) { if (witnessPubKeyHash.output.check(script)) return types.P2WPKH if (witnessScriptHash.output.check(script)) return types.P2WSH if (pubKeyHash.output.check(script)) return types.P2PKH if (scriptHash.output.check(script)) return types.P2SH // XXX: optimization, below functions .decompile before use var chunks = decompile(script) if (multisig.output.check(chunks)) return types.MULTISIG if (pubKey.output.check(chunks)) return types.P2PK if (witnessCommitment.output.check(chunks)) return types.WITNESS_COMMITMENT if (nullData.output.check(chunks)) return types.NULLDATA return types.NONSTANDARD }
n/a
function classifyWitness(script, allowIncomplete) { // XXX: optimization, below functions .decompile before use var chunks = decompile(script) if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH if (witnessScriptHash.input.check(chunks, allowIncomplete)) return types.P2WSH return types.NONSTANDARD }
n/a
function check(script, allowIncomplete) { var chunks = bscript.decompile(script) if (chunks.length < 2) return false if (chunks[0] !== OPS.OP_0) return false if (allowIncomplete) { return chunks.slice(1).every(partialSignature) } return chunks.slice(1).every(bscript.isCanonicalSignature) }
...
P2SH: 'scripthash',
P2WPKH: 'witnesspubkeyhash',
P2WSH: 'witnessscripthash',
WITNESS_COMMITMENT: 'witnesscommitment'
}
function classifyOutput (script) {
if (witnessPubKeyHash.output.check(script)) return types.P2WPKH
if (witnessScriptHash.output.check(script)) return types.P2WSH
if (pubKeyHash.output.check(script)) return types.P2PKH
if (scriptHash.output.check(script)) return types.P2SH
// XXX: optimization, below functions .decompile before use
var chunks = decompile(script)
if (multisig.output.check(chunks)) return types.MULTISIG
...
function decode(buffer, allowIncomplete) { var stack = bscript.decompile(buffer) return decodeStack(stack, allowIncomplete) }
...
}
check.toJSON = function () { return 'multisig input' }
function encodeStack (signatures, scriptPubKey) {
typeforce([partialSignature], signatures)
if (scriptPubKey) {
var scriptData = bscript.multisig.output.decode(scriptPubKey)
if (signatures.length < scriptData.m) {
throw new TypeError('Not enough signatures provided')
}
if (signatures.length > scriptData.pubKeys.length) {
throw new TypeError('Too many signatures provided')
...
function decodeStack(stack, allowIncomplete) { typeforce(check, stack, allowIncomplete) return stack.slice(1) }
n/a
function encode(signatures, scriptPubKey) { return bscript.compile(encodeStack(signatures, scriptPubKey)) }
n/a
function encodeStack(signatures, scriptPubKey) { typeforce([partialSignature], signatures) if (scriptPubKey) { var scriptData = bscript.multisig.output.decode(scriptPubKey) if (signatures.length < scriptData.m) { throw new TypeError('Not enough signatures provided') } if (signatures.length > scriptData.pubKeys.length) { throw new TypeError('Too many signatures provided') } } return [].concat(new Buffer(0), signatures) }
n/a
function check(script, allowIncomplete) { var chunks = bscript.decompile(script) if (chunks.length < 4) return false if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false if (!types.Number(chunks[0])) return false if (!types.Number(chunks[chunks.length - 2])) return false var m = chunks[0] - OP_INT_BASE var n = chunks[chunks.length - 2] - OP_INT_BASE if (m <= 0) return false if (n > 16) return false if (m > n) return false if (n !== chunks.length - 3) return false if (allowIncomplete) return true var keys = chunks.slice(1, -2) return keys.every(bscript.isCanonicalPubKey) }
...
P2SH: 'scripthash',
P2WPKH: 'witnesspubkeyhash',
P2WSH: 'witnessscripthash',
WITNESS_COMMITMENT: 'witnesscommitment'
}
function classifyOutput (script) {
if (witnessPubKeyHash.output.check(script)) return types.P2WPKH
if (witnessScriptHash.output.check(script)) return types.P2WSH
if (pubKeyHash.output.check(script)) return types.P2PKH
if (scriptHash.output.check(script)) return types.P2SH
// XXX: optimization, below functions .decompile before use
var chunks = decompile(script)
if (multisig.output.check(chunks)) return types.MULTISIG
...
function decode(buffer, allowIncomplete) { var chunks = bscript.decompile(buffer) typeforce(check, chunks, allowIncomplete) return { m: chunks[0] - OP_INT_BASE, pubKeys: chunks.slice(1, -2) } }
...
}
check.toJSON = function () { return 'multisig input' }
function encodeStack (signatures, scriptPubKey) {
typeforce([partialSignature], signatures)
if (scriptPubKey) {
var scriptData = bscript.multisig.output.decode(scriptPubKey)
if (signatures.length < scriptData.m) {
throw new TypeError('Not enough signatures provided')
}
if (signatures.length > scriptData.pubKeys.length) {
throw new TypeError('Too many signatures provided')
...
function encode(m, pubKeys) { typeforce({ m: types.Number, pubKeys: [bscript.isCanonicalPubKey] }, { m: m, pubKeys: pubKeys }) var n = pubKeys.length if (n < m) throw new TypeError('Not enough pubKeys provided') return bscript.compile([].concat( OP_INT_BASE + m, pubKeys, OP_INT_BASE + n, OPS.OP_CHECKMULTISIG )) }
n/a
function classifyInput(script, allowIncomplete) { // XXX: optimization, below functions .decompile before use var chunks = decompile(script) if (pubKeyHash.input.check(chunks)) return types.P2PKH if (scriptHash.input.check(chunks, allowIncomplete)) return types.P2SH if (multisig.input.check(chunks, allowIncomplete)) return types.MULTISIG if (pubKey.input.check(chunks)) return types.P2PK return types.NONSTANDARD }
n/a
function classifyOutput(script) { if (witnessPubKeyHash.output.check(script)) return types.P2WPKH if (witnessScriptHash.output.check(script)) return types.P2WSH if (pubKeyHash.output.check(script)) return types.P2PKH if (scriptHash.output.check(script)) return types.P2SH // XXX: optimization, below functions .decompile before use var chunks = decompile(script) if (multisig.output.check(chunks)) return types.MULTISIG if (pubKey.output.check(chunks)) return types.P2PK if (witnessCommitment.output.check(chunks)) return types.WITNESS_COMMITMENT if (nullData.output.check(chunks)) return types.NULLDATA return types.NONSTANDARD }
n/a
function classifyWitness(script, allowIncomplete) { // XXX: optimization, below functions .decompile before use var chunks = decompile(script) if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH if (witnessScriptHash.input.check(chunks, allowIncomplete)) return types.P2WSH return types.NONSTANDARD }
n/a
function compile(chunks) { // TODO: remove me if (Buffer.isBuffer(chunks)) return chunks typeforce(types.Array, chunks) var bufferSize = chunks.reduce(function (accum, chunk) { // data chunk if (Buffer.isBuffer(chunk)) { // adhere to BIP62.3, minimal push policy if (chunk.length === 1 && (chunk[0] === 0x81 || (chunk[0] >= 1 && chunk[0] <= 16))) { return accum + 1 } return accum + pushdata.encodingLength(chunk.length) + chunk.length } // opcode return accum + 1 }, 0.0) var buffer = new Buffer(bufferSize) var offset = 0 chunks.forEach(function (chunk) { // data chunk if (Buffer.isBuffer(chunk)) { // adhere to BIP62.3, minimal push policy if (chunk.length === 1 && chunk[0] >= 1 && chunk[0] <= 16) { var opcode = OP_INT_BASE + chunk[0] buffer.writeUInt8(opcode, offset) offset += 1 return } if (chunk.length === 1 && chunk[0] === 0x81) { buffer.writeUInt8(OPS.OP_1NEGATE, offset) offset += 1 return } offset += pushdata.encode(buffer, chunk.length, offset) chunk.copy(buffer, offset) offset += chunk.length // opcode } else { buffer.writeUInt8(chunk, offset) offset += 1 } }) if (offset !== buffer.length) throw new Error('Could not decode chunks') return buffer }
...
}
// external dependent types
var BigInt = typeforce.quacksLike('BigInteger')
var ECPoint = typeforce.quacksLike('Point')
// exposed, external API
var ECSignature = typeforce.compile({ r: BigInt, s: BigInt })
var Network = typeforce.compile({
messagePrefix: typeforce.oneOf(typeforce.Buffer, typeforce.String),
bip32: {
public: typeforce.UInt32,
private: typeforce.UInt32
},
pubKeyHash: typeforce.UInt8,
...
function decompile(buffer) { // TODO: remove me if (types.Array(buffer)) return buffer typeforce(types.Buffer, buffer) var chunks = [] var i = 0 while (i < buffer.length) { var opcode = buffer[i] // data chunk if ((opcode > OPS.OP_0) && (opcode <= OPS.OP_PUSHDATA4)) { var d = pushdata.decode(buffer, i) // did reading a pushDataInt fail? empty script if (d === null) return [] i += d.size // attempt to read too much data? empty script if (i + d.number > buffer.length) return [] var data = buffer.slice(i, i + d.number) i += d.number chunks.push(data) // opcode } else { chunks.push(opcode) i += 1 } } return chunks }
...
var OPS = require('bitcoin-ops')
function partialSignature (value) {
return value === OPS.OP_0 || bscript.isCanonicalSignature(value)
}
function check (script, allowIncomplete) {
var chunks = bscript.decompile(script)
if (chunks.length < 2) return false
if (chunks[0] !== OPS.OP_0) return false
if (allowIncomplete) {
return chunks.slice(1).every(partialSignature)
}
...
function fromASM(asm) { typeforce(types.String, asm) return compile(asm.split(' ').map(function (chunkStr) { // opcode? if (OPS[chunkStr] !== undefined) return OPS[chunkStr] typeforce(types.Hex, chunkStr) // data! return new Buffer(chunkStr, 'hex') })) }
n/a
function isCanonicalPubKey(buffer) { if (!Buffer.isBuffer(buffer)) return false if (buffer.length < 33) return false switch (buffer[0]) { case 0x02: case 0x03: return buffer.length === 33 case 0x04: return buffer.length === 65 } return false }
n/a
function isCanonicalSignature(buffer) { if (!Buffer.isBuffer(buffer)) return false if (!isDefinedHashType(buffer[buffer.length - 1])) return false return bip66.check(buffer.slice(0, -1)) }
...
// OP_0 [signatures ...]
var bscript = require('../../script')
var typeforce = require('typeforce')
var OPS = require('bitcoin-ops')
function partialSignature (value) {
return value === OPS.OP_0 || bscript.isCanonicalSignature(value)
}
function check (script, allowIncomplete) {
var chunks = bscript.decompile(script)
if (chunks.length < 2) return false
if (chunks[0] !== OPS.OP_0) return false
...
function isDefinedHashType(hashType) { var hashTypeMod = hashType & ~0x80 // return hashTypeMod > SIGHASH_ALL && hashTypeMod < SIGHASH_SINGLE return hashTypeMod > 0x00 && hashTypeMod < 0x04 }
n/a
function isPushOnly(value) { return types.Array(value) && value.every(isPushOnlyChunk) }
n/a
function toASM(chunks) { if (Buffer.isBuffer(chunks)) { chunks = decompile(chunks) } return chunks.map(function (chunk) { // data? if (Buffer.isBuffer(chunk)) return chunk.toString('hex') // opcode! return REVERSE_OPS[chunk] }).join(' ') }
n/a
function toStack(chunks) { chunks = decompile(chunks) typeforce(isPushOnly, chunks) return chunks.map(function (op) { if (Buffer.isBuffer(op)) return op if (op === OPS.OP_0) return new Buffer(0) return scriptNumber.encode(op - OP_INT_BASE) }) }
n/a
function decode(buffer, maxLength, minimal) { maxLength = maxLength || 4 minimal = minimal === undefined ? true : minimal var length = buffer.length if (length === 0) return 0 if (length > maxLength) throw new TypeError('Script number overflow') if (minimal) { if ((buffer[length - 1] & 0x7f) === 0) { if (length <= 1 || (buffer[length - 2] & 0x80) === 0) throw new Error('Non-minimally encoded script number') } } // 40-bit if (length === 5) { var a = buffer.readUInt32LE(0) var b = buffer.readUInt8(4) if (b & 0x80) return -((b & ~0x80) * 0x100000000 + a) return b * 0x100000000 + a } var result = 0 // 32-bit / 24-bit / 16-bit / 8-bit for (var i = 0; i < length; ++i) { result |= buffer[i] << (8 * i) } if (buffer[length - 1] & 0x80) return -(result & ~(0x80 << (8 * (length - 1)))) return result }
...
}
check.toJSON = function () { return 'multisig input' }
function encodeStack (signatures, scriptPubKey) {
typeforce([partialSignature], signatures)
if (scriptPubKey) {
var scriptData = bscript.multisig.output.decode(scriptPubKey)
if (signatures.length < scriptData.m) {
throw new TypeError('Not enough signatures provided')
}
if (signatures.length > scriptData.pubKeys.length) {
throw new TypeError('Too many signatures provided')
...
function encode(number) { var value = Math.abs(number) var size = scriptNumSize(value) var buffer = new Buffer(size) var negative = number < 0 for (var i = 0; i < size; ++i) { buffer.writeUInt8(value & 0xff, i) value >>= 8 } if (buffer[size - 1] & 0x80) { buffer.writeUInt8(negative ? 0x80 : 0x00, size - 1) } else if (negative) { buffer[size - 1] |= 0x80 } return buffer }
n/a
Array = function (value) { return value !== null && value !== undefined && value.constructor === Array }
n/a
function BIP32Path(value) { return typeforce.String(value) && value.match(/^(m\/)?(\d+'?\/)*\d+'?$/) }
n/a
function _quacksLike(value) { return type === getValueTypeName(value) }
n/a
Boolean = function (value) { return typeof value === 'boolean' }
n/a
function _Buffer(value) { return Buffer.isBuffer(value) }
n/a
function BufferN(value) { if (!Buffer.isBuffer(value)) return false if (value.length !== length) { throw errors.tfCustomError('Buffer(Length: ' + length + ')', 'Buffer(Length: ' + value.length + ')') } return true }
n/a
function _BufferN(length) { function BufferN (value) { if (!Buffer.isBuffer(value)) return false if (value.length !== length) { throw errors.tfCustomError('Buffer(Length: ' + length + ')', 'Buffer(Length: ' + value.length + ')') } return true } BufferN.toJSON = function () { return 'Buffer' } return BufferN }
...
wif: typeforce.UInt8
})
// extend typeforce types with ours
var types = {
BigInt: BigInt,
BIP32Path: BIP32Path,
Buffer256bit: typeforce.BufferN(32),
ECPoint: ECPoint,
ECSignature: ECSignature,
Hash160bit: typeforce.BufferN(20),
Hash256bit: typeforce.BufferN(32),
Network: Network,
Satoshi: Satoshi,
UInt31: UInt31
...
function _quacksLike(value) { return type === getValueTypeName(value) }
n/a
function _object(value, strict) { if (!NATIVE.Object(value)) return false if (NATIVE.Null(value)) return false var propertyName try { for (propertyName in type) { var propertyType = type[propertyName] var propertyValue = value[propertyName] typeforce(propertyType, propertyValue, strict) } } catch (e) { throw tfSubError(e, propertyName) } if (strict) { for (propertyName in value) { if (type[propertyName]) continue throw new TfPropertyTypeError(undefined, propertyName) } } return true }
n/a
function Finite(value) { return typeof value === 'number' && isFinite(value) }
n/a
Function = function (value) { return typeof value === 'function' }
n/a
function BufferN(value) { if (!Buffer.isBuffer(value)) return false if (value.length !== length) { throw errors.tfCustomError('Buffer(Length: ' + length + ')', 'Buffer(Length: ' + value.length + ')') } return true }
n/a
function BufferN(value) { if (!Buffer.isBuffer(value)) return false if (value.length !== length) { throw errors.tfCustomError('Buffer(Length: ' + length + ')', 'Buffer(Length: ' + value.length + ')') } return true }
n/a
function Hex(value) { return typeof value === 'string' && /^([0-9a-f]{2})+$/i.test(value) }
n/a
function _HexN(length) { function HexN (value) { if (!Hex(value)) return false if (value.length !== length) { throw errors.tfCustomError('Hex(Length: ' + length + ')', 'Hex(Length: ' + value.length + ')') } return true } HexN.toJSON = function () { return 'Hex' } return HexN }
n/a
function Int16(value) { return ((value << 16) >> 16) === value }
n/a
function Int32(value) { return (value | 0) === value }
n/a
function Int8(value) { return ((value << 24) >> 24) === value }
n/a
function _object(value, strict) { if (!NATIVE.Object(value)) return false if (NATIVE.Null(value)) return false var propertyName try { for (propertyName in type) { var propertyType = type[propertyName] var propertyValue = value[propertyName] typeforce(propertyType, propertyValue, strict) } } catch (e) { throw tfSubError(e, propertyName) } if (strict) { for (propertyName in value) { if (type[propertyName]) continue throw new TfPropertyTypeError(undefined, propertyName) } } return true }
n/a
Null = function (value) { return value === undefined || value === null }
n/a
Number = function (value) { return typeof value === 'number' }
...
var OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1
function check (script, allowIncomplete) {
var chunks = bscript.decompile(script)
if (chunks.length < 4) return false
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false
if (!types.Number(chunks[0])) return false
if (!types.Number(chunks[chunks.length - 2])) return false
var m = chunks[0] - OP_INT_BASE
var n = chunks[chunks.length - 2] - OP_INT_BASE
if (m <= 0) return false
if (n > 16) return false
if (m > n) return false
...
Object = function (value) { return typeof value === 'object' }
n/a
function Satoshi(value) { return typeforce.UInt53(value) && value <= SATOSHI_MAX }
n/a
String = function (value) { return typeof value === 'string' }
...
var UINT31_MAX = Math.pow(2, 31) - 1
function UInt31 (value) {
return typeforce.UInt32(value) && value <= UINT31_MAX
}
function BIP32Path (value) {
return typeforce.String(value) && value.match(/^(m\/)?(\d+'?\/)*\d+
x27;?$/)
}
BIP32Path.toJSON = function () { return 'BIP32 derivation path' }
var SATOSHI_MAX = 21 * 1e14
function Satoshi (value) {
return typeforce.UInt53(value) && value <= SATOSHI_MAX
}
...
function TfPropertyTypeError(type, property, label, value, error, valueTypeName) { this.__error = error || Error.call(this) this.__label = label this.__property = property this.__type = type this.__value = value this.__valueTypeName = valueTypeName var message Object.defineProperty(this, 'message', { enumerable: true, get: function () { if (message) return message if (type) { valueTypeName = valueTypeName || getValueTypeName(value) message = tfPropertyErrorString(type, label, property, value, valueTypeName) } else { message = 'Unexpected property "' + property + '"' } return message } }) }
n/a
function TfTypeError(type, value, valueTypeName) { this.__error = Error.call(this) this.__type = type this.__value = value this.__valueTypeName = valueTypeName var message Object.defineProperty(this, 'message', { enumerable: true, get: function () { if (message) return message valueTypeName = valueTypeName || getValueTypeName(value) message = tfErrorString(type, value, valueTypeName) return message } }) }
n/a
function UInt16(value) { return (value & 0xffff) === value }
n/a
function UInt31(value) { return typeforce.UInt32(value) && value <= UINT31_MAX }
n/a
function UInt32(value) { return (value >>> 0) === value }
...
var typeforce = require('typeforce')
var UINT31_MAX = Math.pow(2, 31) - 1
function UInt31 (value) {
return typeforce.UInt32(value) && value <= UINT31_MAX
}
function BIP32Path (value) {
return typeforce.String(value) && value.match(/^(m\/)?(\d+'?\/)*\d+'?$/)
}
BIP32Path.toJSON = function () { return 'BIP32 derivation path' }
...
function UInt53(value) { return typeof value === 'number' && value >= 0 && value <= UINT53_MAX && Math.floor(value) === value }
...
function BIP32Path (value) {
return typeforce.String(value) && value.match(/^(m\/)?(\d+'?\/)*\d+'?$/)
}
BIP32Path.toJSON = function () { return 'BIP32 derivation path' }
var SATOSHI_MAX = 21 * 1e14
function Satoshi (value) {
return typeforce.UInt53(value) && value <= SATOSHI_MAX
}
// external dependent types
var BigInt = typeforce.quacksLike('BigInteger')
var ECPoint = typeforce.quacksLike('Point')
// exposed, external API
...
function UInt8(value) { return (value & 0xff) === value }
n/a
function arrayOf(type) { type = compile(type) function _arrayOf (array, strict) { if (!NATIVE.Array(array)) return false return array.every(function (value, i) { try { return typeforce(type, value, strict) } catch (e) { throw tfSubError(e, i) } }) } _arrayOf.toJSON = function () { return '[' + tfJSON(type) + ']' } return _arrayOf }
n/a
function __async(type, value, strict, callback) { // default to falsy strict if using shorthand overload if (typeof strict === 'function') return __async(type, value, false, strict) try { typeforce(type, value, strict) } catch (e) { return callback(e) } callback() }
n/a
function compile(type) { if (NATIVE.String(type)) { if (type[0] === '?') return TYPES.maybe(compile(type.slice(1))) return NATIVE[type] || TYPES.quacksLike(type) } else if (type && NATIVE.Object(type)) { if (NATIVE.Array(type)) return TYPES.arrayOf(compile(type[0])) return TYPES.object(type) } else if (NATIVE.Function(type)) { return type } return TYPES.value(type) }
...
}
// external dependent types
var BigInt = typeforce.quacksLike('BigInteger')
var ECPoint = typeforce.quacksLike('Point')
// exposed, external API
var ECSignature = typeforce.compile({ r: BigInt, s: BigInt })
var Network = typeforce.compile({
messagePrefix: typeforce.oneOf(typeforce.Buffer, typeforce.String),
bip32: {
public: typeforce.UInt32,
private: typeforce.UInt32
},
pubKeyHash: typeforce.UInt8,
...
function map(propertyType, propertyKeyType) { propertyType = compile(propertyType) if (propertyKeyType) propertyKeyType = compile(propertyKeyType) function _map (value, strict) { if (!NATIVE.Object(value, strict)) return false if (NATIVE.Null(value, strict)) return false for (var propertyName in value) { try { if (propertyKeyType) { typeforce(propertyKeyType, propertyName, strict) } } catch (e) { throw tfSubError(e, propertyName, 'key') } try { var propertyValue = value[propertyName] typeforce(propertyType, propertyValue, strict) } catch (e) { throw tfSubError(e, propertyName) } } return true } if (propertyKeyType) { _map.toJSON = function () { return '{' + tfJSON(propertyKeyType) + ': ' + tfJSON(propertyType) + '}' } } else { _map.toJSON = function () { return '{' + tfJSON(propertyType) + '}' } } return _map }
n/a
function maybe(type) { type = compile(type) function _maybe (value, strict) { return NATIVE.Null(value) || type(value, strict, maybe) } _maybe.toJSON = function () { return '?' + tfJSON(type) } return _maybe }
n/a
function object(uncompiled) { var type = {} for (var typePropertyName in uncompiled) { type[typePropertyName] = compile(uncompiled[typePropertyName]) } function _object (value, strict) { if (!NATIVE.Object(value)) return false if (NATIVE.Null(value)) return false var propertyName try { for (propertyName in type) { var propertyType = type[propertyName] var propertyValue = value[propertyName] typeforce(propertyType, propertyValue, strict) } } catch (e) { throw tfSubError(e, propertyName) } if (strict) { for (propertyName in value) { if (type[propertyName]) continue throw new TfPropertyTypeError(undefined, propertyName) } } return true } _object.toJSON = function () { return tfJSON(type) } return _object }
n/a
function oneOf() { var types = [].slice.call(arguments).map(compile) function _oneOf (value, strict) { return types.some(function (type) { try { return typeforce(type, value, strict) } catch (e) { return false } }) } _oneOf.toJSON = function () { return types.map(tfJSON).join('|') } return _oneOf }
...
// external dependent types
var BigInt = typeforce.quacksLike('BigInteger')
var ECPoint = typeforce.quacksLike('Point')
// exposed, external API
var ECSignature = typeforce.compile({ r: BigInt, s: BigInt })
var Network = typeforce.compile({
messagePrefix: typeforce.oneOf(typeforce.Buffer, typeforce.String),
bip32: {
public: typeforce.UInt32,
private: typeforce.UInt32
},
pubKeyHash: typeforce.UInt8,
scriptHash: typeforce.UInt8,
wif: typeforce.UInt8
...
function quacksLike(type) { function _quacksLike (value) { return type === getValueTypeName(value) } _quacksLike.toJSON = function () { return type } return _quacksLike }
...
var SATOSHI_MAX = 21 * 1e14
function Satoshi (value) {
return typeforce.UInt53(value) && value <= SATOSHI_MAX
}
// external dependent types
var BigInt = typeforce.quacksLike('BigInteger')
var ECPoint = typeforce.quacksLike('Point')
// exposed, external API
var ECSignature = typeforce.compile({ r: BigInt, s: BigInt })
var Network = typeforce.compile({
messagePrefix: typeforce.oneOf(typeforce.Buffer, typeforce.String),
bip32: {
...
function tuple() { var types = [].slice.call(arguments).map(compile) function _tuple (values, strict) { return types.every(function (type, i) { try { return typeforce(type, values[i], strict) } catch (e) { throw tfSubError(e, i) } }) && (!strict || values.length === arguments.length) } _tuple.toJSON = function () { return '(' + types.map(tfJSON).join(', ') + ')' } return _tuple }
...
var ONE = new Buffer([1])
var ecurve = require('ecurve')
var secp256k1 = ecurve.getCurveByName('secp256k1')
// https://tools.ietf.org/html/rfc6979#section-3.2
function deterministicGenerateK (hash, x, checkSig) {
typeforce(types.tuple(
types.Hash256bit,
types.Buffer256bit,
types.Function
), arguments)
var k = new Buffer(32)
var v = new Buffer(32)
...
function value(expected) { function _value (actual) { return actual === expected } _value.toJSON = function () { return expected } return _value }
n/a