From 2ec928badb188775f9d9e575b472357251f9fe1f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 12 Sep 2017 12:03:56 +0100 Subject: [PATCH] wallet2: simplify tx processing a bit --- src/wallet/wallet2.cpp | 125 +++++++++++++++++------------------------ src/wallet/wallet2.h | 17 +++++- 2 files changed, 68 insertions(+), 74 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 48dffe65e..416fa7025 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -591,24 +591,24 @@ void wallet2::set_unspent(size_t idx) td.m_spent_height = 0; } //---------------------------------------------------------------------------------------------------- -void wallet2::check_acc_out_precomp(const crypto::public_key &spend_public_key, const tx_out &o, const crypto::key_derivation &derivation, size_t i, bool &received, uint64_t &money_transfered, bool &error) const +void wallet2::check_acc_out_precomp(const crypto::public_key &spend_public_key, const tx_out &o, const crypto::key_derivation &derivation, size_t i, tx_scan_info_t &tx_scan_info) const { if (o.target.type() != typeid(txout_to_key)) { - error = true; + tx_scan_info.error = true; LOG_ERROR("wrong type id in transaction out"); return; } - received = is_out_to_acc_precomp(spend_public_key, boost::get(o.target), derivation, i); - if(received) + tx_scan_info.received = is_out_to_acc_precomp(spend_public_key, boost::get(o.target), derivation, i); + if(tx_scan_info.received) { - money_transfered = o.amount; // may be 0 for ringct outputs + tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs } else { - money_transfered = 0; + tx_scan_info.money_transfered = 0; } - error = false; + tx_scan_info.error = false; } //---------------------------------------------------------------------------------------------------- static uint64_t decodeRct(const rct::rctSig & rv, const crypto::public_key &pub, const crypto::secret_key &sec, unsigned int i, rct::key & mask) @@ -649,19 +649,19 @@ bool wallet2::wallet_generate_key_image_helper(const cryptonote::account_keys& a return true; } //---------------------------------------------------------------------------------------------------- -void wallet2::scan_output(const cryptonote::account_keys &keys, const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, cryptonote::keypair &in_ephemeral, crypto::key_image &ki, uint64_t &money_transfered, uint64_t &amount, int &num_vouts_received, uint64_t &tx_money_got_in_outs, rct::key &mask, std::vector &outs) +void wallet2::scan_output(const cryptonote::account_keys &keys, const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, uint64_t &tx_money_got_in_outs, std::vector &outs) { - wallet_generate_key_image_helper(keys, tx_pub_key, i, in_ephemeral, ki); - THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != boost::get(tx.vout[i].target).key, + wallet_generate_key_image_helper(keys, tx_pub_key, i, tx_scan_info.in_ephemeral, tx_scan_info.ki); + THROW_WALLET_EXCEPTION_IF(tx_scan_info.in_ephemeral.pub != boost::get(tx.vout[i].target).key, error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key"); outs.push_back(i); - if (money_transfered == 0) + if (tx_scan_info.money_transfered == 0) { - money_transfered = tools::decodeRct(tx.rct_signatures, tx_pub_key, keys.m_view_secret_key, i, mask); + tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_pub_key, keys.m_view_secret_key, i, tx_scan_info.mask); } - tx_money_got_in_outs += money_transfered; - amount = money_transfered; + tx_money_got_in_outs += tx_scan_info.money_transfered; + tx_scan_info.amount = tx_scan_info.money_transfered; ++num_vouts_received; } //---------------------------------------------------------------------------------------------------- @@ -703,13 +703,9 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote int num_vouts_received = 0; tx_pub_key = pub_key_field.pub_key; bool r = true; - std::deque in_ephemeral(tx.vout.size()); - std::deque ki(tx.vout.size()); - std::deque amount(tx.vout.size()); - std::deque mask(tx.vout.size()); tools::threadpool& tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter; - int threads = tpool.get_max_concurrency(); + std::unique_ptr tx_scan_info{new tx_scan_info_t[tx.vout.size()]}; const cryptonote::account_keys& keys = m_account.get_keys(); crypto::key_derivation derivation; generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation); @@ -719,72 +715,64 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote } else if (miner_tx && m_refresh_type == RefreshOptimizeCoinbase) { - uint64_t money_transfered = 0; - bool error = false, received = false; - check_acc_out_precomp(keys.m_account_address.m_spend_public_key, tx.vout[0], derivation, 0, received, money_transfered, error); - if (error) + check_acc_out_precomp(keys.m_account_address.m_spend_public_key, tx.vout[0], derivation, 0, tx_scan_info[0]); + if (tx_scan_info[0].error) { r = false; } else { // this assumes that the miner tx pays a single address - if (received) + if (tx_scan_info[0].received) { - scan_output(keys, tx, tx_pub_key, 0, in_ephemeral[0], ki[0], money_transfered, amount[0], num_vouts_received, tx_money_got_in_outs, mask[0], outs); + scan_output(keys, tx, tx_pub_key, 0, tx_scan_info[0], num_vouts_received, tx_money_got_in_outs, outs); // process the other outs from that tx - - std::vector money_transfered(tx.vout.size()); - std::deque error(tx.vout.size()); - std::deque received(tx.vout.size()); // the first one was already checked for (size_t i = 1; i < tx.vout.size(); ++i) { tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(keys.m_account_address.m_spend_public_key), std::cref(tx.vout[i]), std::cref(derivation), i, - std::ref(received[i]), std::ref(money_transfered[i]), std::ref(error[i]))); + std::ref(tx_scan_info[i]))); } waiter.wait(); + for (size_t i = 1; i < tx.vout.size(); ++i) { - if (error[i]) + if (tx_scan_info[i].error) { r = false; break; } - if (received[i]) + if (tx_scan_info[i].received) { - scan_output(keys, tx, tx_pub_key, i, in_ephemeral[i], ki[i], money_transfered[i], amount[i], num_vouts_received, tx_money_got_in_outs, mask[i], outs); + scan_output(keys, tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } } } } - else if (tx.vout.size() > 1 && threads > 1) + else if (tx.vout.size() > 1 && tools::threadpool::getInstance().get_max_concurrency() > 1) { tools::threadpool& tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter; - std::vector money_transfered(tx.vout.size()); - std::deque error(tx.vout.size()); - std::deque received(tx.vout.size()); for (size_t i = 0; i < tx.vout.size(); ++i) { - tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(keys.m_account_address.m_spend_public_key), std::cref(tx.vout[i]), std::cref(derivation), i, - std::ref(received[i]), std::ref(money_transfered[i]), std::ref(error[i]))); + tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(keys.m_account_address.m_spend_public_key), + std::cref(tx.vout[i]), std::cref(derivation), i, std::ref(tx_scan_info[i]))); } waiter.wait(); - tx_money_got_in_outs = 0; + for (size_t i = 0; i < tx.vout.size(); ++i) { - if (error[i]) + if (tx_scan_info[i].error) { r = false; break; } - if (received[i]) + if (tx_scan_info[i].received) { - scan_output(keys, tx, tx_pub_key, i, in_ephemeral[i], ki[i], money_transfered[i], amount[i], num_vouts_received, tx_money_got_in_outs, mask[i], outs); + scan_output(keys, tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } } @@ -792,20 +780,15 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote { for (size_t i = 0; i < tx.vout.size(); ++i) { - uint64_t money_transfered = 0; - bool error = false, received = false; - check_acc_out_precomp(keys.m_account_address.m_spend_public_key, tx.vout[i], derivation, i, received, money_transfered, error); - if (error) + check_acc_out_precomp(keys.m_account_address.m_spend_public_key, tx.vout[i], derivation, i, tx_scan_info[i]); + if (tx_scan_info[i].error) { r = false; break; } - else + if (tx_scan_info[i].received) { - if (received) - { - scan_output(keys, tx, tx_pub_key, i, in_ephemeral[i], ki[i], money_transfered, amount[i], num_vouts_received, tx_money_got_in_outs, mask[i], outs); - } + scan_output(keys, tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } } @@ -827,7 +810,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(tx.vout.size() <= o, error::wallet_internal_error, "wrong out in transaction: internal index=" + std::to_string(o) + ", total_outs=" + std::to_string(tx.vout.size())); - auto kit = m_pub_keys.find(in_ephemeral[o].pub); + auto kit = m_pub_keys.find(tx_scan_info[o].in_ephemeral.pub); THROW_WALLET_EXCEPTION_IF(kit != m_pub_keys.end() && kit->second >= m_transfers.size(), error::wallet_internal_error, std::string("Unexpected transfer index from public key: ") + "got " + (kit == m_pub_keys.end() ? "" : boost::lexical_cast(kit->second)) @@ -843,14 +826,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote td.m_global_output_index = o_indices[o]; td.m_tx = (const cryptonote::transaction_prefix&)tx; td.m_txid = txid; - td.m_key_image = ki[o]; + td.m_key_image = tx_scan_info[o].ki; td.m_key_image_known = !m_watch_only; td.m_amount = tx.vout[o].amount; td.m_pk_index = pk_index - 1; if (td.m_amount == 0) { - td.m_mask = mask[o]; - td.m_amount = amount[o]; + td.m_mask = tx_scan_info[o].mask; + td.m_amount = tx_scan_info[o].amount; td.m_rct = true; } else if (miner_tx && tx.version == 2) @@ -865,7 +848,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote } set_unspent(m_transfers.size()-1); m_key_images[td.m_key_image] = m_transfers.size()-1; - m_pub_keys[in_ephemeral[o].pub] = m_transfers.size()-1; + m_pub_keys[tx_scan_info[o].in_ephemeral.pub] = m_transfers.size()-1; LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid); if (0 != m_callback) m_callback->on_money_received(height, txid, tx, td.m_amount); @@ -898,8 +881,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote td.m_pk_index = pk_index - 1; if (td.m_amount == 0) { - td.m_mask = mask[o]; - td.m_amount = amount[o]; + td.m_mask = tx_scan_info[o].mask; + td.m_amount = tx_scan_info[o].amount; td.m_rct = true; } else if (miner_tx && tx.version == 2) @@ -912,7 +895,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote td.m_mask = rct::identity(); td.m_rct = false; } - THROW_WALLET_EXCEPTION_IF(td.get_public_key() != in_ephemeral[o].pub, error::wallet_internal_error, "Inconsistent public keys"); + THROW_WALLET_EXCEPTION_IF(td.get_public_key() != tx_scan_info[o].in_ephemeral.pub, error::wallet_internal_error, "Inconsistent public keys"); THROW_WALLET_EXCEPTION_IF(td.m_spent, error::wallet_internal_error, "Inconsistent spent status"); LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid); @@ -5149,10 +5132,9 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle for (size_t i = 0; i < td.m_tx.vout.size(); ++i) { - uint64_t money_transfered = 0; - bool error = false, received = false; - check_acc_out_precomp(keys.m_account_address.m_spend_public_key, td.m_tx.vout[i], derivation, i, received, money_transfered, error); - if (!error && received) + tx_scan_info_t tx_scan_info; + check_acc_out_precomp(keys.m_account_address.m_spend_public_key, td.m_tx.vout[i], derivation, i, tx_scan_info); + if (!tx_scan_info.error && tx_scan_info.received) return tx_pub_key; } } @@ -5447,18 +5429,17 @@ uint64_t wallet2::import_key_images(const std::vector get_unspent_amounts_vector(); @@ -664,7 +677,7 @@ namespace tools crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const; bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector &unused_transfers_indices, const std::vector &unused_dust_indices) const; std::vector get_only_rct(const std::vector &unused_dust_indices, const std::vector &unused_transfers_indices) const; - void scan_output(const cryptonote::account_keys &keys, const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, cryptonote::keypair &in_ephemeral, crypto::key_image &ki, uint64_t &money_transfered, uint64_t &amount, int &num_vouts_received, uint64_t &tx_money_got_in_outs, rct::key &mask, std::vector &outs); + void scan_output(const cryptonote::account_keys &keys, const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, uint64_t &tx_money_got_in_outs, std::vector &outs); cryptonote::account_base m_account; boost::optional m_daemon_login;