Skip to content

Commit ec81204

Browse files
committed
Merge bitcoin/bitcoin#31622: psbt: add non-default sighash types to PSBTs and unify sighash type match checking
ee045b6 rpc, psbt: Require sighashes match for descriptorprocesspsbt (Ava Chow) 2b7682c psbt: use sighash type field to determine whether to remove non-witness utxos (Ava Chow) 28781b5 psbt: Add sighash types to PSBT when not DEFAULT or ALL (Ava Chow) 15ce1bd psbt: Enforce sighash type of signatures matches psbt (Ava Chow) 1f71cd3 wallet: Remove sighash type enforcement from FillPSBT (Ava Chow) 4c7d767 psbt: Check sighash types in SignPSBTInput and take sighash as optional (Ava Chow) a118256 script: Add IsPayToTaproot() (Ava Chow) d6001dc wallet: change FillPSBT to take sighash as optional (Ava Chow) e58b680 psbt: Return PSBTError from SignPSBTInput (Ava Chow) 2adfd81 tests: Test PSBT sighash type mismatch (Ava Chow) 5a5d26d psbt: Require ECDSA signatures to be validly encoded (Ava Chow) Pull request description: Currently, we do not add the sighash field to PSBTs at all, even when we have signed with a non-default sighash. This PR changes the behavior such that when we (attempt to) sign with a sighash other than DEFAULT or ALL, the sighash type field will be added to the PSBT to inform the later signers that a different sighash type was used by a signer. Notably, this is necessary for MuSig2 support as all signers must sign using the same sighash type, but the sighash is not provided in partial signatures. Furthermore, because the sighash type can also be provided on the command line, we require that if both a command line sighash type and the sighash field is present, they must specify the same sighash type. However, this was being checked by the wallet, rather than the signing code, so the `descriptorprocesspsbt` RPC was not enforcing this restriction at all, and in fact ignored the sighash field entirely. This PR refactors the checking code so that the underlying PSBT signing function `SignPSBTInput` does the check. ACKs for top commit: theStack: re-ACK ee045b6 rkrux: re-ACK ee045b6 fjahr: Code review ACK ee045b6 Tree-SHA512: 4ead5be1ef6756251b827f594beba868a145d75bf7f4ef6f15ad21f0ae4b8d71b38c83494e5a6b75f37fadd097178cddd93d614b962a2c72fc134f00ba2f74ae
2 parents 9a887ba + ee045b6 commit ec81204

27 files changed

+253
-84
lines changed

src/common/messages.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ bilingual_str PSBTErrorString(PSBTError err)
116116
return Untranslated("External signer failed to sign");
117117
case PSBTError::UNSUPPORTED:
118118
return Untranslated("Signer does not support PSBT");
119+
case PSBTError::INCOMPLETE:
120+
return Untranslated("Input needs additional signatures or other data");
121+
case PSBTError::OK:
122+
return Untranslated("No errors");
119123
// no default case, so the compiler can warn about missing cases
120124
}
121125
assert(false);

src/common/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ enum class PSBTError {
2020
EXTERNAL_SIGNER_NOT_FOUND,
2121
EXTERNAL_SIGNER_FAILED,
2222
UNSUPPORTED,
23+
INCOMPLETE,
24+
OK,
2325
};
2426
} // namespace common
2527

src/interfaces/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ class Wallet
205205
int& num_blocks) = 0;
206206

207207
//! Fill PSBT.
208-
virtual std::optional<common::PSBTError> fillPSBT(int sighash_type,
208+
virtual std::optional<common::PSBTError> fillPSBT(std::optional<int> sighash_type,
209209
bool sign,
210210
bool bip32derivs,
211211
size_t* n_signed,

src/node/psbt.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
6464

6565
// Figure out what is missing
6666
SignatureData outdata;
67-
bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, 1, &outdata);
67+
bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, std::nullopt, &outdata) == PSBTError::OK;
6868

6969
// Things are missing
7070
if (!complete) {
@@ -124,7 +124,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
124124
PSBTInput& input = psbtx.inputs[i];
125125
Coin newcoin;
126126

127-
if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, nullptr, 1) || !psbtx.GetInputUTXO(newcoin.out, i)) {
127+
if (SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, nullptr, std::nullopt) != PSBTError::OK || !psbtx.GetInputUTXO(newcoin.out, i)) {
128128
success = false;
129129
break;
130130
} else {

src/psbt.cpp

Lines changed: 82 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
#include <psbt.h>
66

7+
#include <common/types.h>
78
#include <node/types.h>
89
#include <policy/policy.h>
910
#include <script/signingprovider.h>
1011
#include <util/check.h>
1112
#include <util/strencodings.h>
1213

14+
using common::PSBTError;
15+
1316
PartiallySignedTransaction::PartiallySignedTransaction(const CMutableTransaction& tx) : tx(tx)
1417
{
1518
inputs.resize(tx.vin.size());
@@ -372,13 +375,13 @@ PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction&
372375
return txdata;
373376
}
374377

375-
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash, SignatureData* out_sigdata, bool finalize)
378+
PSBTError SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, std::optional<int> sighash, SignatureData* out_sigdata, bool finalize)
376379
{
377380
PSBTInput& input = psbt.inputs.at(index);
378381
const CMutableTransaction& tx = *psbt.tx;
379382

380383
if (PSBTInputSignedAndVerified(psbt, index, txdata)) {
381-
return true;
384+
return PSBTError::OK;
382385
}
383386

384387
// Fill SignatureData with input info
@@ -393,10 +396,10 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
393396
// If we're taking our information from a non-witness UTXO, verify that it matches the prevout.
394397
COutPoint prevout = tx.vin[index].prevout;
395398
if (prevout.n >= input.non_witness_utxo->vout.size()) {
396-
return false;
399+
return PSBTError::MISSING_INPUTS;
397400
}
398401
if (input.non_witness_utxo->GetHash() != prevout.hash) {
399-
return false;
402+
return PSBTError::MISSING_INPUTS;
400403
}
401404
utxo = input.non_witness_utxo->vout[prevout.n];
402405
} else if (!input.witness_utxo.IsNull()) {
@@ -407,19 +410,58 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
407410
// a witness signature in this situation.
408411
require_witness_sig = true;
409412
} else {
410-
return false;
413+
return PSBTError::MISSING_INPUTS;
414+
}
415+
416+
// Get the sighash type
417+
// If both the field and the parameter are provided, they must match
418+
// If only the parameter is provided, use it and add it to the PSBT if it is other than SIGHASH_DEFAULT
419+
// for all input types, and not SIGHASH_ALL for non-taproot input types.
420+
// If neither are provided, use SIGHASH_DEFAULT if it is taproot, and SIGHASH_ALL for everything else.
421+
if (!sighash) sighash = utxo.scriptPubKey.IsPayToTaproot() ? SIGHASH_DEFAULT : SIGHASH_ALL;
422+
Assert(sighash.has_value());
423+
// For user safety, the desired sighash must be provided if the PSBT wants something other than the default set in the previous line.
424+
if (input.sighash_type && input.sighash_type != sighash) {
425+
return PSBTError::SIGHASH_MISMATCH;
426+
}
427+
// Set the PSBT sighash field when sighash is not DEFAULT or ALL
428+
// DEFAULT is allowed for non-taproot inputs since DEFAULT may be passed for them (e.g. the psbt being signed also has taproot inputs)
429+
// Note that signing already aliases DEFAULT to ALL for non-taproot inputs.
430+
if (utxo.scriptPubKey.IsPayToTaproot() ? sighash != SIGHASH_DEFAULT :
431+
(sighash != SIGHASH_DEFAULT && sighash != SIGHASH_ALL)) {
432+
input.sighash_type = sighash;
433+
}
434+
435+
// Check all existing signatures use the sighash type
436+
if (sighash == SIGHASH_DEFAULT) {
437+
if (!input.m_tap_key_sig.empty() && input.m_tap_key_sig.size() != 64) {
438+
return PSBTError::SIGHASH_MISMATCH;
439+
}
440+
for (const auto& [_, sig] : input.m_tap_script_sigs) {
441+
if (sig.size() != 64) return PSBTError::SIGHASH_MISMATCH;
442+
}
443+
} else {
444+
if (!input.m_tap_key_sig.empty() && (input.m_tap_key_sig.size() != 65 || input.m_tap_key_sig.back() != *sighash)) {
445+
return PSBTError::SIGHASH_MISMATCH;
446+
}
447+
for (const auto& [_, sig] : input.m_tap_script_sigs) {
448+
if (sig.size() != 65 || sig.back() != *sighash) return PSBTError::SIGHASH_MISMATCH;
449+
}
450+
for (const auto& [_, sig] : input.partial_sigs) {
451+
if (sig.second.back() != *sighash) return PSBTError::SIGHASH_MISMATCH;
452+
}
411453
}
412454

