Merge bitcoin/bitcoin#31622: psbt: add non-default sighash types to PSBTs and unify sighash type match checking
ee045b61efrpc, psbt: Require sighashes match for descriptorprocesspsbt (Ava Chow)2b7682c372psbt: use sighash type field to determine whether to remove non-witness utxos (Ava Chow)28781b5f06psbt: Add sighash types to PSBT when not DEFAULT or ALL (Ava Chow)15ce1bd73fpsbt: Enforce sighash type of signatures matches psbt (Ava Chow)1f71cd337awallet: Remove sighash type enforcement from FillPSBT (Ava Chow)4c7d767e49psbt: Check sighash types in SignPSBTInput and take sighash as optional (Ava Chow)a118256948script: Add IsPayToTaproot() (Ava Chow)d6001dcd4awallet: change FillPSBT to take sighash as optional (Ava Chow)e58b680923psbt: Return PSBTError from SignPSBTInput (Ava Chow)2adfd81532tests: Test PSBT sighash type mismatch (Ava Chow)5a5d26d612psbt: 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-ACKee045b61efrkrux: re-ACKee045b61effjahr: Code review ACKee045b61efTree-SHA512: 4ead5be1ef6756251b827f594beba868a145d75bf7f4ef6f15ad21f0ae4b8d71b38c83494e5a6b75f37fadd097178cddd93d614b962a2c72fc134f00ba2f74ae
This commit is contained in:
27 files changed
+253
-84
No files matched your search
@@ -59,7 +59,7 @@ void PSBTOperationsDialog::openWithPSBT(PartiallySignedTransaction psbtx)
|
||||
bool complete = FinalizePSBT(psbtx); // Make sure all existing signatures are fully combined before checking for completeness.
|
||||
if (m_wallet_model) {
|
||||
size_t n_could_sign;
|
||||
const auto err{m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, &n_could_sign, m_transaction_data, complete)};
|
||||
const auto err{m_wallet_model->wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/true, &n_could_sign, m_transaction_data, complete)};
|
||||
if (err) {
|
||||
showStatus(tr("Failed to load transaction: %1")
|
||||
.arg(QString::fromStdString(PSBTErrorString(*err).translated)),
|
||||
@@ -83,7 +83,7 @@ void PSBTOperationsDialog::signTransaction()
|
||||
|
||||
WalletModel::UnlockContext ctx(m_wallet_model->requestUnlock());
|
||||
|
||||
const auto err{m_wallet_model->wallet().fillPSBT(SIGHASH_DEFAULT, /*sign=*/true, /*bip32derivs=*/true, &n_signed, m_transaction_data, complete)};
|
||||
const auto err{m_wallet_model->wallet().fillPSBT(std::nullopt, /*sign=*/true, /*bip32derivs=*/true, &n_signed, m_transaction_data, complete)};
|
||||
|
||||
if (err) {
|
||||
showStatus(tr("Failed to sign transaction: %1")
|
||||
@@ -251,7 +251,7 @@ size_t PSBTOperationsDialog::couldSignInputs(const PartiallySignedTransaction &p
|
||||
|
||||
size_t n_signed;
|
||||
bool complete;
|
||||
const auto err{m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/false, &n_signed, m_transaction_data, complete)};
|
||||
const auto err{m_wallet_model->wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/false, &n_signed, m_transaction_data, complete)};
|
||||
|
||||
if (err) {
|
||||
return 0;
|
||||
|
||||
@@ -450,7 +450,7 @@ void SendCoinsDialog::presentPSBT(PartiallySignedTransaction& psbtx)
|
||||
bool SendCoinsDialog::signWithExternalSigner(PartiallySignedTransaction& psbtx, CMutableTransaction& mtx, bool& complete) {
|
||||
std::optional<PSBTError> err;
|
||||
try {
|
||||
err = model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/true, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete);
|
||||
err = model->wallet().fillPSBT(std::nullopt, /*sign=*/true, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete);
|
||||
} catch (const std::runtime_error& e) {
|
||||
QMessageBox::critical(nullptr, tr("Sign failed"), e.what());
|
||||
return false;
|
||||
@@ -507,7 +507,7 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
|
||||
PartiallySignedTransaction psbtx(mtx);
|
||||
bool complete = false;
|
||||
// Fill without signing
|
||||
const auto err{model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete)};
|
||||
const auto err{model->wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete)};
|
||||
assert(!complete);
|
||||
assert(!err);
|
||||
|
||||
@@ -523,7 +523,7 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
|
||||
bool complete = false;
|
||||
// Always fill without signing first. This prevents an external signer
|
||||
// from being called prematurely and is not expensive.
|
||||
const auto err{model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete)};
|
||||
const auto err{model->wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete)};
|
||||
assert(!complete);
|
||||
assert(!err);
|
||||
send_failure = !signWithExternalSigner(psbtx, mtx, complete);
|
||||
|
||||
@@ -521,7 +521,7 @@ bool WalletModel::bumpFee(Txid hash, Txid& new_hash)
|
||||
// "Create Unsigned" clicked
|
||||
PartiallySignedTransaction psbtx(mtx);
|
||||
bool complete = false;
|
||||
const auto err{wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, nullptr, psbtx, complete)};
|
||||
const auto err{wallet().fillPSBT(std::nullopt, /*sign=*/false, /*bip32derivs=*/true, nullptr, psbtx, complete)};
|
||||
if (err || complete) {
|
||||
QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't draft transaction."));
|
||||
return false;
|
||||
|
||||
Reference in new issue
Block a user