Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore Send button when using external signer #555

Merged
merged 3 commits into from
Mar 17, 2022

Conversation

Sjors
Copy link
Member

@Sjors Sjors commented Feb 21, 2022

Fixes #551

For the simplest use case of a wallet with one external signer and "PSBT Controls" disabled in settings (the default), the send dialog will behave the same as when using a wallet with private keys. I.e. there's no "Create Unsigned" button.

When PSBT controls are turned on, you can now actually make a PSBT with signing it; before this PR that button would trigger a sign event and would broadcast the transaction.

In case a multisig, the Send button will sign on the device, and then fall back to presenting a PSBT (same behavior as before #441).

This PR starts with two refactoring commits to move some stuff into a helper function for improved readability in general, and to make the main commit easier to review.

@hebasto
Copy link
Member

hebasto commented Feb 21, 2022

Concept ACK.

I've verified that no new or changed strings are presented.

@hebasto hebasto added this to the 23.0 milestone Feb 21, 2022
@hebasto hebasto added UX All about "how to get things done" Wallet labels Feb 21, 2022
@Sjors Sjors requested a review from achow101 February 21, 2022 14:52
Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK

src/qt/sendcoinsdialog.cpp Outdated Show resolved Hide resolved
// Copy PSBT to clipboard and offer to save
presentPSBT(psbtx);
} else { // Send clicked
assert(!model->wallet().privateKeysDisabled() || model->wallet().hasExternalSigner());
bool complete = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a49bb0c

I think it makes more sense to refactor this to:

bool broadcast = true;
if (model->wallet().hasExternalSigner()) {
    // ...
    bool complete;
    send_failure = !signWithExternalSigner(psbtx, mtx, complete);
    if (complete) {
        // ...
    } else {
        // ...
        broadcast = false
    }
}
if (broadcast) {
    // ...
}

This commit does not change behavior.

Review hint:
git show --color-moved --color-moved-ws=allow-indentation-change
@Sjors Sjors force-pushed the 2022/02/send_button branch from a49bb0c to 33d165d Compare February 24, 2022 11:42
@Sjors
Copy link
Member Author

Sjors commented Feb 24, 2022

Addressed @promag's feedback.

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 2, 2022

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #562 (Warn when sending to already-used Bitcoin addresses by luke-jr)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sjors it will broadcast even if you reject signing on the device, so it's missing broadcast = false in that case.

@@ -502,19 +502,34 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
}

bool send_failure = false;
if (retval == QMessageBox::Save) {
bool broadcast = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

33d165d

diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index c420aa3581..87a0e4a098 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -502,7 +502,6 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
     }

     bool send_failure = false;
-    bool broadcast = true;
     if (retval == QMessageBox::Save) { // Create Unsigned clicked
         CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx())};
         PartiallySignedTransaction psbtx(mtx);
@@ -510,11 +509,13 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
         presentPSBT(psbtx);
     } else { // Send clicked
         assert(!model->wallet().privateKeysDisabled() || model->wallet().hasExternalSigner());
+        bool broadcast = true;
         if (model->wallet().hasExternalSigner()) {
             CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx())};
             PartiallySignedTransaction psbtx(mtx);
             bool complete = false;
             send_failure = !signWithExternalSigner(psbtx, mtx, complete);
+            broadcast = complete;
             // A transaction signed with an external signer is not always complete,
             // e.g. in a multisig wallet.
             if (complete) {
@@ -523,7 +524,6 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
                 m_current_transaction->setWtx(tx);
             } else if (!send_failure) {
                 presentPSBT(psbtx);
-                broadcast = false;
             }
         }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user rejects the transaction then complete = false and it will present the PSBT. We can't tell the difference between rejection and failure, so that's difficult to avoid. I don't see how this patch would change that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If user rejects then complete = false and send_failure = true, so it doesn't presentPSBT() and because
broadcast = true it calls model->sendCoins()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I restructured this code and fix a bit...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM, will re-test.

@Sjors Sjors changed the title Enable Send button when using external signer Restore Send button when using external signer Mar 10, 2022
@jonatack
Copy link
Member

Concept ACK

@Sjors Sjors force-pushed the 2022/02/send_button branch 2 times, most recently from 4ed2a3b to 86e3e2c Compare March 10, 2022 21:21
@kristapsk
Copy link
Contributor

Concept ACK

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested ACK 86e3e2c.

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Untested ACK 86e3e2c code review and debug build, the approach and logic looks correct

A few style and readability suggestions, happy to re-review if you update.

