Finalize and extract done
This commit is contained in:
parent
343297a359
commit
813b84f91f
3 changed files with 400 additions and 93 deletions
217
src/psbt.js
217
src/psbt.js
|
@ -6,6 +6,7 @@ const crypto_1 = require('./crypto');
|
|||
const payments = require('./payments');
|
||||
const bscript = require('./script');
|
||||
const transaction_1 = require('./transaction');
|
||||
const varuint = require('varuint-bitcoin');
|
||||
class Psbt extends bip174_1.Psbt {
|
||||
// protected __TX: Transaction;
|
||||
constructor(network) {
|
||||
|
@ -23,56 +24,75 @@ class Psbt extends bip174_1.Psbt {
|
|||
// }
|
||||
// });
|
||||
}
|
||||
canFinalize(inputIndex) {
|
||||
extractTransaction() {
|
||||
if (!this.inputs.every(isFinalized)) throw new Error('Not finalized');
|
||||
const tx = transaction_1.Transaction.fromBuffer(this.globalMap.unsignedTx);
|
||||
this.inputs.forEach((input, idx) => {
|
||||
if (input.finalScriptSig) tx.ins[idx].script = input.finalScriptSig;
|
||||
if (input.finalScriptWitness) {
|
||||
const decompiled = bscript.decompile(input.finalScriptWitness);
|
||||
if (decompiled) tx.ins[idx].witness = bscript.toStack(decompiled);
|
||||
}
|
||||
});
|
||||
return tx;
|
||||
}
|
||||
finalizeAllInputs() {
|
||||
const inputResults = range(this.inputs.length).map(idx =>
|
||||
this.finalizeInput(idx),
|
||||
);
|
||||
const result = inputResults.every(val => val === true);
|
||||
return {
|
||||
result,
|
||||
inputResults,
|
||||
};
|
||||
}
|
||||
finalizeInput(inputIndex) {
|
||||
const input = utils_1.checkForInput(this.inputs, inputIndex);
|
||||
const script = getScriptFromInput(
|
||||
const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput(
|
||||
inputIndex,
|
||||
input,
|
||||
this.globalMap.unsignedTx,
|
||||
);
|
||||
if (!script) return false;
|
||||
const scriptType = classifyScript(script);
|
||||
const hasSigs = (neededSigs, partialSig) => {
|
||||
if (!partialSig) return false;
|
||||
if (partialSig.length > neededSigs)
|
||||
throw new Error('Too many signatures');
|
||||
return partialSig.length === neededSigs;
|
||||
};
|
||||
switch (scriptType) {
|
||||
case 'pubkey':
|
||||
return hasSigs(1, input.partialSig);
|
||||
case 'pubkeyhash':
|
||||
return hasSigs(1, input.partialSig);
|
||||
case 'multisig':
|
||||
const p2ms = payments.p2ms({ output: script });
|
||||
return hasSigs(p2ms.m, input.partialSig);
|
||||
case 'witnesspubkeyhash':
|
||||
return hasSigs(1, input.partialSig);
|
||||
default:
|
||||
return false;
|
||||
if (!canFinalize(input, script, scriptType)) return false;
|
||||
let finalScriptSig;
|
||||
let finalScriptWitness;
|
||||
// Wow, the payments API is very handy
|
||||
const payment = getPayment(script, scriptType, input.partialSig);
|
||||
const p2wsh = !isP2WSH ? null : payments.p2wsh({ redeem: payment });
|
||||
const p2sh = !isP2SH ? null : payments.p2sh({ redeem: p2wsh || payment });
|
||||
if (isSegwit) {
|
||||
if (p2wsh) {
|
||||
finalScriptWitness = witnessStackToScriptWitness(p2wsh.witness);
|
||||
} else {
|
||||
finalScriptWitness = witnessStackToScriptWitness(payment.witness);
|
||||
}
|
||||
if (p2sh) {
|
||||
finalScriptSig = bscript.compile([p2sh.redeem.output]);
|
||||
}
|
||||
} else {
|
||||
finalScriptSig = payment.input;
|
||||
}
|
||||
if (finalScriptSig)
|
||||
this.addFinalScriptSigToInput(inputIndex, finalScriptSig);
|
||||
if (finalScriptWitness)
|
||||
this.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
|
||||
if (!finalScriptSig && !finalScriptWitness) return false;
|
||||
this.clearFinalizedInput(inputIndex);
|
||||
return true;
|
||||
}
|
||||
signInput(inputIndex, keyPair) {
|
||||
const input = this.inputs[inputIndex];
|
||||
if (input === undefined) throw new Error(`No input #${inputIndex}`);
|
||||
const input = utils_1.checkForInput(this.inputs, inputIndex);
|
||||
if (!keyPair || !keyPair.publicKey)
|
||||
throw new Error('Need Signer to sign input');
|
||||
const { hash, sighashType, script } = getHashForSig(
|
||||
inputIndex,
|
||||
input,
|
||||
this.globalMap.unsignedTx,
|
||||
);
|
||||
const pubkey = keyPair.publicKey;
|
||||
const pubkeyHash = crypto_1.hash160(keyPair.publicKey);
|
||||
const decompiled = bscript.decompile(script);
|
||||
if (decompiled === null) throw new Error('Unknown script error');
|
||||
const hasKey = decompiled.some(element => {
|
||||
if (typeof element === 'number') return false;
|
||||
return element.equals(pubkey) || element.equals(pubkeyHash);
|
||||
});
|
||||
if (!hasKey) {
|
||||
throw new Error(
|
||||
`Can not sign for this input with the key ${pubkey.toString('hex')}`,
|
||||
);
|
||||
}
|
||||
checkScriptForPubkey(pubkey, script);
|
||||
const partialSig = {
|
||||
pubkey,
|
||||
signature: bscript.signature.encode(keyPair.sign(hash), sighashType),
|
||||
|
@ -81,6 +101,77 @@ class Psbt extends bip174_1.Psbt {
|
|||
}
|
||||
}
|
||||
exports.Psbt = Psbt;
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// Helper functions
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
function isFinalized(input) {
|
||||
return !!input.finalScriptSig || !!input.finalScriptWitness;
|
||||
}
|
||||
function getPayment(script, scriptType, partialSig) {
|
||||
let payment;
|
||||
switch (scriptType) {
|
||||
case 'multisig':
|
||||
payment = payments.p2ms({
|
||||
output: script,
|
||||
signatures: partialSig.map(ps => ps.signature),
|
||||
});
|
||||
break;
|
||||
case 'pubkey':
|
||||
payment = payments.p2pk({
|
||||
output: script,
|
||||
signature: partialSig[0].signature,
|
||||
});
|
||||
break;
|
||||
case 'pubkeyhash':
|
||||
payment = payments.p2pkh({
|
||||
output: script,
|
||||
pubkey: partialSig[0].pubkey,
|
||||
signature: partialSig[0].signature,
|
||||
});
|
||||
break;
|
||||
case 'witnesspubkeyhash':
|
||||
payment = payments.p2wpkh({
|
||||
output: script,
|
||||
pubkey: partialSig[0].pubkey,
|
||||
signature: partialSig[0].signature,
|
||||
});
|
||||
break;
|
||||
}
|
||||
return payment;
|
||||
}
|
||||
function canFinalize(input, script, scriptType) {
|
||||
switch (scriptType) {
|
||||
case 'pubkey':
|
||||
case 'pubkeyhash':
|
||||
case 'witnesspubkeyhash':
|
||||
return hasSigs(1, input.partialSig);
|
||||
case 'multisig':
|
||||
const p2ms = payments.p2ms({ output: script });
|
||||
return hasSigs(p2ms.m, input.partialSig);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function checkScriptForPubkey(pubkey, script) {
|
||||
const pubkeyHash = crypto_1.hash160(pubkey);
|
||||
const decompiled = bscript.decompile(script);
|
||||
if (decompiled === null) throw new Error('Unknown script error');
|
||||
const hasKey = decompiled.some(element => {
|
||||
if (typeof element === 'number') return false;
|
||||
return element.equals(pubkey) || element.equals(pubkeyHash);
|
||||
});
|
||||
if (!hasKey) {
|
||||
throw new Error(
|
||||
`Can not sign for this input with the key ${pubkey.toString('hex')}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
const getHashForSig = (inputIndex, input, txBuf) => {
|
||||
const unsignedTx = transaction_1.Transaction.fromBuffer(txBuf);
|
||||
const sighashType =
|
||||
|
@ -202,29 +293,67 @@ const classifyScript = script => {
|
|||
return 'nonstandard';
|
||||
};
|
||||
function getScriptFromInput(inputIndex, input, _unsignedTx) {
|
||||
let script;
|
||||
const res = {
|
||||
script: null,
|
||||
isSegwit: false,
|
||||
isP2SH: false,
|
||||
isP2WSH: false,
|
||||
};
|
||||
if (input.nonWitnessUtxo) {
|
||||
if (input.redeemScript) {
|
||||
script = input.redeemScript;
|
||||
res.isP2SH = true;
|
||||
res.script = input.redeemScript;
|
||||
} else {
|
||||
const unsignedTx = transaction_1.Transaction.fromBuffer(_unsignedTx);
|
||||
const nonWitnessUtxoTx = transaction_1.Transaction.fromBuffer(
|
||||
input.nonWitnessUtxo,
|
||||
);
|
||||
const prevoutIndex = unsignedTx.ins[inputIndex].index;
|
||||
script = nonWitnessUtxoTx.outs[prevoutIndex].script;
|
||||
res.script = nonWitnessUtxoTx.outs[prevoutIndex].script;
|
||||
}
|
||||
} else if (input.witnessUtxo) {
|
||||
res.isSegwit = true;
|
||||
res.isP2SH = !!input.redeemScript;
|
||||
res.isP2WSH = !!input.witnessScript;
|
||||
if (input.witnessScript) {
|
||||
script = input.witnessScript;
|
||||
res.script = input.witnessScript;
|
||||
} else if (input.redeemScript) {
|
||||
script = payments.p2pkh({ hash: input.redeemScript.slice(2) }).output;
|
||||
res.script = payments.p2pkh({
|
||||
hash: input.redeemScript.slice(2),
|
||||
}).output;
|
||||
} else {
|
||||
script = payments.p2pkh({ hash: input.witnessUtxo.script.slice(2) })
|
||||
.output;
|
||||
res.script = payments.p2pkh({
|
||||
hash: input.witnessUtxo.script.slice(2),
|
||||
}).output;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
return script;
|
||||
return res;
|
||||
}
|
||||
const hasSigs = (neededSigs, partialSig) => {
|
||||
if (!partialSig) return false;
|
||||
if (partialSig.length > neededSigs) throw new Error('Too many signatures');
|
||||
return partialSig.length === neededSigs;
|
||||
};
|
||||
function witnessStackToScriptWitness(witness) {
|
||||
let buffer = Buffer.allocUnsafe(0);
|
||||
function writeSlice(slice) {
|
||||
buffer = Buffer.concat([buffer, Buffer.from(slice)]);
|
||||
}
|
||||
function writeVarInt(i) {
|
||||
const currentLen = buffer.length;
|
||||
const varintLen = varuint.encodingLength(i);
|
||||
buffer = Buffer.concat([buffer, Buffer.allocUnsafe(varintLen)]);
|
||||
varuint.encode(i, buffer, currentLen);
|
||||
}
|
||||
function writeVarSlice(slice) {
|
||||
writeVarInt(slice.length);
|
||||
writeSlice(slice);
|
||||
}
|
||||
function writeVector(vector) {
|
||||
writeVarInt(vector.length);
|
||||
vector.forEach(writeVarSlice);
|
||||
}
|
||||
writeVector(witness);
|
||||
return buffer;
|
||||
}
|
||||
const range = n => [...Array(n).keys()];
|
||||
|
|
268
ts_src/psbt.ts
268
ts_src/psbt.ts
|
@ -1,5 +1,5 @@
|
|||
import { Psbt as PsbtBase } from 'bip174';
|
||||
import { PsbtInput } from 'bip174/src/lib/interfaces';
|
||||
import { PartialSig, PsbtInput } from 'bip174/src/lib/interfaces';
|
||||
import { checkForInput } from 'bip174/src/lib/utils';
|
||||
import { hash160 } from './crypto';
|
||||
import { Signer } from './ecpair';
|
||||
|
@ -7,6 +7,7 @@ import { Network } from './networks';
|
|||
import * as payments from './payments';
|
||||
import * as bscript from './script';
|
||||
import { Transaction } from './transaction';
|
||||
const varuint = require('varuint-bitcoin');
|
||||
|
||||
export class Psbt extends PsbtBase {
|
||||
// protected __TX: Transaction;
|
||||
|
@ -25,41 +26,84 @@ export class Psbt extends PsbtBase {
|
|||
// });
|
||||
}
|
||||
|
||||
canFinalize(inputIndex: number): boolean {
|
||||
extractTransaction(): Transaction {
|
||||
if (!this.inputs.every(isFinalized)) throw new Error('Not finalized');
|
||||
const tx = Transaction.fromBuffer(this.globalMap.unsignedTx!);
|
||||
this.inputs.forEach((input, idx) => {
|
||||
if (input.finalScriptSig) tx.ins[idx].script = input.finalScriptSig;
|
||||
if (input.finalScriptWitness) {
|
||||
const decompiled = bscript.decompile(input.finalScriptWitness);
|
||||
if (decompiled) tx.ins[idx].witness = bscript.toStack(decompiled);
|
||||
}
|
||||
});
|
||||
return tx;
|
||||
}
|
||||
|
||||
finalizeAllInputs(): {
|
||||
result: boolean;
|
||||
inputResults: boolean[];
|
||||
} {
|
||||
const inputResults = range(this.inputs.length).map(idx =>
|
||||
this.finalizeInput(idx),
|
||||
);
|
||||
const result = inputResults.every(val => val === true);
|
||||
return {
|
||||
result,
|
||||
inputResults,
|
||||
};
|
||||
}
|
||||
|
||||
finalizeInput(inputIndex: number): boolean {
|
||||
const input = checkForInput(this.inputs, inputIndex);
|
||||
const script = getScriptFromInput(
|
||||
const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput(
|
||||
inputIndex,
|
||||
input,
|
||||
this.globalMap.unsignedTx!,
|
||||
);
|
||||
if (!script) return false;
|
||||
|
||||
const scriptType = classifyScript(script);
|
||||
if (!canFinalize(input, script, scriptType)) return false;
|
||||
|
||||
const hasSigs = (neededSigs: number, partialSig?: any[]): boolean => {
|
||||
if (!partialSig) return false;
|
||||
if (partialSig.length > neededSigs)
|
||||
throw new Error('Too many signatures');
|
||||
return partialSig.length === neededSigs;
|
||||
};
|
||||
let finalScriptSig: Buffer | undefined;
|
||||
let finalScriptWitness: Buffer | undefined;
|
||||
|
||||
switch (scriptType) {
|
||||
case 'pubkey':
|
||||
return hasSigs(1, input.partialSig);
|
||||
case 'pubkeyhash':
|
||||
return hasSigs(1, input.partialSig);
|
||||
case 'multisig':
|
||||
const p2ms = payments.p2ms({ output: script });
|
||||
return hasSigs(p2ms.m!, input.partialSig);
|
||||
case 'witnesspubkeyhash':
|
||||
return hasSigs(1, input.partialSig);
|
||||
default:
|
||||
return false;
|
||||
// Wow, the payments API is very handy
|
||||
const payment: payments.Payment = getPayment(
|
||||
script,
|
||||
scriptType,
|
||||
input.partialSig!,
|
||||
);
|
||||
const p2wsh = !isP2WSH ? null : payments.p2wsh({ redeem: payment });
|
||||
const p2sh = !isP2SH ? null : payments.p2sh({ redeem: p2wsh || payment });
|
||||
|
||||
if (isSegwit) {
|
||||
if (p2wsh) {
|
||||
finalScriptWitness = witnessStackToScriptWitness(p2wsh.witness!);
|
||||
} else {
|
||||
finalScriptWitness = witnessStackToScriptWitness(payment.witness!);
|
||||
}
|
||||
if (p2sh) {
|
||||
finalScriptSig = bscript.compile([p2sh.redeem!.output!]);
|
||||
}
|
||||
} else {
|
||||
finalScriptSig = payment.input;
|
||||
}
|
||||
|
||||
if (finalScriptSig)
|
||||
this.addFinalScriptSigToInput(inputIndex, finalScriptSig);
|
||||
if (finalScriptWitness)
|
||||
this.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
|
||||
if (!finalScriptSig && !finalScriptWitness) return false;
|
||||
|
||||
this.clearFinalizedInput(inputIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
signInput(inputIndex: number, keyPair: Signer): Psbt {
|
||||
const input = this.inputs[inputIndex];
|
||||
if (input === undefined) throw new Error(`No input #${inputIndex}`);
|
||||
const input = checkForInput(this.inputs, inputIndex);
|
||||
if (!keyPair || !keyPair.publicKey)
|
||||
throw new Error('Need Signer to sign input');
|
||||
const { hash, sighashType, script } = getHashForSig(
|
||||
inputIndex,
|
||||
input,
|
||||
|
@ -67,21 +111,8 @@ export class Psbt extends PsbtBase {
|
|||
);
|
||||
|
||||
const pubkey = keyPair.publicKey;
|
||||
const pubkeyHash = hash160(keyPair.publicKey);
|
||||
|
||||
const decompiled = bscript.decompile(script);
|
||||
if (decompiled === null) throw new Error('Unknown script error');
|
||||
|
||||
const hasKey = decompiled.some(element => {
|
||||
if (typeof element === 'number') return false;
|
||||
return element.equals(pubkey) || element.equals(pubkeyHash);
|
||||
});
|
||||
|
||||
if (!hasKey) {
|
||||
throw new Error(
|
||||
`Can not sign for this input with the key ${pubkey.toString('hex')}`,
|
||||
);
|
||||
}
|
||||
checkScriptForPubkey(pubkey, script);
|
||||
|
||||
const partialSig = {
|
||||
pubkey,
|
||||
|
@ -92,6 +123,93 @@ export class Psbt extends PsbtBase {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// Helper functions
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
function isFinalized(input: PsbtInput): boolean {
|
||||
return !!input.finalScriptSig || !!input.finalScriptWitness;
|
||||
}
|
||||
|
||||
function getPayment(
|
||||
script: Buffer,
|
||||
scriptType: string,
|
||||
partialSig: PartialSig[],
|
||||
): payments.Payment {
|
||||
let payment: payments.Payment;
|
||||
switch (scriptType) {
|
||||
case 'multisig':
|
||||
payment = payments.p2ms({
|
||||
output: script,
|
||||
signatures: partialSig.map(ps => ps.signature),
|
||||
});
|
||||
break;
|
||||
case 'pubkey':
|
||||
payment = payments.p2pk({
|
||||
output: script,
|
||||
signature: partialSig[0].signature,
|
||||
});
|
||||
break;
|
||||
case 'pubkeyhash':
|
||||
payment = payments.p2pkh({
|
||||
output: script,
|
||||
pubkey: partialSig[0].pubkey,
|
||||
signature: partialSig[0].signature,
|
||||
});
|
||||
break;
|
||||
case 'witnesspubkeyhash':
|
||||
payment = payments.p2wpkh({
|
||||
output: script,
|
||||
pubkey: partialSig[0].pubkey,
|
||||
signature: partialSig[0].signature,
|
||||
});
|
||||
break;
|
||||
}
|
||||
return payment!;
|
||||
}
|
||||
|
||||
function canFinalize(
|
||||
input: PsbtInput,
|
||||
script: Buffer,
|
||||
scriptType: string,
|
||||
): boolean {
|
||||
switch (scriptType) {
|
||||
case 'pubkey':
|
||||
case 'pubkeyhash':
|
||||
case 'witnesspubkeyhash':
|
||||
return hasSigs(1, input.partialSig);
|
||||
case 'multisig':
|
||||
const p2ms = payments.p2ms({ output: script });
|
||||
return hasSigs(p2ms.m!, input.partialSig);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function checkScriptForPubkey(pubkey: Buffer, script: Buffer): void {
|
||||
const pubkeyHash = hash160(pubkey);
|
||||
|
||||
const decompiled = bscript.decompile(script);
|
||||
if (decompiled === null) throw new Error('Unknown script error');
|
||||
|
||||
const hasKey = decompiled.some(element => {
|
||||
if (typeof element === 'number') return false;
|
||||
return element.equals(pubkey) || element.equals(pubkeyHash);
|
||||
});
|
||||
|
||||
if (!hasKey) {
|
||||
throw new Error(
|
||||
`Can not sign for this input with the key ${pubkey.toString('hex')}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface HashForSigData {
|
||||
script: Buffer;
|
||||
hash: Buffer;
|
||||
|
@ -239,32 +357,86 @@ const classifyScript = (script: Buffer): string => {
|
|||
return 'nonstandard';
|
||||
};
|
||||
|
||||
interface GetScriptReturn {
|
||||
script: Buffer | null;
|
||||
isSegwit: boolean;
|
||||
isP2SH: boolean;
|
||||
isP2WSH: boolean;
|
||||
}
|
||||
function getScriptFromInput(
|
||||
inputIndex: number,
|
||||
input: PsbtInput,
|
||||
_unsignedTx: Buffer,
|
||||
): Buffer | undefined {
|
||||
let script: Buffer;
|
||||
): GetScriptReturn {
|
||||
const res: GetScriptReturn = {
|
||||
script: null,
|
||||
isSegwit: false,
|
||||
isP2SH: false,
|
||||
isP2WSH: false,
|
||||
};
|
||||
if (input.nonWitnessUtxo) {
|
||||
if (input.redeemScript) {
|
||||
script = input.redeemScript;
|
||||
res.isP2SH = true;
|
||||
res.script = input.redeemScript;
|
||||
} else {
|
||||
const unsignedTx = Transaction.fromBuffer(_unsignedTx);
|
||||
const nonWitnessUtxoTx = Transaction.fromBuffer(input.nonWitnessUtxo);
|
||||
const prevoutIndex = unsignedTx.ins[inputIndex].index;
|
||||
script = nonWitnessUtxoTx.outs[prevoutIndex].script;
|
||||
res.script = nonWitnessUtxoTx.outs[prevoutIndex].script;
|
||||
}
|
||||
} else if (input.witnessUtxo) {
|
||||
res.isSegwit = true;
|
||||
res.isP2SH = !!input.redeemScript;
|
||||
res.isP2WSH = !!input.witnessScript;
|
||||
if (input.witnessScript) {
|
||||
script = input.witnessScript;
|
||||
res.script = input.witnessScript;
|
||||
} else if (input.redeemScript) {
|
||||
script = payments.p2pkh({ hash: input.redeemScript.slice(2) }).output!;
|
||||
res.script = payments.p2pkh({
|
||||
hash: input.redeemScript.slice(2),
|
||||
}).output!;
|
||||
} else {
|
||||
script = payments.p2pkh({ hash: input.witnessUtxo.script.slice(2) })
|
||||
.output!;
|
||||
res.script = payments.p2pkh({
|
||||
hash: input.witnessUtxo.script.slice(2),
|
||||
}).output!;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
return script;
|
||||
return res;
|
||||
}
|
||||
|
||||
const hasSigs = (neededSigs: number, partialSig?: any[]): boolean => {
|
||||
if (!partialSig) return false;
|
||||
if (partialSig.length > neededSigs) throw new Error('Too many signatures');
|
||||
return partialSig.length === neededSigs;
|
||||
};
|
||||
|
||||
function witnessStackToScriptWitness(witness: Buffer[]): Buffer {
|
||||
let buffer = Buffer.allocUnsafe(0);
|
||||
|
||||
function writeSlice(slice: Buffer): void {
|
||||
buffer = Buffer.concat([buffer, Buffer.from(slice)]);
|
||||
}
|
||||
|
||||
function writeVarInt(i: number): void {
|
||||
const currentLen = buffer.length;
|
||||
const varintLen = varuint.encodingLength(i);
|
||||
|
||||
buffer = Buffer.concat([buffer, Buffer.allocUnsafe(varintLen)]);
|
||||
varuint.encode(i, buffer, currentLen);
|
||||
}
|
||||
|
||||
function writeVarSlice(slice: Buffer): void {
|
||||
writeVarInt(slice.length);
|
||||
writeSlice(slice);
|
||||
}
|
||||
|
||||
function writeVector(vector: Buffer[]): void {
|
||||
writeVarInt(vector.length);
|
||||
vector.forEach(writeVarSlice);
|
||||
}
|
||||
|
||||
writeVector(witness);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const range = (n: number): number[] => [...Array(n).keys()];
|
||||
|
|
8
types/psbt.d.ts
vendored
8
types/psbt.d.ts
vendored
|
@ -1,9 +1,15 @@
|
|||
import { Psbt as PsbtBase } from 'bip174';
|
||||
import { Signer } from './ecpair';
|
||||
import { Network } from './networks';
|
||||
import { Transaction } from './transaction';
|
||||
export declare class Psbt extends PsbtBase {
|
||||
network?: Network | undefined;
|
||||
constructor(network?: Network | undefined);
|
||||
canFinalize(inputIndex: number): boolean;
|
||||
extractTransaction(): Transaction;
|
||||
finalizeAllInputs(): {
|
||||
result: boolean;
|
||||
inputResults: boolean[];
|
||||
};
|
||||
finalizeInput(inputIndex: number): boolean;
|
||||
signInput(inputIndex: number, keyPair: Signer): Psbt;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue