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. The two line-number columns refer to before and after.
src/wallet/spend.cpp
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#include <consensus/amount.h>
|
|
10
10
|
#include <consensus/validation.h>
|
|
11
11
|
#include <interfaces/chain.h>
|
|
12
|
+
#include <interfaces/wallet.h>
|
|
12
13
|
#include <node/types.h>
|
|
13
14
|
#include <numeric>
|
|
14
15
|
#include <policy/policy.h>
|
|
@@ -46,8 +47,10 @@ TRACEPOINT_SEMAPHORE(coin_selection, aps_create_tx_internal);
|
|
|
46
47
|
namespace wallet {
|
|
47
48
|
util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, FlatSigningProvider& provider,
|
|
48
49
|
const std::map<COutPoint, Coin>& coins,
|
|
49
|
-
const CScript& destination, const SweepBroadcastFn& broadcast)
|
|
50
|
+
const CScript& destination, const SweepBroadcastFn& broadcast,
|
|
51
|
+
interfaces::SweepAuthorization& authorization)
|
|
50
52
|
{
|
|
53
|
+
if (authorization.IsCancelled()) return util::Error{Untranslated("Sweep cancelled")};
|
|
51
54
|
CAmount amount{0};
|
|
52
55
|
CMutableTransaction tx;
|
|
53
56
|
for (const auto& [outpoint, coin] : coins) {
|
|
@@ -71,8 +74,12 @@ util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, Fla
|
|
|
71
74
|
return util::Error{Untranslated("Unable to calculate a stable sweep fee")};
|
|
72
75
|
}
|
|
73
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")};
|
|
74
78
|
CTransactionRef final_tx{MakeTransactionRef(tx)};
|
|
75
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")};
|
|
76
83
|
std::string error;
|
|
77
84
|
if (!broadcast(final_tx, error)) return util::Error{Untranslated("Sweep transaction broadcast failed: " + error)};
|
|
78
85
|
}
|