src/qt/sendcoinsdialog.h Outdated Show resolved Hide resolved
src/qt/sendcoinsdialog.cpp Outdated Show resolved Hide resolved
src/qt/sendcoinsdialog.h Outdated Show resolved Hide resolved
src/qt/sendcoinsdialog.cpp Outdated Show resolved Hide resolved
src/qt/sendcoinsdialog.cpp Outdated Show resolved Hide resolved
src/qt/sendcoinsdialog.h Outdated Show resolved Hide resolved
Copy link
Member

@luke-jr luke-jr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 86e3e2c except for 1 part I'm unsure on

bool complete = false;
// Always fill without signing first. This prevents an external signer
// from being called prematurely and is not expensive.
TransactionError err = model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, nullptr, psbtx, complete);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e1c1c61 claims "Does not change behavior.", yet this is no longer done for wallets without an external signer.

Copy link
Member Author

@Sjors Sjors Mar 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I moved this out of the helper function.

It leads to some duplication in 0538614, but it's probably better to preserve the behavior. It might even useful, though I'm a bit rusty on what PSBT filling does on top of what the wallet already does.

Copy link
Member

@jonatack jonatack Mar 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as a potential follow-up it looks like this code block could be potentially de-duped by extracting to a helper method that returns psbtx and mtx.

        CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx())};
        PartiallySignedTransaction psbtx(mtx);
        bool complete = false;
        TransactionError err = model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete);
        assert(!complete);
        assert(err == TransactionError::OK);

(and TransactionError err could be const)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to avoid touching this now, but I agree it would be good to move into a helper.

@Sjors Sjors force-pushed the 2022/02/send_button branch from 86e3e2c to 225794f Compare March 15, 2022 15:42
@Sjors
Copy link
Member Author

Sjors commented Mar 15, 2022

Addressed @jonatack's feedback, since I had to touch it for the issue @luke-jr raised.

