Refactor getMeaningfulScript
This commit is contained in:
parent
e3bf997d64
commit
97074f8a64
3 changed files with 84 additions and 93 deletions
78
src/psbt.js
78
src/psbt.js
|
@ -1235,7 +1235,7 @@ function pubkeyInInput(pubkey, input, inputIndex, cache) {
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Can't find pubkey in input without Utxo data");
|
throw new Error("Can't find pubkey in input without Utxo data");
|
||||||
}
|
}
|
||||||
const meaningfulScript = checkScripts(
|
const meaningfulScript = getMeaningfulScript(
|
||||||
script,
|
script,
|
||||||
input.redeemScript,
|
input.redeemScript,
|
||||||
input.witnessScript,
|
input.witnessScript,
|
||||||
|
@ -1244,55 +1244,49 @@ function pubkeyInInput(pubkey, input, inputIndex, cache) {
|
||||||
}
|
}
|
||||||
function pubkeyInOutput(pubkey, output, outputIndex, cache) {
|
function pubkeyInOutput(pubkey, output, outputIndex, cache) {
|
||||||
const script = cache.__TX.outs[outputIndex].script;
|
const script = cache.__TX.outs[outputIndex].script;
|
||||||
const meaningfulScript = checkScripts(
|
const meaningfulScript = getMeaningfulScript(
|
||||||
script,
|
script,
|
||||||
output.redeemScript,
|
output.redeemScript,
|
||||||
output.witnessScript,
|
output.witnessScript,
|
||||||
);
|
);
|
||||||
return pubkeyInScript(pubkey, meaningfulScript);
|
return pubkeyInScript(pubkey, meaningfulScript);
|
||||||
}
|
}
|
||||||
function checkScripts(script, redeemScript, witnessScript) {
|
function getMeaningfulScript(script, redeemScript, witnessScript) {
|
||||||
let fail = false;
|
const { p2sh, p2wsh } = payments;
|
||||||
if (isP2SHScript(script)) {
|
const isP2SH = isP2SHScript(script);
|
||||||
if (redeemScript === undefined) {
|
const isP2SHP2WSH = isP2SH && redeemScript && isP2WSHScript(redeemScript);
|
||||||
fail = true;
|
const isP2WSH = isP2WSHScript(script);
|
||||||
} else if (isP2WSHScript(redeemScript)) {
|
if (isP2SH && redeemScript === undefined)
|
||||||
if (witnessScript === undefined) {
|
throw new Error('scriptPubkey is P2SH but redeemScript missing');
|
||||||
fail = true;
|
if ((isP2WSH || isP2SHP2WSH) && witnessScript === undefined)
|
||||||
|
throw new Error(
|
||||||
|
'scriptPubkey or redeemScript is P2WSH but witnessScript missing',
|
||||||
|
);
|
||||||
|
let payment;
|
||||||
|
let meaningfulScript;
|
||||||
|
if (isP2SHP2WSH) {
|
||||||
|
meaningfulScript = witnessScript;
|
||||||
|
payment = p2sh({ redeem: p2wsh({ redeem: { output: meaningfulScript } }) });
|
||||||
|
if (!payment.redeem.output.equals(redeemScript))
|
||||||
|
throw new Error('P2SHP2WSH witnessScript and redeemScript do not match');
|
||||||
|
if (!payment.output.equals(script))
|
||||||
|
throw new Error(
|
||||||
|
'P2SHP2WSH witnessScript+redeemScript and scriptPubkey do not match',
|
||||||
|
);
|
||||||
|
} else if (isP2WSH) {
|
||||||
|
meaningfulScript = witnessScript;
|
||||||
|
payment = p2wsh({ redeem: { output: meaningfulScript } });
|
||||||
|
if (!payment.output.equals(script))
|
||||||
|
throw new Error('P2WSH witnessScript and scriptPubkey do not match');
|
||||||
|
} else if (isP2SH) {
|
||||||
|
meaningfulScript = redeemScript;
|
||||||
|
payment = p2sh({ redeem: { output: meaningfulScript } });
|
||||||
|
if (!payment.output.equals(script))
|
||||||
|
throw new Error('P2SH redeemScript and scriptPubkey do not match');
|
||||||
} else {
|
} else {
|
||||||
fail = !payments
|
meaningfulScript = script;
|
||||||
.p2sh({
|
|
||||||
redeem: payments.p2wsh({
|
|
||||||
redeem: { output: witnessScript },
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.output.equals(script);
|
|
||||||
if (!fail) return witnessScript;
|
|
||||||
}
|
}
|
||||||
} else {
|
return meaningfulScript;
|
||||||
fail = !payments
|
|
||||||
.p2sh({
|
|
||||||
redeem: { output: redeemScript },
|
|
||||||
})
|
|
||||||
.output.equals(script);
|
|
||||||
if (!fail) return redeemScript;
|
|
||||||
}
|
|
||||||
} else if (isP2WSHScript(script)) {
|
|
||||||
if (witnessScript === undefined) {
|
|
||||||
fail = true;
|
|
||||||
} else {
|
|
||||||
fail = !payments
|
|
||||||
.p2wsh({
|
|
||||||
redeem: { output: witnessScript },
|
|
||||||
})
|
|
||||||
.output.equals(script);
|
|
||||||
if (!fail) return witnessScript;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fail) {
|
|
||||||
throw new Error('Incomplete script information');
|
|
||||||
}
|
|
||||||
return script;
|
|
||||||
}
|
}
|
||||||
function pubkeyInScript(pubkey, script) {
|
function pubkeyInScript(pubkey, script) {
|
||||||
const pubkeyHash = crypto_1.hash160(pubkey);
|
const pubkeyHash = crypto_1.hash160(pubkey);
|
||||||
|
|
|
@ -566,7 +566,7 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.inputHasPubkey(0, Buffer.from([]));
|
psbt.inputHasPubkey(0, Buffer.from([]));
|
||||||
}, new RegExp('Incomplete script information'));
|
}, new RegExp('scriptPubkey is P2SH but redeemScript missing'));
|
||||||
|
|
||||||
delete psbt.data.inputs[0].witnessUtxo;
|
delete psbt.data.inputs[0].witnessUtxo;
|
||||||
|
|
||||||
|
@ -581,7 +581,7 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.inputHasPubkey(0, Buffer.from([]));
|
psbt.inputHasPubkey(0, Buffer.from([]));
|
||||||
}, new RegExp('Incomplete script information'));
|
}, new RegExp('scriptPubkey or redeemScript is P2WSH but witnessScript missing'));
|
||||||
|
|
||||||
delete psbt.data.inputs[0].witnessUtxo;
|
delete psbt.data.inputs[0].witnessUtxo;
|
||||||
|
|
||||||
|
@ -601,7 +601,7 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.inputHasPubkey(0, Buffer.from([]));
|
psbt.inputHasPubkey(0, Buffer.from([]));
|
||||||
}, new RegExp('Incomplete script information'));
|
}, new RegExp('scriptPubkey or redeemScript is P2WSH but witnessScript missing'));
|
||||||
|
|
||||||
psbt.updateInput(0, {
|
psbt.updateInput(0, {
|
||||||
witnessScript: Buffer.from([0x51]),
|
witnessScript: Buffer.from([0x51]),
|
||||||
|
@ -631,7 +631,7 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.outputHasPubkey(0, Buffer.from([]));
|
psbt.outputHasPubkey(0, Buffer.from([]));
|
||||||
}, new RegExp('Incomplete script information'));
|
}, new RegExp('scriptPubkey is P2SH but redeemScript missing'));
|
||||||
|
|
||||||
(psbt as any).__CACHE.__TX.outs[0].script = payments.p2wsh({
|
(psbt as any).__CACHE.__TX.outs[0].script = payments.p2wsh({
|
||||||
redeem: { output: Buffer.from([0x51]) },
|
redeem: { output: Buffer.from([0x51]) },
|
||||||
|
@ -639,7 +639,7 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.outputHasPubkey(0, Buffer.from([]));
|
psbt.outputHasPubkey(0, Buffer.from([]));
|
||||||
}, new RegExp('Incomplete script information'));
|
}, new RegExp('scriptPubkey or redeemScript is P2WSH but witnessScript missing'));
|
||||||
|
|
||||||
(psbt as any).__CACHE.__TX.outs[0].script = payments.p2sh({
|
(psbt as any).__CACHE.__TX.outs[0].script = payments.p2sh({
|
||||||
redeem: payments.p2wsh({
|
redeem: payments.p2wsh({
|
||||||
|
@ -655,7 +655,7 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.outputHasPubkey(0, Buffer.from([]));
|
psbt.outputHasPubkey(0, Buffer.from([]));
|
||||||
}, new RegExp('Incomplete script information'));
|
}, new RegExp('scriptPubkey or redeemScript is P2WSH but witnessScript missing'));
|
||||||
|
|
||||||
delete psbt.data.outputs[0].redeemScript;
|
delete psbt.data.outputs[0].redeemScript;
|
||||||
|
|
||||||
|
@ -665,7 +665,7 @@ describe(`Psbt`, () => {
|
||||||
|
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
psbt.outputHasPubkey(0, Buffer.from([]));
|
psbt.outputHasPubkey(0, Buffer.from([]));
|
||||||
}, new RegExp('Incomplete script information'));
|
}, new RegExp('scriptPubkey is P2SH but redeemScript missing'));
|
||||||
|
|
||||||
psbt.updateOutput(0, {
|
psbt.updateOutput(0, {
|
||||||
redeemScript: payments.p2wsh({
|
redeemScript: payments.p2wsh({
|
||||||
|
|
|
@ -1587,7 +1587,7 @@ function pubkeyInInput(
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Can't find pubkey in input without Utxo data");
|
throw new Error("Can't find pubkey in input without Utxo data");
|
||||||
}
|
}
|
||||||
const meaningfulScript = checkScripts(
|
const meaningfulScript = getMeaningfulScript(
|
||||||
script,
|
script,
|
||||||
input.redeemScript,
|
input.redeemScript,
|
||||||
input.witnessScript,
|
input.witnessScript,
|
||||||
|
@ -1602,7 +1602,7 @@ function pubkeyInOutput(
|
||||||
cache: PsbtCache,
|
cache: PsbtCache,
|
||||||
): boolean {
|
): boolean {
|
||||||
const script = cache.__TX.outs[outputIndex].script;
|
const script = cache.__TX.outs[outputIndex].script;
|
||||||
const meaningfulScript = checkScripts(
|
const meaningfulScript = getMeaningfulScript(
|
||||||
script,
|
script,
|
||||||
output.redeemScript,
|
output.redeemScript,
|
||||||
output.witnessScript,
|
output.witnessScript,
|
||||||
|
@ -1610,52 +1610,49 @@ function pubkeyInOutput(
|
||||||
return pubkeyInScript(pubkey, meaningfulScript);
|
return pubkeyInScript(pubkey, meaningfulScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkScripts(
|
function getMeaningfulScript(
|
||||||
script: Buffer,
|
script: Buffer,
|
||||||
redeemScript?: Buffer,
|
redeemScript?: Buffer,
|
||||||
witnessScript?: Buffer,
|
witnessScript?: Buffer,
|
||||||
): Buffer {
|
): Buffer {
|
||||||
let fail = false;
|
const { p2sh, p2wsh } = payments;
|
||||||
if (isP2SHScript(script)) {
|
const isP2SH = isP2SHScript(script);
|
||||||
if (redeemScript === undefined) {
|
const isP2SHP2WSH = isP2SH && redeemScript && isP2WSHScript(redeemScript);
|
||||||
fail = true;
|
const isP2WSH = isP2WSHScript(script);
|
||||||
} else if (isP2WSHScript(redeemScript)) {
|
|
||||||
if (witnessScript === undefined) {
|
if (isP2SH && redeemScript === undefined)
|
||||||
fail = true;
|
throw new Error('scriptPubkey is P2SH but redeemScript missing');
|
||||||
|
if ((isP2WSH || isP2SHP2WSH) && witnessScript === undefined)
|
||||||
|
throw new Error(
|
||||||
|
'scriptPubkey or redeemScript is P2WSH but witnessScript missing',
|
||||||
|
);
|
||||||
|
|
||||||
|
let payment: payments.Payment;
|
||||||
|
let meaningfulScript: Buffer;
|
||||||
|
|
||||||
|
if (isP2SHP2WSH) {
|
||||||
|
meaningfulScript = witnessScript!;
|
||||||
|
payment = p2sh({ redeem: p2wsh({ redeem: { output: meaningfulScript } }) });
|
||||||
|
if (!payment.redeem!.output!.equals(redeemScript!))
|
||||||
|
throw new Error('P2SHP2WSH witnessScript and redeemScript do not match');
|
||||||
|
if (!payment.output!.equals(script!))
|
||||||
|
throw new Error(
|
||||||
|
'P2SHP2WSH witnessScript+redeemScript and scriptPubkey do not match',
|
||||||
|
);
|
||||||
|
} else if (isP2WSH) {
|
||||||
|
meaningfulScript = witnessScript!;
|
||||||
|
payment = p2wsh({ redeem: { output: meaningfulScript } });
|
||||||
|
if (!payment.output!.equals(script!))
|
||||||
|
throw new Error('P2WSH witnessScript and scriptPubkey do not match');
|
||||||
|
} else if (isP2SH) {
|
||||||
|
meaningfulScript = redeemScript!;
|
||||||
|
payment = p2sh({ redeem: { output: meaningfulScript } });
|
||||||
|
if (!payment.output!.equals(script!))
|
||||||
|
throw new Error('P2SH redeemScript and scriptPubkey do not match');
|
||||||
} else {
|
} else {
|
||||||
fail = !payments
|
meaningfulScript = script;
|
||||||
.p2sh({
|
|
||||||
redeem: payments.p2wsh({
|
|
||||||
redeem: { output: witnessScript },
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.output!.equals(script);
|
|
||||||
if (!fail) return witnessScript;
|
|
||||||
}
|
}
|
||||||
} else {
|
return meaningfulScript;
|
||||||
fail = !payments
|
|
||||||
.p2sh({
|
|
||||||
redeem: { output: redeemScript },
|
|
||||||
})
|
|
||||||
.output!.equals(script);
|
|
||||||
if (!fail) return redeemScript;
|
|
||||||
}
|
|
||||||
} else if (isP2WSHScript(script)) {
|
|
||||||
if (witnessScript === undefined) {
|
|
||||||
fail = true;
|
|
||||||
} else {
|
|
||||||
fail = !payments
|
|
||||||
.p2wsh({
|
|
||||||
redeem: { output: witnessScript },
|
|
||||||
})
|
|
||||||
.output!.equals(script);
|
|
||||||
if (!fail) return witnessScript;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fail) {
|
|
||||||
throw new Error('Incomplete script information');
|
|
||||||
}
|
|
||||||
return script;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function pubkeyInScript(pubkey: Buffer, script: Buffer): boolean {
|
function pubkeyInScript(pubkey: Buffer, script: Buffer): boolean {
|
||||||
|
|
Loading…
Add table
Reference in a new issue