mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-19 21:31:33 +02:00
Verify PSBT inputs rather than check for fields being empty
This commit is contained in:
parent
a52ff619a4
commit
d25699280a
@ -59,7 +59,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
|
||||
}
|
||||
|
||||
// Check if it is final
|
||||
if (!utxo.IsNull() && !PSBTInputSigned(input)) {
|
||||
if (!PSBTInputSignedAndVerified(psbtx, i, &txdata)) {
|
||||
input_analysis.is_final = false;
|
||||
|
||||
// Figure out what is missing
|
||||
|
33
src/psbt.cpp
33
src/psbt.cpp
@ -4,6 +4,7 @@
|
||||
|
||||
#include <psbt.h>
|
||||
|
||||
#include <policy/policy.h>
|
||||
#include <util/check.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
@ -273,11 +274,41 @@ void PSBTOutput::Merge(const PSBTOutput& output)
|
||||
if (m_tap_internal_key.IsNull() && !output.m_tap_internal_key.IsNull()) m_tap_internal_key = output.m_tap_internal_key;
|
||||
if (m_tap_tree.empty() && !output.m_tap_tree.empty()) m_tap_tree = output.m_tap_tree;
|
||||
}
|
||||
|
||||
bool PSBTInputSigned(const PSBTInput& input)
|
||||
{
|
||||
return !input.final_script_sig.empty() || !input.final_script_witness.IsNull();
|
||||
}
|
||||
|
||||
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData* txdata)
|
||||
{
|
||||
CTxOut utxo;
|
||||
assert(psbt.inputs.size() >= input_index);
|
||||
const PSBTInput& input = psbt.inputs[input_index];
|
||||
|
||||
if (input.non_witness_utxo) {
|
||||
// If we're taking our information from a non-witness UTXO, verify that it matches the prevout.
|
||||
COutPoint prevout = psbt.tx->vin[input_index].prevout;
|
||||
if (prevout.n >= input.non_witness_utxo->vout.size()) {
|
||||
return false;
|
||||
}
|
||||
if (input.non_witness_utxo->GetHash() != prevout.hash) {
|
||||
return false;
|
||||
}
|
||||
utxo = input.non_witness_utxo->vout[prevout.n];
|
||||
} else if (!input.witness_utxo.IsNull()) {
|
||||
utxo = input.witness_utxo;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (txdata) {
|
||||
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});
|
||||
} else {
|
||||
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});
|
||||
}
|
||||
}
|
||||
|
||||
size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt) {
|
||||
size_t count = 0;
|
||||
for (const auto& input : psbt.inputs) {
|
||||
@ -331,7 +362,7 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
|
||||
PSBTInput& input = psbt.inputs.at(index);
|
||||
const CMutableTransaction& tx = *psbt.tx;
|
||||
|
||||
if (PSBTInputSigned(input)) {
|
||||
if (PSBTInputSignedAndVerified(psbt, index, txdata)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1218,9 +1218,12 @@ std::string PSBTRoleName(PSBTRole role);
|
||||
/** Compute a PrecomputedTransactionData object from a psbt. */
|
||||
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction& psbt);
|
||||
|
||||
/** Checks whether a PSBTInput is already signed. */
|
||||
/** Checks whether a PSBTInput is already signed by checking for non-null finalized fields. */
|
||||
bool PSBTInputSigned(const PSBTInput& input);
|
||||
|
||||
/** Checks whether a PSBTInput is already signed by doing script verification using final fields. */
|
||||
bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned int input_index, const PrecomputedTransactionData* txdata);
|
||||
|
||||
/** Signs a PSBTInput, verifying that all provided data matches what is being signed.
|
||||
*
|
||||
* txdata should be the output of PrecomputePSBTData (which can be shared across
|
||||
|
Loading…
x
Reference in New Issue
Block a user