Skip to content

Commit 97074f8

Browse files
committed
Refactor getMeaningfulScript
1 parent e3bf997 commit 97074f8

File tree

3 files changed

+84
-93
lines changed

3 files changed

+84
-93
lines changed

src/psbt.js

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ function pubkeyInInput(pubkey, input, inputIndex, cache) {
12351235
} else {
12361236
throw new Error("Can't find pubkey in input without Utxo data");
12371237
}
1238-
const meaningfulScript = checkScripts(
1238+
const meaningfulScript = getMeaningfulScript(
12391239
script,
12401240
input.redeemScript,
12411241
input.witnessScript,
@@ -1244,55 +1244,49 @@ function pubkeyInInput(pubkey, input, inputIndex, cache) {
12441244
}
12451245
function pubkeyInOutput(pubkey, output, outputIndex, cache) {
12461246
const script = cache.__TX.outs[outputIndex].script;
1247-
const meaningfulScript = checkScripts(
1247+
const meaningfulScript = getMeaningfulScript(
12481248
script,
12491249
output.redeemScript,
12501250
output.witnessScript,
12511251
);
12521252
return pubkeyInScript(pubkey, meaningfulScript);
12531253
}
1254-
function checkScripts(script, redeemScript, witnessScript) {
1255-
let fail = false;
1256-
if (isP2SHScript(script)) {
1257-
if (redeemScript === undefined) {
1258-
fail = true;
1259-
} else if (isP2WSHScript(redeemScript)) {
1260-
if (witnessScript === undefined) {
1261-
fail = true;
1262-
} else {
1263-
fail = !payments
1264-
.p2sh({
1265-
redeem: payments.p2wsh({
1266-
redeem: { output: witnessScript },
1267-
}),
1268-
})
1269-
.output.equals(script);
1270-
if (!fail) return witnessScript;
1271-
}
1272-
} else {
1273-
fail = !payments
1274-
.p2sh({
1275-
redeem: { output: redeemScript },
1276-
})
1277-
.output.equals(script);
1278-
if (!fail) return redeemScript;
1279-
}
1280-
} else if (isP2WSHScript(script)) {
1281-
if (witnessScript === undefined) {
1282-
fail = true;
1283-
} else {
1284-
fail = !payments
1285-
.p2wsh({
1286-
redeem: { output: witnessScript },
1287-
})
1288-
.output.equals(script);
1289-
if (!fail) return witnessScript;
1290-
}
1291-
}
1292-
if (fail) {
1293-
throw new Error('Incomplete script information');
1254+
function getMeaningfulScript(script, redeemScript, witnessScript) {
1255+
const { p2sh, p2wsh } = payments;
1256+
const isP2SH = isP2SHScript(script);
1257+
const isP2SHP2WSH = isP2SH && redeemScript && isP2WSHScript(redeemScript);
1258+
const isP2WSH = isP2WSHScript(script);
1259+
if (isP2SH && redeemScript === undefined)
1260+
throw new Error('scriptPubkey is P2SH but redeemScript missing');
1261+
if ((isP2WSH || isP2SHP2WSH) && witnessScript === undefined)
1262+
throw new Error(
1263+
'scriptPubkey or redeemScript is P2WSH but witnessScript missing',
1264+
);
1265+
let payment;
1266+
let meaningfulScript;
1267+
if (isP2SHP2WSH) {
1268+
meaningfulScript = witnessScript;
1269+
payment = p2sh({ redeem: p2wsh({ redeem: { output: meaningfulScript } }) });
1270+
if (!payment.redeem.output.equals(redeemScript))
1271+
throw new Error('P2SHP2WSH witnessScript and redeemScript do not match');
1272+
if (!payment.output.equals(script))
1273+
throw new Error(
1274+
'P2SHP2WSH witnessScript+redeemScript and scriptPubkey do not match',
1275+
);
1276+
} else if (isP2WSH) {
1277+
meaningfulScript = witnessScript;
1278+
payment = p2wsh({ redeem: { output: meaningfulScript } });
1279+
if (!payment.output.equals(script))
1280+
throw new Error('P2WSH witnessScript and scriptPubkey do not match');
1281+
} else if (isP2SH) {
1282+
meaningfulScript = redeemScript;
1283+
payment = p2sh({ redeem: { output: meaningfulScript } });
1284+
if (!payment.output.equals(script))
1285+
throw new Error('P2SH redeemScript and scriptPubkey do not match');
1286+
} else {
1287+
meaningfulScript = script;
12941288
}
1295-
return script;
1289+
return meaningfulScript;
12961290
}
12971291
function pubkeyInScript(pubkey, script) {
12981292
const pubkeyHash = crypto_1.hash160(pubkey);

test/psbt.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ describe(`Psbt`, () => {
566566

567567
assert.throws(() => {
568568
psbt.inputHasPubkey(0, Buffer.from([]));
569-
}, new RegExp('Incomplete script information'));
569+
}, new RegExp('scriptPubkey is P2SH but redeemScript missing'));
570570

571571
delete psbt.data.inputs[0].witnessUtxo;
572572

@@ -581,7 +581,7 @@ describe(`Psbt`, () => {
581581

582582
assert.throws(() => {
583583
psbt.inputHasPubkey(0, Buffer.from([]));
584-
}, new RegExp('Incomplete script information'));
584+
}, new RegExp('scriptPubkey or redeemScript is P2WSH but witnessScript missing'));
585585

586586
delete psbt.data.inputs[0].witnessUtxo;
587587

@@ -601,7 +601,7 @@ describe(`Psbt`, () => {
601601

602602
assert.throws(() => {
603603
psbt.inputHasPubkey(0, Buffer.from([]));
604-
}, new RegExp('Incomplete script information'));
604+
}, new RegExp('scriptPubkey or redeemScript is P2WSH but witnessScript missing'));
605605

606606
psbt.updateInput(0, {
607607
witnessScript: Buffer.from([0x51]),
@@ -631,15 +631,15 @@ describe(`Psbt`, () => {
631631

632632
assert.throws(() => {
633633
psbt.outputHasPubkey(0, Buffer.from([]));
634-
}, new RegExp('Incomplete script information'));
634+
}, new RegExp('scriptPubkey is P2SH but redeemScript missing'));
635635

636636
(psbt as any).__CACHE.__TX.outs[0].script = payments.p2wsh({
637637
redeem: { output: Buffer.from([0x51]) },
638638
}).output!;
639639

640640
assert.throws(() => {
641641
psbt.outputHasPubkey(0, Buffer.from([]));
642-
}, new RegExp('Incomplete script information'));
642+
}, new RegExp('scriptPubkey or redeemScript is P2WSH but witnessScript missing'));
643643

644644
(psbt as any).__CACHE.__TX.outs[0].script = payments.p2sh({
645645
redeem: payments.p2wsh({
@@ -655,7 +655,7 @@ describe(`Psbt`, () => {
655655

656656
assert.throws(() => {
657657
psbt.outputHasPubkey(0, Buffer.from([]));
658-
}, new RegExp('Incomplete script information'));
658+
}, new RegExp('scriptPubkey or redeemScript is P2WSH but witnessScript missing'));
659659

660660
delete psbt.data.outputs[0].redeemScript;
661661

@@ -665,7 +665,7 @@ describe(`Psbt`, () => {
665665

666666
assert.throws(() => {
667667
psbt.outputHasPubkey(0, Buffer.from([]));
668-
}, new RegExp('Incomplete script information'));
668+
}, new RegExp('scriptPubkey is P2SH but redeemScript missing'));
669669

670670
psbt.updateOutput(0, {
671671
redeemScript: payments.p2wsh({

ts_src/psbt.ts

Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,7 +1587,7 @@ function pubkeyInInput(
15871587
} else {
15881588
throw new Error("Can't find pubkey in input without Utxo data");
15891589
}
1590-
const meaningfulScript = checkScripts(
1590+
const meaningfulScript = getMeaningfulScript(
15911591
script,
15921592
input.redeemScript,
15931593
input.witnessScript,
@@ -1602,60 +1602,57 @@ function pubkeyInOutput(
16021602
cache: PsbtCache,
16031603
): boolean {
16041604
const script = cache.__TX.outs[outputIndex].script;
1605-
const meaningfulScript = checkScripts(
1605+
const meaningfulScript = getMeaningfulScript(
16061606
script,
16071607
output.redeemScript,
16081608
output.witnessScript,
16091609
);
16101610
return pubkeyInScript(pubkey, meaningfulScript);
16111611
}
16121612

1613-
function checkScripts(
1613+
function getMeaningfulScript(
16141614
script: Buffer,
16151615
redeemScript?: Buffer,
16161616
witnessScript?: Buffer,
16171617
): Buffer {
1618-
let fail = false;
1619-
if (isP2SHScript(script)) {
1620-
if (redeemScript === undefined) {
1621-
fail = true;
1622-
} else if (isP2WSHScript(redeemScript)) {
1623-
if (witnessScript === undefined) {
1624-
fail = true;
1625-
} else {
1626-
fail = !payments
1627-
.p2sh({
1628-
redeem: payments.p2wsh({
1629-
redeem: { output: witnessScript },
1630-
}),
1631-
})
1632-
.output!.equals(script);
1633-
if (!fail) return witnessScript;
1634-
}
1635-
} else {
1636-
fail = !payments
1637-
.p2sh({
1638-
redeem: { output: redeemScript },
1639-
})
1640-
.output!.equals(script);
1641-
if (!fail) return redeemScript;
1642-
}
1643-
} else if (isP2WSHScript(script)) {
1644-
if (witnessScript === undefined) {
1645-
fail = true;
1646-
} else {
1647-
fail = !payments
1648-
.p2wsh({
1649-
redeem: { output: witnessScript },
1650-
})
1651-
.output!.equals(script);
1652-
if (!fail) return witnessScript;
1653-
}
1654-
}
1655-
if (fail) {
1656-
throw new Error('Incomplete script information');
1618+
const { p2sh, p2wsh } = payments;
1619+
const isP2SH = isP2SHScript(script);
1620+
const isP2SHP2WSH = isP2SH && redeemScript && isP2WSHScript(redeemScript);
1621+
const isP2WSH = isP2WSHScript(script);
1622+
1623+
if (isP2SH && redeemScript === undefined)
1624+
throw new Error('scriptPubkey is P2SH but redeemScript missing');
1625+
if ((isP2WSH || isP2SHP2WSH) && witnessScript === undefined)
1626+
throw new Error(
1627+
'scriptPubkey or redeemScript is P2WSH but witnessScript missing',
1628+
);
1629+
1630+
let payment: payments.Payment;
1631+
let meaningfulScript: Buffer;
1632+
1633+
if (isP2SHP2WSH) {
1634+
meaningfulScript = witnessScript!;
1635+
payment = p2sh({ redeem: p2wsh({ redeem: { output: meaningfulScript } }) });
1636+
if (!payment.redeem!.output!.equals(redeemScript!))
1637+
throw new Error('P2SHP2WSH witnessScript and redeemScript do not match');
1638+
if (!payment.output!.equals(script!))
1639+
throw new Error(
1640+
'P2SHP2WSH witnessScript+redeemScript and scriptPubkey do not match',
1641+
);
1642+
} else if (isP2WSH) {
1643+
meaningfulScript = witnessScript!;
1644+
payment = p2wsh({ redeem: { output: meaningfulScript } });
1645+
if (!payment.output!.equals(script!))
1646+
throw new Error('P2WSH witnessScript and scriptPubkey do not match');
1647+
} else if (isP2SH) {
1648+
meaningfulScript = redeemScript!;
1649+
payment = p2sh({ redeem: { output: meaningfulScript } });
1650+
if (!payment.output!.equals(script!))
1651+
throw new Error('P2SH redeemScript and scriptPubkey do not match');
1652+
} else {
1653+
meaningfulScript = script;
16571654
}
1658-
return script;
1655+
return meaningfulScript;
16591656
}
16601657

16611658
function pubkeyInScript(pubkey: Buffer, script: Buffer): boolean {

0 commit comments

Comments
 (0)