From d86469844eb9ae7ba33c3650a4b7fad9cd1d4218 Mon Sep 17 00:00:00 2001 From: selsta Date: Fri, 2 Oct 2026 20:05:42 +0200 Subject: [PATCH] wallet2: trim stale transfer maps after output imports (cherry picked from commit 7d7a74848780f4f42a0e1376badf62a79240a02f) --- src/wallet/wallet2.cpp | 28 ++++++++++++++++++++++++++++ src/wallet/wallet2.h | 1 + 2 files changed, 29 insertions(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index e08d203b8..75f5e9898 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -6614,6 +6614,24 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass } } //---------------------------------------------------------------------------------------------------- +void wallet2::trim_transfer_maps(size_t num_transfers) +{ + for (auto it = m_key_images.begin(); it != m_key_images.end(); ) + { + if (it->second >= num_transfers) + it = m_key_images.erase(it); + else + ++it; + } + for (auto it = m_pub_keys.begin(); it != m_pub_keys.end(); ) + { + if (it->second >= num_transfers) + it = m_pub_keys.erase(it); + else + ++it; + } +} +//---------------------------------------------------------------------------------------------------- void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf) { boost::system::error_code e; @@ -6728,6 +6746,10 @@ void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf) ar >> *this; } } + // Repair stale indices from older output imports. + if (!m_has_ever_refreshed_from_node) + trim_transfer_maps(m_transfers.size()); + for (const auto &key_image : m_key_images) THROW_WALLET_EXCEPTION_IF(key_image.second >= m_transfers.size(), error::wallet_internal_error, std::string("Key images cache contains illegal transfer offset: ") + std::to_string(key_image.second) @@ -15184,7 +15206,10 @@ size_t wallet2::import_outputs(const std::tuple m_transfers.size()) m_transfers.resize(offset + output_array.size()); else if (num_outputs < m_transfers.size()) + { + trim_transfer_maps(num_outputs); m_transfers.resize(num_outputs); + } for (size_t i = 0; i < output_array.size(); ++i) { @@ -15264,7 +15289,10 @@ size_t wallet2::import_outputs(const std::tuple m_transfers.size()) m_transfers.resize(offset + output_array.size()); else if (num_outputs < m_transfers.size()) + { + trim_transfer_maps(num_outputs); m_transfers.resize(num_outputs); + } for (size_t i = 0; i < output_array.size(); ++i) { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index ec8893873..a3c792b87 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1856,6 +1856,7 @@ private: bool load_keys_buf(const std::string& keys_buf, const epee::wipeable_string& password); bool load_keys_buf(const std::string& keys_buf, const epee::wipeable_string& password, boost::optional& keys_to_encrypt); void load_wallet_cache(const bool use_fs, const std::string& cache_buf = ""); + void trim_transfer_maps(size_t num_transfers); void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map, size_t> *output_tracker_cache = NULL, bool ignore_callbacks = false); bool should_skip_block(const cryptonote::block &b, uint64_t height) const; void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector &tx_cache_data, size_t tx_cache_data_offset, std::map, size_t> *output_tracker_cache = NULL);