Defer transaction signing until user clicks Send #915

pull 151henry151 wants to merge 1 commits into bitcoin-core:master from 151henry151:fix-30070-defer-signing changing 3 files +36 −4
  1. 151henry151 commented at 7:19 pm on November 22, 2025: contributor

    Fixes #30070

    When creating an unsigned PSBT from the GUI, the transaction was already signed during preparation, causing legacy inputs to have non-empty scriptSig fields. The PSBT parser then rejects them.

    This defers signing until the user clicks “Send” instead of signing during preparation. Fee calculation still works since transactions can be created without signing.

    Follows the approach suggested by @achow101 in the issue comments.

  2. DrahtBot commented at 7:19 pm on November 22, 2025: contributor

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

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK achow101

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    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.

  3. hebasto renamed this:
    qt: Defer transaction signing until user clicks Send
    Defer transaction signing until user clicks Send
    on Nov 22, 2025
  4. DrahtBot added the label CI failed on Nov 22, 2025
  5. 151henry151 commented at 6:02 pm on November 23, 2025: contributor
    It looks like the one failing check is a CI issue with disk space too low. I’m not sure how to address that. I think the code of the PR is correct.
  6. 151henry151 commented at 9:51 pm on November 29, 2025: contributor
    @achow101 would you like to check this out and let me know if it looks OK?
  7. maflcko closed this on Dec 17, 2025

  8. maflcko reopened this on Dec 17, 2025

  9. 151henry151 commented at 6:40 pm on January 18, 2026: contributor
    Should I push an empty commit to trigger a re-run of the CI here, or is there some other action needed?
  10. hebasto commented at 3:59 pm on January 19, 2026: member

    Should I push an empty commit to trigger a re-run of the CI here, or is there some other action needed?

    No action needed.

  11. hebasto commented at 3:59 pm on January 19, 2026: member
  12. hebasto removed the label CI failed on Jan 19, 2026
  13. hebasto added the label Wallet on Jan 19, 2026
  14. in src/qt/walletmodel.cpp:150 in 58adbcf88a
    146@@ -147,7 +147,7 @@ bool WalletModel::validateAddress(const QString& address) const
    147     return IsValidDestinationString(address.toStdString());
    148 }
    149 
    150-WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl& coinControl)
    151+WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl& coinControl, bool sign)
    


    achow101 commented at 8:51 pm on January 19, 2026:
    prepareTransaction has only a single caller that already sets sign = false. I don’t think this needs to take a parameter, it can just always not sign.

    151henry151 commented at 5:26 pm on January 20, 2026:
    suggestion implemented
  15. in src/qt/sendcoinsdialog.cpp:551 in 58adbcf88a
    546+            // Sign the transaction now that the user has confirmed they want to send.
    547+            CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx())};
    548+            PartiallySignedTransaction psbtx(mtx);
    549+            bool complete = false;
    550+            // Fill and sign the PSBT
    551+            const auto err{model->wallet().fillPSBT(std::nullopt, /*sign=*/true, /*bip32derivs=*/false, /*n_signed=*/nullptr, psbtx, complete)};
    


    achow101 commented at 8:53 pm on January 19, 2026:
    Creating the PSBT and calling fillPSBT on it is being done for all of the other cases in this function, and hence is now duplicated 3 times. This can be refactored so that the PSBT is always created and filled at the top of the function, and each action can do whatever specific thing it needs to do with that PSBT.

    151henry151 commented at 5:26 pm on January 20, 2026:
    refactored as suggested
  16. achow101 commented at 8:54 pm on January 19, 2026: member
    Concept ACK
  17. 151henry151 force-pushed on Jan 20, 2026
  18. DrahtBot added the label CI failed on Jan 20, 2026
  19. DrahtBot added the label Needs rebase on Feb 10, 2026
  20. 151henry151 force-pushed on Feb 11, 2026
  21. DrahtBot removed the label Needs rebase on Feb 11, 2026
  22. 151henry151 force-pushed on Feb 11, 2026
  23. 151henry151 commented at 4:56 am on February 11, 2026: contributor
    For the rebase, I kept master’s new createTransaction usage and error flow, wired in the defer-signing logic (sign parameter), and re-added the AmountExceedsBalance check after a successful result. I initially missed updating that to AmountExceedsBalance, but I’ve corrected it. If anyone wants to check this out and let me know if it looks correct, I’d appreciate any feedback. Thanks
  24. DrahtBot removed the label CI failed on Feb 11, 2026
  25. 151henry151 commented at 9:44 pm on March 1, 2026: contributor
    Would anyone like to take another look at this? Any review or feedback welcomed
  26. in src/qt/sendcoinsdialog.cpp:275 in 9b65413cef


    johnny9 commented at 4:08 pm on March 4, 2026:
    You might need to validate that this works with encrypted wallets. You likely need this UnlockContext to sign later on.

    151henry151 commented at 10:09 pm on March 5, 2026:
    @johnny9 I think I’ve addressed this correctly with 39a5fed – it passed my local tests; do you want to check it out and see if it looks good to you?

    johnny9 commented at 3:01 pm on March 8, 2026:
    You should go ahead and delete this unlock context now as I don’t think you need it anymore

    johnny9 commented at 3:09 pm on March 8, 2026:
    This is a little different now that the current transaction isn’t signed yet so the kvB is different now than before. Can either change the dialog to make this clear or adjust this size to be the same as the estimated size the fee calculation uses.

    johnny9 commented at 3:34 pm on March 8, 2026:

    For this example vsize should equal the fee (208 kvB and 208 sat fee). Without your changes they were same and now the size of the transaction doesnt include the signed portion so it isn’t matching the fee.

  27. johnny9 commented at 4:09 pm on March 4, 2026: contributor
    Double check this works with locked encrypted wallets
  28. johnny9 changes_requested
  29. johnny9 commented at 4:35 pm on March 4, 2026: contributor

    Need to move the UnlockContext when you sign the transaction otherwise it fails to send now.

    https://github.com/user-attachments/assets/6b7e6894-b803-4753-9f20-66541af63633

  30. 151henry151 commented at 4:42 pm on March 4, 2026: contributor
    Thanks @johnny9 , I’ll take a closer look this evening
  31. qt: Defer transaction signing until user clicks Send
    This fixes issue #30070 where creating unsigned PSBTs from the GUI
    would fail because the transaction was already signed during preparation,
    causing legacy inputs to have non-empty scriptSig fields.
    
    The fix defers signing until the user explicitly clicks 'Send', allowing
    truly unsigned PSBTs to be created while still supporting fee calculation.
    39a5fed760
  32. 151henry151 force-pushed on Mar 5, 2026
  33. DrahtBot added the label CI failed on Mar 6, 2026
  34. johnny9 commented at 3:14 pm on March 8, 2026: contributor

    Moving the UnlockContext in the “Send” click flow resolved the previous issue. I think the previous UnlockContext is no longer needed.

    I also see that the send confirmation dialog isn’t as accurate as it was previously so should adjust what the dialog says or expose the correct fee estimated size through the model.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/gui. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-03-11 04:20 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me