qt: move PSBT signing off GUI thread#145
Conversation
cddc002 to
1930473
Compare
PR ReviewFindings
Consensus Impact
The PR changes wallet signing orchestration and stateful PQC counter cancellation boundaries in Review ScopeReviewed issue #140 as the backing contract, issue #141 as the stated follow-up boundary, the PR body, all three commits and 15 changed files, and surrounding wallet, SPKM, Qt, external-signer, and unlock-lifetime paths. Both prior review threads are resolved, with no open threads. Exact-head CI and sanitizer logs were inspected. Deep Checks PerformedTraced worker-owned PSBT publication, cloned-wallet lifetime, unlock/relock handling, generation guards, queued callbacks, dialog destruction, wallet unload, and thread joining. I followed cancellation through the pre-reservation callback and the post-commit counter observer, checked partial-signing and error paths, and attempted to disprove the finding by searching every use of the captured usage report and reviewing the failure tests. Issue FitThe implementation otherwise satisfies the central contract: signing runs through a worker-owned wallet and PSBT, progress is queued to the GUI, cancellation is honored before durable reservation and ignored afterward, successful results are applied once, failures preserve the displayed PSBT, and destroyed models/dialogs are guarded. Provider ordering remains serial, as permitted by #140. The remaining mismatch is reporting capacity consumed before a later signing failure. The current failure test neither simulates a reservation nor supplies/asserts a usage report. qbit-Specific ChecksReviewed P2MR counter reservation timing, encrypted-wallet snapshots, cancellation boundaries, original-PSBT preservation, external-signer fallback, and wallet-unload lifetime. PQC usage remains wallet-local and is not inserted into the portable PSBT. No changes were made to P2MR commitments, signature inputs, address encoding, witness layout, consensus, mining, or networking. Validation ReviewedFull Validation and required gates passed at head The author additionally reports a successful build, 40/40 focused wallet tests, and all current Residual Risk
|
|
Addressed in GPG-signed commit
Verification at this head:
This is intentionally scoped to |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 435fbba. Configure here.
| notify_progress(SigningProgressPhase::VERIFYING_TRANSACTION, | ||
| static_cast<unsigned int>(i + 1), | ||
| static_cast<unsigned int>(psbtx.inputs.size()), | ||
| static_cast<unsigned int>(i)); |
There was a problem hiding this comment.
Ignored cancel on progress updates
Medium Severity
Several new FillPSBT progress updates after an input signs, after finalize, and during verification call the cancellable progress callback but ignore its result. The PSBT dialog still records cancel_observed when the user cancels on those updates, so signing can finish successfully yet the UI reports cancellation and never applies the signed PSBT.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 435fbba. Configure here.


Summary
PSBTOperationsDialoginto a cloned-wallet worker context so multi-input P2MR signing no longer blocks the Qt event loop.Closes #140.
Testing
Commands and results:
cmake --build build --target bitcoin_wallet qbit-qt test_qbit-qt test_qbit -j"$(sysctl -n hw.ncpu)"— passed.build/bin/test_qbit '--run_test=wallet_p2mr_parallel_signing_tests,psbt_p2mr_tests,psbt_wallet_tests,wallet_p2mr_signing_tests' --log_level=test_suite— 40/40 passed.QT_QPA_PLATFORM=cocoa build/bin/test_qbit-qt— the newPSBTOperationsDialogTestspassed 9/9 and all other relevant wallet/Qt lifecycle classes passed. The binary still reports one unrelated failure in the unchangedRPCNestedTestsstale genesis-transaction hash assertion.All checks passed!).git diff --check— passed.Target Branch
1.x.xrelease branch.Risk / Review Notes
Notes:
QPointer/generation guards prevent callbacks into destroyed dialogs or wallet models. Dialog destruction joins the worker, and wallet unload leaves the worker-owned clone valid until completion.Docs / Process Impact
libbitcoinpqc Subtree Checklist (if
src/libbitcoinpqcchanged)Not applicable;
src/libbitcoinpqcis unchanged.Note
Medium Risk
Touches wallet PSBT signing, PQC counter reservation, and async Qt lifetime; behavior changes are mostly UI threading but incorrect cancel or clone handling could affect signing outcomes.
Overview
PSBT signing in the Qt GUI no longer blocks the event loop.
PSBTOperationsDialogrunsfillPSBTon a worker thread using a cloned wallet, shows phased progress (prepare, PQC counter reservation, signing, finalize, verify), and applies the signed PSBT on the GUI thread only after success.Cancellation is honored via a new
SigningProgressCallbackoninterfaces::Wallet::fillPSBTandCWallet::FillPSBT, with cancel disabled once PQC counters are durably reserved. The send flow maps the new verifying phase into its existing finalizing progress UI.Status UX appends PQC usage details after signing attempts, and nine Qt tests cover responsiveness, cancel boundaries, dialog/wallet lifetime, and failure preserving the original PSBT.
Reviewed by Cursor Bugbot for commit 435fbba. Bugbot is set up for automated code reviews on this repo. Configure here.
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.