Skip to content

Commit

Permalink
Merge bitcoin-core/gui#399: Fix "Load PSBT" functionality when no wal…
Browse files Browse the repository at this point in the history
…let loaded

0237d95 qt: Add Load PSBT functionaliy with nowallet (Prateek Sancheti)

Pull request description:

  This PR provides a fix to the issue mentioned in bitcoin#232.

  Currently, the **_Load PSBT_** functionality works well in case a wallet is loaded but does nothing when a wallet isn't loaded.

  If a function cannot work without a wallet being loaded, it is disabled by default (It is unclickable as shown in the image).

  For e.g. One cannot `Close Wallet` or `Backup Wallet` or `Sign Messages` without a wallet being loaded. And hence they are disabled. But if you notice, `Load PSBT` options are not disabled by default even when a wallet isn't loaded.

  >  ![Screenshot 2021-08-07 at 11 46 30 PM](https://user-images.githubusercontent.com/54016434/128610208-45376026-0e91-4268-abdf-342e3cec5917.png)

  As mentioned by hebasto in the issue description :

  ```
  <hebasto> achow101: does "File" -> "Load PSBT from {file|clipboard}" make any sense when no wallet is loaded?
  <achow101> hebasto: yes, for finalize and sending
  ```

  This means **_Load PSBT_**  should be working just as similar whether wallets are being loaded or not.

  After making the required changes to the code, The **_Load PSBT_** works as expected even with no wallet loaded and the PSBT is finalized.

  | Master | PR |
  |-------------|---------------|
  | ![Hnet com-image (1)](https://user-images.githubusercontent.com/54016434/128611454-4dfc3fd3-ecc0-48f0-8408-60eb98035694.gif) | ![Hnet com-image (2)](https://user-images.githubusercontent.com/54016434/128611461-982468d2-9cd0-4f9b-9392-c25b6c8857e2.gif) |

  Close bitcoin#232

ACKs for top commit:
  achow101:
    re-ACK 0237d95
  hebasto:
    ACK 0237d95, tested on Linux Mint 20.2 (Qt 5.12.8).

Tree-SHA512: 8d928c5bfd3c2b286ddcacd0b367c872de8bc3d3d9d82280faeadc60d738b86af328c060b5763ade364c9b386b23f95580c2eb1147b16373fbb713170c100350
  • Loading branch information
hebasto committed Aug 11, 2021
2 parents 77e23ca + 0237d95 commit e614cc8
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 58 deletions.
3 changes: 3 additions & 0 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
connect(activity, &CreateWalletActivity::finished, activity, &QObject::deleteLater);
activity->create();
});
connect(walletFrame, &WalletFrame::message, [this](const QString& title, const QString& message, unsigned int style) {
this->message(title, message, style);
});
setCentralWidget(walletFrame);
} else
#endif // ENABLE_WALLET
Expand Down
33 changes: 22 additions & 11 deletions src/qt/psbtoperationsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,22 @@ void PSBTOperationsDialog::openWithPSBT(PartiallySignedTransaction psbtx)
{
m_transaction_data = psbtx;

bool complete;
size_t n_could_sign;
FinalizePSBT(psbtx); // Make sure all existing signatures are fully combined before checking for completeness.
TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, &n_could_sign, m_transaction_data, complete);
if (err != TransactionError::OK) {
showStatus(tr("Failed to load transaction: %1")
.arg(QString::fromStdString(TransactionErrorString(err).translated)), StatusLevel::ERR);
return;
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;
TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, &n_could_sign, m_transaction_data, complete);
if (err != TransactionError::OK) {
showStatus(tr("Failed to load transaction: %1")
.arg(QString::fromStdString(TransactionErrorString(err).translated)),
StatusLevel::ERR);
return;
}
m_ui->signTransactionButton->setEnabled(!complete && !m_wallet_model->wallet().privateKeysDisabled() && n_could_sign > 0);
} else {
m_ui->signTransactionButton->setEnabled(false);
}

m_ui->broadcastTransactionButton->setEnabled(complete);
m_ui->signTransactionButton->setEnabled(!complete && !m_wallet_model->wallet().privateKeysDisabled() && n_could_sign > 0);

updateTransactionDisplay();
}
Expand Down Expand Up @@ -133,7 +137,7 @@ void PSBTOperationsDialog::saveTransaction() {
}
CTxDestination address;
ExtractDestination(out.scriptPubKey, address);
QString amount = BitcoinUnits::format(m_wallet_model->getOptionsModel()->getDisplayUnit(), out.nValue);
QString amount = BitcoinUnits::format(m_client_model->getOptionsModel()->getDisplayUnit(), out.nValue);
QString address_str = QString::fromStdString(EncodeDestination(address));
filename_suggestion.append(address_str + "-" + amount);
first = false;
Expand Down Expand Up @@ -224,6 +228,10 @@ void PSBTOperationsDialog::showStatus(const QString &msg, StatusLevel level) {
}