413455
sigdata.witness = false;
414456
bool sig_complete;
415457
if (txdata == nullptr) {
416458
sig_complete = ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, utxo.scriptPubKey, sigdata);
417459
} else {
418-
MutableTransactionSignatureCreator creator(tx, index, utxo.nValue, txdata, sighash);
460+
MutableTransactionSignatureCreator creator(tx, index, utxo.nValue, txdata, *sighash);
419461
sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
420462
}
421463
// Verify that a witness signature was produced in case one was required.
422-
if (require_witness_sig && !sigdata.witness) return false;
464+
if (require_witness_sig && !sigdata.witness) return PSBTError::INCOMPLETE;
423465

424466
// If we are not finalizing, set sigdata.complete to false to not set the scriptWitness
425467
if (!finalize && sigdata.complete) sigdata.complete = false;
@@ -442,39 +484,44 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
442484
out_sigdata->missing_witness_script = sigdata.missing_witness_script;
443485
}
444486

445-
return sig_complete;
487+
return sig_complete ? PSBTError::OK : PSBTError::INCOMPLETE;
446488
}
447489

448-
void RemoveUnnecessaryTransactions(PartiallySignedTransaction& psbtx, const int& sighash_type)
490+
void RemoveUnnecessaryTransactions(PartiallySignedTransaction& psbtx)
449491
{
450-
// Only drop non_witness_utxos if sighash_type != SIGHASH_ANYONECANPAY
451-
if ((sighash_type & 0x80) != SIGHASH_ANYONECANPAY) {
452-
// Figure out if any non_witness_utxos should be dropped
453-
std::vector<unsigned int> to_drop;
454-
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
455-
const auto& input = psbtx.inputs.at(i);
456-
int wit_ver;
457-
std::vector<unsigned char> wit_prog;
458-
if (input.witness_utxo.IsNull() || !input.witness_utxo.scriptPubKey.IsWitnessProgram(wit_ver, wit_prog)) {
459-
// There's a non-segwit input or Segwit v0, so we cannot drop any witness_utxos
460-
to_drop.clear();
461-
break;
462-
}
463-
if (wit_ver == 0) {
464-
// Segwit v0, so we cannot drop any non_witness_utxos
465-
to_drop.clear();
466-
break;
467-
}
468-
if (input.non_witness_utxo) {
469-
to_drop.push_back(i);
470-
}
492+
// Figure out if any non_witness_utxos should be dropped
493+
std::vector<unsigned int> to_drop;
494+
for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
495+
const auto& input = psbtx.inputs.at(i);
496+
int wit_ver;
497+
std::vector<unsigned char> wit_prog;
498+
if (input.witness_utxo.IsNull() || !input.witness_utxo.scriptPubKey.IsWitnessProgram(wit_ver, wit_prog)) {
499+
// There's a non-segwit input, so we cannot drop any non_witness_utxos
500+
to_drop.clear();
501+
break;
502+
}
503+
if (wit_ver == 0) {
504+
// Segwit v0, so we cannot drop any non_witness_utxos
505+
to_drop.clear();
506+
break;
507+
}
508+
// non_witness_utxos cannot be dropped if the sighash type includes SIGHASH_ANYONECANPAY
509+
// Since callers should have called SignPSBTInput which updates the sighash type in the PSBT, we only
510+
// need to look at that field. If it is not present, then we can assume SIGHASH_DEFAULT or SIGHASH_ALL.
511+
if (input.sighash_type != std::nullopt && (*input.sighash_type & 0x80) == SIGHASH_ANYONECANPAY) {
512+
to_drop.clear();
513+
break;
471514
}
472515

473-
// Drop the non_witness_utxos that we can drop
474-
for (unsigned int i : to_drop) {
475-
psbtx.inputs.at(i).non_witness_utxo = nullptr;
516+
if (input.non_witness_utxo) {
517+
to_drop.push_back(i);
476518
}
477519
}
520+
521+
// Drop the non_witness_utxos that we can drop
522+
for (unsigned int i : to_drop) {
523+
psbtx.inputs.at(i).non_witness_utxo = nullptr;
524+
}
478525
}
479526

480527
bool FinalizePSBT(PartiallySignedTransaction& psbtx)
@@ -486,7 +533,8 @@ bool FinalizePSBT(PartiallySignedTransaction& psbtx)
486533
bool complete = true;
487534
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
488535
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
489-
complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, SIGHASH_ALL, nullptr, true);
536+
PSBTInput& input = psbtx.inputs.at(i);
537+
complete &= (SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, input.sighash_type, nullptr, true) == PSBTError::OK);
490538
}
491539

