diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -131,12 +131,13 @@ WalletRescanReserver reserver(wallet.get()); reserver.reserve(); const CBlockIndex *const null_block = nullptr; - const CBlockIndex *stop_block; + const CBlockIndex *stop_block, *failed_block; QCOMPARE(wallet->ScanForWalletTransactions( - ::ChainActive().Genesis(), nullptr, reserver, stop_block, - true /* fUpdate */), + ::ChainActive().Genesis(), nullptr, reserver, failed_block, + stop_block, true /* fUpdate */), CWallet::ScanResult::SUCCESS); - QCOMPARE(stop_block, null_block); + QCOMPARE(stop_block, ::ChainActive().Tip()); + QCOMPARE(failed_block, null_block); } wallet->SetBroadcastTransactions(true); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4092,12 +4092,12 @@ } } - const CBlockIndex *stopBlock; + const CBlockIndex *failed_block, *stopBlock; CWallet::ScanResult result = pwallet->ScanForWalletTransactions( - pindexStart, pindexStop, reserver, stopBlock, true); + pindexStart, pindexStop, reserver, failed_block, stopBlock, true); switch (result) { case CWallet::ScanResult::SUCCESS: - stopBlock = pindexStop ? pindexStop : pChainTip; + // stopBlock set by ScanForWalletTransactions break; case CWallet::ScanResult::FAILURE: throw JSONRPCError( diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -54,11 +54,13 @@ AddKey(wallet, coinbaseKey); WalletRescanReserver reserver(&wallet); reserver.reserve(); - const CBlockIndex *stop_block; - BOOST_CHECK_EQUAL(wallet.ScanForWalletTransactions( - oldTip, nullptr, reserver, stop_block), - CWallet::ScanResult::SUCCESS); - BOOST_CHECK_EQUAL(stop_block, null_block); + const CBlockIndex *stop_block, *failed_block; + BOOST_CHECK_EQUAL( + wallet.ScanForWalletTransactions(oldTip, nullptr, reserver, + failed_block, stop_block), + CWallet::ScanResult::SUCCESS); + BOOST_CHECK_EQUAL(failed_block, null_block); + BOOST_CHECK_EQUAL(stop_block, newTip); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN); } @@ -74,11 +76,13 @@ AddKey(wallet, coinbaseKey); WalletRescanReserver reserver(&wallet); reserver.reserve(); - const CBlockIndex *stop_block; - BOOST_CHECK_EQUAL(wallet.ScanForWalletTransactions( - oldTip, nullptr, reserver, stop_block), - CWallet::ScanResult::FAILURE); - BOOST_CHECK_EQUAL(oldTip, stop_block); + const CBlockIndex *stop_block, *failed_block; + BOOST_CHECK_EQUAL( + wallet.ScanForWalletTransactions(oldTip, nullptr, reserver, + failed_block, stop_block), + CWallet::ScanResult::FAILURE); + BOOST_CHECK_EQUAL(failed_block, oldTip); + BOOST_CHECK_EQUAL(stop_block, newTip); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN); } @@ -317,12 +321,13 @@ WalletRescanReserver reserver(wallet.get()); reserver.reserve(); const CBlockIndex *const null_block = nullptr; - const CBlockIndex *stop_block; - BOOST_CHECK_EQUAL( - wallet->ScanForWalletTransactions(ChainActive().Genesis(), nullptr, - reserver, stop_block), - CWallet::ScanResult::SUCCESS); - BOOST_CHECK_EQUAL(stop_block, null_block); + const CBlockIndex *stop_block, *failed_block; + BOOST_CHECK_EQUAL(wallet->ScanForWalletTransactions( + ChainActive().Genesis(), nullptr, reserver, + failed_block, stop_block), + CWallet::ScanResult::SUCCESS); + BOOST_CHECK_EQUAL(stop_block, ChainActive().Tip()); + BOOST_CHECK_EQUAL(failed_block, null_block); } ~ListCoinsTestingSetup() { wallet.reset(); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1068,6 +1068,7 @@ const CBlockIndex *const pindexStop, const WalletRescanReserver &reserver, const CBlockIndex *&failed_block, + const CBlockIndex *&stop_block, bool fUpdate = false); void TransactionRemovedFromMempool(const CTransactionRef &ptx) override; void ReacceptWalletTransactions(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1802,11 +1802,11 @@ } if (startBlock) { - const CBlockIndex *failedBlock; + const CBlockIndex *failedBlock, *stop_block; // TODO: this should take into account failure by ScanResult::USER_ABORT if (ScanResult::FAILURE == ScanForWalletTransactions(startBlock, nullptr, reserver, - failedBlock, update)) { + failedBlock, stop_block, update)) { return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1; } } @@ -1820,8 +1820,10 @@ * * @param[in] pindexStop if not a nullptr, the scan will stop at this * block-index - * @param[out] failed_block if FAILURE is returned, will be set to the most - * recent block that could not be scanned, otherwise nullptr. + * @param[out] failed_block if FAILURE is returned, the most recent block + * that could not be scanned, otherwise nullptr + * @param[out] stop_block the most recent block that could be scanned, + * otherwise nullptr if no block could be scanned * * @return ScanResult indicating success or failure of the scan. SUCCESS if * scan was successful. FAILURE if a complete rescan was not possible (due to @@ -1835,7 +1837,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions( const CBlockIndex *const pindexStart, const CBlockIndex *const pindexStop, const WalletRescanReserver &reserver, const CBlockIndex *&failed_block, - bool fUpdate) { + const CBlockIndex *&stop_block, bool fUpdate) { int64_t nNow = GetTime(); assert(reserver.isReserved()); @@ -1907,7 +1909,12 @@ SyncTransaction(block.vtx[posInBlock], pindex, posInBlock, fUpdate); } + // scan succeeded, record block as most recent successfully + // scanned + stop_block = pindex; } else { + // could not scan block, keep scanning but record this block as + // the most recent failure failed_block = pindex; } if (pindex == pindexStop) { @@ -4722,11 +4729,12 @@ nStart = GetTimeMillis(); { WalletRescanReserver reserver(walletInstance.get()); - const CBlockIndex *stop_block; + const CBlockIndex *stop_block, *failed_block; if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions( - pindexRescan, nullptr, reserver, stop_block, true))) { + pindexRescan, nullptr, reserver, failed_block, stop_block, + true))) { InitError( _("Failed to rescan the wallet during initialization")); return nullptr;