From b4ab654f119ca5538a7d5796cb0620415cca347d Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sat, 6 Apr 2024 17:21:03 +0200 Subject: [PATCH] fixed wallet bug in calculating last available global index in zarcanum era --- src/currency_core/currency_config.h | 2 +- src/wallet/wallet2.cpp | 76 +++++++++++++++++++++++------ src/wallet/wallet2.h | 20 +++++--- 3 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 487502f4..16646940 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -250,7 +250,7 @@ #define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin" -#define WALLET_FILE_SERIALIZATION_VERSION 165 +#define WALLET_FILE_SERIALIZATION_VERSION 166 #define WALLET_FILE_LAST_SUPPORTED_VERSION 165 #define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index a4039a7a..37b1d069 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -523,6 +523,59 @@ void wallet2::add_rollback_event(uint64_t h, const wallet_event_t& ev) m_rollback_events.emplace_back(h, ev); } //---------------------------------------------------------------------------------------------------- +#define M_LAST_ZC_GLOBAL_INDEXS_MAX_SIZE 30 +void wallet2::add_to_last_zc_global_indexs(uint64_t h, uint64_t last_zc_output_index) +{ + //m_last_zc_global_indexs.remove_if_expiration_less_than(m_last_known_daemon_height - (WALLET_DEFAULT_TX_SPENDABLE_AGE * 2) ); + + if (m_last_zc_global_indexs.size()) + { + if (m_last_zc_global_indexs.begin()->first > h) + { + //new block added on top of last one, simply add new record + m_last_zc_global_indexs.push_front(std::make_pair(h, last_zc_output_index)); + } + else if (m_last_zc_global_indexs.begin()->first < h) + { + //looks like reorganize, pop all records before + while (m_last_zc_global_indexs.size() && m_last_zc_global_indexs.begin()->first >= h) + { + m_last_zc_global_indexs.erase(m_last_zc_global_indexs.begin()); + } + m_last_zc_global_indexs.push_front(std::make_pair(h, last_zc_output_index)); + } + else + { + //equals, same h but new last_zc_output_index, just update it, should be always bigger then prev + WLT_THROW_IF_FALSE_WITH_CODE(m_last_zc_global_indexs.begin()->second <= last_zc_output_index, + "condition m_last_zc_global_indexs.begin()->second " << m_last_zc_global_indexs.begin()->second << " <= last_zc_output_index " << last_zc_output_index << " failed", API_RETURN_CODE_INTERNAL_ERROR); + m_last_zc_global_indexs.begin()->second = last_zc_output_index; + } + } + else + { + //new block added on top of last one, simply add new record + m_last_zc_global_indexs.push_front(std::make_pair(h, last_zc_output_index)); + } + + if (m_last_zc_global_indexs.size() > M_LAST_ZC_GLOBAL_INDEXS_MAX_SIZE) + m_last_zc_global_indexs.pop_back(); +} +//---------------------------------------------------------------------------------------------------- +uint64_t wallet2::get_actual_zc_global_index() +{ + WLT_THROW_IF_FALSE_WITH_CODE(m_last_zc_global_indexs.size(), "m_last_zc_global_indexs is empty", API_RETURN_CODE_INTERNAL_ERROR); + for (auto it = m_last_zc_global_indexs.begin(); it != m_last_zc_global_indexs.end(); it++) + { + if (it->first <= m_last_known_daemon_height - WALLET_DEFAULT_TX_SPENDABLE_AGE) + { + return it->second; + } + } + WLT_THROW_IF_FALSE_WITH_CODE(false, "doesn't have anything that match expected height = " << m_last_known_daemon_height - WALLET_DEFAULT_TX_SPENDABLE_AGE, API_RETURN_CODE_INTERNAL_ERROR); + throw std::runtime_error(""); //mostly to suppress compiler warning +} +//---------------------------------------------------------------------------------------------------- void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t height, const currency::block& b, const std::vector* pglobal_indexes) { //check for transaction spends @@ -540,11 +593,7 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t { if (pglobal_indexes->size()) { - //store global index that is under coinage, so we can used in decoy selection algo - if (ptc.height < m_last_known_daemon_height && m_last_known_daemon_height - ptc.height > WALLET_DEFAULT_TX_SPENDABLE_AGE) - { - m_last_zc_global_index = pglobal_indexes->back(); - } + add_to_last_zc_global_indexs(ptc.height, pglobal_indexes->back()); } } @@ -6224,13 +6273,6 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector= zarcanum_start_from) - { - //in Zarcanum era - //const uint64_t test_scale_size = current_size - 1 - zarcanum_start_from; - zarcanum_decoy_set_generator.init(m_last_zc_global_index); - } bool need_to_request = fake_outputs_count != 0; COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request req = AUTO_VAL_INIT(req); @@ -6256,7 +6298,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vectorm_global_output_index); + build_distribution_for_input(rdisttib.global_offsets, it->m_global_output_index); need_to_request = true; } else @@ -6474,12 +6516,16 @@ void wallet2::select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS amount_entry.outs = local_outs; } //---------------------------------------------------------------------------------------------------------------- -void wallet2::build_distribution_for_input(decoy_selection_generator& zarcanum_decoy_set_generator, std::vector& offsets, uint64_t own_index) +void wallet2::build_distribution_for_input(std::vector& offsets, uint64_t own_index) { + decoy_selection_generator zarcanum_decoy_set_generator; + zarcanum_decoy_set_generator.init(get_actual_zc_global_index()); + THROW_IF_FALSE_WALLET_INT_ERR_EX(zarcanum_decoy_set_generator.is_initialized(), "zarcanum_decoy_set_generator are not initialized"); if (m_core_runtime_config.hf4_minimum_mixins) { - offsets = zarcanum_decoy_set_generator.generate_unique_reversed_distribution(m_last_zc_global_index - 1 > WALLET_FETCH_RANDOM_OUTS_SIZE ? WALLET_FETCH_RANDOM_OUTS_SIZE: m_last_zc_global_index - 1, own_index); + uint64_t actual_zc_index = get_actual_zc_global_index(); + offsets = zarcanum_decoy_set_generator.generate_unique_reversed_distribution(actual_zc_index - 1 > WALLET_FETCH_RANDOM_OUTS_SIZE ? WALLET_FETCH_RANDOM_OUTS_SIZE : actual_zc_index - 1, own_index); } } //---------------------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 28b1fbd8..9bb4676a 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -148,9 +148,7 @@ namespace tools std::unordered_map m_pending_key_images; // (out_pk -> ki) pairs of change outputs to be added in watch-only wallet without spend sec key uint64_t m_last_pow_block_h = 0; std::list> m_rollback_events; - uint64_t m_last_zc_global_index = 0; - - + std::list > m_last_zc_global_indexs; // , biggest height comes in front //variables that not being serialized std::atomic m_last_bc_timestamp = 0; @@ -223,7 +221,16 @@ namespace tools a & m_rollback_events; a & m_whitelisted_assets; a & m_use_assets_whitelisting; - a & m_last_zc_global_index; + if (ver <= 165) + { + uint64_t last_zc_global_index = 0; + a& last_zc_global_index; + m_last_zc_global_indexs.push_back(std::make_pair(uint64_t(0), last_zc_global_index)); + } + else + { + a& m_last_zc_global_indexs; + } } }; @@ -762,7 +769,8 @@ private: void handle_money(const currency::block& b, const process_transaction_context& tx_process_context); void load_wti_from_process_transaction_context(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context); bool process_payment_id_for_wti(wallet_public::wallet_transfer_info& wti, const process_transaction_context& tx_process_context); - + void add_to_last_zc_global_indexs(uint64_t h, uint64_t last_zc_output_index); + uint64_t get_actual_zc_global_index(); void handle_pulled_blocks(size_t& blocks_added, std::atomic& stop, currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks); std::string get_alias_for_address(const std::string& addr); @@ -868,7 +876,7 @@ private: void remove_transfer_from_amount_gindex_map(uint64_t tid); uint64_t get_alias_cost(const std::string& alias); detail::split_strategy_id_t get_current_split_strategy(); - void build_distribution_for_input(decoy_selection_generator& zarcanum_decoy_set_generator, std::vector& offsets, uint64_t own_index); + void build_distribution_for_input(std::vector& offsets, uint64_t own_index); void select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount & amount_entry, uint64_t own_g_index); static void wti_to_csv_entry(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);