Skip to content
Bitcoin Roots

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

src/wallet/spend.cpp

Before: src/wallet/spend.cpp · After: src/wallet/spend.cpp

File metadata
index 086673b5b21323eaecee546b588b696803eb57c4..587575b2d2c582aef54b8a865918fe32995bdc5d 100644

Download original patch · Release notes

Diff rows 1–30 of 30. 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/wallet/spend.cpp CHANGED
@@ -9,6 +9,7 @@
9
  #include <consensus/amount.h>
10
  #include <consensus/validation.h>
11
  #include <interfaces/chain.h>
 
12
  #include <node/types.h>
13
  #include <numeric>
14
  #include <policy/policy.h>
@@ -46,8 +47,10 @@ TRACEPOINT_SEMAPHORE(coin_selection, aps_create_tx_internal);
46
  namespace wallet {
47
  util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, FlatSigningProvider& provider,
48
  const std::map<COutPoint, Coin>& coins,
49
- const CScript& destination, const SweepBroadcastFn& broadcast)
 
50
  {
 
51
  CAmount amount{0};
52
  CMutableTransaction tx;
53
  for (const auto& [outpoint, coin] : coins) {
@@ -71,8 +74,12 @@ util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, Fla
71
  return util::Error{Untranslated("Unable to calculate a stable sweep fee")};
72
  }
73
  if (IsDust(tx.vout[0], wallet.chain().relayMinFee())) return util::Error{Untranslated("Swept output would be dust")};
 
74
  CTransactionRef final_tx{MakeTransactionRef(tx)};
75
  if (broadcast) {
 
 
 
76
  std::string error;
77
  if (!broadcast(final_tx, error)) return util::Error{Untranslated("Sweep transaction broadcast failed: " + error)};
78
  }
 
9
  #include <consensus/amount.h>
10
  #include <consensus/validation.h>
11
  #include <interfaces/chain.h>
12
+ #include <interfaces/wallet.h>
13
  #include <node/types.h>
14
  #include <numeric>
15
  #include <policy/policy.h>
 
47
  namespace wallet {
48
  util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, FlatSigningProvider& provider,
49
  const std::map<COutPoint, Coin>& coins,
50
+ const CScript& destination, const SweepBroadcastFn& broadcast,
51
+ interfaces::SweepAuthorization& authorization)
52
  {
53
+ if (authorization.IsCancelled()) return util::Error{Untranslated("Sweep cancelled")};
54
  CAmount amount{0};
55
  CMutableTransaction tx;
56
  for (const auto& [outpoint, coin] : coins) {
 
74
  return util::Error{Untranslated("Unable to calculate a stable sweep fee")};
75
  }
76
  if (IsDust(tx.vout[0], wallet.chain().relayMinFee())) return util::Error{Untranslated("Swept output would be dust")};
77
+ if (authorization.IsCancelled()) return util::Error{Untranslated("Sweep cancelled")};
78
  CTransactionRef final_tx{MakeTransactionRef(tx)};
79
  if (broadcast) {
80
+ // This is the last safe cancellation point. BeginBroadcast and Cancel
81
+ // use one atomic state transition, so only one of them can succeed.
82
+ if (!authorization.BeginBroadcast()) return util::Error{Untranslated("Sweep cancelled")};
83
  std::string error;
84
  if (!broadcast(final_tx, error)) return util::Error{Untranslated("Sweep transaction broadcast failed: " + error)};
85
  }