Skip to content
Bitcoin Roots

v30.3-roots.1 · Commit 28: [PATCH 28/68] fix(wallet): secure asynchronous sweep cancellation

src/interfaces/wallet.h

Before: src/interfaces/wallet.h · After: src/interfaces/wallet.h

File metadata
index e8015073e0e274bb37d7d0593de56f9c89bf9cbe..87bef444e79e4b73482d71375826d4e67551a13d 100644

Download original patch · Release notes

Diff rows 1–47 of 47. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.

src/interfaces/wallet.h CHANGED
@@ -18,6 +18,7 @@
18
  #include <util/result.h>
19
  #include <util/ui_change_type.h>
20
 
 
21
  #include <cstdint>
22
  #include <functional>
23
  #include <map>
@@ -57,6 +58,31 @@ struct WalletTxOut;
57
  struct WalletTxStatus;
58
  struct WalletMigrationResult;
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  //! Result of a transient-private-key sweep. The supplied key is never retained
61
  //! by this interface or by the wallet.
62
  struct WalletSweepResult {
@@ -121,7 +147,8 @@ public:
121
  virtual util::Result<WalletSweepResult> sweepPrivateKey(const SecureString& private_key,
122
  const CTxDestination& destination,
123
  bool broadcast,
124
- const std::optional<Txid>& expected_txid = std::nullopt) = 0;
 
125
 
126
  //! Add or update address.
127
  virtual bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<wallet::AddressPurpose>& purpose) = 0;
 
18
  #include <util/result.h>
19
  #include <util/ui_change_type.h>
20
 
21
+ #include <atomic>
22
  #include <cstdint>
23
  #include <functional>
24
  #include <map>
 
58
  struct WalletTxStatus;
59
  struct WalletMigrationResult;
60
 
61
+ //! Shared authorization for an asynchronous sweep. Cancellation and the final
62
+ //! transition into broadcast are mutually exclusive, so a successful cancel
63
+ //! guarantees that broadcast cannot start afterwards.
64
+ class SweepAuthorization
65
+ {
66
+ public:
67
+ bool Cancel()
68
+ {
69
+ State expected{State::ACTIVE};
70
+ if (m_state.compare_exchange_strong(expected, State::CANCELLED)) return true;
71
+ return expected == State::CANCELLED;
72
+ }
73
+ bool IsCancelled() const { return m_state.load() == State::CANCELLED; }
74
+ bool BeginBroadcast()
75
+ {
76
+ State expected{State::ACTIVE};
77
+ return m_state.compare_exchange_strong(expected, State::BROADCAST_STARTED);
78
+ }
79
+ bool BroadcastStarted() const { return m_state.load() == State::BROADCAST_STARTED; }
80
+
81
+ private:
82
+ enum class State : uint8_t { ACTIVE, CANCELLED, BROADCAST_STARTED };
83
+ std::atomic<State> m_state{State::ACTIVE};
84
+ };
85
+
86
  //! Result of a transient-private-key sweep. The supplied key is never retained
87
  //! by this interface or by the wallet.
88
  struct WalletSweepResult {
 
147
  virtual util::Result<WalletSweepResult> sweepPrivateKey(const SecureString& private_key,
148
  const CTxDestination& destination,
149
  bool broadcast,
150
+ const std::optional<Txid>& expected_txid,
151
+ const std::shared_ptr<SweepAuthorization>& authorization) = 0;
152
 
153
  //! Add or update address.
154
  virtual bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<wallet::AddressPurpose>& purpose) = 0;