Skip to content

Commit

Permalink
Add RAII wallet rescan reserver
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasschnelli committed Jan 24, 2018
1 parent 8d0b610 commit dbf8556
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
20 changes: 20 additions & 0 deletions src/wallet/rpcdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,11 @@ UniValue importaddress(const JSONRPCRequest& request)
if (fRescan && fPruneMode)
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");

WalletRescanReserver reserver(pwallet);
if (fRescan && !reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}

// Whether to import a p2sh version, too
bool fP2SH = false;
if (!request.params[3].isNull())
Expand Down Expand Up @@ -429,6 +434,11 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (fRescan && fPruneMode)
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");

WalletRescanReserver reserver(pwallet);
if (fRescan && !reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}

if (!IsHex(request.params[0].get_str()))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
Expand Down Expand Up @@ -480,6 +490,11 @@ UniValue importwallet(const JSONRPCRequest& request)
if (fPruneMode)
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");

WalletRescanReserver reserver(pwallet);
if (!reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}

int64_t nTimeBegin = 0;
bool fGood = true;
{
Expand Down Expand Up @@ -1138,6 +1153,11 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
}
}

WalletRescanReserver reserver(pwallet);
if (fRescan && !reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}

int64_t now = 0;
bool fRunScan = false;
int64_t nLowestTimestamp = 0;
Expand Down
3 changes: 2 additions & 1 deletion src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3398,7 +3398,8 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
);
}

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

Expand Down
33 changes: 33 additions & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
static std::atomic<bool> fFlushScheduled;
std::atomic<bool> fAbortRescan;
std::atomic<bool> fScanningWallet;
std::mutex mutexScanning;
friend class WalletRescanReserver;


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

/** RAII object to check and reserve a wallet rescan */
class WalletRescanReserver
{
private:
CWalletRef m_wallet;
bool m_could_reserve;
public:
explicit WalletRescanReserver(CWalletRef w) : m_wallet(w), m_could_reserve(false) {}

bool reserve()
{
assert(!m_could_reserve);
std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
if (m_wallet->fScanningWallet) {
return false;
}
m_wallet->fScanningWallet = true;
m_could_reserve = true;
return true;
}

~WalletRescanReserver()
{
std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
if (m_could_reserve) {
m_wallet->fScanningWallet = false;
}
}
};

#endif // BITCOIN_WALLET_WALLET_H

0 comments on commit dbf8556

Please sign in to comment.