v31.1-roots.1 · Commit 6: [PATCH 06/17] feat(wallet): preserve Roots signing and spend controls on v31
src/rpc/blockchain.cpp
Before: src/rpc/blockchain.cpp · After: src/rpc/blockchain.cpp
File metadata
index c631a93674aa296f74871ff7c3db3b1aa12ea741..c9fff1f49e43e26fa54047e13365e54f1fb5ed11 100644
Download original patch · Release notes
Diff rows 1–130 of 130. 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/rpc/blockchain.cpp
CHANGED
|
@@ -2194,7 +2194,7 @@ static RPCHelpMan getblockstats()
|
|
|
2194
2194
|
|
|
2195
2195
|
namespace {
|
|
2196
2196
|
//! Search for a given set of pubkey scripts
|
|
2197
|
-
bool FindScriptPubKey(std::atomic<int>& scan_progress, const std::atomic<bool>& should_abort, int64_t& count, CCoinsViewCursor* cursor, const std::set<CScript>& needles, std::map<COutPoint, Coin>& out_results, std::function<void()>& interruption_point)
|
|
2197
|
+
bool FindScriptPubKey(std::atomic<int>& scan_progress, const std::atomic<bool>& should_abort, int64_t& count, CCoinsViewCursor* cursor, const std::set<CScript>& needles, std::map<COutPoint, Coin>& out_results, std::function<void()>& interruption_point, const std::function<bool()>& local_should_abort = {})
|
|
2198
2198
|
{
|
|
2199
2199
|
scan_progress = 0;
|
|
2200
2200
|
count = 0;
|
|
@@ -2202,9 +2202,8 @@ bool FindScriptPubKey(std::atomic<int>& scan_progress, const std::atomic<bool>&
|
|
|
2202
2202
|
COutPoint key;
|
|
2203
2203
|
Coin coin;
|
|
2204
2204
|
if (!cursor->GetKey(key) || !cursor->GetValue(coin)) return false;
|
|
2205
|
-
if (++count % 8192 == 0) {
|
|
2206
|
-
interruption_point();
|
|
2207
|
-
if (should_abort) {
|
|
2205
|
+
if (rpc::scan::CheckInterruption(++count, interruption_point)) {
|
|
2206
|
+
if (should_abort || (local_should_abort && local_should_abort())) {
|
|
2208
2207
|
// allow to abort the scan via the abort reference
|
|
2209
2208
|
return false;
|
|
2210
2209
|
}
|
|
@@ -2225,33 +2224,42 @@ bool FindScriptPubKey(std::atomic<int>& scan_progress, const std::atomic<bool>&
|
|
|
2225
2224
|
} // namespace
|
|
2226
2225
|
|
|
2227
2226
|
/** RAII object to prevent concurrency issue when scanning the txout set */
|
|
2228
|
-
static std::atomic<int> g_scan_progress;
|
|
2229
|
-
static std::atomic<bool> g_scan_in_progress;
|
|
2230
|
-
static std::atomic<bool> g_should_abort_scan;
|
|
2231
|
-
class CoinsViewScanReserver
|
|
2232
|
-
{
|
|
2233
|
-
private:
|
|
2234
|
-
bool m_could_reserve{false};
|
|
2235
|
-
public:
|
|
2236
|
-
explicit CoinsViewScanReserver() = default;
|
|
2227
|
+
std::atomic<int> rpc::scan::g_progress;
|
|
2228
|
+
std::atomic<bool> rpc::scan::g_in_progress;
|
|
2229
|
+
std::atomic<bool> rpc::scan::g_should_abort;
|
|
2230
|
+
bool rpc::scan::Reserver::reserve() {
|
|
2231
|
+
CHECK_NONFATAL(!m_reserved);
|
|
2232
|
+
if (g_in_progress.exchange(true)) return false;
|
|
2233
|
+
CHECK_NONFATAL(g_progress == 0);
|
|
2234
|
+
m_reserved = true;
|
|
2235
|
+
return true;
|
|
2236
|
+
}
|
|
2237
|
+
rpc::scan::Reserver::~Reserver() { if (m_reserved) { g_progress = 0; g_in_progress = false; } }
|
|
2238
|
+
bool rpc::scan::CheckInterruption(int64_t count, const std::function<void()>& interruption) { if (count % 8192 != 0) return false; interruption(); return true; }
|
|
2239
|
+
using rpc::scan::Reserver;
|
|
2237
2240
|
|
|
2238
|
-
bool reserve() {
|
|
2239
|
-
CHECK_NONFATAL(!m_could_reserve);
|
|
2240
|
-
if (g_scan_in_progress.exchange(true)) {
|
|
2241
|
-
return false;
|
|
2242
|
-
}
|
|
2243
|
-
CHECK_NONFATAL(g_scan_progress == 0);
|
|
2244
|
-
m_could_reserve = true;
|
|
2245
|
-
return true;
|
|
2241
|
+
interfaces::ScanResult ScanUTXOSet(NodeContext& node, const std::set<CScript>& needles, std::map<COutPoint, Coin>& coins,
|
|
2242
|
+
const std::function<bool()>& should_abort)
|
|
2243
|
+
{
|
|
2244
|
+
Reserver reserver;
|
|
2245
|
+
if (!reserver.reserve()) return interfaces::ScanResult::BUSY;
|
|
2246
|
+
if (should_abort && should_abort()) return interfaces::ScanResult::ABORTED;
|
|
2247
|
+
std::unique_ptr<CCoinsViewCursor> cursor;
|
|
2248
|
+
{
|
|
2249
|
+
ChainstateManager& chainman = EnsureChainman(node);
|
|
2250
|
+
LOCK(cs_main);
|
|
2251
|
+
Chainstate& chainstate = chainman.ActiveChainstate();
|
|
2252
|
+
chainstate.ForceFlushStateToDisk(/*wipe_cache=*/false);
|
|
2253
|
+
cursor = CHECK_NONFATAL(chainstate.CoinsDB().Cursor());
|
|
2246
2254
|
}
|
|
2247
|
-
|
|
2248
|
-
~CoinsViewScanReserver() {
|
|
2249
|
-
if (m_could_reserve) {
|
|
2250
|
-
g_scan_in_progress = false;
|
|
2251
|
-
g_scan_progress = 0;
|
|
2252
|
-
}
|
|
2255
|
+
rpc::scan::g_should_abort = false;
|
|
2256
|
+
std::atomic<int> progress;
|
|
2257
|
+
int64_t count;
|
|
2258
|
+
if (FindScriptPubKey(progress, rpc::scan::g_should_abort, count, cursor.get(), needles, coins, node.rpc_interruption_point, should_abort)) {
|
|
2259
|
+
return interfaces::ScanResult::SUCCESS;
|
|
2253
2260
|
}
|
|
2254
|
-
};
|
|
2261
|
+
return rpc::scan::g_should_abort || (should_abort && should_abort()) ? interfaces::ScanResult::ABORTED : interfaces::ScanResult::UNAVAILABLE;
|
|
2262
|
+
}
|
|
2255
2263
|
|
|
2256
2264
|
static const auto scan_action_arg_desc = RPCArg{
|
|
2257
2265
|
"action", RPCArg::Type::STR, RPCArg::Optional::NO, "The action to execute\n"
|
|
@@ -2358,24 +2366,24 @@ static RPCHelpMan scantxoutset()
|
|
|
2358
2366
|
UniValue result(UniValue::VOBJ);
|
|
2359
2367
|
const auto action{self.Arg<std::string_view>("action")};
|
|
2360
2368
|
if (action == "status") {
|
|
2361
|
-
CoinsViewScanReserver reserver;
|
|
2369
|
+
Reserver reserver;
|
|
2362
2370
|
if (reserver.reserve()) {
|
|
2363
2371
|
// no scan in progress
|
|
2364
2372
|
return UniValue::VNULL;
|
|
2365
2373
|
}
|
|
2366
|
-
result.pushKV("progress", g_scan_progress.load());
|
|
2374
|
+
result.pushKV("progress", rpc::scan::g_progress.load());
|
|
2367
2375
|
return result;
|
|
2368
2376
|
} else if (action == "abort") {
|
|
2369
|
-
CoinsViewScanReserver reserver;
|
|
2377
|
+
Reserver reserver;
|
|
2370
2378
|
if (reserver.reserve()) {
|
|
2371
2379
|
// reserve was possible which means no scan was running
|
|
2372
2380
|
return false;
|
|
2373
2381
|
}
|
|
2374
2382
|
// set the abort flag
|
|
2375
|
-
g_should_abort_scan = true;
|
|
2383
|
+
rpc::scan::g_should_abort = true;
|
|
2376
2384
|
return true;
|
|
2377
2385
|
} else if (action == "start") {
|
|
2378
|
-
CoinsViewScanReserver reserver;
|
|
2386
|
+
Reserver reserver;
|
|
2379
2387
|
if (!reserver.reserve()) {
|
|
2380
2388
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
|
|
2381
2389
|
}
|
|
@@ -2403,7 +2411,7 @@ static RPCHelpMan scantxoutset()
|
|
|
2403
2411
|
UniValue unspents(UniValue::VARR);
|
|
2404
2412
|
std::vector<CTxOut> input_txos;
|
|
2405
2413
|
std::map<COutPoint, Coin> coins;
|
|
2406
|
-
g_should_abort_scan = false;
|
|
2414
|
+
rpc::scan::g_should_abort = false;
|
|
2407
2415
|
int64_t count = 0;
|
|
2408
2416
|
std::unique_ptr<CCoinsViewCursor> pcursor;
|
|
2409
2417
|
const CBlockIndex* tip;
|
|
@@ -2416,7 +2424,7 @@ static RPCHelpMan scantxoutset()
|
|
|
2416
2424
|
pcursor = CHECK_NONFATAL(active_chainstate.CoinsDB().Cursor());
|
|
2417
2425
|
tip = CHECK_NONFATAL(active_chainstate.m_chain.Tip());
|
|
2418
2426
|
}
|
|
2419
|
-
bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins, node.rpc_interruption_point);
|
|
2427
|
+
bool res = FindScriptPubKey(rpc::scan::g_progress, rpc::scan::g_should_abort, count, pcursor.get(), needles, coins, node.rpc_interruption_point);
|
|
2420
2428
|
result.pushKV("success", res);
|
|
2421
2429
|
result.pushKV("txouts", count);
|
|
2422
2430
|
result.pushKV("height", tip->nHeight);
|