Browse Source

Finalize should chain this as well.

psbt
junderw 6 years ago
parent
commit
b8c341dea0
No known key found for this signature in database GPG Key ID: B256185D3A971908
  1. 30
      src/psbt.js
  2. 23
      test/integration/transactions-psbt.js
  3. 38
      ts_src/psbt.ts
  4. 8
      types/psbt.d.ts

30
src/psbt.js

@ -187,14 +187,9 @@ class Psbt extends bip174_1.Psbt {
return c.__FEE_RATE; return c.__FEE_RATE;
} }
finalizeAllInputs() { finalizeAllInputs() {
const inputResults = range(this.inputs.length).map(idx => utils_1.checkForInput(this.inputs, 0); // making sure we have at least one
this.finalizeInput(idx), range(this.inputs.length).forEach(idx => this.finalizeInput(idx));
); return this;
const result = inputResults.every(val => val === true);
return {
result,
inputResults,
};
} }
finalizeInput(inputIndex) { finalizeInput(inputIndex) {
const input = utils_1.checkForInput(this.inputs, inputIndex); const input = utils_1.checkForInput(this.inputs, inputIndex);
@ -203,9 +198,10 @@ class Psbt extends bip174_1.Psbt {
input, input,
this.__CACHE, this.__CACHE,
); );
if (!script) return false; if (!script) throw new Error(`No script found for input #${inputIndex}`);
const scriptType = classifyScript(script); const scriptType = classifyScript(script);
if (!canFinalize(input, script, scriptType)) return false; if (!canFinalize(input, script, scriptType))
throw new Error(`Can not finalize input #${inputIndex}`);
const { finalScriptSig, finalScriptWitness } = getFinalScripts( const { finalScriptSig, finalScriptWitness } = getFinalScripts(
script, script,
scriptType, scriptType,
@ -218,9 +214,17 @@ class Psbt extends bip174_1.Psbt {
this.addFinalScriptSigToInput(inputIndex, finalScriptSig); this.addFinalScriptSigToInput(inputIndex, finalScriptSig);
if (finalScriptWitness) if (finalScriptWitness)
this.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness); this.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
if (!finalScriptSig && !finalScriptWitness) return false; if (!finalScriptSig && !finalScriptWitness)
throw new Error(`Unknown error finalizing input #${inputIndex}`);
this.clearFinalizedInput(inputIndex); this.clearFinalizedInput(inputIndex);
return true; return this;
}
validateAllSignatures() {
utils_1.checkForInput(this.inputs, 0); // making sure we have at least one
const results = range(this.inputs.length).map(idx =>
this.validateSignatures(idx),
);
return results.reduce((final, res) => res === true && final, true);
} }
validateSignatures(inputIndex, pubkey) { validateSignatures(inputIndex, pubkey) {
const input = this.inputs[inputIndex]; const input = this.inputs[inputIndex];
@ -261,7 +265,7 @@ class Psbt extends bip174_1.Psbt {
// as input information is added, then eventually // as input information is added, then eventually
// optimize this method. // optimize this method.
const results = []; const results = [];
for (const [i] of this.inputs.entries()) { for (const i of range(this.inputs.length)) {
try { try {
this.signInput(i, keyPair); this.signInput(i, keyPair);
results.push(true); results.push(true);

23
test/integration/transactions-psbt.js

@ -225,26 +225,25 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
} = inputData } = inputData
assert.deepStrictEqual({ hash, index, witnessUtxo, redeemScript }, inputData) assert.deepStrictEqual({ hash, index, witnessUtxo, redeemScript }, inputData)
} }
const keyPair = p2sh.keys[0]
const outputData = {
script: p2sh.payment.output, // sending to myself for fun
value: 2e4
}
const psbt = new bitcoin.Psbt({ network: regtest }) const tx = new bitcoin.Psbt()
.addInput(inputData) .addInput(inputData)
.addOutput({ .addOutput(outputData)
address: regtestUtils.RANDOM_ADDRESS, .sign(keyPair)
value: 2e4 .finalizeAllInputs()
}) .extractTransaction()
.signInput(0, p2sh.keys[0])
assert.strictEqual(psbt.validateSignatures(0), true)
psbt.finalizeAllInputs()
const tx = psbt.extractTransaction()
// build and broadcast to the Bitcoin RegTest network // build and broadcast to the Bitcoin RegTest network
await regtestUtils.broadcast(tx.toHex()) await regtestUtils.broadcast(tx.toHex())
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: p2sh.payment.address,
vout: 0, vout: 0,
value: 2e4 value: 2e4
}) })