size_t PSBTOperationsDialog::couldSignInputs(const PartiallySignedTransaction &psbtx) {
if (!m_wallet_model) {
return 0;
}

size_t n_signed;
bool complete;
TransactionError err = m_wallet_model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, false /* bip32derivs */, &n_signed, m_transaction_data, complete);
Expand All @@ -246,7 +254,10 @@ void PSBTOperationsDialog::showTransactionStatus(const PartiallySignedTransactio
case PSBTRole::SIGNER: {
QString need_sig_text = tr("Transaction still needs signature(s).");
StatusLevel level = StatusLevel::INFO;
if (m_wallet_model->wallet().privateKeysDisabled()) {
if (!m_wallet_model) {
need_sig_text += " " + tr("(But no wallet is loaded.)");
level = StatusLevel::WARN;
} else if (m_wallet_model->wallet().privateKeysDisabled()) {
need_sig_text += " " + tr("(But this wallet cannot sign transactions.)");
level = StatusLevel::WARN;
} else if (n_could_sign < 1) {
Expand Down
42 changes: 39 additions & 3 deletions src/qt/walletframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@

#include <qt/walletframe.h>

#include <node/ui_interface.h>
#include <psbt.h>
#include <qt/guiutil.h>
#include <qt/overviewpage.h>
#include <qt/psbtoperationsdialog.h>
#include <qt/walletmodel.h>
#include <qt/walletview.h>

#include <cassert>

#include <QApplication>
#include <QClipboard>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
Expand Down Expand Up @@ -184,10 +190,40 @@ void WalletFrame::gotoVerifyMessageTab(QString addr)

void WalletFrame::gotoLoadPSBT(bool from_clipboard)
{
WalletView *walletView = currentWalletView();
if (walletView) {
walletView->gotoLoadPSBT(from_clipboard);
std::string data;

if (from_clipboard) {
std::string raw = QApplication::clipboard()->text().toStdString();
bool invalid;
data = DecodeBase64(raw, &invalid);
if (invalid) {
Q_EMIT message(tr("Error"), tr("Unable to decode PSBT from clipboard (invalid base64)"), CClientUIInterface::MSG_ERROR);
return;
}
} else {
QString filename = GUIUtil::getOpenFileName(this,
tr("Load Transaction Data"), QString(),
tr("Partially Signed Transaction (*.psbt)"), nullptr);
if (filename.isEmpty()) return;
if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) == MAX_FILE_SIZE_PSBT) {
Q_EMIT message(tr("Error"), tr("PSBT file must be smaller than 100 MiB"), CClientUIInterface::MSG_ERROR);
return;
}
std::ifstream in(filename.toLocal8Bit().data(), std::ios::binary);
data = std::string(std::istreambuf_iterator<char>{in}, {});
}

std::string error;
PartiallySignedTransaction psbtx;
if (!DecodeRawPSBT(psbtx, data, error)) {
Q_EMIT message(tr("Error"), tr("Unable to decode PSBT") + "\n" + QString::fromStdString(error), CClientUIInterface::MSG_ERROR);
return;
}

PSBTOperationsDialog* dlg = new PSBTOperationsDialog(this, currentWalletModel(), clientModel);
dlg->openWithPSBT(psbtx);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->exec();
}

void WalletFrame::encryptWallet()
Expand Down
1 change: 1 addition & 0 deletions src/qt/walletframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class WalletFrame : public QFrame

Q_SIGNALS:
void createWalletButtonClicked();
void message(const QString& title, const QString& message, unsigned int style);

private:
QStackedWidget *walletStack;
Expand Down
42 changes: 0 additions & 42 deletions src/qt/walletview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <qt/askpassphrasedialog.h>
#include <qt/clientmodel.h>
#include <qt/guiutil.h>
#include <qt/psbtoperationsdialog.h>
#include <qt/optionsmodel.h>
#include <qt/overviewpage.h>
#include <qt/platformstyle.h>
Expand All @@ -21,13 +20,10 @@

#include <interfaces/node.h>
#include <node/ui_interface.h>
#include <psbt.h>
#include <util/strencodings.h>

#include <QAction>
#include <QActionGroup>
#include <QApplication>
#include <QClipboard>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QProgressDialog>
Expand Down Expand Up @@ -205,44 +201,6 @@ void WalletView::gotoVerifyMessageTab(QString addr)
signVerifyMessageDialog->setAddress_VM(addr);
}

void WalletView::gotoLoadPSBT(bool from_clipboard)
{
std::string data;

if (from_clipboard) {
std::string raw = QApplication::clipboard()->text().toStdString();
bool invalid;
data = DecodeBase64(raw, &invalid);
if (invalid) {
Q_EMIT message(tr("Error"), tr("Unable to decode PSBT from clipboard (invalid base64)"), CClientUIInterface::MSG_ERROR);
return;
}
} else {
QString filename = GUIUtil::getOpenFileName(this,
tr("Load Transaction Data"), QString(),
tr("Partially Signed Transaction (*.psbt)"), nullptr);
if (filename.isEmpty()) return;
if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) == MAX_FILE_SIZE_PSBT) {
Q_EMIT message(tr("Error"), tr("PSBT file must be smaller than 100 MiB"), CClientUIInterface::MSG_ERROR);
return;
}
std::ifstream in(filename.toLocal8Bit().data(), std::ios::binary);
data = std::string(std::istreambuf_iterator<char>{in}, {});
}

std::string error;
PartiallySignedTransaction psbtx;
if (!DecodeRawPSBT(psbtx, data, error)) {
Q_EMIT message(tr("Error"), tr("Unable to decode PSBT") + "\n" + QString::fromStdString(error), CClientUIInterface::MSG_ERROR);
return;
}

PSBTOperationsDialog* dlg = new PSBTOperationsDialog(this, walletModel, clientModel);
dlg->openWithPSBT(psbtx);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->exec();
}

bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
return sendCoinsPage->handlePaymentRequest(recipient);
Expand Down
2 changes: 0 additions & 2 deletions src/qt/walletview.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ public Q_SLOTS:
void gotoSignMessageTab(QString addr = "");
/** Show Sign/Verify Message dialog and switch to verify message tab */
void gotoVerifyMessageTab(QString addr = "");
/** Load Partially Signed Bitcoin Transaction */
void gotoLoadPSBT(bool from_clipboard = false);

/** Show incoming transaction notification for new transactions.
Expand Down

0 comments on commit e614cc8

Please sign in to comment.