Add strictNullChecks
This commit is contained in:
parent
4cddc83016
commit
fdf0006fde
22 changed files with 114 additions and 112 deletions
|
@ -75,8 +75,8 @@ export function fromOutputScript (output: Buffer, network: Network): string { //
|
||||||
export function toOutputScript (address: string, network: Network): Buffer {
|
export function toOutputScript (address: string, network: Network): Buffer {
|
||||||
network = network || networks.bitcoin
|
network = network || networks.bitcoin
|
||||||
|
|
||||||
let decodeBase58: Base58CheckResult
|
let decodeBase58: Base58CheckResult | undefined = undefined
|
||||||
let decodeBech32: Bech32Result
|
let decodeBech32: Bech32Result | undefined = undefined
|
||||||
try {
|
try {
|
||||||
decodeBase58 = fromBase58Check(address)
|
decodeBase58 = fromBase58Check(address)
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
|
@ -20,8 +20,8 @@ interface ECPairOptions {
|
||||||
export interface ECPairInterface {
|
export interface ECPairInterface {
|
||||||
compressed: boolean
|
compressed: boolean
|
||||||
network: Network
|
network: Network
|
||||||
privateKey: Buffer
|
privateKey: Buffer | null
|
||||||
publicKey: Buffer
|
publicKey: Buffer | null
|
||||||
toWIF(): string
|
toWIF(): string
|
||||||
sign(hash: Buffer): Buffer
|
sign(hash: Buffer): Buffer
|
||||||
verify(hash: Buffer, signature: Buffer): Buffer
|
verify(hash: Buffer, signature: Buffer): Buffer
|
||||||
|
@ -31,9 +31,9 @@ export interface ECPairInterface {
|
||||||
class ECPair implements ECPairInterface {
|
class ECPair implements ECPairInterface {
|
||||||
compressed: boolean
|
compressed: boolean
|
||||||
network: Network
|
network: Network
|
||||||
private __d: Buffer
|
private __d: Buffer | null
|
||||||
private __Q: Buffer
|
private __Q: Buffer | null
|
||||||
constructor (d: Buffer | void, Q: Buffer | void, options: ECPairOptions) {
|
constructor (d: Buffer | null, Q: Buffer | null, options: ECPairOptions) {
|
||||||
if (options === undefined) options = {}
|
if (options === undefined) options = {}
|
||||||
this.compressed = options.compressed === undefined ? true : options.compressed
|
this.compressed = options.compressed === undefined ? true : options.compressed
|
||||||
this.network = options.network || NETWORKS.bitcoin
|
this.network = options.network || NETWORKS.bitcoin
|
||||||
|
@ -43,11 +43,11 @@ class ECPair implements ECPairInterface {
|
||||||
if (Q) this.__Q = ecc.pointCompress(Q, this.compressed)
|
if (Q) this.__Q = ecc.pointCompress(Q, this.compressed)
|
||||||
}
|
}
|
||||||
|
|
||||||
get privateKey (): Buffer {
|
get privateKey (): Buffer | null {
|
||||||
return this.__d
|
return this.__d
|
||||||
}
|
}
|
||||||
|
|
||||||
get publicKey (): Buffer {
|
get publicKey (): Buffer | null {
|
||||||
if (!this.__Q) this.__Q = ecc.pointFromScalar(this.__d, this.compressed)
|
if (!this.__Q) this.__Q = ecc.pointFromScalar(this.__d, this.compressed)
|
||||||
return this.__Q
|
return this.__Q
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ function fromWIF (string: string, network: Network | Array<Network>): ECPair {
|
||||||
|
|
||||||
// list of networks?
|
// list of networks?
|
||||||
if (types.Array(network)) {
|
if (types.Array(network)) {
|
||||||
network = (<Array<Network>>network).filter(function (x: Network) {
|
network = <Network>(<Array<Network>>network).filter(function (x: Network) {
|
||||||
return version === x.wif
|
return version === x.wif
|
||||||
}).pop()
|
}).pop()
|
||||||
|
|
||||||
|
|
|
@ -36,17 +36,17 @@ export function p2data (a: Payment, opts: PaymentOpts): Payment {
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'data', function () {
|
lazy.prop(o, 'data', function () {
|
||||||
if (!a.output) return
|
if (!a.output) return
|
||||||
return bscript.decompile(a.output).slice(1)
|
return (<Array<Buffer | number>>bscript.decompile(a.output)).slice(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
// extended validation
|
// extended validation
|
||||||
if (opts.validate) {
|
if (opts.validate) {
|
||||||
if (a.output) {
|
if (a.output) {
|
||||||
const chunks = bscript.decompile(a.output)
|
const chunks = bscript.decompile(a.output)
|
||||||
if (chunks[0] !== OPS.OP_RETURN) throw new TypeError('Output is invalid')
|
if ((<Array<Buffer | number>>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 (!(<Array<Buffer | number>>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, <Array<Buffer>>o.data)) throw new TypeError('Data mismatch')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ export function prop (object: Object, name: string, f: ()=>any): void {
|
||||||
|
|
||||||
export function value <T>(f: ()=>T): ()=>T {
|
export function value <T>(f: ()=>T): ()=>T {
|
||||||
let value: T
|
let value: T
|
||||||
return function () {
|
return function (): T {
|
||||||
if (value !== undefined) return value
|
if (value !== undefined) return value
|
||||||
value = f()
|
value = f()
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -28,7 +28,7 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment {
|
||||||
opts = Object.assign({ validate: true }, opts || {})
|
opts = Object.assign({ validate: true }, opts || {})
|
||||||
|
|
||||||
function isAcceptableSignature (x: Buffer | number) {
|
function isAcceptableSignature (x: Buffer | number) {
|
||||||
return bscript.isCanonicalScriptSignature(<Buffer>x) || (opts.allowIncomplete && (<number>x === OPS.OP_0))
|
return bscript.isCanonicalScriptSignature(<Buffer>x) || (opts.allowIncomplete && (<number>x === OPS.OP_0)) !== undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
typef({
|
typef({
|
||||||
|
@ -45,12 +45,12 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment {
|
||||||
const network = a.network || BITCOIN_NETWORK
|
const network = a.network || BITCOIN_NETWORK
|
||||||
const o: Payment = { network }
|
const o: Payment = { network }
|
||||||
|
|
||||||
let chunks: Array<Buffer | number>
|
let chunks: Array<Buffer | number> = []
|
||||||
let decoded = false
|
let decoded = false
|
||||||
function decode (output: Buffer | Array<Buffer | number>): void {
|
function decode (output: Buffer | Array<Buffer | number>): void {
|
||||||
if (decoded) return
|
if (decoded) return
|
||||||
decoded = true
|
decoded = true
|
||||||
chunks = bscript.decompile(output)
|
chunks = <Array<Buffer | number>>bscript.decompile(output)
|
||||||
o.m = <number>chunks[0] - OP_INT_BASE
|
o.m = <number>chunks[0] - OP_INT_BASE
|
||||||
o.n = <number>chunks[chunks.length - 2] - OP_INT_BASE
|
o.n = <number>chunks[chunks.length - 2] - OP_INT_BASE
|
||||||
o.pubkeys = <Array<Buffer>>chunks.slice(1, -2)
|
o.pubkeys = <Array<Buffer>>chunks.slice(1, -2)
|
||||||
|
@ -60,7 +60,7 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment {
|
||||||
if (!a.m) return
|
if (!a.m) return
|
||||||
if (!o.n) return
|
if (!o.n) return
|
||||||
if (!a.pubkeys) return
|
if (!a.pubkeys) return
|
||||||
return bscript.compile([].concat(
|
return bscript.compile((<Array<Buffer | number>>[]).concat(
|
||||||
OP_INT_BASE + a.m,
|
OP_INT_BASE + a.m,
|
||||||
a.pubkeys,
|
a.pubkeys,
|
||||||
OP_INT_BASE + o.n,
|
OP_INT_BASE + o.n,
|
||||||
|
@ -83,7 +83,7 @@ export function p2ms (a: Payment, opts: PaymentOpts): Payment {
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'signatures', function () {
|
lazy.prop(o, 'signatures', function () {
|
||||||
if (!a.input) return
|
if (!a.input) return
|
||||||
return bscript.decompile(a.input).slice(1)
|
return (<Array<Buffer | number>>bscript.decompile(a.input)).slice(1)
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', function () {
|
||||||
if (!a.signatures) return
|
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 (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) throw new TypeError('Output is invalid')
|
||||||
|
|
||||||
if (
|
if (
|
||||||
o.m <= 0 ||
|
<number>(<Payment>o).m <= 0 ||
|
||||||
o.n > 16 ||
|
<number>(<Payment>o).n > 16 ||
|
||||||
o.m > o.n ||
|
<number>(<Payment>o).m > <number>(<Payment>o).n ||
|
||||||
o.n !== chunks.length - 3) throw new TypeError('Output is invalid')
|
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 (!(<Array<Buffer>>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.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.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, (<Array<Buffer>>o.pubkeys))) throw new TypeError('Pubkeys mismatch')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.pubkeys) {
|
if (a.pubkeys) {
|
||||||
if (a.n !== undefined && a.n !== a.pubkeys.length) throw new TypeError('Pubkey count mismatch')
|
if (a.n !== undefined && a.n !== a.pubkeys.length) throw new TypeError('Pubkey count mismatch')
|
||||||
o.n = a.pubkeys.length
|
o.n = a.pubkeys.length
|
||||||
|
|
||||||
if (o.n < o.m) throw new TypeError('Pubkey count cannot be less than m')
|
if (o.n < <number>(<Payment>o).m) throw new TypeError('Pubkey count cannot be less than m')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.signatures) {
|
if (a.signatures) {
|
||||||
if (a.signatures.length < o.m) throw new TypeError('Not enough signatures provided')
|
if (a.signatures.length < <number>(<Payment>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 > <number>(<Payment>o).m) throw new TypeError('Too many signatures provided')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.input) {
|
if (a.input) {
|
||||||
if (a.input[0] !== OPS.OP_0) throw new TypeError('Input is invalid')
|
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 ((<Array<Buffer>>o.signatures).length === 0 || !(<Array<Buffer>>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.signatures && !stacksEqual(a.signatures, (<Array<Buffer>>o.signatures))) throw new TypeError('Signature mismatch')
|
||||||
if (a.m !== undefined && a.m !== a.signatures.length) throw new TypeError('Signature count mismatch')
|
if (a.m !== undefined && a.m !== (<Array<Buffer>>a.signatures).length) throw new TypeError('Signature count mismatch')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ export function p2pk (a: Payment, opts: PaymentOpts): Payment {
|
||||||
input: typef.maybe(typef.Buffer)
|
input: typef.maybe(typef.Buffer)
|
||||||
}, a)
|
}, a)
|
||||||
|
|
||||||
const _chunks = lazy.value(function () { return bscript.decompile(a.input) })
|
const _chunks = <()=>Array<Buffer | number>>lazy.value(function () { return bscript.decompile(<Buffer>a.input) })
|
||||||
|
|
||||||
const network = a.network || BITCOIN_NETWORK
|
const network = a.network || BITCOIN_NETWORK
|
||||||
const o: Payment = { network }
|
const o: Payment = { network }
|
||||||
|
@ -45,7 +45,7 @@ export function p2pk (a: Payment, opts: PaymentOpts): Payment {
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'signature', function () {
|
lazy.prop(o, 'signature', function () {
|
||||||
if (!a.input) return
|
if (!a.input) return
|
||||||
return _chunks()[0]
|
return <Buffer>_chunks()[0]
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', function () {
|
||||||
if (!a.signature) return
|
if (!a.signature) return
|
||||||
|
@ -61,16 +61,16 @@ export function p2pk (a: Payment, opts: PaymentOpts): Payment {
|
||||||
if (a.output) {
|
if (a.output) {
|
||||||
if (a.output[a.output.length - 1] !== OPS.OP_CHECKSIG) throw new TypeError('Output is invalid')
|
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 (!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(<Buffer>o.pubkey)) throw new TypeError('Pubkey mismatch')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.signature) {
|
if (a.signature) {
|
||||||
if (a.input && !a.input.equals(o.input)) throw new TypeError('Signature mismatch')
|
if (a.input && !a.input.equals(<Buffer>o.input)) throw new TypeError('Signature mismatch')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.input) {
|
if (a.input) {
|
||||||
if (_chunks().length !== 1) throw new TypeError('Input is invalid')
|
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(<Buffer>o.signature)) throw new TypeError('Input has invalid signature')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
const hash = payload.slice(1)
|
const hash = payload.slice(1)
|
||||||
return { version, hash }
|
return { version, hash }
|
||||||
})
|
})
|
||||||
const _chunks = lazy.value(function () { return bscript.decompile(a.input) })
|
const _chunks = <()=>Array<Buffer | number>>lazy.value(function () { return bscript.decompile(<Buffer>a.input) })
|
||||||
|
|
||||||
const network = a.network || BITCOIN_NETWORK
|
const network = a.network || BITCOIN_NETWORK
|
||||||
const o: Payment = { network }
|
const o: Payment = { network }
|
||||||
|
@ -54,7 +54,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
lazy.prop(o, 'hash', function () {
|
lazy.prop(o, 'hash', function () {
|
||||||
if (a.output) return a.output.slice(3, 23)
|
if (a.output) return a.output.slice(3, 23)
|
||||||
if (a.address) return _address().hash
|
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(<Buffer>a.pubkey || <Buffer>o.pubkey)
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', function () {
|
||||||
if (!o.hash) return
|
if (!o.hash) return
|
||||||
|
@ -68,11 +68,11 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'pubkey', function () {
|
lazy.prop(o, 'pubkey', function () {
|
||||||
if (!a.input) return
|
if (!a.input) return
|
||||||
return _chunks()[1]
|
return <Buffer>_chunks()[1]
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'signature', function () {
|
lazy.prop(o, 'signature', function () {
|
||||||
if (!a.input) return
|
if (!a.input) return
|
||||||
return _chunks()[0]
|
return <Buffer>_chunks()[0]
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', function () {
|
||||||
if (!a.pubkey) return
|
if (!a.pubkey) return
|
||||||
|
@ -86,7 +86,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
|
|
||||||
// extended validation
|
// extended validation
|
||||||
if (opts.validate) {
|
if (opts.validate) {
|
||||||
let hash: Buffer
|
let hash: Buffer = Buffer.from([])
|
||||||
if (a.address) {
|
if (a.address) {
|
||||||
if (_address().version !== network.pubKeyHash) throw new TypeError('Invalid version or Network mismatch')
|
if (_address().version !== network.pubKeyHash) throw new TypeError('Invalid version or Network mismatch')
|
||||||
if (_address().hash.length !== 20) throw new TypeError('Invalid address')
|
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 (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
|
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')
|
a.output[24] !== OPS.OP_CHECKSIG) throw new TypeError('Output is invalid')
|
||||||
|
|
||||||
const hash2 = a.output.slice(3, 23)
|
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
|
else hash = hash2
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.pubkey) {
|
if (a.pubkey) {
|
||||||
const pkh = bcrypto.hash160(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
|
else hash = pkh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ export function p2pkh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
if (a.pubkey && !a.pubkey.equals(<Buffer>chunks[1])) throw new TypeError('Pubkey mismatch')
|
if (a.pubkey && !a.pubkey.equals(<Buffer>chunks[1])) throw new TypeError('Pubkey mismatch')
|
||||||
|
|
||||||
const pkh = bcrypto.hash160(<Buffer>chunks[1])
|
const pkh = bcrypto.hash160(<Buffer>chunks[1])
|
||||||
if (hash && !hash.equals(pkh)) throw new TypeError('Hash mismatch')
|
if (hash.length > 0 && !hash.equals(pkh)) throw new TypeError('Hash mismatch')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Payment, PaymentOpts } from './index'
|
import { Payment, PaymentOpts } from './index'
|
||||||
|
import { Network } from '../networks'
|
||||||
import * as bscript from '../script'
|
import * as bscript from '../script'
|
||||||
import * as bcrypto from '../crypto'
|
import * as bcrypto from '../crypto'
|
||||||
import * as lazy from './lazy'
|
import * as lazy from './lazy'
|
||||||
|
@ -59,7 +60,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
const hash = payload.slice(1)
|
const hash = payload.slice(1)
|
||||||
return { version, hash }
|
return { version, hash }
|
||||||
})
|
})
|
||||||
const _chunks = lazy.value(function () { return bscript.decompile(a.input) })
|
const _chunks = <()=>Array<Buffer | number>>lazy.value(function () { return bscript.decompile(<Buffer>a.input) })
|
||||||
const _redeem = lazy.value(function (): Payment {
|
const _redeem = lazy.value(function (): Payment {
|
||||||
const chunks = _chunks()
|
const chunks = _chunks()
|
||||||
return {
|
return {
|
||||||
|
@ -75,7 +76,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
if (!o.hash) return
|
if (!o.hash) return
|
||||||
|
|
||||||
const payload = Buffer.allocUnsafe(21)
|
const payload = Buffer.allocUnsafe(21)
|
||||||
payload.writeUInt8(network.scriptHash, 0)
|
payload.writeUInt8((<Network>o.network).scriptHash, 0)
|
||||||
o.hash.copy(payload, 1)
|
o.hash.copy(payload, 1)
|
||||||
return bs58check.encode(payload)
|
return bs58check.encode(payload)
|
||||||
})
|
})
|
||||||
|
@ -101,8 +102,8 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'input', function () {
|
lazy.prop(o, 'input', function () {
|
||||||
if (!a.redeem || !a.redeem.input || !a.redeem.output) return
|
if (!a.redeem || !a.redeem.input || !a.redeem.output) return
|
||||||
return bscript.compile([].concat(
|
return bscript.compile((<Array<Buffer | number>>[]).concat(
|
||||||
bscript.decompile(a.redeem.input),
|
<Array<Buffer | number>>bscript.decompile(a.redeem.input),
|
||||||
a.redeem.output
|
a.redeem.output
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
@ -112,7 +113,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (opts.validate) {
|
if (opts.validate) {
|
||||||
let hash: Buffer
|
let hash: Buffer = Buffer.from([])
|
||||||
if (a.address) {
|
if (a.address) {
|
||||||
if (_address().version !== network.scriptHash) throw new TypeError('Invalid version or Network mismatch')
|
if (_address().version !== network.scriptHash) throw new TypeError('Invalid version or Network mismatch')
|
||||||
if (_address().hash.length !== 20) throw new TypeError('Invalid address')
|
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 (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
|
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')
|
a.output[22] !== OPS.OP_EQUAL) throw new TypeError('Output is invalid')
|
||||||
|
|
||||||
const hash2 = a.output.slice(2, 22)
|
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
|
else hash = hash2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ export function p2sh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
|
|
||||||
// match hash against other sources
|
// match hash against other sources
|
||||||
const hash2 = bcrypto.hash160(redeem.output)
|
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
|
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('Empty input')
|
||||||
if (hasInput && hasWitness) throw new TypeError('Input and witness provided')
|
if (hasInput && hasWitness) throw new TypeError('Input and witness provided')
|
||||||
if (hasInput) {
|
if (hasInput) {
|
||||||
const richunks = bscript.decompile(redeem.input)
|
const richunks = <Array<Buffer | number>>bscript.decompile(redeem.input)
|
||||||
if (!bscript.isPushOnly(richunks)) throw new TypeError('Non push-only scriptSig')
|
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) {
|
if (a.input) {
|
||||||
const redeem = _redeem()
|
const redeem = _redeem()
|
||||||
if (a.redeem.output && !a.redeem.output.equals(<Buffer>redeem.output)) throw new TypeError('Redeem.output mismatch')
|
if (a.redeem.output && !a.redeem.output.equals(<Buffer>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(<Buffer>redeem.input)) throw new TypeError('Redeem.input mismatch')
|
||||||
}
|
}
|
||||||
|
|
||||||
checkRedeem(a.redeem)
|
checkRedeem(a.redeem)
|
||||||
|
|
|
@ -59,7 +59,7 @@ export function p2wpkh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
lazy.prop(o, 'hash', function () {
|
lazy.prop(o, 'hash', function () {
|
||||||
if (a.output) return a.output.slice(2, 22)
|
if (a.output) return a.output.slice(2, 22)
|
||||||
if (a.address) return _address().data
|
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(<Buffer>a.pubkey || <Buffer>o.pubkey)
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'output', function () {
|
lazy.prop(o, 'output', function () {
|
||||||
if (!o.hash) return
|
if (!o.hash) return
|
||||||
|
@ -89,7 +89,7 @@ export function p2wpkh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
|
|
||||||
// extended validation
|
// extended validation
|
||||||
if (opts.validate) {
|
if (opts.validate) {
|
||||||
let hash: Buffer
|
let hash: Buffer = Buffer.from([])
|
||||||
if (a.address) {
|
if (a.address) {
|
||||||
if (network && network.bech32 !== _address().prefix) throw new TypeError('Invalid prefix or Network mismatch')
|
if (network && network.bech32 !== _address().prefix) throw new TypeError('Invalid prefix or Network mismatch')
|
||||||
if (_address().version !== 0x00) throw new TypeError('Invalid address version')
|
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 (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
|
else hash = a.hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,13 +107,13 @@ export function p2wpkh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
a.output.length !== 22 ||
|
a.output.length !== 22 ||
|
||||||
a.output[0] !== OPS.OP_0 ||
|
a.output[0] !== OPS.OP_0 ||
|
||||||
a.output[1] !== 0x14) throw new TypeError('Output is invalid')
|
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)
|
else hash = a.output.slice(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.pubkey) {
|
if (a.pubkey) {
|
||||||
const pkh = bcrypto.hash160(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
|
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')
|
if (a.pubkey && !a.pubkey.equals(a.witness[1])) throw new TypeError('Pubkey mismatch')
|
||||||
|
|
||||||
const pkh = bcrypto.hash160(a.witness[1])
|
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')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Payment, PaymentOpts } from './index'
|
import { Payment, PaymentOpts } from './index'
|
||||||
|
import { Network } from '../networks'
|
||||||
import * as bscript from '../script'
|
import * as bscript from '../script'
|
||||||
import * as bcrypto from '../crypto'
|
import * as bcrypto from '../crypto'
|
||||||
import * as lazy from './lazy'
|
import * as lazy from './lazy'
|
||||||
|
@ -58,7 +59,7 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
data: Buffer.from(data)
|
data: Buffer.from(data)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const _rchunks = lazy.value(function () { return bscript.decompile(a.redeem.input) })
|
const _rchunks = <()=>Array<Buffer | number>>lazy.value(function () { return bscript.decompile(<Buffer>(<Payment>a.redeem).input) })
|
||||||
|
|
||||||
let network = a.network
|
let network = a.network
|
||||||
if (!network) {
|
if (!network) {
|
||||||
|
@ -71,7 +72,7 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
if (!o.hash) return
|
if (!o.hash) return
|
||||||
const words = bech32.toWords(o.hash)
|
const words = bech32.toWords(o.hash)
|
||||||
words.unshift(0x00)
|
words.unshift(0x00)
|
||||||
return bech32.encode(network.bech32, words)
|
return bech32.encode((<Network>network).bech32, words)
|
||||||
})
|
})
|
||||||
lazy.prop(o, 'hash', function () {
|
lazy.prop(o, 'hash', function () {
|
||||||
if (a.output) return a.output.slice(2)
|
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
|
// assign, and blank the existing input
|
||||||
o.redeem = Object.assign({ witness: stack }, a.redeem)
|
o.redeem = Object.assign({ witness: stack }, a.redeem)
|
||||||
o.redeem.input = EMPTY_BUFFER
|
o.redeem.input = EMPTY_BUFFER
|
||||||
return [].concat(stack, a.redeem.output)
|
return (<Array<Buffer>>[]).concat(stack, a.redeem.output)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!a.redeem) return
|
if (!a.redeem) return
|
||||||
if (!a.redeem.output) return
|
if (!a.redeem.output) return
|
||||||
if (!a.redeem.witness) return
|
if (!a.redeem.witness) return
|
||||||
return [].concat(a.redeem.witness, a.redeem.output)
|
return (<Array<Buffer>>[]).concat(a.redeem.witness, a.redeem.output)
|
||||||
})
|
})
|
||||||
|
|
||||||
// extended validation
|
// extended validation
|
||||||
if (opts.validate) {
|
if (opts.validate) {
|
||||||
let hash: Buffer
|
let hash: Buffer = Buffer.from([])
|
||||||
if (a.address) {
|
if (a.address) {
|
||||||
if (_address().prefix !== network.bech32) throw new TypeError('Invalid prefix or Network mismatch')
|
if (_address().prefix !== network.bech32) throw new TypeError('Invalid prefix or Network mismatch')
|
||||||
if (_address().version !== 0x00) throw new TypeError('Invalid address version')
|
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 (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
|
else hash = a.hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
a.output[0] !== OPS.OP_0 ||
|
a.output[0] !== OPS.OP_0 ||
|
||||||
a.output[1] !== 0x20) throw new TypeError('Output is invalid')
|
a.output[1] !== 0x20) throw new TypeError('Output is invalid')
|
||||||
const hash2 = a.output.slice(2)
|
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
|
else hash = hash2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,11 +159,11 @@ export function p2wsh (a: Payment, opts: PaymentOpts): Payment {
|
||||||
|
|
||||||
// is the redeem output non-empty?
|
// is the redeem output non-empty?
|
||||||
if (a.redeem.output) {
|
if (a.redeem.output) {
|
||||||
if (bscript.decompile(a.redeem.output).length === 0) throw new TypeError('Redeem.output is invalid')
|
if ((<Array<Buffer | number>>bscript.decompile(a.redeem.output)).length === 0) throw new TypeError('Redeem.output is invalid')
|
||||||
|
|
||||||
// match hash against other sources
|
// match hash against other sources
|
||||||
const hash2 = bcrypto.sha256(a.redeem.output)
|
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
|
else hash = hash2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ export function compile (chunks: Buffer | Array<number | Buffer>): Buffer {
|
||||||
return buffer
|
return buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decompile (buffer: Buffer | Array<number | Buffer>): Array<number | Buffer> {
|
export function decompile (buffer: Buffer | Array<number | Buffer>): Array<number | Buffer> | null {
|
||||||
// TODO: remove me
|
// TODO: remove me
|
||||||
if (chunksIsArray(buffer)) return buffer
|
if (chunksIsArray(buffer)) return buffer
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ export function decompile (buffer: Buffer | Array<number | Buffer>): Array<numbe
|
||||||
|
|
||||||
export function toASM (chunks: Buffer | Array<number | Buffer>): string {
|
export function toASM (chunks: Buffer | Array<number | Buffer>): string {
|
||||||
if (chunksIsBuffer(chunks)) {
|
if (chunksIsBuffer(chunks)) {
|
||||||
chunks = decompile(chunks)
|
chunks = <Array<number | Buffer>>decompile(chunks)
|
||||||
}
|
}
|
||||||
|
|
||||||
return chunks.map(function (chunk) {
|
return chunks.map(function (chunk) {
|
||||||
|
@ -171,7 +171,7 @@ export function fromASM (asm: string): Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toStack (chunks: Buffer | Array<number | Buffer>): Array<Buffer> {
|
export function toStack (chunks: Buffer | Array<number | Buffer>): Array<Buffer> {
|
||||||
chunks = decompile(chunks)
|
chunks = <Array<number | Buffer>>decompile(chunks)
|
||||||
typeforce(isPushOnly, chunks)
|
typeforce(isPushOnly, chunks)
|
||||||
|
|
||||||
return chunks.map(function (op) {
|
return chunks.map(function (op) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ function partialSignature (value: number | Buffer): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function check (script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean {
|
export function check (script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean {
|
||||||
const chunks = bscript.decompile(script)
|
const chunks = <Array<number | Buffer>>bscript.decompile(script)
|
||||||
if (chunks.length < 2) return false
|
if (chunks.length < 2) return false
|
||||||
if (chunks[0] !== OPS.OP_0) return false
|
if (chunks[0] !== OPS.OP_0) return false
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ const OPS = require('bitcoin-ops')
|
||||||
const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1
|
const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1
|
||||||
|
|
||||||
export function check (script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean {
|
export function check (script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean {
|
||||||
const chunks = bscript.decompile(script)
|
const chunks = <Array<number | Buffer>>bscript.decompile(script)
|
||||||
|
|
||||||
if (chunks.length < 4) return false
|
if (chunks.length < 4) return false
|
||||||
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false
|
if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG) return false
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import * as bscript from '../../script'
|
import * as bscript from '../../script'
|
||||||
|
|
||||||
export function check (script: Buffer | Array<number | Buffer>): boolean {
|
export function check (script: Buffer | Array<number | Buffer>): boolean {
|
||||||
const chunks = bscript.decompile(script)
|
const chunks = <Array<number | Buffer>>bscript.decompile(script)
|
||||||
|
|
||||||
return chunks.length === 1 &&
|
return chunks.length === 1 &&
|
||||||
bscript.isCanonicalScriptSignature(<Buffer>chunks[0])
|
bscript.isCanonicalScriptSignature(<Buffer>chunks[0])
|
||||||
|
|
|
@ -4,7 +4,7 @@ import * as bscript from '../../script'
|
||||||
const OPS = require('bitcoin-ops')
|
const OPS = require('bitcoin-ops')
|
||||||
|
|
||||||
export function check (script: Buffer | Array<number | Buffer>): boolean {
|
export function check (script: Buffer | Array<number | Buffer>): boolean {
|
||||||
const chunks = bscript.decompile(script)
|
const chunks = <Array<number | Buffer>>bscript.decompile(script)
|
||||||
|
|
||||||
return chunks.length === 2 &&
|
return chunks.length === 2 &&
|
||||||
bscript.isCanonicalPubKey(<Buffer>chunks[0]) &&
|
bscript.isCanonicalPubKey(<Buffer>chunks[0]) &&
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import * as bscript from '../../script'
|
import * as bscript from '../../script'
|
||||||
|
|
||||||
export function check (script: Buffer | Array<number | Buffer>): boolean {
|
export function check (script: Buffer | Array<number | Buffer>): boolean {
|
||||||
const chunks = bscript.decompile(script)
|
const chunks = <Array<number | Buffer>>bscript.decompile(script)
|
||||||
|
|
||||||
return chunks.length === 2 &&
|
return chunks.length === 2 &&
|
||||||
bscript.isCanonicalScriptSignature(<Buffer>chunks[0]) &&
|
bscript.isCanonicalScriptSignature(<Buffer>chunks[0]) &&
|
||||||
|
|
|
@ -10,13 +10,13 @@ import * as p2wsho from '../witnessscripthash/output'
|
||||||
const Buffer = require('safe-buffer').Buffer
|
const Buffer = require('safe-buffer').Buffer
|
||||||
|
|
||||||
export function check (script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean {
|
export function check (script: Buffer | Array<number | Buffer>, allowIncomplete?: boolean): boolean {
|
||||||
const chunks = bscript.decompile(script)
|
const chunks = <Array<number | Buffer>>bscript.decompile(script)
|
||||||
if (chunks.length < 1) return false
|
if (chunks.length < 1) return false
|
||||||
|
|
||||||
const lastChunk = chunks[chunks.length - 1]
|
const lastChunk = chunks[chunks.length - 1]
|
||||||
if (!Buffer.isBuffer(lastChunk)) return false
|
if (!Buffer.isBuffer(lastChunk)) return false
|
||||||
|
|
||||||
const scriptSigChunks = bscript.decompile(bscript.compile(chunks.slice(0, -1)))
|
const scriptSigChunks = <Array<number | Buffer>>bscript.decompile(bscript.compile(chunks.slice(0, -1)))
|
||||||
const redeemScriptChunks = bscript.decompile(<Buffer>lastChunk)
|
const redeemScriptChunks = bscript.decompile(<Buffer>lastChunk)
|
||||||
|
|
||||||
// is redeemScript a valid script?
|
// is redeemScript a valid script?
|
||||||
|
|
|
@ -32,5 +32,5 @@ export function encode (commitment: Buffer): Buffer {
|
||||||
export function decode (buffer: Buffer): Buffer {
|
export function decode (buffer: Buffer): Buffer {
|
||||||
typeforce(check, buffer)
|
typeforce(check, buffer)
|
||||||
|
|
||||||
return (<Buffer>bscript.decompile(buffer)[1]).slice(4, 36)
|
return (<Buffer>(<Array<number | Buffer>>bscript.decompile(buffer))[1]).slice(4, 36)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ function isCompressedCanonicalPubKey (pubKey: Buffer): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function check (script: Buffer | Array<number | Buffer>): boolean {
|
export function check (script: Buffer | Array<number | Buffer>): boolean {
|
||||||
const chunks = bscript.decompile(script)
|
const chunks = <Array<number | Buffer>>bscript.decompile(script)
|
||||||
|
|
||||||
return chunks.length === 2 &&
|
return chunks.length === 2 &&
|
||||||
bscript.isCanonicalScriptSignature(<Buffer>chunks[0]) &&
|
bscript.isCanonicalScriptSignature(<Buffer>chunks[0]) &&
|
||||||
|
|
|
@ -182,7 +182,7 @@ export class Transaction {
|
||||||
return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash)
|
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(
|
typeforce(types.tuple(
|
||||||
types.Hash256bit,
|
types.Hash256bit,
|
||||||
types.UInt32,
|
types.UInt32,
|
||||||
|
@ -199,7 +199,7 @@ export class Transaction {
|
||||||
hash: hash,
|
hash: hash,
|
||||||
index: index,
|
index: index,
|
||||||
script: scriptSig || EMPTY_SCRIPT,
|
script: scriptSig || EMPTY_SCRIPT,
|
||||||
sequence: sequence,
|
sequence: <number>sequence,
|
||||||
witness: EMPTY_WITNESS
|
witness: EMPTY_WITNESS
|
||||||
}) - 1)
|
}) - 1)
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ export class Transaction {
|
||||||
if (inIndex >= this.ins.length) return ONE
|
if (inIndex >= this.ins.length) return ONE
|
||||||
|
|
||||||
// ignore OP_CODESEPARATOR
|
// ignore OP_CODESEPARATOR
|
||||||
const ourScript = bscript.compile(bscript.decompile(prevOutScript).filter((x) => {
|
const ourScript = bscript.compile((<Array<Buffer | number>>bscript.decompile(prevOutScript)).filter((x) => {
|
||||||
return x !== <number>opcodes.OP_CODESEPARATOR
|
return x !== <number>opcodes.OP_CODESEPARATOR
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -475,7 +475,7 @@ export class Transaction {
|
||||||
let offset = initialOffset || 0
|
let offset = initialOffset || 0
|
||||||
|
|
||||||
function writeSlice (slice: Buffer): void {
|
function writeSlice (slice: Buffer): void {
|
||||||
offset += slice.copy(buffer, offset)
|
offset += slice.copy(<Buffer>buffer, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeUInt8 (i: number) {
|
function writeUInt8 (i: number) {
|
||||||
|
|
|
@ -24,8 +24,8 @@ interface TxbInput {
|
||||||
redeemScript?: Buffer
|
redeemScript?: Buffer
|
||||||
redeemScriptType?: string
|
redeemScriptType?: string
|
||||||
prevOutType?: string
|
prevOutType?: string
|
||||||
pubkeys?: Array<Buffer>
|
pubkeys?: Array<Buffer> | Array<undefined>
|
||||||
signatures?: Array<Buffer>
|
signatures?: Array<Buffer> | Array<Buffer | undefined>
|
||||||
witness?: Array<Buffer>
|
witness?: Array<Buffer>
|
||||||
witnessScript?: Buffer
|
witnessScript?: Buffer
|
||||||
witnessScriptType?: string
|
witnessScriptType?: string
|
||||||
|
@ -38,7 +38,7 @@ interface TxbInput {
|
||||||
interface TxbOutput {
|
interface TxbOutput {
|
||||||
type: string
|
type: string
|
||||||
pubkeys?: Array<Buffer>
|
pubkeys?: Array<Buffer>
|
||||||
signatures?: Array<Buffer>
|
signatures?: Array<Buffer> | Array<Buffer | undefined>
|
||||||
maxSignatures?: number
|
maxSignatures?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ export class TransactionBuilder {
|
||||||
private __inputs: Array<TxbInput>
|
private __inputs: Array<TxbInput>
|
||||||
private __tx: Transaction
|
private __tx: Transaction
|
||||||
|
|
||||||
constructor (network: Network, maximumFeeRate?: number) {
|
constructor (network?: Network, maximumFeeRate?: number) {
|
||||||
this.__prevTxSet = {}
|
this.__prevTxSet = {}
|
||||||
this.network = network || networks.bitcoin
|
this.network = network || networks.bitcoin
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ export class TransactionBuilder {
|
||||||
throw new Error('No, this would invalidate signatures')
|
throw new Error('No, this would invalidate signatures')
|
||||||
}
|
}
|
||||||
|
|
||||||
let value: number
|
let value: number | undefined = undefined
|
||||||
|
|
||||||
// is it a hex string?
|
// is it a hex string?
|
||||||
if (txIsString(txHash)) {
|
if (txIsString(txHash)) {
|
||||||
|
@ -225,7 +225,7 @@ export class TransactionBuilder {
|
||||||
this.__inputs.forEach((input, i) => {
|
this.__inputs.forEach((input, i) => {
|
||||||
if (!input.prevOutType && !allowIncomplete) throw new Error('Transaction is not complete')
|
if (!input.prevOutType && !allowIncomplete) throw new Error('Transaction is not complete')
|
||||||
|
|
||||||
const result = build(input.prevOutType, input, allowIncomplete)
|
const result = build(<string>input.prevOutType, input, allowIncomplete)
|
||||||
if (!result) {
|
if (!result) {
|
||||||
if (!allowIncomplete && input.prevOutType === SCRIPT_TYPES.NONSTANDARD) throw new Error('Unknown input type')
|
if (!allowIncomplete && input.prevOutType === SCRIPT_TYPES.NONSTANDARD) throw new Error('Unknown input type')
|
||||||
if (!allowIncomplete) throw new Error('Not enough information')
|
if (!allowIncomplete) throw new Error('Not enough information')
|
||||||
|
@ -263,7 +263,7 @@ export class TransactionBuilder {
|
||||||
throw new Error('Inconsistent redeemScript')
|
throw new Error('Inconsistent redeemScript')
|
||||||
}
|
}
|
||||||
|
|
||||||
const ourPubKey = keyPair.publicKey || keyPair.getPublicKey()
|
const ourPubKey = keyPair.publicKey || (<()=>Buffer>keyPair.getPublicKey)()
|
||||||
if (!canSign(input)) {
|
if (!canSign(input)) {
|
||||||
if (witnessValue !== undefined) {
|
if (witnessValue !== undefined) {
|
||||||
if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue')
|
if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue')
|
||||||
|
@ -284,15 +284,15 @@ export class TransactionBuilder {
|
||||||
// ready to sign
|
// ready to sign
|
||||||
let signatureHash: Buffer
|
let signatureHash: Buffer
|
||||||
if (input.hasWitness) {
|
if (input.hasWitness) {
|
||||||
signatureHash = this.__tx.hashForWitnessV0(vin, input.signScript, input.value, hashType)
|
signatureHash = this.__tx.hashForWitnessV0(vin, <Buffer>input.signScript, <number>input.value, hashType)
|
||||||
} else {
|
} else {
|
||||||
signatureHash = this.__tx.hashForSignature(vin, input.signScript, hashType)
|
signatureHash = this.__tx.hashForSignature(vin, <Buffer>input.signScript, hashType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// enforce in order signing of public keys
|
// enforce in order signing of public keys
|
||||||
const signed = input.pubkeys.some((pubKey, i) => {
|
const signed = (<Array<Buffer>>input.pubkeys).some((pubKey, i) => {
|
||||||
if (!ourPubKey.equals(pubKey)) return false
|
if (!ourPubKey.equals(pubKey)) return false
|
||||||
if (input.signatures[i]) throw new Error('Signature already exists')
|
if ((<Array<Buffer>>input.signatures)[i]) throw new Error('Signature already exists')
|
||||||
|
|
||||||
// TODO: add tests
|
// TODO: add tests
|
||||||
if (ourPubKey.length !== 33 && input.hasWitness) {
|
if (ourPubKey.length !== 33 && input.hasWitness) {
|
||||||
|
@ -300,7 +300,7 @@ export class TransactionBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
const signature = keyPair.sign(signatureHash)
|
const signature = keyPair.sign(signatureHash)
|
||||||
input.signatures[i] = bscript.signature.encode(signature, hashType)
|
;(<Array<Buffer>>input.signatures)[i] = bscript.signature.encode(signature, hashType)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ export class TransactionBuilder {
|
||||||
return this.__inputs.every(input => {
|
return this.__inputs.every(input => {
|
||||||
if (input.signatures === undefined) return true
|
if (input.signatures === undefined) return true
|
||||||
|
|
||||||
return input.signatures.every(signature => {
|
return input.signatures.every(<(signature: Buffer | undefined)=>boolean>(signature => {
|
||||||
if (!signature) return true
|
if (!signature) return true
|
||||||
const hashType = signatureHashType(signature)
|
const hashType = signatureHashType(signature)
|
||||||
|
|
||||||
|
@ -360,13 +360,13 @@ export class TransactionBuilder {
|
||||||
// of more outputs
|
// of more outputs
|
||||||
return nInputs <= nOutputs
|
return nInputs <= nOutputs
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private __overMaximumFees (bytes: number): boolean {
|
private __overMaximumFees (bytes: number): boolean {
|
||||||
// not all inputs will have .value defined
|
// 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 + (<number>x.value >>> 0), 0)
|
||||||
|
|
||||||
// but all outputs do, and if we have any input value
|
// but all outputs do, and if we have any input value
|
||||||
// we can immediately determine if the outputs are too small
|
// we can immediately determine if the outputs are too small
|
||||||
|
@ -493,13 +493,13 @@ function expandInput (scriptSig: Buffer, witnessStack: Array<Buffer>, type?: str
|
||||||
// could be done in expandInput, but requires the original Transaction for hashForSignature
|
// could be done in expandInput, but requires the original Transaction for hashForSignature
|
||||||
function fixMultisigOrder (input: TxbInput, transaction: Transaction, vin: number): void {
|
function fixMultisigOrder (input: TxbInput, transaction: Transaction, vin: number): void {
|
||||||
if (input.redeemScriptType !== SCRIPT_TYPES.P2MS || !input.redeemScript) return
|
if (input.redeemScriptType !== SCRIPT_TYPES.P2MS || !input.redeemScript) return
|
||||||
if (input.pubkeys.length === input.signatures.length) return
|
if ((<Array<Buffer>>input.pubkeys).length === (<Array<Buffer>>input.signatures).length) return
|
||||||
|
|
||||||
const unmatched = input.signatures.concat()
|
const unmatched = (<Array<Buffer | undefined>>input.signatures).concat()
|
||||||
|
|
||||||
input.signatures = input.pubkeys.map(pubKey => {
|
input.signatures = <Array<Buffer | undefined>>(<Array<Buffer>>input.pubkeys).map(pubKey => {
|
||||||
const keyPair = ECPair.fromPublicKey(pubKey)
|
const keyPair = ECPair.fromPublicKey(pubKey)
|
||||||
let match
|
let match: Buffer | undefined
|
||||||
|
|
||||||
// check for a signature
|
// check for a signature
|
||||||
unmatched.some((signature, i) => {
|
unmatched.some((signature, i) => {
|
||||||
|
@ -508,7 +508,7 @@ function fixMultisigOrder (input: TxbInput, transaction: Transaction, vin: numbe
|
||||||
|
|
||||||
// TODO: avoid O(n) hashForSignature
|
// TODO: avoid O(n) hashForSignature
|
||||||
const parsed = bscript.signature.decode(signature)
|
const parsed = bscript.signature.decode(signature)
|
||||||
const hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType)
|
const hash = transaction.hashForSignature(vin, (<Buffer>input.redeemScript), parsed.hashType)
|
||||||
|
|
||||||
// skip if signature does not match pubKey
|
// skip if signature does not match pubKey
|
||||||
if (!keyPair.verify(hash, parsed.signature)) return false
|
if (!keyPair.verify(hash, parsed.signature)) return false
|
||||||
|
@ -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 || []
|
const pubkeys = input.pubkeys || []
|
||||||
let signatures = input.signatures || []
|
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 })
|
return payments.p2ms({ m, pubkeys, signatures }, { allowIncomplete, validate })
|
||||||
}
|
}
|
||||||
case SCRIPT_TYPES.P2SH: {
|
case SCRIPT_TYPES.P2SH: {
|
||||||
const redeem = build(input.redeemScriptType, input, allowIncomplete)
|
const redeem = build(<string>input.redeemScriptType, input, allowIncomplete)
|
||||||
if (!redeem) return
|
if (!redeem) return
|
||||||
|
|
||||||
return payments.p2sh({
|
return payments.p2sh({
|
||||||
|
@ -789,7 +789,7 @@ function build (type: string, input: TxbInput, allowIncomplete: boolean): any {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case SCRIPT_TYPES.P2WSH: {
|
case SCRIPT_TYPES.P2WSH: {
|
||||||
const redeem = build(input.witnessScriptType, input, allowIncomplete)
|
const redeem = build(<string>input.witnessScriptType, input, allowIncomplete)
|
||||||
if (!redeem) return
|
if (!redeem) return
|
||||||
|
|
||||||
return payments.p2wsh({
|
return payments.p2wsh({
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
"strict": false,
|
"strict": false,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"strictNullChecks": false,
|
"strictNullChecks": true,
|
||||||
"strictFunctionTypes": true,
|
"strictFunctionTypes": true,
|
||||||
"strictBindCallApply": true,
|
"strictBindCallApply": true,
|
||||||
"strictPropertyInitialization": false,
|
"strictPropertyInitialization": false,
|
||||||
"noImplicitThis": false,
|
"noImplicitThis": true,
|
||||||
"alwaysStrict": false,
|
"alwaysStrict": true,
|
||||||
"esModuleInterop": true
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
|
Loading…
Reference in a new issue