Skip to content

Commit d256992

Browse files
committed
Verify PSBT inputs rather than check for fields being empty
1 parent a52ff61 commit d256992

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

src/node/psbt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
5959
}
6060

6161
// Check if it is final
62-
if (!utxo.IsNull() && !PSBTInputSigned(input)) {
62+
if (!PSBTInputSignedAndVerified(psbtx, i, &txdata)) {
6363
input_analysis.is_final = false;
6464

6565
// Figure out what is missing

src/psbt.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <psbt.h>
66

7+
#include <policy/policy.h>
78
#include <util/check.h>
89
#include <util/strencodings.h>
910

@@ -273,11 +274,41 @@ void PSBTOutput::Merge(const PSBTOutput& output)
273274
if (m_tap_internal_key.IsNull() && !output.m_tap_internal_key.IsNull()) m_tap_internal_key = output.m_tap_internal_key;
274275
if (m_tap_tree.empty() && !output.m_tap_tree.empty()) m_tap_tree = output.m_tap_tree;
275276
}
277+
276278
bool PSBTInputSigned(const PSBTInput& input)
277279
{
278280
return !input.final_script_sig.empty() || !input.final_script_witness.IsNull();
279281
}
280282

283+
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData* txdata)
284+
{
285+
CTxOut utxo;
286+
assert(psbt.inputs.size() >= input_index);
287+
const PSBTInput& input = psbt.inputs[input_index];
288+
289+
if (input.non_witness_utxo) {
290+
// If we're taking our information from a non-witness UTXO, verify that it matches the prevout.
291+
COutPoint prevout = psbt.tx->vin[input_index].prevout;
292+
if (prevout.n >= input.non_witness_utxo->vout.size()) {
293+
return false;
294+
}
295+
if (input.non_witness_utxo->GetHash() != prevout.hash) {
296+
return false;
297+
}
298+
utxo = input.non_witness_utxo->vout[prevout.n];
299+
} else if (!input.witness_utxo.IsNull()) {
300+
utxo = input.witness_utxo;
301+
} else {
302+
return false;
303+
}
304+
305+
if (txdata) {
306+
return VerifyScript(input.final_script_sig, utxo.scriptPubKey, &input.final_script_witness, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker{&(*psbt.tx), input_index, utxo.nValue, *txdata, MissingDataBehavior::FAIL});
307+
} else {
308+
return VerifyScript(input.final_script_sig, utxo.scriptPubKey, &input.final_script_witness, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker{&(*psbt.tx), input_index, utxo.nValue, MissingDataBehavior::FAIL});
309+
}
310+
}
311+
281312
size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt) {
282313
size_t count = 0;
283314
for (const auto& input : psbt.inputs) {
@@ -331,7 +362,7 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
331362
PSBTInput& input = psbt.inputs.at(index);
332363
const CMutableTransaction& tx = *psbt.tx;
333364

334-
if (PSBTInputSigned(input)) {
365+
if (PSBTInputSignedAndVerified(psbt, index, txdata)) {
335366
return true;
336367
}
337368

src/psbt.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1218,9 +1218,12 @@ std::string PSBTRoleName(PSBTRole role);
12181218
/** Compute a PrecomputedTransactionData object from a psbt. */
12191219
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction& psbt);
12201220

1221-
/** Checks whether a PSBTInput is already signed. */
1221+
/** Checks whether a PSBTInput is already signed by checking for non-null finalized fields. */
12221222
bool PSBTInputSigned(const PSBTInput& input);
12231223

1224+
/** Checks whether a PSBTInput is already signed by doing script verification using final fields. */
1225+
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData* txdata);
1226+
12241227
/** Signs a PSBTInput, verifying that all provided data matches what is being signed.
12251228
*
12261229
* txdata should be the output of PrecomputePSBTData (which can be shared across

0 commit comments

Comments
 (0)