@@ -1598,7 +1598,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
1598
1598
1599
1599
if (start) {
1600
1600
// 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);
1602
1602
if (result.status == ScanResult::FAILURE) {
1603
1603
int64_t time_max;
1604
1604
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
1615
1615
*
1616
1616
* @param[in] start_block Scan starting block. If block is not on the active
1617
1617
* chain, the scan will return SUCCESS immediately.
1618
+ * @param[in] start_height Height of start_block
1618
1619
* @param[in] max_height Optional max scanning height. If unset there is
1619
1620
* no maximum and scanning can continue to the tip
1620
1621
*
@@ -1628,7 +1629,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
1628
1629
* the main chain after to the addition of any new keys you want to detect
1629
1630
* transactions for.
1630
1631
*/
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 )
1632
1633
{
1633
1634
int64_t nNow = GetTime ();
1634
1635
int64_t start_time = GetTimeMillis ();
@@ -1642,38 +1643,32 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
1642
1643
1643
1644
fAbortRescan = false ;
1644
1645
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);
1661
1651
double progress_current = progress_begin;
1662
- while (block_height && !fAbortRescan && !chain ().shutdownRequested ()) {
1652
+ int block_height = start_height;
1653
+ while (!fAbortRescan && !chain ().shutdownRequested ()) {
1663
1654
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 ) {
1665
1656
ShowProgress (strprintf (" %s " + _ (" Rescanning..." ).translated , GetDisplayName ()), std::max (1 , std::min (99 , (int )(m_scanning_progress * 100 ))));
1666
1657
}
1667
1658
if (GetTime () >= nNow + 60 ) {
1668
1659
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);
1670
1661
}
1671
1662
1672
1663
CBlock block;
1664
+ bool next_block;
1665
+ uint256 next_block_hash;
1666
+ bool reorg = false ;
1673
1667
if (chain ().findBlock (block_hash, FoundBlock ().data (block)) && !block.IsNull ()) {
1674
1668
auto locked_chain = chain ().lock ();
1675
1669
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) {
1677
1672
// Abort scan if current block is no longer active, to prevent
1678
1673
// marking transactions as coming from the wrong block.
1679
1674
// TODO: This should return success instead of failure, see
@@ -1683,36 +1678,37 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
1683
1678
break ;
1684
1679
}
1685
1680
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);
1687
1682
SyncTransaction (block.vtx [posInBlock], confirm, fUpdate );
1688
1683
}
1689
1684
// scan succeeded, record block as most recent successfully scanned
1690
1685
result.last_scanned_block = block_hash;
1691
- result.last_scanned_height = * block_height;
1686
+ result.last_scanned_height = block_height;
1692
1687
} else {
1693
1688
// could not scan block, keep scanning but record this block as the most recent failure
1694
1689
result.last_failed_block = block_hash;
1695
1690
result.status = ScanResult::FAILURE;
1691
+ next_block = chain ().findNextBlock (block_hash, block_height, FoundBlock ().hash (next_block_hash), &reorg);
1696
1692
}
1697
- if (max_height && * block_height >= *max_height) {
1693
+ if (max_height && block_height >= *max_height) {
1698
1694
break ;
1699
1695
}
1700
1696
{
1701
1697
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) {
1704
1699
// break successfully when rescan has reached the tip, or
1705
1700
// previous block is no longer on the chain due to a reorg
1706
1701
break ;
1707
1702
}
1708
1703
1709
1704
// increment block and verification progress
1710
- block_hash = locked_chain->getBlockHash (++*block_height);
1705
+ block_hash = next_block_hash;
1706
+ ++block_height;
1711
1707
progress_current = chain ().guessVerificationProgress (block_hash);
1712
1708
1713
1709
// handle updated tip hash
1714
1710
const uint256 prev_tip_hash = tip_hash;
1715
- tip_hash = locked_chain-> getBlockHash (*tip_height );
1711
+ tip_hash = WITH_LOCK (cs_wallet, return GetLastBlockHash () );
1716
1712
if (!max_height && prev_tip_hash != tip_hash) {
1717
1713
// in case the tip has changed, update progress max
1718
1714
progress_end = chain ().guessVerificationProgress (tip_hash);
@@ -1721,10 +1717,10 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
1721
1717
}
1722
1718
ShowProgress (strprintf (" %s " + _ (" Rescanning..." ).translated , GetDisplayName ()), 100 ); // hide progress dialog in GUI
1723
1719
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);
1725
1721
result.status = ScanResult::USER_ABORT;
1726
1722
} 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);
1728
1724
result.status = ScanResult::USER_ABORT;
1729
1725
} else {
1730
1726
WalletLogPrintf (" Rescan completed in %15dms\n " , GetTimeMillis () - start_time);
@@ -4049,7 +4045,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
4049
4045
4050
4046
{
4051
4047
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 )) {
4053
4049
error = _ (" Failed to rescan the wallet during initialization" ).translated ;
4054
4050
return nullptr ;
4055
4051
}
0 commit comments