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;
|