Skip to content

Commit dbf8556

Browse files
committed
Add RAII wallet rescan reserver
1 parent 8d0b610 commit dbf8556

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

src/wallet/rpcdump.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ UniValue importaddress(const JSONRPCRequest& request)
262262
if (fRescan && fPruneMode)
263263
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
264264

265+
WalletRescanReserver reserver(pwallet);
266+
if (fRescan && !reserver.reserve()) {
267+
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
268+
}
269+
265270
// Whether to import a p2sh version, too
266271
bool fP2SH = false;
267272
if (!request.params[3].isNull())
@@ -429,6 +434,11 @@ UniValue importpubkey(const JSONRPCRequest& request)
429434
if (fRescan && fPruneMode)
430435
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
431436

437+
WalletRescanReserver reserver(pwallet);
438+
if (fRescan && !reserver.reserve()) {
439+
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
440+
}
441+
432442
if (!IsHex(request.params[0].get_str()))
433443
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
434444
std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
@@ -480,6 +490,11 @@ UniValue importwallet(const JSONRPCRequest& request)
480490
if (fPruneMode)
481491
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
482492

493+
WalletRescanReserver reserver(pwallet);
494+
if (!reserver.reserve()) {
495+
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
496+
}
497+
483498
int64_t nTimeBegin = 0;
484499
bool fGood = true;
485500
{
@@ -1138,6 +1153,11 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
11381153
}
11391154
}
11401155

1156+
WalletRescanReserver reserver(pwallet);
1157+
if (fRescan && !reserver.reserve()) {
1158+
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
1159+
}
1160+
11411161
int64_t now = 0;
11421162
bool fRunScan = false;
11431163
int64_t nLowestTimestamp = 0;

src/wallet/rpcwallet.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3398,7 +3398,8 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
33983398
);
33993399
}
34003400

3401-
if (pwallet->IsScanning()) {
3401+
WalletRescanReserver reserver(pwallet);
3402+
if (!reserver.reserve()) {
34023403
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
34033404
}
34043405

src/wallet/wallet.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
669669
static std::atomic<bool> fFlushScheduled;
670670
std::atomic<bool> fAbortRescan;
671671
std::atomic<bool> fScanningWallet;
672+
std::mutex mutexScanning;
673+
friend class WalletRescanReserver;
674+
672675

673676
/**
674677
* Select a set of coins such that nValueRet >= nTargetValue and at least
@@ -1263,4 +1266,34 @@ CTxDestination GetDestinationForKey(const CPubKey& key, OutputType);
12631266
/** Get all destinations (potentially) supported by the wallet for the given key. */
12641267
std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key);
12651268

1269+
/** RAII object to check and reserve a wallet rescan */
1270+
class WalletRescanReserver
1271+
{
1272+
private:
1273+
CWalletRef m_wallet;
1274+
bool m_could_reserve;
1275+
public:
1276+
explicit WalletRescanReserver(CWalletRef w) : m_wallet(w), m_could_reserve(false) {}
1277+
1278+
bool reserve()
1279+
{
1280+
assert(!m_could_reserve);
1281+
std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
1282+
if (m_wallet->fScanningWallet) {
1283+
return false;
1284+
}
1285+
m_wallet->fScanningWallet = true;
1286+
m_could_reserve = true;
1287+
return true;
1288+
}
1289+
1290+
~WalletRescanReserver()
1291+
{
1292+
std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
1293+
if (m_could_reserve) {
1294+
m_wallet->fScanningWallet = false;
1295+
}
1296+
}
1297+
};
1298+
12661299
#endif // BITCOIN_WALLET_WALLET_H

0 commit comments

Comments
 (0)