492540
return complete;

src/psbt.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef BITCOIN_PSBT_H
66
#define BITCOIN_PSBT_H
77

8+
#include <common/types.h>
89
#include <node/transaction.h>
910
#include <policy/feerate.h>
1011
#include <primitives/transaction.h>
@@ -21,6 +22,8 @@ namespace node {
2122
enum class TransactionError;
2223
} // namespace node
2324

25+
using common::PSBTError;
26+
2427
// Magic bytes
2528
static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
2629

@@ -520,6 +523,11 @@ struct PSBTInput
520523
std::vector<unsigned char> sig;
521524
s >> sig;
522525

526+
// Check that the signature is validly encoded
527+
if (sig.empty() || !CheckSignatureEncoding(sig, SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_STRICTENC, nullptr)) {
528+
throw std::ios_base::failure("Signature is not a valid encoding");
529+
}
530+
523531
// Add to list
524532
partial_sigs.emplace(pubkey.GetID(), SigPair(pubkey, std::move(sig)));
525533
break;
@@ -1396,10 +1404,10 @@ bool PSBTInputSignedAndVerified(const PartiallySignedTransaction psbt, unsigned
13961404
* txdata should be the output of PrecomputePSBTData (which can be shared across
13971405
* multiple SignPSBTInput calls). If it is nullptr, a dummy signature will be created.
13981406
**/
1399-
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash = SIGHASH_ALL, SignatureData* out_sigdata = nullptr, bool finalize = true);
1407+
[[nodiscard]] PSBTError SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, std::optional<int> sighash = std::nullopt, SignatureData* out_sigdata = nullptr, bool finalize = true);
14001408

14011409
/** Reduces the size of the PSBT by dropping unnecessary `non_witness_utxos` (i.e. complete previous transactions) from a psbt when all inputs are segwit v1. */
1402-
void RemoveUnnecessaryTransactions(PartiallySignedTransaction& psbtx, const int& sighash_type);
1410+
void RemoveUnnecessaryTransactions(PartiallySignedTransaction& psbtx);
14031411

14041412
/** Counts the unsigned inputs of a PSBT. */
14051413
size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt);

