|
@ -16,6 +16,21 @@ const typeforce = require('typeforce'); |
|
|
|
|
|
|
|
|
const SCRIPT_TYPES = classify.types; |
|
|
const SCRIPT_TYPES = classify.types; |
|
|
|
|
|
|
|
|
|
|
|
const PREVOUT_TYPES: Set<string> = new Set([ |
|
|
|
|
|
// Raw
|
|
|
|
|
|
'p2pkh', |
|
|
|
|
|
'p2pk', |
|
|
|
|
|
'p2wpkh', |
|
|
|
|
|
'p2ms', |
|
|
|
|
|
// P2SH wrapped
|
|
|
|
|
|
'p2sh-p2wpkh', |
|
|
|
|
|
'p2sh-p2ms', |
|
|
|
|
|
// P2WSH wrapped
|
|
|
|
|
|
'p2wsh-p2ms', |
|
|
|
|
|
// P2SH-P2WSH wrapper
|
|
|
|
|
|
'p2sh-p2wsh-p2ms', |
|
|
|
|
|
]); |
|
|
|
|
|
|
|
|
type MaybeBuffer = Buffer | undefined; |
|
|
type MaybeBuffer = Buffer | undefined; |
|
|
type TxbSignatures = Buffer[] | MaybeBuffer[]; |
|
|
type TxbSignatures = Buffer[] | MaybeBuffer[]; |
|
|
type TxbPubkeys = MaybeBuffer[]; |
|
|
type TxbPubkeys = MaybeBuffer[]; |
|
@ -50,6 +65,16 @@ interface TxbOutput { |
|
|
maxSignatures?: number; |
|
|
maxSignatures?: number; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
interface TxbSignArg { |
|
|
|
|
|
prevOutScriptType: string; |
|
|
|
|
|
vin: number; |
|
|
|
|
|
keyPair: ECPairInterface; |
|
|
|
|
|
redeemScript?: Buffer; |
|
|
|
|
|
hashType?: number; |
|
|
|
|
|
witnessValue?: number; |
|
|
|
|
|
witnessScript?: Buffer; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
function txIsString(tx: Buffer | string | Transaction): tx is string { |
|
|
function txIsString(tx: Buffer | string | Transaction): tx is string { |
|
|
return typeof tx === 'string' || tx instanceof String; |
|
|
return typeof tx === 'string' || tx instanceof String; |
|
|
} |
|
|
} |
|
@ -197,13 +222,102 @@ export class TransactionBuilder { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
sign( |
|
|
sign( |
|
|
vin: number, |
|
|
signParams: number | TxbSignArg, |
|
|
keyPair: ECPairInterface, |
|
|
keyPair: ECPairInterface, |
|
|
redeemScript?: Buffer, |
|
|
redeemScript?: Buffer, |
|
|
hashType?: number, |
|
|
hashType?: number, |
|
|
witnessValue?: number, |
|
|
witnessValue?: number, |
|
|
witnessScript?: Buffer, |
|
|
witnessScript?: Buffer, |
|
|
): void { |
|
|
): void { |
|
|
|
|
|
let vin: number; |
|
|
|
|
|
if (typeof signParams === 'number') { |
|
|
|
|
|
console.warn( |
|
|
|
|
|
'DEPRECATED: TransactionBuilder sign method arguments ' + |
|
|
|
|
|
'will change in v6, please use the TxbSignArg interface', |
|
|
|
|
|
); |
|
|
|
|
|
vin = signParams; |
|
|
|
|
|
} else if (typeof signParams === 'object') { |
|
|
|
|
|
if (!PREVOUT_TYPES.has(signParams.prevOutScriptType)) { |
|
|
|
|
|
throw new TypeError( |
|
|
|
|
|
`Unknown prevOutScriptType "${signParams.prevOutScriptType}"`, |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
typeforce(typeforce.tuple(typeforce.Number, typeforce.Object), [ |
|
|
|
|
|
signParams.vin, |
|
|
|
|
|
signParams.keyPair, |
|
|
|
|
|
]); |
|
|
|
|
|
vin = signParams.vin; |
|
|
|
|
|
keyPair = signParams.keyPair; |
|
|
|
|
|
const prevOutType = (this.__INPUTS[vin] || []).prevOutType; |
|
|
|
|
|
switch (signParams.prevOutScriptType) { |
|
|
|
|
|
case 'p2pkh': |
|
|
|
|
|
if (prevOutType !== 'pubkeyhash') { |
|
|
|
|
|
throw new TypeError(`input #${vin} is not of type p2pkh`); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case 'p2pk': |
|
|
|
|
|
if (prevOutType !== 'pubkey') { |
|
|
|
|
|
throw new TypeError(`input #${vin} is not of type p2pk`); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case 'p2wpkh': |
|
|
|
|
|
if (prevOutType !== 'witnesspubkeyhash') { |
|
|
|
|
|
throw new TypeError(`input #${vin} is not of type p2wpkh`); |
|
|
|
|
|
} |
|
|
|
|
|
typeforce(typeforce.Buffer, signParams.witnessScript); |
|
|
|
|
|
typeforce(typeforce.Satoshi, signParams.witnessValue); |
|
|
|
|
|
witnessScript = signParams.witnessScript; |
|
|
|
|
|
witnessValue = signParams.witnessValue; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'p2ms': |
|
|
|
|
|
if (prevOutType !== 'multisig') { |
|
|
|
|
|
throw new TypeError(`input #${vin} is not of type p2ms`); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case 'p2sh-p2wpkh': |
|
|
|
|
|
if (prevOutType !== 'scripthash') { |
|
|
|
|
|
throw new TypeError(`input #${vin} is not of type p2sh-p2wpkh`); |
|
|
|
|
|
} |
|
|
|
|
|
typeforce(typeforce.Buffer, signParams.witnessScript); |
|
|
|
|
|
typeforce(typeforce.Buffer, signParams.redeemScript); |
|
|
|
|
|
typeforce(typeforce.Satoshi, signParams.witnessValue); |
|
|
|
|
|
witnessScript = signParams.witnessScript; |
|
|
|
|
|
redeemScript = signParams.redeemScript; |
|
|
|
|
|
witnessValue = signParams.witnessValue; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'p2sh-p2ms': |
|
|
|
|
|
if (prevOutType !== 'scripthash') { |
|
|
|
|
|
throw new TypeError(`input #${vin} is not of type p2sh-p2ms`); |
|
|
|
|
|
} |
|
|
|
|
|
typeforce(typeforce.Buffer, signParams.redeemScript); |
|
|
|
|
|
redeemScript = signParams.redeemScript; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'p2wsh-p2ms': |
|
|
|
|
|
if (prevOutType !== 'witnessscripthash') { |
|
|
|
|
|
throw new TypeError(`input #${vin} is not of type p2wsh-p2ms`); |
|
|
|
|
|
} |
|
|
|
|
|
typeforce(typeforce.Buffer, signParams.witnessScript); |
|
|
|
|
|
typeforce(typeforce.Satoshi, signParams.witnessValue); |
|
|
|
|
|
witnessScript = signParams.witnessScript; |
|
|
|
|
|
witnessValue = signParams.witnessValue; |
|
|
|
|
|
break; |
|
|
|
|
|
case 'p2sh-p2wsh-p2ms': |
|
|
|
|
|
if (prevOutType !== 'scripthash') { |
|
|
|
|
|
throw new TypeError(`input #${vin} is not of type p2sh-p2wsh-p2ms`); |
|
|
|
|
|
} |
|
|
|
|
|
typeforce(typeforce.Buffer, signParams.witnessScript); |
|
|
|
|
|
typeforce(typeforce.Buffer, signParams.redeemScript); |
|
|
|
|
|
typeforce(typeforce.Satoshi, signParams.witnessValue); |
|
|
|
|
|
witnessScript = signParams.witnessScript; |
|
|
|
|
|
redeemScript = signParams.redeemScript; |
|
|
|
|
|
witnessValue = signParams.witnessValue; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
throw new TypeError( |
|
|
|
|
|
'TransactionBuilder sign first arg must be TxbSignArg or number', |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
// TODO: remove keyPair.network matching in 4.0.0
|
|
|
// TODO: remove keyPair.network matching in 4.0.0
|
|
|
if (keyPair.network && keyPair.network !== this.network) |
|
|
if (keyPair.network && keyPair.network !== this.network) |
|
|
throw new TypeError('Inconsistent network'); |
|
|
throw new TypeError('Inconsistent network'); |
|
|