From 10ade8c5913f3b30e895249e1a574fd21905d8d8 Mon Sep 17 00:00:00 2001 From: woodser <13068859+woodser@users.noreply.github.com> Date: Wed, 5 Aug 2026 16:18:33 -0400 Subject: [PATCH] wallet2: honor max_blocks bound during fast_refresh hash pulls (cherry picked from commit bbd6350751876f24ad21eb70cbfb12670659e927) --- src/wallet/wallet2.cpp | 25 +++++++++++++++++++------ src/wallet/wallet2.h | 2 +- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 849739f72..ff2a86420 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -140,6 +140,8 @@ using namespace cryptonote; #define FIRST_REFRESH_GRANULARITY 1024 +#define MAX_HASH_PULLS_PER_REFRESH 3 // hash pulls per bounded refresh call, so single-threaded callers stay responsive + #define GAMMA_SHAPE 19.28 #define GAMMA_SCALE (1/1.61) @@ -3953,9 +3955,10 @@ void wallet2::process_pool_state(const std::vector &short_chain_history, bool force) +bool wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list &short_chain_history, bool force, uint64_t max_pulls) { std::vector hashes; + uint64_t num_pulls = 0; const uint64_t checkpoint_height = (stop_height < 1000) ? 0 : m_checkpoints.get_nearest_checkpoint_height(stop_height); if ((stop_height > checkpoint_height && m_blockchain.size()-1 < checkpoint_height) && !force) @@ -3973,13 +3976,15 @@ void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, size_t current_index = m_blockchain.size(); while(m_run.load(std::memory_order_relaxed) && current_index < stop_height) { + if (max_pulls > 0 && num_pulls++ >= max_pulls) + return false; // pull budget reached, caller may resume on a later call pull_hashes(0, blocks_start_height, short_chain_history, hashes); if (hashes.size() <= 3) - return; + return true; if (blocks_start_height < m_blockchain.offset()) { MERROR("Blocks start before blockchain offset: " << blocks_start_height << " " << m_blockchain.offset()); - return; + return true; } current_index = blocks_start_height; if (hashes.size() + current_index < stop_height) { @@ -4008,13 +4013,14 @@ void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, else if(bl_id != m_blockchain[current_index]) { //split detected here !!! - return; + return true; } ++current_index; if (current_index >= stop_height) - return; + return true; } } + return true; } @@ -4146,7 +4152,14 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo if (!start_height) start_height = std::max(m_refresh_from_block_height, m_skip_to_height);; // we can shortcut by only pulling hashes up to the start_height - fast_refresh(start_height, blocks_start_height, short_chain_history); + const uint64_t pre_hashes_height = m_blockchain.size(); + const uint64_t max_pulls = max_blocks == std::numeric_limits::max() ? 0 : MAX_HASH_PULLS_PER_REFRESH; + if (!fast_refresh(start_height, blocks_start_height, short_chain_history, false, max_pulls)) + { + // pull budget reached before start_height, report hashes added and resume on next call + blocks_fetched = m_blockchain.size() - pre_hashes_height; + return; + } // regenerate the history now that we've got a full set of hashes short_chain_history.clear(); get_short_chain_history(short_chain_history, (m_first_refresh_done || trusted_daemon) ? 1 : FIRST_REFRESH_GRANULARITY); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 0834a1479..e46f0bb41 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1868,7 +1868,7 @@ private: void clear_user_data(); void pull_blocks(bool first, bool try_incremental, uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::vector &blocks, std::vector &o_indices, uint64_t ¤t_height); void pull_hashes(uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::vector &hashes); - void fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list &short_chain_history, bool force = false); + bool fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list &short_chain_history, bool force = false, uint64_t max_pulls = 0); void pull_and_parse_next_blocks(bool first, bool try_incremental, uint64_t start_height, uint64_t &blocks_start_height, std::list &short_chain_history, const std::vector &prev_blocks, const std::vector &prev_parsed_blocks, std::vector &blocks, std::vector &parsed_blocks, bool &last, bool &error, std::exception_ptr &exception); void process_parsed_blocks(uint64_t start_height, const std::vector &blocks, const std::vector &parsed_blocks, uint64_t& blocks_added, std::map, size_t> *output_tracker_cache = NULL); bool accept_pool_tx_for_processing(const crypto::hash &txid, const std::unordered_set &payments_tx_hashes);