Skip to content
Bitcoin Roots

v29.4-roots.4 · Commit 28: [PATCH 28/37] fix(wallet): secure asynchronous sweep cancellation

src/interfaces/wallet.h

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

File metadata
index 491aa530362aa8f43762af0446350e25623e6343..e47bb182dd3d333261e7131dbeb1e50337cec1b3 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. The two line-number columns refer to before and after.

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