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

23
test/integration/transactions-psbt.js

@ -225,26 +225,25 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
} = 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)
.addOutput({
address: regtestUtils.RANDOM_ADDRESS,
value: 2e4
})
.signInput(0, p2sh.keys[0])
assert.strictEqual(psbt.validateSignatures(0), true)
psbt.finalizeAllInputs()
const tx = psbt.extractTransaction()
.addOutput(outputData)
.sign(keyPair)
.finalizeAllInputs()
.extractTransaction()
// build and broadcast to the Bitcoin RegTest network
await regtestUtils.broadcast(tx.toHex())
await regtestUtils.verify({
txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS,
address: p2sh.payment.address,
vout: 0,
value: 2e4
})

38
ts_src/psbt.ts

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

8
types/psbt.d.ts

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

Loading…
Cancel
Save