Make sure WalletRescanReserver has successfully reserved the rescan
This commit is contained in:
parent
dbf8556b4d
commit
bc356b4268
6 changed files with 44 additions and 21 deletions
|
@ -169,7 +169,9 @@ void TestGUI()
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
wallet.ScanForWalletTransactions(chainActive.Genesis(), nullptr, true);
|
WalletRescanReserver reserver(&wallet);
|
||||||
|
reserver.reserve();
|
||||||
|
wallet.ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver, true);
|
||||||
}
|
}
|
||||||
wallet.SetBroadcastTransactions(true);
|
wallet.SetBroadcastTransactions(true);
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
WalletRescanReserver reserver(pwallet);
|
||||||
bool fRescan = true;
|
bool fRescan = true;
|
||||||
{
|
{
|
||||||
LOCK2(cs_main, pwallet->cs_wallet);
|
LOCK2(cs_main, pwallet->cs_wallet);
|
||||||
|
@ -119,6 +120,10 @@ UniValue importprivkey(const JSONRPCRequest& request)
|
||||||
if (fRescan && fPruneMode)
|
if (fRescan && fPruneMode)
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
|
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
|
||||||
|
|
||||||
|
if (fRescan && !reserver.reserve()) {
|
||||||
|
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
|
||||||
|
}
|
||||||
|
|
||||||
CBitcoinSecret vchSecret;
|
CBitcoinSecret vchSecret;
|
||||||
bool fGood = vchSecret.SetString(strSecret);
|
bool fGood = vchSecret.SetString(strSecret);
|
||||||
|
|
||||||
|
@ -153,7 +158,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fRescan) {
|
if (fRescan) {
|
||||||
pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */);
|
pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
@ -290,7 +295,7 @@ UniValue importaddress(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
if (fRescan)
|
if (fRescan)
|
||||||
{
|
{
|
||||||
pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */);
|
pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
|
||||||
pwallet->ReacceptWalletTransactions();
|
pwallet->ReacceptWalletTransactions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +462,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
if (fRescan)
|
if (fRescan)
|
||||||
{
|
{
|
||||||
pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */);
|
pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
|
||||||
pwallet->ReacceptWalletTransactions();
|
pwallet->ReacceptWalletTransactions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +586,7 @@ UniValue importwallet(const JSONRPCRequest& request)
|
||||||
pwallet->ShowProgress("", 100); // hide progress dialog in GUI
|
pwallet->ShowProgress("", 100); // hide progress dialog in GUI
|
||||||
pwallet->UpdateTimeFirstKey(nTimeBegin);
|
pwallet->UpdateTimeFirstKey(nTimeBegin);
|
||||||
}
|
}
|
||||||
pwallet->RescanFromTime(nTimeBegin, false /* update */);
|
pwallet->RescanFromTime(nTimeBegin, reserver, false /* update */);
|
||||||
pwallet->MarkDirty();
|
pwallet->MarkDirty();
|
||||||
|
|
||||||
if (!fGood)
|
if (!fGood)
|
||||||
|
@ -1201,7 +1206,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fRescan && fRunScan && requests.size()) {
|
if (fRescan && fRunScan && requests.size()) {
|
||||||
int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, true /* update */);
|
int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */);
|
||||||
pwallet->ReacceptWalletTransactions();
|
pwallet->ReacceptWalletTransactions();
|
||||||
|
|
||||||
if (scannedTime > nLowestTimestamp) {
|
if (scannedTime > nLowestTimestamp) {
|
||||||
|
|
|
@ -3441,7 +3441,7 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions(pindexStart, pindexStop, true);
|
CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions(pindexStart, pindexStop, reserver, true);
|
||||||
if (!stopBlock) {
|
if (!stopBlock) {
|
||||||
if (pwallet->IsAbortingRescan()) {
|
if (pwallet->IsAbortingRescan()) {
|
||||||
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
|
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
|
||||||
|
|
|
@ -384,7 +384,9 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
||||||
{
|
{
|
||||||
CWallet wallet;
|
CWallet wallet;
|
||||||
AddKey(wallet, coinbaseKey);
|
AddKey(wallet, coinbaseKey);
|
||||||
BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip, nullptr));
|
WalletRescanReserver reserver(&wallet);
|
||||||
|
reserver.reserve();
|
||||||
|
BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip, nullptr, reserver));
|
||||||
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN);
|
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +399,9 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
||||||
{
|
{
|
||||||
CWallet wallet;
|
CWallet wallet;
|
||||||
AddKey(wallet, coinbaseKey);
|
AddKey(wallet, coinbaseKey);
|
||||||
BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip, nullptr));
|
WalletRescanReserver reserver(&wallet);
|
||||||
|
reserver.reserve();
|
||||||
|
BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip, nullptr, reserver));
|
||||||
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN);
|
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +612,9 @@ public:
|
||||||
bool firstRun;
|
bool firstRun;
|
||||||
wallet->LoadWallet(firstRun);
|
wallet->LoadWallet(firstRun);
|
||||||
AddKey(*wallet, coinbaseKey);
|
AddKey(*wallet, coinbaseKey);
|
||||||
wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr);
|
WalletRescanReserver reserver(wallet.get());
|
||||||
|
reserver.reserve();
|
||||||
|
wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ListCoinsTestingSetup()
|
~ListCoinsTestingSetup()
|
||||||
|
|
|
@ -1612,7 +1612,7 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
|
||||||
* @return Earliest timestamp that could be successfully scanned from. Timestamp
|
* @return Earliest timestamp that could be successfully scanned from. Timestamp
|
||||||
* returned will be higher than startTime if relevant blocks could not be read.
|
* returned will be higher than startTime if relevant blocks could not be read.
|
||||||
*/
|
*/
|
||||||
int64_t CWallet::RescanFromTime(int64_t startTime, bool update)
|
int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
|
||||||
{
|
{
|
||||||
// Find starting block. May be null if nCreateTime is greater than the
|
// Find starting block. May be null if nCreateTime is greater than the
|
||||||
// highest blockchain timestamp, in which case there is nothing that needs
|
// highest blockchain timestamp, in which case there is nothing that needs
|
||||||
|
@ -1625,7 +1625,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, bool update)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startBlock) {
|
if (startBlock) {
|
||||||
const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, nullptr, update);
|
const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, nullptr, reserver, update);
|
||||||
if (failedBlock) {
|
if (failedBlock) {
|
||||||
return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1;
|
return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1;
|
||||||
}
|
}
|
||||||
|
@ -1649,11 +1649,12 @@ int64_t CWallet::RescanFromTime(int64_t startTime, bool update)
|
||||||
* the main chain after to the addition of any new keys you want to detect
|
* the main chain after to the addition of any new keys you want to detect
|
||||||
* transactions for.
|
* transactions for.
|
||||||
*/
|
*/
|
||||||
CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, bool fUpdate)
|
CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver &reserver, bool fUpdate)
|
||||||
{
|
{
|
||||||
int64_t nNow = GetTime();
|
int64_t nNow = GetTime();
|
||||||
const CChainParams& chainParams = Params();
|
const CChainParams& chainParams = Params();
|
||||||
|
|
||||||
|
assert(reserver.isReserved());
|
||||||
if (pindexStop) {
|
if (pindexStop) {
|
||||||
assert(pindexStop->nHeight >= pindexStart->nHeight);
|
assert(pindexStop->nHeight >= pindexStart->nHeight);
|
||||||
}
|
}
|
||||||
|
@ -1662,8 +1663,6 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
|
||||||
CBlockIndex* ret = nullptr;
|
CBlockIndex* ret = nullptr;
|
||||||
{
|
{
|
||||||
fAbortRescan = false;
|
fAbortRescan = false;
|
||||||
fScanningWallet = true;
|
|
||||||
|
|
||||||
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
|
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
|
||||||
CBlockIndex* tip = nullptr;
|
CBlockIndex* tip = nullptr;
|
||||||
double dProgressStart;
|
double dProgressStart;
|
||||||
|
@ -1727,8 +1726,6 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
|
||||||
LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex));
|
LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex));
|
||||||
}
|
}
|
||||||
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
|
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
|
||||||
|
|
||||||
fScanningWallet = false;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -4039,7 +4036,14 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
nStart = GetTimeMillis();
|
nStart = GetTimeMillis();
|
||||||
walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, true);
|
{
|
||||||
|
WalletRescanReserver reserver(walletInstance);
|
||||||
|
if (!reserver.reserve()) {
|
||||||
|
InitError(_("Failed to rescan the wallet during initialization"));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true);
|
||||||
|
}
|
||||||
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
||||||
walletInstance->SetBestChain(chainActive.GetLocator());
|
walletInstance->SetBestChain(chainActive.GetLocator());
|
||||||
walletInstance->dbw->IncrementUpdateCounter();
|
walletInstance->dbw->IncrementUpdateCounter();
|
||||||
|
|
|
@ -659,6 +659,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WalletRescanReserver; //forward declarations for ScanForWalletTransactions/RescanFromTime
|
||||||
/**
|
/**
|
||||||
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
|
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
|
||||||
* and provides the ability to create new transactions.
|
* and provides the ability to create new transactions.
|
||||||
|
@ -668,7 +669,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
|
||||||
private:
|
private:
|
||||||
static std::atomic<bool> fFlushScheduled;
|
static std::atomic<bool> fFlushScheduled;
|
||||||
std::atomic<bool> fAbortRescan;
|
std::atomic<bool> fAbortRescan;
|
||||||
std::atomic<bool> fScanningWallet;
|
std::atomic<bool> fScanningWallet; //controlled by WalletRescanReserver
|
||||||
std::mutex mutexScanning;
|
std::mutex mutexScanning;
|
||||||
friend class WalletRescanReserver;
|
friend class WalletRescanReserver;
|
||||||
|
|
||||||
|
@ -948,8 +949,8 @@ public:
|
||||||
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
|
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
|
||||||
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
|
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
|
||||||
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate);
|
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate);
|
||||||
int64_t RescanFromTime(int64_t startTime, bool update);
|
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
|
||||||
CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, bool fUpdate = false);
|
CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver& reserver, bool fUpdate = false);
|
||||||
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
|
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
|
||||||
void ReacceptWalletTransactions();
|
void ReacceptWalletTransactions();
|
||||||
void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override;
|
void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override;
|
||||||
|
@ -1287,6 +1288,11 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isReserved() const
|
||||||
|
{
|
||||||
|
return (m_could_reserve && m_wallet->fScanningWallet);
|
||||||
|
}
|
||||||
|
|
||||||
~WalletRescanReserver()
|
~WalletRescanReserver()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
|
std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
|
||||||
|
|
Loading…
Add table
Reference in a new issue