38
ts_src/psbt.ts

@ -233,31 +233,24 @@ export class Psbt extends PsbtBase {
return c.__FEE_RATE!; return c.__FEE_RATE!;
} }
finalizeAllInputs(): { finalizeAllInputs(): this {
result: boolean; checkForInput(this.inputs, 0); // making sure we have at least one
inputResults: boolean[]; range(this.inputs.length).forEach(idx => this.finalizeInput(idx));
} { return this;
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 { finalizeInput(inputIndex: number): this {
const input = checkForInput(this.inputs, inputIndex); const input = checkForInput(this.inputs, inputIndex);
const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput( const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput(
inputIndex, inputIndex,
input, input,
this.__CACHE, this.__CACHE,
); );
if (!script) return false; if (!script) throw new Error(`No script found for input #${inputIndex}`);
const scriptType = classifyScript(script); const scriptType = classifyScript(script);
if (!canFinalize(input, script, scriptType)) return false; if (!canFinalize(input, script, scriptType))
throw new Error(`Can not finalize input #${inputIndex}`);
const { finalScriptSig, finalScriptWitness } = getFinalScripts( const { finalScriptSig, finalScriptWitness } = getFinalScripts(
script, script,
@ -272,10 +265,19 @@ export class Psbt extends PsbtBase {
this.addFinalScriptSigToInput(inputIndex, finalScriptSig); this.addFinalScriptSigToInput(inputIndex, finalScriptSig);
if (finalScriptWitness) if (finalScriptWitness)
this.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness); this.addFinalScriptWitnessToInput(inputIndex, finalScriptWitness);
if (!finalScriptSig && !finalScriptWitness) return false; if (!finalScriptSig && !finalScriptWitness)
throw new Error(`Unknown error finalizing input #${inputIndex}`);
this.clearFinalizedInput(inputIndex); this.clearFinalizedInput(inputIndex);
return true; return this;
}
validateAllSignatures(): boolean {
checkForInput(this.inputs, 0); // making sure we have at least one
const results = range(this.inputs.length).map(idx =>
this.validateSignatures(idx),
);
return results.reduce((final, res) => res === true && final, true);
} }
validateSignatures(inputIndex: number, pubkey?: Buffer): boolean { validateSignatures(inputIndex: number, pubkey?: Buffer): boolean {
@ -319,7 +321,7 @@ export class Psbt extends PsbtBase {
// as input information is added, then eventually // as input information is added, then eventually
// optimize this method. // optimize this method.
const results: boolean[] = []; const results: boolean[] = [];
for (const [i] of this.inputs.entries()) { for (const i of range(this.inputs.length)) {
try { try {
this.signInput(i, keyPair); this.signInput(i, keyPair);
results.push(true); results.push(true);

8
types/psbt.d.ts

@ -20,11 +20,9 @@ export declare class Psbt extends PsbtBase {
addNonWitnessUtxoToInput(inputIndex: number, nonWitnessUtxo: NonWitnessUtxo): this; addNonWitnessUtxoToInput(inputIndex: number, nonWitnessUtxo: NonWitnessUtxo): this;
extractTransaction(disableFeeCheck?: boolean): Transaction; extractTransaction(disableFeeCheck?: boolean): Transaction;
getFeeRate(): number; getFeeRate(): number;
finalizeAllInputs(): { finalizeAllInputs(): this;
result: boolean; finalizeInput(inputIndex: number): this;
inputResults: boolean[]; validateAllSignatures(): boolean;
};
finalizeInput(inputIndex: number): boolean;
validateSignatures(inputIndex: number, pubkey?: Buffer): boolean; validateSignatures(inputIndex: number, pubkey?: Buffer): boolean;
sign(keyPair: Signer): this; sign(keyPair: Signer): this;
signAsync(keyPair: SignerAsync): Promise<void>; signAsync(keyPair: SignerAsync): Promise<void>;

Loading…
Cancel
Save