From 73c42b78929ee0a16317358b177fde8e32d69dba Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 12 Jun 2020 23:32:06 +0200 Subject: [PATCH] implemented prefetch of outputs before transfer --- src/rpc/core_rpc_server.cpp | 15 ++++-- src/rpc/core_rpc_server_commands_defs.h | 10 ++-- src/wallet/wallet2.cpp | 66 ++++++++++++++++++++++--- src/wallet/wallet2.h | 2 + 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index e98918a4..e65af49c 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -379,14 +379,19 @@ namespace currency bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, connection_context& cntx) { CHECK_CORE_READY(); - bool r = m_core.get_tx_outputs_gindexs(req.txid, res.o_indexes); - if(!r) + res.tx_global_outs.resize(req.txids.size()); + size_t i = 0; + for (auto& txid : req.txids) { - res.status = "Failed"; - return true; + bool r = m_core.get_tx_outputs_gindexs(txid, res.tx_global_outs[i].v); + if (!r) + { + res.status = API_RETURN_CODE_FAIL; + return true; + } + i++; } res.status = API_RETURN_CODE_OK; - LOG_PRINT_L2("COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES: [" << res.o_indexes.size() << "]"); return true; } //------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index c2e22bf6..a362a15c 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -238,19 +238,21 @@ namespace currency { struct request { - crypto::hash txid; + std::list txids; + BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB(txid) + KV_SERIALIZE_CONTAINER_POD_AS_BLOB(txids) END_KV_SERIALIZE_MAP() }; struct response { - std::vector o_indexes; + std::vector > > tx_global_outs; + //std::vector o_indexes; std::string status; BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(o_indexes) + KV_SERIALIZE(tx_global_outs) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 00fa9f7c..0cb042d5 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -240,19 +240,43 @@ size_t wallet2::scan_for_transaction_entries(const crypto::hash& tx_id, const cr } //---------------------------------------------------------------------------------------------------- void wallet2::fetch_tx_global_indixes(const currency::transaction& tx, std::vector& goutputs_indexes) +{ + std::list> txs; + txs.push_back(tx); + std::vector > res; + fetch_tx_global_indixes(txs, res); + THROW_IF_FALSE_WALLET_INT_ERR_EX(res.size() == 1, "fetch_tx_global_indixes for single entry returned wrong result: res.size()=" << res.size()); + goutputs_indexes = res[0]; +} +//---------------------------------------------------------------------------------------------------- +void wallet2::fetch_tx_global_indixes(const std::list>& txs, std::vector>& goutputs_indexes) { currency::COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request req = AUTO_VAL_INIT(req); currency::COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response res = AUTO_VAL_INIT(res); - req.txid = get_transaction_hash(tx); + for (auto& tx : txs) + { + req.txids.push_back(get_transaction_hash(tx)); + } + bool r = m_core_proxy->call_COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES(req, res); THROW_IF_TRUE_WALLET_EX(!r, error::no_connection_to_daemon, "get_o_indexes.bin"); THROW_IF_TRUE_WALLET_EX(res.status == API_RETURN_CODE_BUSY, error::daemon_busy, "get_o_indexes.bin"); THROW_IF_TRUE_WALLET_EX(res.status != API_RETURN_CODE_OK, error::get_out_indices_error, res.status); - THROW_IF_TRUE_WALLET_EX(res.o_indexes.size() != tx.vout.size(), error::wallet_internal_error, - "transactions outputs size=" + std::to_string(tx.vout.size()) + - " not match with COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES response size=" + std::to_string(res.o_indexes.size())); + THROW_IF_FALSE_WALLET_INT_ERR_EX(res.tx_global_outs.size() == txs.size(), "res.tx_global_outs.size()(" << res.tx_global_outs.size() + << ") == txs.size()(" << txs.size() << ")"); + goutputs_indexes.resize(txs.size()); + auto it_resp = res.tx_global_outs.begin(); + auto it_txs = txs.begin(); + size_t i = 0; + for (; it_resp != res.tx_global_outs.end();) + { + THROW_IF_FALSE_WALLET_INT_ERR_EX(it_resp->v.size() == it_txs->get().vout.size(), + "transactions outputs size=" << it_txs->get().vout.size() << + " not match with COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES response[i] size=" << it_resp->v.size()); - goutputs_indexes = res.o_indexes; + goutputs_indexes[i] = it_resp->v; + it_resp++; it_txs++; i++; + } } //---------------------------------------------------------------------------------------------------- @@ -2902,8 +2926,8 @@ bool wallet2::get_pos_entries(currency::COMMAND_RPC_SCAN_POS::request& req) { for (size_t i = 0; i != m_transfers.size(); i++) { - WLT_CHECK_AND_ASSERT_MES(tr.m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED, false, "Wrong output input in transaction"); auto& tr = m_transfers[i]; + WLT_CHECK_AND_ASSERT_MES(tr.m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED, false, "Wrong output input in transaction"); uint64_t stake_unlock_time = 0; if (!is_transfer_okay_for_pos(tr, stake_unlock_time)) continue; @@ -3788,6 +3812,31 @@ bool wallet2::prepare_tx_sources(uint64_t needed_money, size_t fake_outputs_coun return prepare_tx_sources(fake_outputs_count, sources, selected_indicies, found_money); } //---------------------------------------------------------------------------------------------------- +void wallet2::prefetch_global_indicies_if_needed(std::vector& selected_indicies) +{ + std::list> txs; + std::list indices_that_requested_global_indicies; + for (uint64_t i : selected_indicies) + { + if (m_transfers[i].m_global_output_index == WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED) + { + indices_that_requested_global_indicies.push_back(i); + txs.push_back(m_transfers[i].m_ptx_wallet_info->m_tx); + } + } + + std::vector > outputs_for_all_txs; + fetch_tx_global_indixes(txs, outputs_for_all_txs); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(txs.size() == outputs_for_all_txs.size(), "missmatch sizes txs.size() == outputs_for_all_txs.size()"); + auto it_indices = indices_that_requested_global_indicies.begin(); + auto it_ooutputs = outputs_for_all_txs.begin(); + for (; it_ooutputs != outputs_for_all_txs.end();) + { + transfer_details& td = m_transfers[*it_indices]; + td.m_global_output_index = (*it_ooutputs)[td.m_internal_output_index]; + } +} +//---------------------------------------------------------------------------------------------------- bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector& sources, std::vector& selected_indicies, uint64_t& found_money) { typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry; @@ -3826,6 +3875,9 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector* pglobal_indexes); void fetch_tx_global_indixes(const currency::transaction& tx, std::vector& goutputs_indexes); + void fetch_tx_global_indixes(const std::list>& txs, std::vector>& goutputs_indexes); void detach_blockchain(uint64_t including_height); bool extract_offers_from_transfer_entry(size_t i, std::unordered_map& offers_local); bool select_my_offers(std::list& offers); @@ -883,6 +884,7 @@ private: bool prepare_tx_sources(size_t fake_outputs_count, std::vector& sources, std::vector& selected_indicies, uint64_t& found_money); bool prepare_tx_sources(crypto::hash multisig_id, std::vector& sources, uint64_t& found_money); bool prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake_outputs_count, std::vector& sources, std::vector& selected_indicies, uint64_t& found_money); + void prefetch_global_indicies_if_needed(std::vector& selected_indicies); uint64_t get_needed_money(uint64_t fee, const std::vector& dsts); void prepare_tx_destinations(uint64_t needed_money, uint64_t found_money,