src/qt/psbtoperationsdialog.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void PSBTOperationsDialog::openWithPSBT(PartiallySignedTransaction psbtx)
5959
bool complete = FinalizePSBT(psbtx); // Make sure all existing signatures are fully combined before checking for completeness.
6060
if (m_wallet_model) {
6161
size_t n_could_sign;
62-
const auto err{m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, &n_could_sign, m_transaction_data, complete)};
62+
const auto err{m_wallet_model->wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/true, &n_could_sign, m_transaction_data, complete)};
6363
if (err) {
6464
showStatus(tr("Failed to load transaction: %1")
6565
.arg(QString::fromStdString(PSBTErrorString(*err).translated)),
@@ -83,7 +83,7 @@ void PSBTOperationsDialog::signTransaction()
8383

8484
WalletModel::UnlockContext ctx(m_wallet_model->requestUnlock());
8585

86-
const auto err{m_wallet_model->wallet().fillPSBT(SIGHASH_DEFAULT, /*sign=*/true, /*bip32derivs=*/true, &n_signed, m_transaction_data, complete)};
86+
const auto err{m_wallet_model->wallet().fillPSBT(std::nullopt, /*sign=*/true, /*bip32derivs=*/true, &n_signed, m_transaction_data, complete)};
8787

8888
if (err) {
8989
showStatus(tr("Failed to sign transaction: %1")
@@ -251,7 +251,7 @@ size_t PSBTOperationsDialog::couldSignInputs(const PartiallySignedTransaction &p
251251

252252
size_t n_signed;
253253
bool complete;
254-
const auto err{m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/false, &n_signed, m_transaction_data, complete)};
254+
const auto err{m_wallet_model->wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/false, &n_signed, m_transaction_data, complete)};
255255

256256
if (err) {
257257
return 0;

src/qt/sendcoinsdialog.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ void SendCoinsDialog::presentPSBT(PartiallySignedTransaction& psbtx)
450450
bool SendCoinsDialog::signWithExternalSigner(PartiallySignedTransaction& psbtx, CMutableTransaction& mtx, bool& complete) {
451451
std::optional<PSBTError> err;
452452
try {
453-
err = model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/true, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete);
453+
err = model->wallet().fillPSBT(std::nullopt, /*sign=*/true, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete);
454454
} catch (const std::runtime_error& e) {
455455
QMessageBox::critical(nullptr, tr("Sign failed"), e.what());
456456
return false;
@@ -507,7 +507,7 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
507507
PartiallySignedTransaction psbtx(mtx);
508508
bool complete = false;
509509
// Fill without signing
510-
const auto err{model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete)};
510+
const auto err{model->wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete)};
511511
assert(!complete);
512512
assert(!err);
513513

@@ -523,7 +523,7 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
523523
bool complete = false;
524524
// Always fill without signing first. This prevents an external signer
525525
// from being called prematurely and is not expensive.
526-
const auto err{model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete)};
526+
const auto err{model->wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete)};
527527
assert(!complete);
528528
assert(!err);
529529
send_failure = !signWithExternalSigner(psbtx, mtx, complete);

src/qt/walletmodel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ bool WalletModel::bumpFee(Txid hash, Txid& new_hash)
521521
// "Create Unsigned" clicked
522522
PartiallySignedTransaction psbtx(mtx);
523523
bool complete = false;
524-
const auto err{wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, nullptr, psbtx, complete)};
524+
const auto err{wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/true, nullptr, psbtx, complete)};
525525
if (err || complete) {
526526
QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't draft transaction."));
527527
return false;

src/rpc/rawtransaction.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static std::vector<RPCArg> CreateTxDoc()
163163

164164
// Update PSBT with information from the mempool, the UTXO set, the txindex, and the provided descriptors.
165165
// Optionally, sign the inputs that we can using information from the descriptors.
166-
PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std::any& context, const HidingSigningProvider& provider, int sighash_type, bool finalize)
166+
PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std::any& context, const HidingSigningProvider& provider, std::optional<int> sighash_type, bool finalize)
167167
{
168168
// Unserialize the transactions
169169
PartiallySignedTransaction psbtx;
@@ -235,15 +235,18 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
235235
// Note that SignPSBTInput does a lot more than just constructing ECDSA signatures.
236236
// We only actually care about those if our signing provider doesn't hide private
237237
// information, as is the case with `descriptorprocesspsbt`
238-
SignPSBTInput(provider, psbtx, /*index=*/i, &txdata, sighash_type, /*out_sigdata=*/nullptr, finalize);
238+
// Only error for mismatching sighash types as it is critical that the sighash to sign with matches the PSBT's
239+
if (SignPSBTInput(provider, psbtx, /*index=*/i, &txdata, sighash_type, /*out_sigdata=*/nullptr, finalize) == common::PSBTError::SIGHASH_MISMATCH) {
240+
throw JSONRPCPSBTError(common::PSBTError::SIGHASH_MISMATCH);
241+
}
239242
}
240243

241244
// Update script/keypath information using descriptor data.
242245
for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
243246
UpdatePSBTOutput(provider, psbtx, i);
244247
}
245248

246-
RemoveUnnecessaryTransactions(psbtx, /*sighash_type=*/1);
249+
RemoveUnnecessaryTransactions(psbtx);
247250

248251
return psbtx;
249252
}
@@ -1802,7 +1805,7 @@ static RPCHelpMan utxoupdatepsbt()
18021805
request.params[0].get_str(),
18031806
request.context,
18041807
HidingSigningProvider(&provider, /*hide_secret=*/true, /*hide_origin=*/false),
1805-
/*sighash_type=*/SIGHASH_ALL,
1808+
/*sighash_type=*/std::nullopt,
18061809
/*finalize=*/false);
18071810

18081811
DataStream ssTx{};
@@ -2072,7 +2075,7 @@ RPCHelpMan descriptorprocesspsbt()
20722075
EvalDescriptorStringOrObject(descs[i], provider, /*expand_priv=*/true);
20732076
}
20742077

2075-
int sighash_type = ParseSighashString(request.params[2]);
2078+
std::optional<int> sighash_type = ParseSighashString(request.params[2]);
20762079
bool bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();
20772080
bool finalize = request.params[4].isNull() ? true : request.params[4].get_bool();
20782081

0 commit comments

Comments
 (0)