From d269bff2ab4c4e1d21aeea101dd8510b826a044e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 22 Oct 2017 09:54:07 +0100 Subject: [PATCH] wallet2: use a vector, not a list, for selected_transfers Friendlier on memory/speed, we know in advance the max amount of items, which are small and constant size, and there's a lot of list walking involved. --- src/wallet/wallet2.cpp | 21 +++++++++-------- src/wallet/wallet2.h | 52 ++++++++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index a87803206..b8d05e813 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3272,7 +3272,7 @@ float wallet2::get_output_relatedness(const transfer_details &td0, const transfe return 0.0f; } //---------------------------------------------------------------------------------------------------- -size_t wallet2::pop_best_value_from(const transfer_container &transfers, std::vector &unused_indices, const std::list& selected_transfers, bool smallest) const +size_t wallet2::pop_best_value_from(const transfer_container &transfers, std::vector &unused_indices, const std::vector& selected_transfers, bool smallest) const { std::vector candidates; float best_relatedness = 1.0f; @@ -3280,7 +3280,7 @@ size_t wallet2::pop_best_value_from(const transfer_container &transfers, std::ve { const transfer_details &candidate = transfers[unused_indices[n]]; float relatedness = 0.0f; - for (std::list::const_iterator i = selected_transfers.begin(); i != selected_transfers.end(); ++i) + for (std::vector::const_iterator i = selected_transfers.begin(); i != selected_transfers.end(); ++i) { float r = get_output_relatedness(candidate, transfers[*i]); if (r > relatedness) @@ -3321,7 +3321,7 @@ size_t wallet2::pop_best_value_from(const transfer_container &transfers, std::ve return pop_index (unused_indices, candidates[idx]); } //---------------------------------------------------------------------------------------------------- -size_t wallet2::pop_best_value(std::vector &unused_indices, const std::list& selected_transfers, bool smallest) const +size_t wallet2::pop_best_value(std::vector &unused_indices, const std::vector& selected_transfers, bool smallest) const { return pop_best_value_from(m_transfers, unused_indices, selected_transfers, smallest); } @@ -3330,9 +3330,10 @@ size_t wallet2::pop_best_value(std::vector &unused_indices, const std::l // returns: // direct return: amount of money found // modified reference: selected_transfers, a list of iterators/indices of input sources -uint64_t wallet2::select_transfers(uint64_t needed_money, std::vector unused_transfers_indices, std::list& selected_transfers, bool trusted_daemon) +uint64_t wallet2::select_transfers(uint64_t needed_money, std::vector unused_transfers_indices, std::vector& selected_transfers, bool trusted_daemon) { uint64_t found_money = 0; + selected_transfers.reserve(unused_transfers_indices.size()); while (found_money < needed_money && !unused_transfers_indices.empty()) { size_t idx = pop_best_value(unused_transfers_indices, selected_transfers); @@ -4073,7 +4074,7 @@ bool wallet2::tx_add_fake_output(std::vector> &outs, const std::list &selected_transfers, size_t fake_outputs_count) { +void wallet2::light_wallet_get_outs(std::vector> &outs, const std::vector &selected_transfers, size_t fake_outputs_count) { MDEBUG("LIGHTWALLET - Getting random outs"); @@ -4177,7 +4178,7 @@ void wallet2::light_wallet_get_outs(std::vector> &outs, const std::list &selected_transfers, size_t fake_outputs_count) +void wallet2::get_outs(std::vector> &outs, const std::vector &selected_transfers, size_t fake_outputs_count) { LOG_PRINT_L2("fake_outputs_count: " << fake_outputs_count); outs.clear(); @@ -4412,7 +4413,7 @@ void wallet2::get_outs(std::vector> } template -void wallet2::transfer_selected(const std::vector& dsts, const std::list& selected_transfers, size_t fake_outputs_count, +void wallet2::transfer_selected(const std::vector& dsts, const std::vector& selected_transfers, size_t fake_outputs_count, std::vector> &outs, uint64_t unlock_time, uint64_t fee, const std::vector& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx) { @@ -4566,7 +4567,7 @@ void wallet2::transfer_selected(const std::vector dsts, const std::list& selected_transfers, size_t fake_outputs_count, +void wallet2::transfer_selected_rct(std::vector dsts, const std::vector& selected_transfers, size_t fake_outputs_count, std::vector> &outs, uint64_t unlock_time, uint64_t fee, const std::vector& extra, cryptonote::transaction& tx, pending_tx &ptx) { @@ -5361,7 +5362,7 @@ std::vector wallet2::create_transactions_2(std::vector selected_transfers; + std::vector selected_transfers; std::vector dsts; cryptonote::transaction tx; pending_tx ptx; @@ -5844,7 +5845,7 @@ std::vector wallet2::create_transactions_from(const crypton { uint64_t accumulated_fee, accumulated_outputs, accumulated_change; struct TX { - std::list selected_transfers; + std::vector selected_transfers; std::vector dsts; cryptonote::transaction tx; pending_tx ptx; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index f1e12a700..7b3cb8437 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -282,7 +282,7 @@ namespace tools std::vector sources; cryptonote::tx_destination_entry change_dts; std::vector splitted_dsts; // split, includes change - std::list selected_transfers; + std::vector selected_transfers; std::vector extra; uint64_t unlock_time; bool use_rct; @@ -303,7 +303,7 @@ namespace tools uint64_t dust, fee; bool dust_added_to_fee; cryptonote::tx_destination_entry change_dts; - std::list selected_transfers; + std::vector selected_transfers; std::string key_images; crypto::secret_key tx_key; std::vector additional_tx_keys; @@ -501,10 +501,10 @@ namespace tools void transfer(const std::vector& dsts, const size_t fake_outputs_count, const std::vector &unused_transfers_indices, uint64_t unlock_time, uint64_t fee, const std::vector& extra, bool trusted_daemon); void transfer(const std::vector& dsts, const size_t fake_outputs_count, const std::vector &unused_transfers_indices, uint64_t unlock_time, uint64_t fee, const std::vector& extra, cryptonote::transaction& tx, pending_tx& ptx, bool trusted_daemon); template - void transfer_selected(const std::vector& dsts, const std::list& selected_transfers, size_t fake_outputs_count, + void transfer_selected(const std::vector& dsts, const std::vector& selected_transfers, size_t fake_outputs_count, std::vector> &outs, uint64_t unlock_time, uint64_t fee, const std::vector& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx); - void transfer_selected_rct(std::vector dsts, const std::list& selected_transfers, size_t fake_outputs_count, + void transfer_selected_rct(std::vector dsts, const std::vector& selected_transfers, size_t fake_outputs_count, std::vector> &outs, uint64_t unlock_time, uint64_t fee, const std::vector& extra, cryptonote::transaction& tx, pending_tx &ptx); @@ -700,8 +700,8 @@ namespace tools std::vector select_available_unmixable_outputs(bool trusted_daemon); std::vector select_available_mixable_outputs(bool trusted_daemon); - size_t pop_best_value_from(const transfer_container &transfers, std::vector &unused_dust_indices, const std::list& selected_transfers, bool smallest = false) const; - size_t pop_best_value(std::vector &unused_dust_indices, const std::list& selected_transfers, bool smallest = false) const; + size_t pop_best_value_from(const transfer_container &transfers, std::vector &unused_dust_indices, const std::vector& selected_transfers, bool smallest = false) const; + size_t pop_best_value(std::vector &unused_dust_indices, const std::vector& selected_transfers, bool smallest = false) const; void set_tx_note(const crypto::hash &txid, const std::string ¬e); std::string get_tx_note(const crypto::hash &txid) const; @@ -757,7 +757,7 @@ namespace tools // Send an import request to lw node. returns info about import fee, address and payment_id bool light_wallet_import_wallet_request(cryptonote::COMMAND_RPC_IMPORT_WALLET_REQUEST::response &response); // get random outputs from light wallet server - void light_wallet_get_outs(std::vector> &outs, const std::list &selected_transfers, size_t fake_outputs_count); + void light_wallet_get_outs(std::vector> &outs, const std::vector &selected_transfers, size_t fake_outputs_count); // Parse rct string bool light_wallet_parse_rct_str(const std::string& rct_string, const crypto::public_key& tx_pub_key, uint64_t internal_output_index, rct::key& decrypted_mask, rct::key& rct_commit, bool decrypt) const; // check if key image is ours @@ -808,7 +808,7 @@ namespace tools void fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list &short_chain_history); void pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list &short_chain_history, const std::list &prev_blocks, std::list &blocks, std::vector &o_indices, bool &error); void process_blocks(uint64_t start_height, const std::list &blocks, const std::vector &o_indices, uint64_t& blocks_added); - uint64_t select_transfers(uint64_t needed_money, std::vector unused_transfers_indices, std::list& selected_transfers, bool trusted_daemon); + uint64_t select_transfers(uint64_t needed_money, std::vector unused_transfers_indices, std::vector& selected_transfers, bool trusted_daemon); bool prepare_file_names(const std::string& file_path); void process_unconfirmed(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height); void process_outgoing(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received, uint32_t subaddr_account, const std::set& subaddr_indices); @@ -827,7 +827,7 @@ namespace tools std::vector pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set &subaddr_indices) const; void set_spent(size_t idx, uint64_t height); void set_unspent(size_t idx); - void get_outs(std::vector> &outs, const std::list &selected_transfers, size_t fake_outputs_count); + void get_outs(std::vector> &outs, const std::vector &selected_transfers, size_t fake_outputs_count); bool tx_add_fake_output(std::vector> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const; bool wallet_generate_key_image_helper(const cryptonote::account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, cryptonote::keypair& in_ephemeral, crypto::key_image& ki); crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const; @@ -916,8 +916,8 @@ BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 5) BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 17) BOOST_CLASS_VERSION(tools::wallet2::unsigned_tx_set, 0) BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 0) -BOOST_CLASS_VERSION(tools::wallet2::tx_construction_data, 1) -BOOST_CLASS_VERSION(tools::wallet2::pending_tx, 1) +BOOST_CLASS_VERSION(tools::wallet2::tx_construction_data, 2) +BOOST_CLASS_VERSION(tools::wallet2::pending_tx, 2) namespace boost { @@ -1172,7 +1172,16 @@ namespace boost a & x.sources; a & x.change_dts; a & x.splitted_dsts; - a & x.selected_transfers; + if (ver < 2) + { + // load list to vector + std::list selected_transfers; + a & selected_transfers; + x.selected_transfers.clear(); + x.selected_transfers.reserve(selected_transfers.size()); + for (size_t t: selected_transfers) + x.selected_transfers.push_back(t); + } a & x.extra; a & x.unlock_time; a & x.use_rct; @@ -1184,6 +1193,9 @@ namespace boost } a & x.subaddr_account; a & x.subaddr_indices; + if (ver < 2) + return; + a & x.selected_transfers; } template @@ -1194,7 +1206,16 @@ namespace boost a & x.fee; a & x.dust_added_to_fee; a & x.change_dts; - a & x.selected_transfers; + if (ver < 2) + { + // load list to vector + std::list selected_transfers; + a & selected_transfers; + x.selected_transfers.clear(); + x.selected_transfers.reserve(selected_transfers.size()); + for (size_t t: selected_transfers) + x.selected_transfers.push_back(t); + } a & x.key_images; a & x.tx_key; a & x.dests; @@ -1202,6 +1223,9 @@ namespace boost if (ver < 1) return; a & x.additional_tx_keys; + if (ver < 2) + return; + a & x.selected_transfers; } } } @@ -1291,7 +1315,7 @@ namespace tools // randomly select inputs for transaction // throw if requested send amount is greater than (unlocked) amount available to send - std::list selected_transfers; + std::vector selected_transfers; uint64_t found_money = select_transfers(needed_money, unused_transfers_indices, selected_transfers, trusted_daemon); THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_unlocked_money, found_money, needed_money - fee, fee);