Add ability to get redeemScript|witnessScript from finalized scripts

This commit is contained in:
junderw 2020-04-29 13:32:57 +09:00
parent c9f399e509
commit 5d19abfb85
No known key found for this signature in database
GPG key ID: A9273B5AD3E47B45
3 changed files with 96 additions and 16 deletions

View file

@ -293,8 +293,9 @@ class Psbt {
script,
inputIndex,
'input',
input.redeemScript,
input.witnessScript,
input.redeemScript || redeemFromFinalScriptSig(input.finalScriptSig),
input.witnessScript ||
redeemFromFinalWitnessScript(input.finalScriptWitness),
);
const type = result.type === 'raw' ? '' : result.type + '-';
const mainType = classifyScript(result.meaningfulScript);
@ -1272,6 +1273,36 @@ function pubkeyInOutput(pubkey, output, outputIndex, cache) {
);
return pubkeyInScript(pubkey, meaningfulScript);
}
function redeemFromFinalScriptSig(finalScript) {
if (!finalScript) return;
const decomp = bscript.decompile(finalScript);
if (!decomp) return;
const lastItem = decomp[decomp.length - 1];
if (
!Buffer.isBuffer(lastItem) ||
isPubkeyLike(lastItem) ||
isSigLike(lastItem)
)
return;
const sDecomp = bscript.decompile(lastItem);
if (!sDecomp) return;
return lastItem;
}
function redeemFromFinalWitnessScript(finalScript) {
if (!finalScript) return;
const decomp = scriptWitnessToWitnessStack(finalScript);
const lastItem = decomp[decomp.length - 1];
if (isPubkeyLike(lastItem)) return;
const sDecomp = bscript.decompile(lastItem);
if (!sDecomp) return;
return lastItem;
}
function isPubkeyLike(buf) {
return buf.length === 33 && bscript.isCanonicalPubKey(buf);
}
function isSigLike(buf) {
return bscript.isCanonicalScriptSignature(buf);
}
function getMeaningfulScript(
script,
index,

View file

@ -543,7 +543,8 @@ describe(`Psbt`, () => {
});
describe('getInputType', () => {
const { publicKey } = ECPair.makeRandom();
const key = ECPair.makeRandom();
const { publicKey } = key;
const p2wpkhPub = (pubkey: Buffer): Buffer =>
payments.p2wpkh({
pubkey,
@ -569,19 +570,26 @@ describe(`Psbt`, () => {
redeemGetter,
witnessGetter,
expectedType,
finalize,
}: any): void {
const psbt = new Psbt();
psbt.addInput({
hash:
'0000000000000000000000000000000000000000000000000000000000000000',
index: 0,
witnessUtxo: {
script: outerScript(innerScript(publicKey)),
value: 2e3,
},
...(redeemGetter ? { redeemScript: redeemGetter(publicKey) } : {}),
...(witnessGetter ? { witnessScript: witnessGetter(publicKey) } : {}),
});
psbt
.addInput({
hash:
'0000000000000000000000000000000000000000000000000000000000000000',
index: 0,
witnessUtxo: {
script: outerScript(innerScript(publicKey)),
value: 2e3,
},
...(redeemGetter ? { redeemScript: redeemGetter(publicKey) } : {}),
...(witnessGetter ? { witnessScript: witnessGetter(publicKey) } : {}),
})
.addOutput({
script: Buffer.from('0014d85c2b71d0060b09c9886aeb815e50991dda124d'),
value: 1800,
});
if (finalize) psbt.signInput(0, key).finalizeInput(0);
const type = psbt.getInputType(0);
assert.strictEqual(type, expectedType, 'incorrect input type');
}
@ -613,6 +621,7 @@ describe(`Psbt`, () => {
redeemGetter: p2wpkhPub,
witnessGetter: null,
expectedType: 'p2sh-witnesspubkeyhash',
finalize: true,
},
{
innerScript: p2pkhPub,
@ -620,6 +629,7 @@ describe(`Psbt`, () => {
redeemGetter: null,
witnessGetter: p2pkhPub,
expectedType: 'p2wsh-pubkeyhash',
finalize: true,
},
{
innerScript: p2pkhPub,

View file

@ -363,8 +363,9 @@ export class Psbt {
script,
inputIndex,
'input',
input.redeemScript,
input.witnessScript,
input.redeemScript || redeemFromFinalScriptSig(input.finalScriptSig),
input.witnessScript ||
redeemFromFinalWitnessScript(input.finalScriptWitness),
);
const type = result.type === 'raw' ? '' : result.type + '-';
const mainType = classifyScript(result.meaningfulScript);
@ -1642,6 +1643,44 @@ function pubkeyInOutput(
return pubkeyInScript(pubkey, meaningfulScript);
}
function redeemFromFinalScriptSig(
finalScript: Buffer | undefined,
): Buffer | undefined {
if (!finalScript) return;
const decomp = bscript.decompile(finalScript);
if (!decomp) return;
const lastItem = decomp[decomp.length - 1];
if (
!Buffer.isBuffer(lastItem) ||
isPubkeyLike(lastItem) ||
isSigLike(lastItem)
)
return;
const sDecomp = bscript.decompile(lastItem);
if (!sDecomp) return;
return lastItem;
}
function redeemFromFinalWitnessScript(
finalScript: Buffer | undefined,
): Buffer | undefined {
if (!finalScript) return;
const decomp = scriptWitnessToWitnessStack(finalScript);
const lastItem = decomp[decomp.length - 1];
if (isPubkeyLike(lastItem)) return;
const sDecomp = bscript.decompile(lastItem);
if (!sDecomp) return;
return lastItem;
}
function isPubkeyLike(buf: Buffer): boolean {
return buf.length === 33 && bscript.isCanonicalPubKey(buf);
}
function isSigLike(buf: Buffer): boolean {
return bscript.isCanonicalScriptSignature(buf);
}
function getMeaningfulScript(
script: Buffer,
index: number,