* Scan the block chain (starting in start_block) for transactions * from or to us. If max_height is not set, the * mempool will be scanned as well. * * @param[in] start_block Scan starting block. If block is not on the active * chain, the scan will return SUCCESS immediately. * @param[in] start_height Height of start_block * @param[in] max_height Optional max scannin
| 1875 | * transactions for. |
| 1876 | */ |
| 1877 | CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, const bool save_progress) |
| 1878 | { |
| 1879 | constexpr auto INTERVAL_TIME{60s}; |
| 1880 | auto current_time{reserver.now()}; |
| 1881 | auto start_time{reserver.now()}; |
| 1882 | |
| 1883 | assert(reserver.isReserved()); |
| 1884 | |
| 1885 | uint256 block_hash = start_block; |
| 1886 | ScanResult result; |
| 1887 | |
| 1888 | std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter; |
| 1889 | if (chain().hasBlockFilterIndex(BlockFilterType::BASIC)) fast_rescan_filter = std::make_unique<FastWalletRescanFilter>(*this); |
| 1890 | |
| 1891 | WalletLogPrintf("Rescan started from block %s... (%s)\n", start_block.ToString(), |
| 1892 | fast_rescan_filter ? "fast variant using block filters" : "slow variant inspecting all blocks"); |
| 1893 | |
| 1894 | ShowProgress(strprintf("[%s] %s", DisplayName(), _("Rescanning…")), 0); // show rescan progress in GUI as dialog or on splashscreen, if rescan required on startup (e.g. due to corruption) |
| 1895 | uint256 tip_hash = WITH_LOCK(cs_wallet, return GetLastBlockHash()); |
| 1896 | uint256 end_hash = tip_hash; |
| 1897 | if (max_height) chain().findAncestorByHeight(tip_hash, *max_height, FoundBlock().hash(end_hash)); |
| 1898 | double progress_begin = chain().guessVerificationProgress(block_hash); |
| 1899 | double progress_end = chain().guessVerificationProgress(end_hash); |
| 1900 | double progress_current = progress_begin; |
| 1901 | int block_height = start_height; |
| 1902 | while (!fAbortRescan && !chain().shutdownRequested()) { |
| 1903 | if (progress_end - progress_begin > 0.0) { |
| 1904 | m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin); |
| 1905 | } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal) |
| 1906 | m_scanning_progress = 0; |
| 1907 | } |
| 1908 | if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) { |
| 1909 | ShowProgress(strprintf("[%s] %s", DisplayName(), _("Rescanning…")), std::max(1, std::min(99, (int)(m_scanning_progress * 100)))); |
| 1910 | } |
| 1911 | |
| 1912 | bool next_interval = reserver.now() >= current_time + INTERVAL_TIME; |
| 1913 | if (next_interval) { |
| 1914 | current_time = reserver.now(); |
| 1915 | WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current); |
| 1916 | } |
| 1917 | |
| 1918 | bool fetch_block{true}; |
| 1919 | if (fast_rescan_filter) { |
| 1920 | fast_rescan_filter->UpdateIfNeeded(); |
| 1921 | auto matches_block{fast_rescan_filter->MatchesBlock(block_hash)}; |
| 1922 | if (matches_block.has_value()) { |
| 1923 | if (*matches_block) { |
| 1924 | LogDebug(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (filter matched)\n", block_height, block_hash.ToString()); |
| 1925 | } else { |
| 1926 | result.last_scanned_block = block_hash; |
| 1927 | result.last_scanned_height = block_height; |
| 1928 | fetch_block = false; |
| 1929 | } |
| 1930 | } else { |
| 1931 | LogDebug(BCLog::SCAN, "Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n", block_height, block_hash.ToString()); |
| 1932 | } |
| 1933 | } |
| 1934 |