@Sjors Sjors force-pushed the 2022/02/send_button branch 2 times, most recently from 347871f to 0538614 Compare March 15, 2022 15:49
bool SendCoinsDialog::signWithExternalSigner(PartiallySignedTransaction& psbtx, CMutableTransaction& mtx, bool& complete) {
TransactionError err;
try {
err = model->wallet().fillPSBT(SIGHASH_ALL, /*sign=*/false, /*bip32derivs=*/true, /*n_signed=*/nullptr, psbtx, complete);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sign was true here - why was it changed to false?

Copy link
Member Author

@Sjors Sjors Mar 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes, I broke that during the style fix.
(fixed and re-tested on device this time)

Sjors and others added 2 commits March 16, 2022 10:28
Does not change behavior.

Review hint:
git show --color-moved --color-moved-ws=allow-indentation-change
Before this change the send confirmation dialog would keep the Send option disabled. The Create Unsigned choice would actually send. This is potentially confusing.

With this change the Create Unsigned button will not attempt to sign and always produce a PSBT. The Send button will attempt to sign, and only return a PSBT if more signatures are needed.

When using an external signer, the Create Unsigned option only appears when PSBT controls are enabled in the wallet settings.

This commit maintains the pre-existing behavior of filling the PSBT (without signing) even when not using an external signer.

Closes bitcoin-core#551

Co-authored-by: Jon Atack <jon@atack.com>
@Sjors Sjors force-pushed the 2022/02/send_button branch from 0538614 to 2efdfb8 Compare March 16, 2022 09:29
Copy link
Member

@luke-jr luke-jr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 2efdfb8

@jonatack
Copy link
Member

utACK 2efdfb8 diff review since my last review, code re-review, rebased to current master, verified clean debug build of each commit

@hebasto hebasto merged commit aece566 into bitcoin-core:master Mar 17, 2022
hebasto pushed a commit to hebasto/bitcoin that referenced this pull request Mar 17, 2022
This commit does not change behavior.

Review hint:
git show --color-moved --color-moved-ws=allow-indentation-change

Github-Pull: bitcoin-core/gui#555
Rebased-From: 026b5b4
hebasto pushed a commit to hebasto/bitcoin that referenced this pull request Mar 17, 2022
Does not change behavior.

Review hint:
git show --color-moved --color-moved-ws=allow-indentation-change

Github-Pull: bitcoin-core/gui#555
Rebased-From: 4b5a6cd
hebasto pushed a commit to hebasto/bitcoin that referenced this pull request Mar 17, 2022
Before this change the send confirmation dialog would keep the Send option disabled. The Create Unsigned choice would actually send. This is potentially confusing.

With this change the Create Unsigned button will not attempt to sign and always produce a PSBT. The Send button will attempt to sign, and only return a PSBT if more signatures are needed.

When using an external signer, the Create Unsigned option only appears when PSBT controls are enabled in the wallet settings.

This commit maintains the pre-existing behavior of filling the PSBT (without signing) even when not using an external signer.

Closes bitcoin#551

Co-authored-by: Jon Atack <jon@atack.com>

Github-Pull: bitcoin-core/gui#555
Rebased-From: 2efdfb8
@hebasto
Copy link
Member

hebasto commented Mar 17, 2022

Backported in bitcoin/bitcoin#24596.

@jonatack
Copy link
Member

It might be good to have another tested ACK of the latest push.

@Sjors
Copy link
Member Author

Sjors commented Mar 17, 2022

@achow101?

sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Mar 18, 2022
maflcko pushed a commit to bitcoin/bitcoin that referenced this pull request Mar 24, 2022
70f2c57 options: flip listenonion to false if not listening (Vasil Dimov)
642f272 gui: restore Send for external signer (Sjors Provoost)
9406946 refactor: helper function signWithExternalSigner() (Sjors Provoost)
fc421d4 move-only: helper function to present PSBT (Sjors Provoost)

Pull request description:

  Backports from the GUI repo:
  - bitcoin-core/gui#555
  - bitcoin-core/gui#568

ACKs for top commit:
  Sjors:
    utACK 70f2c57
  gruve-p:
    ACK 70f2c57

Tree-SHA512: 883c442f8b789a9d11c949179e4382843cbb979a89a625bef3f481c7070421681d9db2af0e5b2449abca362c8ba05cf61db5893aeb6a9237b02088c2fb71e93e
fujicoin pushed a commit to fujicoin/fujicoin-23.0 that referenced this pull request Mar 25, 2022
This commit does not change behavior.

Review hint:
git show --color-moved --color-moved-ws=allow-indentation-change

Conflicts:
	src/qt/sendcoinsdialog.cpp

Github-Pull: bitcoin-core/gui#555
Rebased-From: 026b5b4523317fdefc69cf5cec55f76f18ad0c0a
fujicoin pushed a commit to fujicoin/fujicoin-23.0 that referenced this pull request Mar 25, 2022
Does not change behavior.

Review hint:
git show --color-moved --color-moved-ws=allow-indentation-change

Github-Pull: bitcoin-core/gui#555
Rebased-From: 4b5a6cd14967b8ec3cb525e4cb18628de6c15091
fujicoin pushed a commit to fujicoin/fujicoin-23.0 that referenced this pull request Mar 25, 2022
Before this change the send confirmation dialog would keep the Send option disabled. The Create Unsigned choice would actually send. This is potentially confusing.

With this change the Create Unsigned button will not attempt to sign and always produce a PSBT. The Send button will attempt to sign, and only return a PSBT if more signatures are needed.

When using an external signer, the Create Unsigned option only appears when PSBT controls are enabled in the wallet settings.

This commit maintains the pre-existing behavior of filling the PSBT (without signing) even when not using an external signer.

Closes #551

Co-authored-by: Jon Atack <jon@atack.com>

Github-Pull: bitcoin-core/gui#555
Rebased-From: 2efdfb88aab6496dcf2b98e0de30635bc6bade85
backpacker69 pushed a commit to peercoin/peercoin that referenced this pull request Jan 18, 2023
This commit does not change behavior.

Review hint:
git show --color-moved --color-moved-ws=allow-indentation-change

Github-Pull: bitcoin-core/gui#555
Rebased-From: 026b5b4523317fdefc69cf5cec55f76f18ad0c0a
backpacker69 pushed a commit to peercoin/peercoin that referenced this pull request Jan 18, 2023
Does not change behavior.

Review hint:
git show --color-moved --color-moved-ws=allow-indentation-change

Github-Pull: bitcoin-core/gui#555
Rebased-From: 4b5a6cd14967b8ec3cb525e4cb18628de6c15091
backpacker69 pushed a commit to peercoin/peercoin that referenced this pull request Jan 18, 2023
Before this change the send confirmation dialog would keep the Send option disabled. The Create Unsigned choice would actually send. This is potentially confusing.

With this change the Create Unsigned button will not attempt to sign and always produce a PSBT. The Send button will attempt to sign, and only return a PSBT if more signatures are needed.

When using an external signer, the Create Unsigned option only appears when PSBT controls are enabled in the wallet settings.

This commit maintains the pre-existing behavior of filling the PSBT (without signing) even when not using an external signer.

Closes #551

Co-authored-by: Jon Atack <jon@atack.com>

Github-Pull: bitcoin-core/gui#555
Rebased-From: 2efdfb88aab6496dcf2b98e0de30635bc6bade85
@bitcoin-core bitcoin-core locked and limited conversation to collaborators Jun 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
UX All about "how to get things done" Wallet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

External signer Send button disabled
7 participants