@@ -1598,7 +1598,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
15981598
15991599 if (start) {
16001600 // TODO: this should take into account failure by ScanResult::USER_ABORT
1601- ScanResult result = ScanForWalletTransactions (start_block, {} /* stop_block */ , reserver, update);
1601+ ScanResult result = ScanForWalletTransactions (start_block, start_height, {} /* max_height */ , reserver, update);
16021602 if (result.status == ScanResult::FAILURE) {
16031603 int64_t time_max;
16041604 CHECK_NONFATAL (chain ().findBlock (result.last_failed_block , FoundBlock ().maxTime (time_max)));
@@ -1615,6 +1615,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
16151615 *
16161616 * @param[in] start_block Scan starting block. If block is not on the active
16171617 * chain, the scan will return SUCCESS immediately.
1618+ * @param[in] start_height Height of start_block
16181619 * @param[in] max_height Optional max scanning height. If unset there is
16191620 * no maximum and scanning can continue to the tip
16201621 *
@@ -1628,7 +1629,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
16281629 * the main chain after to the addition of any new keys you want to detect
16291630 * transactions for.
16301631 */
1631- CWallet::ScanResult CWallet::ScanForWalletTransactions (const uint256& start_block, Optional<int > max_height, const WalletRescanReserver& reserver, bool fUpdate )
1632+ CWallet::ScanResult CWallet::ScanForWalletTransactions (const uint256& start_block, int start_height, Optional<int > max_height, const WalletRescanReserver& reserver, bool fUpdate )
16321633{
16331634 int64_t nNow = GetTime ();
16341635 int64_t start_time = GetTimeMillis ();
@@ -1642,38 +1643,32 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
16421643
16431644 fAbortRescan = false ;
16441645 ShowProgress (strprintf (" %s " + _ (" Rescanning..." ).translated , GetDisplayName ()), 0 ); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
1645- uint256 tip_hash;
1646- // The way the 'block_height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
1647- Optional<int > block_height = MakeOptional (false , int ());
1648- double progress_begin;
1649- double progress_end;
1650- {
1651- auto locked_chain = chain ().lock ();
1652- if (Optional<int > tip_height = locked_chain->getHeight ()) {
1653- tip_hash = locked_chain->getBlockHash (*tip_height);
1654- }
1655- block_height = locked_chain->getBlockHeight (block_hash);
1656- uint256 end_hash = tip_hash;
1657- if (max_height) chain ().findAncestorByHeight (tip_hash, *max_height, FoundBlock ().hash (end_hash));
1658- progress_begin = chain ().guessVerificationProgress (block_hash);
1659- progress_end = chain ().guessVerificationProgress (end_hash);
1660- }
1646+ uint256 tip_hash = WITH_LOCK (cs_wallet, return GetLastBlockHash ());
1647+ uint256 end_hash = tip_hash;
1648+ if (max_height) chain ().findAncestorByHeight (tip_hash, *max_height, FoundBlock ().hash (end_hash));
1649+ double progress_begin = chain ().guessVerificationProgress (block_hash);
1650+ double progress_end = chain ().guessVerificationProgress (end_hash);
16611651 double progress_current = progress_begin;
1662- while (block_height && !fAbortRescan && !chain ().shutdownRequested ()) {
1652+ int block_height = start_height;
1653+ while (!fAbortRescan && !chain ().shutdownRequested ()) {
16631654 m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
1664- if (* block_height % 100 == 0 && progress_end - progress_begin > 0.0 ) {
1655+ if (block_height % 100 == 0 && progress_end - progress_begin > 0.0 ) {
16651656 ShowProgress (strprintf (" %s " + _ (" Rescanning..." ).translated , GetDisplayName ()), std::max (1 , std::min (99 , (int )(m_scanning_progress * 100 ))));
16661657 }
16671658 if (GetTime () >= nNow + 60 ) {
16681659 nNow = GetTime ();
1669- WalletLogPrintf (" Still rescanning. At block %d. Progress=%f\n " , * block_height, progress_current);
1660+ WalletLogPrintf (" Still rescanning. At block %d. Progress=%f\n " , block_height, progress_current);
16701661 }
16711662
16721663 CBlock block;
1664+ bool next_block;
1665+ uint256 next_block_hash;
1666+ bool reorg = false ;
16731667 if (chain ().findBlock (block_hash, FoundBlock ().data (block)) && !block.IsNull ()) {
16741668 auto locked_chain = chain ().lock ();
16751669 LOCK (cs_wallet);
1676- if (!locked_chain->getBlockHeight (block_hash)) {
1670+ next_block = chain ().findNextBlock (block_hash, block_height, FoundBlock ().hash (next_block_hash), &reorg);
1671+ if (reorg) {
16771672 // Abort scan if current block is no longer active, to prevent
16781673 // marking transactions as coming from the wrong block.
16791674 // TODO: This should return success instead of failure, see
@@ -1683,36 +1678,37 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
16831678 break ;
16841679 }
16851680 for (size_t posInBlock = 0 ; posInBlock < block.vtx .size (); ++posInBlock) {
1686- CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, * block_height, block_hash, posInBlock);
1681+ CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, block_height, block_hash, posInBlock);
16871682 SyncTransaction (block.vtx [posInBlock], confirm, fUpdate );
16881683 }
16891684 // scan succeeded, record block as most recent successfully scanned
16901685 result.last_scanned_block = block_hash;
1691- result.last_scanned_height = * block_height;
1686+ result.last_scanned_height = block_height;
16921687 } else {
16931688 // could not scan block, keep scanning but record this block as the most recent failure
16941689 result.last_failed_block = block_hash;
16951690 result.status = ScanResult::FAILURE;
1691+ next_block = chain ().findNextBlock (block_hash, block_height, FoundBlock ().hash (next_block_hash), &reorg);
16961692 }
1697- if (max_height && * block_height >= *max_height) {
1693+ if (max_height && block_height >= *max_height) {
16981694 break ;
16991695 }
17001696 {
17011697 auto locked_chain = chain ().lock ();
1702- Optional<int > tip_height = locked_chain->getHeight ();
1703- if (!tip_height || *tip_height <= block_height || !locked_chain->getBlockHeight (block_hash)) {
1698+ if (!next_block || reorg) {
17041699 // break successfully when rescan has reached the tip, or
17051700 // previous block is no longer on the chain due to a reorg
17061701 break ;
17071702 }
17081703
17091704 // increment block and verification progress
1710- block_hash = locked_chain->getBlockHash (++*block_height);
1705+ block_hash = next_block_hash;
1706+ ++block_height;
17111707 progress_current = chain ().guessVerificationProgress (block_hash);
17121708
17131709 // handle updated tip hash
17141710 const uint256 prev_tip_hash = tip_hash;
1715- tip_hash = locked_chain-> getBlockHash (*tip_height );
1711+ tip_hash = WITH_LOCK (cs_wallet, return GetLastBlockHash () );
17161712 if (!max_height && prev_tip_hash != tip_hash) {
17171713 // in case the tip has changed, update progress max
17181714 progress_end = chain ().guessVerificationProgress (tip_hash);
@@ -1721,10 +1717,10 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
17211717 }
17221718 ShowProgress (strprintf (" %s " + _ (" Rescanning..." ).translated , GetDisplayName ()), 100 ); // hide progress dialog in GUI
17231719 if (block_height && fAbortRescan ) {
1724- WalletLogPrintf (" Rescan aborted at block %d. Progress=%f\n " , * block_height, progress_current);
1720+ WalletLogPrintf (" Rescan aborted at block %d. Progress=%f\n " , block_height, progress_current);
17251721 result.status = ScanResult::USER_ABORT;
17261722 } else if (block_height && chain ().shutdownRequested ()) {
1727- WalletLogPrintf (" Rescan interrupted by shutdown request at block %d. Progress=%f\n " , * block_height, progress_current);
1723+ WalletLogPrintf (" Rescan interrupted by shutdown request at block %d. Progress=%f\n " , block_height, progress_current);
17281724 result.status = ScanResult::USER_ABORT;
17291725 } else {
17301726 WalletLogPrintf (" Rescan completed in %15dms\n " , GetTimeMillis () - start_time);
@@ -4049,7 +4045,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
40494045
40504046 {
40514047 WalletRescanReserver reserver (walletInstance.get ());
4052- if (!reserver.reserve () || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions (locked_chain->getBlockHash (rescan_height), {} /* stop block */ , reserver, true /* update */ ).status )) {
4048+ if (!reserver.reserve () || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions (locked_chain->getBlockHash (rescan_height), rescan_height, {} /* max height */ , reserver, true /* update */ ).status )) {
40534049 error = _ (" Failed to rescan the wallet during initialization" ).translated ;
40544050 return nullptr ;
40554051 }
0 commit comments