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, script,
inputIndex, inputIndex,
'input', 'input',
input.redeemScript, input.redeemScript || redeemFromFinalScriptSig(input.finalScriptSig),
input.witnessScript, input.witnessScript ||
redeemFromFinalWitnessScript(input.finalScriptWitness),
); );
const type = result.type === 'raw' ? '' : result.type + '-'; const type = result.type === 'raw' ? '' : result.type + '-';
const mainType = classifyScript(result.meaningfulScript); const mainType = classifyScript(result.meaningfulScript);
@ -1272,6 +1273,36 @@ function pubkeyInOutput(pubkey, output, outputIndex, cache) {
); );
return pubkeyInScript(pubkey, meaningfulScript); 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( function getMeaningfulScript(
script, script,
index, index,

View file

@ -543,7 +543,8 @@ describe(`Psbt`, () => {
}); });
describe('getInputType', () => { describe('getInputType', () => {
const { publicKey } = ECPair.makeRandom(); const key = ECPair.makeRandom();
const { publicKey } = key;
const p2wpkhPub = (pubkey: Buffer): Buffer => const p2wpkhPub = (pubkey: Buffer): Buffer =>
payments.p2wpkh({ payments.p2wpkh({
pubkey, pubkey,
@ -569,9 +570,11 @@ describe(`Psbt`, () => {
redeemGetter, redeemGetter,
witnessGetter, witnessGetter,
expectedType, expectedType,
finalize,
}: any): void { }: any): void {
const psbt = new Psbt(); const psbt = new Psbt();
psbt.addInput({ psbt
.addInput({
hash: hash:
'0000000000000000000000000000000000000000000000000000000000000000', '0000000000000000000000000000000000000000000000000000000000000000',
index: 0, index: 0,
@ -581,7 +584,12 @@ describe(`Psbt`, () => {
}, },
...(redeemGetter ? { redeemScript: redeemGetter(publicKey) } : {}), ...(redeemGetter ? { redeemScript: redeemGetter(publicKey) } : {}),
...(witnessGetter ? { witnessScript: witnessGetter(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); const type = psbt.getInputType(0);
assert.strictEqual(type, expectedType, 'incorrect input type'); assert.strictEqual(type, expectedType, 'incorrect input type');
} }
@ -613,6 +621,7 @@ describe(`Psbt`, () => {
redeemGetter: p2wpkhPub, redeemGetter: p2wpkhPub,
witnessGetter: null, witnessGetter: null,
expectedType: 'p2sh-witnesspubkeyhash', expectedType: 'p2sh-witnesspubkeyhash',
finalize: true,
}, },
{ {
innerScript: p2pkhPub, innerScript: p2pkhPub,
@ -620,6 +629,7 @@ describe(`Psbt`, () => {
redeemGetter: null, redeemGetter: null,
witnessGetter: p2pkhPub, witnessGetter: p2pkhPub,
expectedType: 'p2wsh-pubkeyhash', expectedType: 'p2wsh-pubkeyhash',
finalize: true,
}, },
{ {
innerScript: p2pkhPub, innerScript: p2pkhPub,

View file

@ -363,8 +363,9 @@ export class Psbt {
script, script,
inputIndex, inputIndex,
'input', 'input',
input.redeemScript, input.redeemScript || redeemFromFinalScriptSig(input.finalScriptSig),
input.witnessScript, input.witnessScript ||
redeemFromFinalWitnessScript(input.finalScriptWitness),
); );
const type = result.type === 'raw' ? '' : result.type + '-'; const type = result.type === 'raw' ? '' : result.type + '-';
const mainType = classifyScript(result.meaningfulScript); const mainType = classifyScript(result.meaningfulScript);
@ -1642,6 +1643,44 @@ function pubkeyInOutput(
return pubkeyInScript(pubkey, meaningfulScript); 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( function getMeaningfulScript(
script: Buffer, script: Buffer,
index: number, index: number,