From 9bb66ab66013fc3024fad00bceeb22a330b5bc1b Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Thu, 2 Mar 2017 15:24:50 -0500 Subject: Add RescanFromTime method and use from rpcdump No change in behavior. --- src/wallet/rpcdump.cpp | 26 +++++++++----------------- src/wallet/wallet.cpp | 32 ++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 3 +++ 3 files changed, 44 insertions(+), 17 deletions(-) (limited to 'src/wallet') diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 3efbeafe4f..9359887e0d 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -149,7 +149,7 @@ UniValue importprivkey(const JSONRPCRequest& request) pwallet->UpdateTimeFirstKey(1); if (fRescan) { - pwallet->ScanForWalletTransactions(chainActive.Genesis(), true); + pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */); } } @@ -279,7 +279,7 @@ UniValue importaddress(const JSONRPCRequest& request) if (fRescan) { - pwallet->ScanForWalletTransactions(chainActive.Genesis(), true); + pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */); pwallet->ReacceptWalletTransactions(); } @@ -437,7 +437,7 @@ UniValue importpubkey(const JSONRPCRequest& request) if (fRescan) { - pwallet->ScanForWalletTransactions(chainActive.Genesis(), true); + pwallet->RescanFromTime(TIMESTAMP_MIN, true /* update */); pwallet->ReacceptWalletTransactions(); } @@ -537,11 +537,7 @@ UniValue importwallet(const JSONRPCRequest& request) file.close(); pwallet->ShowProgress("", 100); // hide progress dialog in GUI pwallet->UpdateTimeFirstKey(nTimeBegin); - - CBlockIndex *pindex = chainActive.FindEarliestAtLeast(nTimeBegin - TIMESTAMP_WINDOW); - - LogPrintf("Rescanning last %i blocks\n", pindex ? chainActive.Height() - pindex->nHeight + 1 : 0); - pwallet->ScanForWalletTransactions(pindex); + pwallet->RescanFromTime(nTimeBegin - TIMESTAMP_WINDOW, false /* update */); pwallet->MarkDirty(); if (!fGood) @@ -1117,14 +1113,10 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) } if (fRescan && fRunScan && requests.size()) { - CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max(nLowestTimestamp - TIMESTAMP_WINDOW, 0)) : chainActive.Genesis(); - CBlockIndex* scanFailed = nullptr; - if (pindex) { - scanFailed = pwallet->ScanForWalletTransactions(pindex, true); - pwallet->ReacceptWalletTransactions(); - } + int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp - TIMESTAMP_WINDOW, true /* update */); + pwallet->ReacceptWalletTransactions(); - if (scanFailed) { + if (scannedTime > nLowestTimestamp - TIMESTAMP_WINDOW) { std::vector results = response.getValues(); response.clear(); response.setArray(); @@ -1134,7 +1126,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) // range, or if the import result already has an error set, let // the result stand unmodified. Otherwise replace the result // with an error message. - if (GetImportTimestamp(request, now) - TIMESTAMP_WINDOW > scanFailed->GetBlockTimeMax() || results.at(i).exists("error")) { + if (scannedTime <= GetImportTimestamp(request, now) - TIMESTAMP_WINDOW || results.at(i).exists("error")) { response.push_back(results.at(i)); } else { UniValue result = UniValue(UniValue::VOBJ); @@ -1150,7 +1142,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) "caused by pruning or data corruption (see bitcoind log for details) and could " "be dealt with by downloading and rescanning the relevant blocks (see -reindex " "and -rescan options).", - GetImportTimestamp(request, now), scanFailed->GetBlockTimeMax(), TIMESTAMP_WINDOW))); + GetImportTimestamp(request, now), scannedTime - 1, TIMESTAMP_WINDOW))); response.push_back(std::move(result)); } ++i; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 880a6a8bd7..06f8fc0458 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -221,6 +221,10 @@ bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector& listReceived, } +/** + * Scan active chain for relevant transactions after importing keys. This should + * be called whenever new keys are added to the wallet, with the oldest key + * creation time minus TIMESTAMP_WINDOW. + * + * @return Earliest timestamp that could be successfully scanned from. Timestamp + * returned may be higher than startTime if some blocks could not be read. + */ +int64_t CWallet::RescanFromTime(int64_t startTime, bool update) +{ + AssertLockHeld(cs_main); + AssertLockHeld(cs_wallet); + + // Find starting block. May be null if nCreateTime is greater than the + // highest blockchain timestamp, in which case there is nothing that needs + // to be scanned. + CBlockIndex* const startBlock = chainActive.FindEarliestAtLeast(startTime); + LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0); + + if (startBlock) { + const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, update); + if (failedBlock) { + return failedBlock->GetBlockTimeMax() + 1; + } + } + return startTime; +} + /** * Scan the block chain (starting in pindexStart) for transactions * from or to us. If fUpdate is true, found transactions that already diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a3974bf00b..b6459f765c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -67,6 +67,8 @@ static const bool DEFAULT_USE_HD_WALLET = true; extern const char * DEFAULT_WALLET_DAT; +static const int64_t TIMESTAMP_MIN = 0; + class CBlockIndex; class CCoinControl; class COutput; @@ -918,6 +920,7 @@ public: void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) override; void BlockDisconnected(const std::shared_ptr& pblock) override; bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); + int64_t RescanFromTime(int64_t startTime, bool update); CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override; -- cgit v1.2.3