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. The two line-number columns refer to before and after.

src/interfaces/wallet.h CHANGED
@@ -18,6 +18,7 @@
18
18
  #include <util/result.h>
19
19
  #include <util/ui_change_type.h>
20
20
 
21
+ #include <atomic>
21
22
  #include <cstdint>
22
23
  #include <functional>
23
24
  #include <map>
@@ -57,6 +58,31 @@ struct WalletTxOut;
57
58
  struct WalletTxStatus;
58
59
  struct WalletMigrationResult;
59
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
+
60
86
  //! Result of a transient-private-key sweep. The supplied key is never retained
61
87
  //! by this interface or by the wallet.
62
88
  struct WalletSweepResult {
@@ -121,7 +147,8 @@ public:
121
147
  virtual util::Result<WalletSweepResult> sweepPrivateKey(const SecureString& private_key,
122
148
  const CTxDestination& destination,
123
149
  bool broadcast,
124
- const std::optional<Txid>& expected_txid = std::nullopt) = 0;
150
+ const std::optional<Txid>& expected_txid,
151
+ const std::shared_ptr<SweepAuthorization>& authorization) = 0;
125
152
 
126
153
  //! Add or update address.
127
154
  virtual bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<wallet::AddressPurpose>& purpose) = 0;