From fdf0006fdeb54f6bcd6d4e244b4ba5eb354ace81 Mon Sep 17 00:00:00 2001 From: junderw Date: Sat, 29 Dec 2018 01:55:07 +0900 Subject: [PATCH] Add strictNullChecks --- src/address.ts | 4 +- src/ecpair.ts | 16 ++++---- src/payments/embed.ts | 8 ++-- src/payments/lazy.ts | 2 +- src/payments/p2ms.ts | 32 ++++++++-------- src/payments/p2pk.ts | 10 ++--- src/payments/p2pkh.ts | 18 ++++----- src/payments/p2sh.ts | 21 ++++++----- src/payments/p2wpkh.ts | 12 +++--- src/payments/p2wsh.ts | 19 +++++----- src/script.ts | 6 +-- src/templates/multisig/input.ts | 2 +- src/templates/multisig/output.ts | 2 +- src/templates/pubkey/input.ts | 2 +- src/templates/pubkey/output.ts | 2 +- src/templates/pubkeyhash/input.ts | 2 +- src/templates/scripthash/input.ts | 4 +- src/templates/witnesscommitment/output.ts | 2 +- src/templates/witnesspubkeyhash/input.ts | 2 +- src/transaction.ts | 8 ++-- src/transaction_builder.ts | 46 +++++++++++------------ tsconfig.json | 6 +-- 22 files changed, 114 insertions(+), 112 deletions(-) diff --git a/src/address.ts b/src/address.ts index f273b43..c9ffeeb 100644 --- a/src/address.ts +++ b/src/address.ts @@ -75,8 +75,8 @@ export function fromOutputScript (output: Buffer, network: Network): string { // export function toOutputScript (address: string, network: Network): Buffer { network = network || networks.bitcoin - let decodeBase58: Base58CheckResult - let decodeBech32: Bech32Result + let decodeBase58: Base58CheckResult | undefined = undefined + let decodeBech32: Bech32Result | undefined = undefined try { decodeBase58 = fromBase58Check(address) } catch (e) {} diff --git a/src/ecpair.ts b/src/ecpair.ts index cb835d1..a7426ae 100644 --- a/src/ecpair.ts +++ b/src/ecpair.ts @@ -20,8 +20,8 @@ interface ECPairOptions { export interface ECPairInterface { compressed: boolean network: Network - privateKey: Buffer - publicKey: Buffer + privateKey: Buffer | null + publicKey: Buffer | null toWIF(): string sign(hash: Buffer): Buffer verify(hash: Buffer, signature: Buffer): Buffer @@ -31,9 +31,9 @@ export interface ECPairInterface { class ECPair implements ECPairInterface { compressed: boolean network: Network - private __d: Buffer - private __Q: Buffer - constructor (d: Buffer | void, Q: Buffer | void, options: ECPairOptions) { + private __d: Buffer | null + private __Q: Buffer | null + constructor (d: Buffer | null, Q: Buffer | null, options: ECPairOptions) { if (options === undefined) options = {} this.compressed = options.compressed === undefined ? true : options.compressed this.network = options.network || NETWORKS.bitcoin @@ -43,11 +43,11 @@ class ECPair implements ECPairInterface { if (Q) this.__Q = ecc.pointCompress(Q, this.compressed) } - get privateKey (): Buffer { + get privateKey (): Buffer | null { return this.__d } - get publicKey (): Buffer { + get publicKey (): Buffer | null { if (!this.__Q) this.__Q = ecc.pointFromScalar(this.__d, this.compressed) return this.__Q } @@ -87,7 +87,7 @@ function fromWIF (string: string, network: Network | Array): ECPair { // list of networks? if (types.Array(network)) { - network = (>network).filter(function (x: Network) { + network = (>network).filter(function (x: Network) { return version === x.wif }).pop() diff --git a/src/payments/embed.ts b/src/payments/embed.ts index a28747f..2526fe0 100644 --- a/src/payments/embed.ts +++ b/src/payments/embed.ts @@ -36,17 +36,17 @@ export function p2data (a: Payment, opts: PaymentOpts): Payment { }) lazy.prop(o, 'data', function () { if (!a.output) return - return bscript.decompile(a.output).slice(1) + return (>bscript.decompile(a.output)).slice(1) }) // extended validation if (opts.validate) { if (a.output) { const chunks = bscript.decompile(a.output) - if (chunks[0] !== OPS.OP_RETURN) throw new TypeError('Output is invalid') - if (!chunks.slice(1).every(typef.Buffer)) throw new TypeError('Output is invalid') + if ((>chunks)[0] !== OPS.OP_RETURN) throw new TypeError('Output is invalid') + if (!(>chunks).slice(1).every(typef.Buffer)) throw new TypeError('Output is invalid') - if (a.data && !stacksEqual(a.data, o.data)) throw new TypeError('Data mismatch') + if (a.data && !stacksEqual(a.data, >o.data)) throw new TypeError('Data mismatch') } } diff --git a/src/payments/lazy.ts b/src/payments/lazy.ts index 6a4cbe3..1d4af68 100644 --- a/src/payments/lazy.ts +++ b/src/payments/lazy.ts @@ -20,7 +20,7 @@ export function prop (object: Object, name: string, f: ()=>any): void { export function value (f: ()=>T): ()=>T { let value: T - return function () { + return function (): T { if (value !== undefined) return value value = f() return value diff --git a/src/payments/p2ms.ts b/src/payments/p2ms.ts index 2142ff1..b8a05b3 100644 --- a/src/payments/p2ms.ts +++ b/src/payments/p2ms.ts @@ -28,7 +28,7 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment { opts = Object.assign({ validate: true }, opts || {}) function isAcceptableSignature (x: Buffer | number) { - return bscript.isCanonicalScriptSignature(x) || (opts.allowIncomplete && (x === OPS.OP_0)) + return bscript.isCanonicalScriptSignature(x) || (opts.allowIncomplete && (x === OPS.OP_0)) !== undefined } typef({ @@ -45,12 +45,12 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment { const network = a.network || BITCOIN_NETWORK const o: Payment = { network } - let chunks: Array + let chunks: Array = [] let decoded = false function decode (output: Buffer | Array): void { if (decoded) return decoded = true - chunks = bscript.decompile(output) + chunks = >bscript.decompile(output) o.m = chunks[0] - OP_INT_BASE o.n = chunks[chunks.length - 2] - OP_INT_BASE o.pubkeys = >chunks.slice(1, -2) @@ -60,7 +60,7 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment { if (!a.m) return if (!o.n) return if (!a.pubkeys) return - return bscript.compile([].concat( + return bscript.compile((>[]).concat( OP_INT_BASE + a.m, a.pubkeys, OP_INT_BASE + o.n, @@ -83,7 +83,7 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment { }) lazy.prop(o, 'signatures', function () { if (!a.input) return - return bscript.decompile(a.input).slice(1) + return (>bscript.decompile(a.input)).slice(1) }) lazy.prop(o, 'input', function () { if (!a.signatures) return @@ -103,35 +103,35 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment { if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) throw new TypeError('Output is invalid') if ( - o.m <= 0 || - o.n > 16 || - o.m > o.n || + (o).m <= 0 || + (o).n > 16 || + (o).m > (o).n || o.n !== chunks.length - 3) throw new TypeError('Output is invalid') - if (!o.pubkeys.every(x => ecc.isPoint(x))) throw new TypeError('Output is invalid') + if (!(>o.pubkeys).every(x => ecc.isPoint(x))) throw new TypeError('Output is invalid') if (a.m !== undefined && a.m !== o.m) throw new TypeError('m mismatch') if (a.n !== undefined && a.n !== o.n) throw new TypeError('n mismatch') - if (a.pubkeys && !stacksEqual(a.pubkeys, o.pubkeys)) throw new TypeError('Pubkeys mismatch') + if (a.pubkeys && !stacksEqual(a.pubkeys, (>o.pubkeys))) throw new TypeError('Pubkeys mismatch') } if (a.pubkeys) { if (a.n !== undefined && a.n !== a.pubkeys.length) throw new TypeError('Pubkey count mismatch') o.n = a.pubkeys.length - if (o.n < o.m) throw new TypeError('Pubkey count cannot be less than m') + if (o.n < (o).m) throw new TypeError('Pubkey count cannot be less than m') } if (a.signatures) { - if (a.signatures.length < o.m) throw new TypeError('Not enough signatures provided') - if (a.signatures.length > o.m) throw new TypeError('Too many signatures provided') + if (a.signatures.length < (o).m) throw new TypeError('Not enough signatures provided') + if (a.signatures.length > (o).m) throw new TypeError('Too many signatures provided') } if (a.input) { if (a.input[0] !== OPS.OP_0) throw new TypeError('Input is invalid') - if (o.signatures.length === 0 || !o.signatures.every(isAcceptableSignature)) throw new TypeError('Input has invalid signature(s)') + if ((>o.signatures).length === 0 || !(>o.signatures).every(isAcceptableSignature)) throw new TypeError('Input has invalid signature(s)') - if (a.signatures && !stacksEqual(a.signatures, o.signatures)) throw new TypeError('Signature mismatch') - if (a.m !== undefined && a.m !== a.signatures.length) throw new TypeError('Signature count mismatch') + if (a.signatures && !stacksEqual(a.signatures, (>o.signatures))) throw new TypeError('Signature mismatch') + if (a.m !== undefined && a.m !== (>a.signatures).length) throw new TypeError('Signature count mismatch') } } diff --git a/src/payments/p2pk.ts b/src/payments/p2pk.ts index a1ac5e8..45b3577 100644 --- a/src/payments/p2pk.ts +++ b/src/payments/p2pk.ts @@ -27,7 +27,7 @@ export function p2pk (a: Payment, opts: PaymentOpts): Payment { input: typef.maybe(typef.Buffer) }, a) - const _chunks = lazy.value(function () { return bscript.decompile(a.input) }) + const _chunks = <()=>Array>lazy.value(function () { return bscript.decompile(a.input) }) const network = a.network || BITCOIN_NETWORK const o: Payment = { network } @@ -45,7 +45,7 @@ export function p2pk (a: Payment, opts: PaymentOpts): Payment { }) lazy.prop(o, 'signature', function () { if (!a.input) return - return _chunks()[0] + return _chunks()[0] }) lazy.prop(o, 'input', function () { if (!a.signature) return @@ -61,16 +61,16 @@ export function p2pk (a: Payment, opts: PaymentOpts): Payment { if (a.output) { if (a.output[a.output.length - 1] !== OPS.OP_CHECKSIG) throw new TypeError('Output is invalid') if (!ecc.isPoint(o.pubkey)) throw new TypeError('Output pubkey is invalid') - if (a.pubkey && !a.pubkey.equals(o.pubkey)) throw new TypeError('Pubkey mismatch') + if (a.pubkey && !a.pubkey.equals(o.pubkey)) throw new TypeError('Pubkey mismatch') } if (a.signature) { - if (a.input && !a.input.equals(o.input)) throw new TypeError('Signature mismatch') + if (a.input && !a.input.equals(o.input)) throw new TypeError('Signature mismatch') } if (a.input) { if (_chunks().length !== 1) throw new TypeError('Input is invalid') - if (!bscript.isCanonicalScriptSignature(o.signature)) throw new TypeError('Input has invalid signature') + if (!bscript.isCanonicalScriptSignature(o.signature)) throw new TypeError('Input has invalid signature') } } diff --git a/src/payments/p2pkh.ts b/src/payments/p2pkh.ts index e32f933..f2054b0 100644 --- a/src/payments/p2pkh.ts +++ b/src/payments/p2pkh.ts @@ -38,7 +38,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment { const hash = payload.slice(1) return { version, hash } }) - const _chunks = lazy.value(function () { return bscript.decompile(a.input) }) + const _chunks = <()=>Array>lazy.value(function () { return bscript.decompile(a.input) }) const network = a.network || BITCOIN_NETWORK const o: Payment = { network } @@ -54,7 +54,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment { lazy.prop(o, 'hash', function () { if (a.output) return a.output.slice(3, 23) if (a.address) return _address().hash - if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey || o.pubkey) + if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey || o.pubkey) }) lazy.prop(o, 'output', function () { if (!o.hash) return @@ -68,11 +68,11 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment { }) lazy.prop(o, 'pubkey', function () { if (!a.input) return - return _chunks()[1] + return _chunks()[1] }) lazy.prop(o, 'signature', function () { if (!a.input) return - return _chunks()[0] + return _chunks()[0] }) lazy.prop(o, 'input', function () { if (!a.pubkey) return @@ -86,7 +86,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment { // extended validation if (opts.validate) { - let hash: Buffer + let hash: Buffer = Buffer.from([]) if (a.address) { if (_address().version !== network.pubKeyHash) throw new TypeError('Invalid version or Network mismatch') if (_address().hash.length !== 20) throw new TypeError('Invalid address') @@ -94,7 +94,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment { } if (a.hash) { - if (hash && !hash.equals(a.hash)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(a.hash)) throw new TypeError('Hash mismatch') else hash = a.hash } @@ -108,13 +108,13 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment { a.output[24] !== OPS.OP_CHECKSIG) throw new TypeError('Output is invalid') const hash2 = a.output.slice(3, 23) - if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(hash2)) throw new TypeError('Hash mismatch') else hash = hash2 } if (a.pubkey) { const pkh = bcrypto.hash160(a.pubkey) - if (hash && !hash.equals(pkh)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(pkh)) throw new TypeError('Hash mismatch') else hash = pkh } @@ -128,7 +128,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment { if (a.pubkey && !a.pubkey.equals(chunks[1])) throw new TypeError('Pubkey mismatch') const pkh = bcrypto.hash160(chunks[1]) - if (hash && !hash.equals(pkh)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(pkh)) throw new TypeError('Hash mismatch') } } diff --git a/src/payments/p2sh.ts b/src/payments/p2sh.ts index 2219f33..6facde9 100644 --- a/src/payments/p2sh.ts +++ b/src/payments/p2sh.ts @@ -1,4 +1,5 @@ import { Payment, PaymentOpts } from './index' +import { Network } from '../networks' import * as bscript from '../script' import * as bcrypto from '../crypto' import * as lazy from './lazy' @@ -59,7 +60,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { const hash = payload.slice(1) return { version, hash } }) - const _chunks = lazy.value(function () { return bscript.decompile(a.input) }) + const _chunks = <()=>Array>lazy.value(function () { return bscript.decompile(a.input) }) const _redeem = lazy.value(function (): Payment { const chunks = _chunks() return { @@ -75,7 +76,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { if (!o.hash) return const payload = Buffer.allocUnsafe(21) - payload.writeUInt8(network.scriptHash, 0) + payload.writeUInt8((o.network).scriptHash, 0) o.hash.copy(payload, 1) return bs58check.encode(payload) }) @@ -101,8 +102,8 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { }) lazy.prop(o, 'input', function () { if (!a.redeem || !a.redeem.input || !a.redeem.output) return - return bscript.compile([].concat( - bscript.decompile(a.redeem.input), + return bscript.compile((>[]).concat( + >bscript.decompile(a.redeem.input), a.redeem.output )) }) @@ -112,7 +113,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { }) if (opts.validate) { - let hash: Buffer + let hash: Buffer = Buffer.from([]) if (a.address) { if (_address().version !== network.scriptHash) throw new TypeError('Invalid version or Network mismatch') if (_address().hash.length !== 20) throw new TypeError('Invalid address') @@ -120,7 +121,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { } if (a.hash) { - if (hash && !hash.equals(a.hash)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(a.hash)) throw new TypeError('Hash mismatch') else hash = a.hash } @@ -132,7 +133,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { a.output[22] !== OPS.OP_EQUAL) throw new TypeError('Output is invalid') const hash2 = a.output.slice(2, 22) - if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(hash2)) throw new TypeError('Hash mismatch') else hash = hash2 } @@ -145,7 +146,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { // match hash against other sources const hash2 = bcrypto.hash160(redeem.output) - if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(hash2)) throw new TypeError('Hash mismatch') else hash = hash2 } @@ -155,7 +156,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { if (!hasInput && !hasWitness) throw new TypeError('Empty input') if (hasInput && hasWitness) throw new TypeError('Input and witness provided') if (hasInput) { - const richunks = bscript.decompile(redeem.input) + const richunks = >bscript.decompile(redeem.input) if (!bscript.isPushOnly(richunks)) throw new TypeError('Non push-only scriptSig') } } @@ -174,7 +175,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment { if (a.input) { const redeem = _redeem() if (a.redeem.output && !a.redeem.output.equals(redeem.output)) throw new TypeError('Redeem.output mismatch') - if (a.redeem.input && !a.redeem.input.equals(redeem.input)) throw new TypeError('Redeem.input mismatch') + if (a.redeem.input && !a.redeem.input.equals(redeem.input)) throw new TypeError('Redeem.input mismatch') } checkRedeem(a.redeem) diff --git a/src/payments/p2wpkh.ts b/src/payments/p2wpkh.ts index a25d037..7089246 100644 --- a/src/payments/p2wpkh.ts +++ b/src/payments/p2wpkh.ts @@ -59,7 +59,7 @@ export function p2wpkh (a: Payment, opts: PaymentOpts): Payment { lazy.prop(o, 'hash', function () { if (a.output) return a.output.slice(2, 22) if (a.address) return _address().data - if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey || o.pubkey) + if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey || o.pubkey) }) lazy.prop(o, 'output', function () { if (!o.hash) return @@ -89,7 +89,7 @@ export function p2wpkh (a: Payment, opts: PaymentOpts): Payment { // extended validation if (opts.validate) { - let hash: Buffer + let hash: Buffer = Buffer.from([]) if (a.address) { if (network && network.bech32 !== _address().prefix) throw new TypeError('Invalid prefix or Network mismatch') if (_address().version !== 0x00) throw new TypeError('Invalid address version') @@ -98,7 +98,7 @@ export function p2wpkh (a: Payment, opts: PaymentOpts): Payment { } if (a.hash) { - if (hash && !hash.equals(a.hash)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(a.hash)) throw new TypeError('Hash mismatch') else hash = a.hash } @@ -107,13 +107,13 @@ export function p2wpkh (a: Payment, opts: PaymentOpts): Payment { a.output.length !== 22 || a.output[0] !== OPS.OP_0 || a.output[1] !== 0x14) throw new TypeError('Output is invalid') - if (hash && !hash.equals(a.output.slice(2))) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(a.output.slice(2))) throw new TypeError('Hash mismatch') else hash = a.output.slice(2) } if (a.pubkey) { const pkh = bcrypto.hash160(a.pubkey) - if (hash && !hash.equals(pkh)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(pkh)) throw new TypeError('Hash mismatch') else hash = pkh } @@ -126,7 +126,7 @@ export function p2wpkh (a: Payment, opts: PaymentOpts): Payment { if (a.pubkey && !a.pubkey.equals(a.witness[1])) throw new TypeError('Pubkey mismatch') const pkh = bcrypto.hash160(a.witness[1]) - if (hash && !hash.equals(pkh)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(pkh)) throw new TypeError('Hash mismatch') } } diff --git a/src/payments/p2wsh.ts b/src/payments/p2wsh.ts index d94d446..c70cfb6 100644 --- a/src/payments/p2wsh.ts +++ b/src/payments/p2wsh.ts @@ -1,4 +1,5 @@ import { Payment, PaymentOpts } from './index' +import { Network } from '../networks' import * as bscript from '../script' import * as bcrypto from '../crypto' import * as lazy from './lazy' @@ -58,7 +59,7 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment { data: Buffer.from(data) } }) - const _rchunks = lazy.value(function () { return bscript.decompile(a.redeem.input) }) + const _rchunks = <()=>Array>lazy.value(function () { return bscript.decompile((a.redeem).input) }) let network = a.network if (!network) { @@ -71,7 +72,7 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment { if (!o.hash) return const words = bech32.toWords(o.hash) words.unshift(0x00) - return bech32.encode(network.bech32, words) + return bech32.encode((network).bech32, words) }) lazy.prop(o, 'hash', function () { if (a.output) return a.output.slice(2) @@ -111,18 +112,18 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment { // assign, and blank the existing input o.redeem = Object.assign({ witness: stack }, a.redeem) o.redeem.input = EMPTY_BUFFER - return [].concat(stack, a.redeem.output) + return (>[]).concat(stack, a.redeem.output) } if (!a.redeem) return if (!a.redeem.output) return if (!a.redeem.witness) return - return [].concat(a.redeem.witness, a.redeem.output) + return (>[]).concat(a.redeem.witness, a.redeem.output) }) // extended validation if (opts.validate) { - let hash: Buffer + let hash: Buffer = Buffer.from([]) if (a.address) { if (_address().prefix !== network.bech32) throw new TypeError('Invalid prefix or Network mismatch') if (_address().version !== 0x00) throw new TypeError('Invalid address version') @@ -131,7 +132,7 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment { } if (a.hash) { - if (hash && !hash.equals(a.hash)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(a.hash)) throw new TypeError('Hash mismatch') else hash = a.hash } @@ -141,7 +142,7 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment { a.output[0] !== OPS.OP_0 || a.output[1] !== 0x20) throw new TypeError('Output is invalid') const hash2 = a.output.slice(2) - if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(hash2)) throw new TypeError('Hash mismatch') else hash = hash2 } @@ -158,11 +159,11 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment { // is the redeem output non-empty? if (a.redeem.output) { - if (bscript.decompile(a.redeem.output).length === 0) throw new TypeError('Redeem.output is invalid') + if ((>bscript.decompile(a.redeem.output)).length === 0) throw new TypeError('Redeem.output is invalid') // match hash against other sources const hash2 = bcrypto.sha256(a.redeem.output) - if (hash && !hash.equals(hash2)) throw new TypeError('Hash mismatch') + if (hash.length > 0 && !hash.equals(hash2)) throw new TypeError('Hash mismatch') else hash = hash2 } diff --git a/src/script.ts b/src/script.ts index 88bc46e..6d9bfc9 100644 --- a/src/script.ts +++ b/src/script.ts @@ -94,7 +94,7 @@ export function compile (chunks: Buffer | Array): Buffer { return buffer } -export function decompile (buffer: Buffer | Array): Array { +export function decompile (buffer: Buffer | Array): Array | null { // TODO: remove me if (chunksIsArray(buffer)) return buffer @@ -141,7 +141,7 @@ export function decompile (buffer: Buffer | Array): Array): string { if (chunksIsBuffer(chunks)) { - chunks = decompile(chunks) + chunks = >decompile(chunks) } return chunks.map(function (chunk) { @@ -171,7 +171,7 @@ export function fromASM (asm: string): Buffer { } export function toStack (chunks: Buffer | Array): Array { - chunks = decompile(chunks) + chunks = >decompile(chunks) typeforce(isPushOnly, chunks) return chunks.map(function (op) { diff --git a/src/templates/multisig/input.ts b/src/templates/multisig/input.ts index 2060242..abf0982 100644 --- a/src/templates/multisig/input.ts +++ b/src/templates/multisig/input.ts @@ -8,7 +8,7 @@ function partialSignature (value: number | Buffer): boolean { } export function check (script: Buffer | Array, allowIncomplete?: boolean): boolean { - const chunks = bscript.decompile(script) + const chunks = >bscript.decompile(script) if (chunks.length < 2) return false if (chunks[0] !== OPS.OP_0) return false diff --git a/src/templates/multisig/output.ts b/src/templates/multisig/output.ts index 50c701e..e4fa333 100644 --- a/src/templates/multisig/output.ts +++ b/src/templates/multisig/output.ts @@ -6,7 +6,7 @@ const OPS = require('bitcoin-ops') const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1 export function check (script: Buffer | Array, allowIncomplete?: boolean): boolean { - const chunks = bscript.decompile(script) + const chunks = >bscript.decompile(script) if (chunks.length < 4) return false if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false diff --git a/src/templates/pubkey/input.ts b/src/templates/pubkey/input.ts index f4b8bf7..f9245e4 100644 --- a/src/templates/pubkey/input.ts +++ b/src/templates/pubkey/input.ts @@ -3,7 +3,7 @@ import * as bscript from '../../script' export function check (script: Buffer | Array): boolean { - const chunks = bscript.decompile(script) + const chunks = >bscript.decompile(script) return chunks.length === 1 && bscript.isCanonicalScriptSignature(chunks[0]) diff --git a/src/templates/pubkey/output.ts b/src/templates/pubkey/output.ts index 2728f68..f60cc05 100644 --- a/src/templates/pubkey/output.ts +++ b/src/templates/pubkey/output.ts @@ -4,7 +4,7 @@ import * as bscript from '../../script' const OPS = require('bitcoin-ops') export function check (script: Buffer | Array): boolean { - const chunks = bscript.decompile(script) + const chunks = >bscript.decompile(script) return chunks.length === 2 && bscript.isCanonicalPubKey(chunks[0]) && diff --git a/src/templates/pubkeyhash/input.ts b/src/templates/pubkeyhash/input.ts index ffdc929..f27f809 100644 --- a/src/templates/pubkeyhash/input.ts +++ b/src/templates/pubkeyhash/input.ts @@ -3,7 +3,7 @@ import * as bscript from '../../script' export function check (script: Buffer | Array): boolean { - const chunks = bscript.decompile(script) + const chunks = >bscript.decompile(script) return chunks.length === 2 && bscript.isCanonicalScriptSignature(chunks[0]) && diff --git a/src/templates/scripthash/input.ts b/src/templates/scripthash/input.ts index 908a87b..93e7d58 100644 --- a/src/templates/scripthash/input.ts +++ b/src/templates/scripthash/input.ts @@ -10,13 +10,13 @@ import * as p2wsho from '../witnessscripthash/output' const Buffer = require('safe-buffer').Buffer export function check (script: Buffer | Array, allowIncomplete?: boolean): boolean { - const chunks = bscript.decompile(script) + const chunks = >bscript.decompile(script) if (chunks.length < 1) return false const lastChunk = chunks[chunks.length - 1] if (!Buffer.isBuffer(lastChunk)) return false - const scriptSigChunks = bscript.decompile(bscript.compile(chunks.slice(0, -1))) + const scriptSigChunks = >bscript.decompile(bscript.compile(chunks.slice(0, -1))) const redeemScriptChunks = bscript.decompile(lastChunk) // is redeemScript a valid script? diff --git a/src/templates/witnesscommitment/output.ts b/src/templates/witnesscommitment/output.ts index 1b3a182..d89b8e2 100644 --- a/src/templates/witnesscommitment/output.ts +++ b/src/templates/witnesscommitment/output.ts @@ -32,5 +32,5 @@ export function encode (commitment: Buffer): Buffer { export function decode (buffer: Buffer): Buffer { typeforce(check, buffer) - return (bscript.decompile(buffer)[1]).slice(4, 36) + return ((>bscript.decompile(buffer))[1]).slice(4, 36) } diff --git a/src/templates/witnesspubkeyhash/input.ts b/src/templates/witnesspubkeyhash/input.ts index 36f0606..91b8357 100644 --- a/src/templates/witnesspubkeyhash/input.ts +++ b/src/templates/witnesspubkeyhash/input.ts @@ -7,7 +7,7 @@ function isCompressedCanonicalPubKey (pubKey: Buffer): boolean { } export function check (script: Buffer | Array): boolean { - const chunks = bscript.decompile(script) + const chunks = >bscript.decompile(script) return chunks.length === 2 && bscript.isCanonicalScriptSignature(chunks[0]) && diff --git a/src/transaction.ts b/src/transaction.ts index 91956c5..af17449 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -182,7 +182,7 @@ export class Transaction { return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash) } - addInput (hash: Buffer, index: number, sequence: number, scriptSig: Buffer): number { + addInput (hash: Buffer, index: number, sequence?: number, scriptSig?: Buffer): number { typeforce(types.tuple( types.Hash256bit, types.UInt32, @@ -199,7 +199,7 @@ export class Transaction { hash: hash, index: index, script: scriptSig || EMPTY_SCRIPT, - sequence: sequence, + sequence: sequence, witness: EMPTY_WITNESS }) - 1) } @@ -293,7 +293,7 @@ export class Transaction { if (inIndex >= this.ins.length) return ONE // ignore OP_CODESEPARATOR - const ourScript = bscript.compile(bscript.decompile(prevOutScript).filter((x) => { + const ourScript = bscript.compile((>bscript.decompile(prevOutScript)).filter((x) => { return x !== opcodes.OP_CODESEPARATOR })) @@ -475,7 +475,7 @@ export class Transaction { let offset = initialOffset || 0 function writeSlice (slice: Buffer): void { - offset += slice.copy(buffer, offset) + offset += slice.copy(buffer, offset) } function writeUInt8 (i: number) { diff --git a/src/transaction_builder.ts b/src/transaction_builder.ts index e4c9c09..41d524e 100644 --- a/src/transaction_builder.ts +++ b/src/transaction_builder.ts @@ -24,8 +24,8 @@ interface TxbInput { redeemScript?: Buffer redeemScriptType?: string prevOutType?: string - pubkeys?: Array - signatures?: Array + pubkeys?: Array | Array + signatures?: Array | Array witness?: Array witnessScript?: Buffer witnessScriptType?: string @@ -38,7 +38,7 @@ interface TxbInput { interface TxbOutput { type: string pubkeys?: Array - signatures?: Array + signatures?: Array | Array maxSignatures?: number } @@ -57,7 +57,7 @@ export class TransactionBuilder { private __inputs: Array private __tx: Transaction - constructor (network: Network, maximumFeeRate?: number) { + constructor (network?: Network, maximumFeeRate?: number) { this.__prevTxSet = {} this.network = network || networks.bitcoin @@ -125,7 +125,7 @@ export class TransactionBuilder { throw new Error('No, this would invalidate signatures') } - let value: number + let value: number | undefined = undefined // is it a hex string? if (txIsString(txHash)) { @@ -225,7 +225,7 @@ export class TransactionBuilder { this.__inputs.forEach((input, i) => { if (!input.prevOutType && !allowIncomplete) throw new Error('Transaction is not complete') - const result = build(input.prevOutType, input, allowIncomplete) + const result = build(input.prevOutType, input, allowIncomplete) if (!result) { if (!allowIncomplete && input.prevOutType === SCRIPT_TYPES.NONSTANDARD) throw new Error('Unknown input type') if (!allowIncomplete) throw new Error('Not enough information') @@ -263,7 +263,7 @@ export class TransactionBuilder { throw new Error('Inconsistent redeemScript') } - const ourPubKey = keyPair.publicKey || keyPair.getPublicKey() + const ourPubKey = keyPair.publicKey || (<()=>Buffer>keyPair.getPublicKey)() if (!canSign(input)) { if (witnessValue !== undefined) { if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue') @@ -284,15 +284,15 @@ export class TransactionBuilder { // ready to sign let signatureHash: Buffer if (input.hasWitness) { - signatureHash = this.__tx.hashForWitnessV0(vin, input.signScript, input.value, hashType) + signatureHash = this.__tx.hashForWitnessV0(vin, input.signScript, input.value, hashType) } else { - signatureHash = this.__tx.hashForSignature(vin, input.signScript, hashType) + signatureHash = this.__tx.hashForSignature(vin, input.signScript, hashType) } // enforce in order signing of public keys - const signed = input.pubkeys.some((pubKey, i) => { + const signed = (>input.pubkeys).some((pubKey, i) => { if (!ourPubKey.equals(pubKey)) return false - if (input.signatures[i]) throw new Error('Signature already exists') + if ((>input.signatures)[i]) throw new Error('Signature already exists') // TODO: add tests if (ourPubKey.length !== 33 && input.hasWitness) { @@ -300,7 +300,7 @@ export class TransactionBuilder { } const signature = keyPair.sign(signatureHash) - input.signatures[i] = bscript.signature.encode(signature, hashType) + ;(>input.signatures)[i] = bscript.signature.encode(signature, hashType) return true }) @@ -348,7 +348,7 @@ export class TransactionBuilder { return this.__inputs.every(input => { if (input.signatures === undefined) return true - return input.signatures.every(signature => { + return input.signatures.every(<(signature: Buffer | undefined)=>boolean>(signature => { if (!signature) return true const hashType = signatureHashType(signature) @@ -360,13 +360,13 @@ export class TransactionBuilder { // of more outputs return nInputs <= nOutputs } - }) + })) }) } private __overMaximumFees (bytes: number): boolean { // not all inputs will have .value defined - const incoming = this.__inputs.reduce((a, x) => a + (x.value >>> 0), 0) + const incoming = this.__inputs.reduce((a, x) => 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 @@ -493,13 +493,13 @@ function expandInput (scriptSig: Buffer, witnessStack: Array, type?: str // could be done in expandInput, but requires the original Transaction for hashForSignature function fixMultisigOrder (input: TxbInput, transaction: Transaction, vin: number): void { if (input.redeemScriptType !== SCRIPT_TYPES.P2MS || !input.redeemScript) return - if (input.pubkeys.length === input.signatures.length) return + if ((>input.pubkeys).length === (>input.signatures).length) return - const unmatched = input.signatures.concat() + const unmatched = (>input.signatures).concat() - input.signatures = input.pubkeys.map(pubKey => { + input.signatures = >(>input.pubkeys).map(pubKey => { const keyPair = ECPair.fromPublicKey(pubKey) - let match + let match: Buffer | undefined // check for a signature unmatched.some((signature, i) => { @@ -508,7 +508,7 @@ function fixMultisigOrder (input: TxbInput, transaction: Transaction, vin: numbe // TODO: avoid O(n) hashForSignature const parsed = bscript.signature.decode(signature) - const hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType) + const hash = transaction.hashForSignature(vin, (input.redeemScript), parsed.hashType) // skip if signature does not match pubKey if (!keyPair.verify(hash, parsed.signature)) return false @@ -740,7 +740,7 @@ function prepareInput (input: TxbInput, ourPubKey: Buffer, redeemScript: Buffer, } } -function build (type: string, input: TxbInput, allowIncomplete: boolean): any { //TODO payment type +function build (type: string, input: TxbInput, allowIncomplete?: boolean): any { //TODO payment type const pubkeys = input.pubkeys || [] let signatures = input.signatures || [] @@ -777,7 +777,7 @@ function build (type: string, input: TxbInput, allowIncomplete: boolean): any { return payments.p2ms({ m, pubkeys, signatures }, { allowIncomplete, validate }) } case SCRIPT_TYPES.P2SH: { - const redeem = build(input.redeemScriptType, input, allowIncomplete) + const redeem = build(input.redeemScriptType, input, allowIncomplete) if (!redeem) return return payments.p2sh({ @@ -789,7 +789,7 @@ function build (type: string, input: TxbInput, allowIncomplete: boolean): any { }) } case SCRIPT_TYPES.P2WSH: { - const redeem = build(input.witnessScriptType, input, allowIncomplete) + const redeem = build(input.witnessScriptType, input, allowIncomplete) if (!redeem) return return payments.p2wsh({ diff --git a/tsconfig.json b/tsconfig.json index f8bd5e2..cfc286a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,12 +10,12 @@ "allowJs": false, "strict": false, "noImplicitAny": true, - "strictNullChecks": false, + "strictNullChecks": true, "strictFunctionTypes": true, "strictBindCallApply": true, "strictPropertyInitialization": false, - "noImplicitThis": false, - "alwaysStrict": false, + "noImplicitThis": true, + "alwaysStrict": true, "esModuleInterop": true }, "include": [