From e4844828deca4ea2fc7ce815a32d6dd4f66359fd Mon Sep 17 00:00:00 2001 From: junderw Date: Tue, 23 Jul 2019 14:59:54 +0900 Subject: [PATCH 1/2] Check signatures for finalized inputs too --- src/psbt.js | 23 +++++++++++++++++++++-- test/psbt.js | 3 +++ ts_src/psbt.ts | 23 +++++++++++++++++++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/psbt.js b/src/psbt.js index 8fbb2bb..0898bc6 100644 --- a/src/psbt.js +++ b/src/psbt.js @@ -626,8 +626,27 @@ function checkFees(psbt, cache, opts) { function checkInputsForPartialSig(inputs, action) { inputs.forEach(input => { let throws = false; - if ((input.partialSig || []).length === 0) return; - input.partialSig.forEach(pSig => { + let pSigs = []; + if ((input.partialSig || []).length === 0) { + if (!input.finalScriptSig && !input.finalScriptWitness) return; + const scriptItems = !input.finalScriptSig + ? [] + : bscript.decompile(input.finalScriptSig) || []; + const witnessItems = !input.finalScriptWitness + ? [] + : bscript.decompile(input.finalScriptWitness) || []; + pSigs = scriptItems + .concat(witnessItems) + .filter(item => { + return ( + Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item) + ); + }) + .map(sig => ({ signature: sig })); + } else { + pSigs = input.partialSig; + } + pSigs.forEach(pSig => { const { hashType } = bscript.signature.decode(pSig.signature); const whitelist = []; const isAnyoneCanPay = diff --git a/test/psbt.js b/test/psbt.js index b670a99..467e426 100644 --- a/test/psbt.js +++ b/test/psbt.js @@ -625,6 +625,9 @@ describe(`Psbt`, () => { }, new RegExp('Can not modify transaction, signatures exist.')) psbt.validateSignaturesOfInput(0) psbt.finalizeAllInputs() + assert.throws(() => { + psbt.setVersion(3) + }, new RegExp('Can not modify transaction, signatures exist.')) assert.strictEqual( psbt.extractTransaction().toHex(), '02000000013ebc8203037dda39d482bf41ff3be955996c50d9d4f7cfc3d2097a694a7' + diff --git a/ts_src/psbt.ts b/ts_src/psbt.ts index 83e9dee..707ca21 100644 --- a/ts_src/psbt.ts +++ b/ts_src/psbt.ts @@ -795,8 +795,27 @@ function checkFees(psbt: Psbt, cache: PsbtCache, opts: PsbtOpts): void { function checkInputsForPartialSig(inputs: PsbtInput[], action: string): void { inputs.forEach(input => { let throws = false; - if ((input.partialSig || []).length === 0) return; - input.partialSig!.forEach(pSig => { + let pSigs: PartialSig[] = []; + if ((input.partialSig || []).length === 0) { + if (!input.finalScriptSig && !input.finalScriptWitness) return; + const scriptItems = !input.finalScriptSig + ? [] + : bscript.decompile(input.finalScriptSig) || []; + const witnessItems = !input.finalScriptWitness + ? [] + : bscript.decompile(input.finalScriptWitness) || []; + pSigs = scriptItems + .concat(witnessItems) + .filter(item => { + return ( + Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item) + ); + }) + .map(sig => ({ signature: sig })) as PartialSig[]; + } else { + pSigs = input.partialSig!; + } + pSigs.forEach(pSig => { const { hashType } = bscript.signature.decode(pSig.signature); const whitelist: string[] = []; const isAnyoneCanPay = hashType & Transaction.SIGHASH_ANYONECANPAY; From 06b38a7d834cf2b07e81bd3375f5f29028f0bf45 Mon Sep 17 00:00:00 2001 From: junderw Date: Tue, 23 Jul 2019 15:51:12 +0900 Subject: [PATCH 2/2] Refactor: add function getPsigsFromInputFinalScripts --- src/psbt.js | 29 +++++++++++++++-------------- ts_src/psbt.ts | 30 ++++++++++++++++-------------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/psbt.js b/src/psbt.js index 0898bc6..051de6e 100644 --- a/src/psbt.js +++ b/src/psbt.js @@ -629,20 +629,7 @@ function checkInputsForPartialSig(inputs, action) { let pSigs = []; if ((input.partialSig || []).length === 0) { if (!input.finalScriptSig && !input.finalScriptWitness) return; - const scriptItems = !input.finalScriptSig - ? [] - : bscript.decompile(input.finalScriptSig) || []; - const witnessItems = !input.finalScriptWitness - ? [] - : bscript.decompile(input.finalScriptWitness) || []; - pSigs = scriptItems - .concat(witnessItems) - .filter(item => { - return ( - Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item) - ); - }) - .map(sig => ({ signature: sig })); + pSigs = getPsigsFromInputFinalScripts(input); } else { pSigs = input.partialSig; } @@ -918,6 +905,20 @@ function getPayment(script, scriptType, partialSig) { } return payment; } +function getPsigsFromInputFinalScripts(input) { + const scriptItems = !input.finalScriptSig + ? [] + : bscript.decompile(input.finalScriptSig) || []; + const witnessItems = !input.finalScriptWitness + ? [] + : bscript.decompile(input.finalScriptWitness) || []; + return scriptItems + .concat(witnessItems) + .filter(item => { + return Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item); + }) + .map(sig => ({ signature: sig })); +} function getScriptFromInput(inputIndex, input, cache) { const unsignedTx = cache.__TX; const res = { diff --git a/ts_src/psbt.ts b/ts_src/psbt.ts index 707ca21..eb09155 100644 --- a/ts_src/psbt.ts +++ b/ts_src/psbt.ts @@ -798,20 +798,7 @@ function checkInputsForPartialSig(inputs: PsbtInput[], action: string): void { let pSigs: PartialSig[] = []; if ((input.partialSig || []).length === 0) { if (!input.finalScriptSig && !input.finalScriptWitness) return; - const scriptItems = !input.finalScriptSig - ? [] - : bscript.decompile(input.finalScriptSig) || []; - const witnessItems = !input.finalScriptWitness - ? [] - : bscript.decompile(input.finalScriptWitness) || []; - pSigs = scriptItems - .concat(witnessItems) - .filter(item => { - return ( - Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item) - ); - }) - .map(sig => ({ signature: sig })) as PartialSig[]; + pSigs = getPsigsFromInputFinalScripts(input); } else { pSigs = input.partialSig!; } @@ -1140,6 +1127,21 @@ function getPayment( return payment!; } +function getPsigsFromInputFinalScripts(input: PsbtInput): PartialSig[] { + const scriptItems = !input.finalScriptSig + ? [] + : bscript.decompile(input.finalScriptSig) || []; + const witnessItems = !input.finalScriptWitness + ? [] + : bscript.decompile(input.finalScriptWitness) || []; + return scriptItems + .concat(witnessItems) + .filter(item => { + return Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item); + }) + .map(sig => ({ signature: sig })) as PartialSig[]; +} + interface GetScriptReturn { script: Buffer | null; isSegwit: boolean;