diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 7c8c04366f7..412bd5dfc6b 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -268,6 +268,8 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa } // prepare transaction for getting txFee earlier + // Create unsigned transaction to support creating unsigned PSBTs. + // Signing is deferred until the user clicks "Send". m_current_transaction = std::make_unique(recipients); WalletModel::SendCoinsReturn prepareStatus; @@ -344,7 +346,7 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa // append transaction size //: When reviewing a newly created PSBT (via Send flow), the transaction fee is shown, with "virtual size" of the transaction displayed for context - question_string.append(" (" + tr("%1 kvB", "PSBT transaction creation").arg((double)m_current_transaction->getTransactionSize() / 1000, 0, 'g', 3) + "): "); + question_string.append(" (" + tr("%1 kvB (unsigned)", "PSBT transaction creation").arg((double)m_current_transaction->getTransactionSize() / 1000, 0, 'g', 3) + "): "); // append transaction fee value question_string.append(""); @@ -497,6 +499,12 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked) presentPSBT(psbtx); } else { // "Send" clicked + WalletModel::UnlockContext ctx(model->requestUnlock()); + if (!ctx.isValid()) { + fNewRecipientAllowed = true; + return; + } + assert(!model->wallet().privateKeysDisabled() || model->wallet().hasExternalSigner()); bool broadcast = true; if (model->wallet().hasExternalSigner()) { @@ -522,6 +530,21 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked) presentPSBT(psbtx); } } + } else { + // Sign the transaction now that the user has confirmed they want to send. + CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx())}; + PartiallySignedTransaction psbtx(mtx); + bool complete = false; + const auto err{model->wallet().fillPSBT({.sign = true, .bip32_derivs = false}, /*n_signed=*/nullptr, psbtx, complete)}; + if (err || !complete) { + Q_EMIT message(tr("Send Coins"), tr("Failed to sign transaction."), + CClientUIInterface::MSG_ERROR); + send_failure = true; + broadcast = false; + } else { + CHECK_NONFATAL(FinalizeAndExtractPSBT(psbtx, mtx)); + m_current_transaction->setWtx(MakeTransactionRef(mtx)); + } } // Broadcast the transaction, unless an external signer was used and it diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index a9142b930d5..26cf83c8188 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -203,7 +203,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact try { auto& newTx = transaction.getWtx(); - const auto& res = m_wallet->createTransaction(vecSend, coinControl, /*sign=*/!wallet().privateKeysDisabled(), /*change_pos=*/std::nullopt); + const auto& res = m_wallet->createTransaction(vecSend, coinControl, /*sign=*/false, /*change_pos=*/std::nullopt); if (!res) { Q_EMIT message(tr("Send Coins"), QString::fromStdString(util::ErrorString(res).translated), CClientUIInterface::MSG_ERROR);