From a970a4e3cf03dd714713f1ac1274ca1f41bc4583 Mon Sep 17 00:00:00 2001 From: luigi1111 Date: Tue, 1 Nov 2016 11:24:04 -0500 Subject: [PATCH] refresh speedup Compute derivation only once per tx, instead of once per output. Approx 33% faster while using 75% as much CPU on my machine. Note old functions in cryptonote_core (lookup_acc_outs and is_out_to_acc) are still used by tests. --- .../cryptonote_format_utils.cpp | 7 +++++ src/cryptonote_core/cryptonote_format_utils.h | 1 + src/wallet/wallet2.cpp | 29 +++++++++---------- src/wallet/wallet2.h | 2 +- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index 6d64a43c..234422e3 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -876,6 +876,13 @@ namespace cryptonote return pk == out_key.key; } //--------------------------------------------------------------- + bool is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index) + { + crypto::public_key pk; + derive_public_key(derivation, output_index, spend_public_key, pk); + return pk == out_key.key; + } + //--------------------------------------------------------------- bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered) { crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx); diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h index 24db8008..d5dd6494 100644 --- a/src/cryptonote_core/cryptonote_format_utils.h +++ b/src/cryptonote_core/cryptonote_format_utils.h @@ -115,6 +115,7 @@ namespace cryptonote bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id); bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, size_t output_index); + bool is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& money_transfered); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered); bool get_tx_fee(const transaction& tx, uint64_t & fee); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 8ea60537..5a59c6f7 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -195,7 +195,7 @@ void wallet2::set_unspent(size_t idx) td.m_spent_height = 0; } //---------------------------------------------------------------------------------------------------- -void wallet2::check_acc_out(const account_keys &acc, const tx_out &o, const crypto::public_key &tx_pub_key, 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, bool &received, uint64_t &money_transfered, bool &error) const { if (o.target.type() != typeid(txout_to_key)) { @@ -203,7 +203,7 @@ void wallet2::check_acc_out(const account_keys &acc, const tx_out &o, const cryp LOG_ERROR("wrong type id in transaction out"); return; } - received = is_out_to_acc(acc, boost::get(o.target), tx_pub_key, i); + received = is_out_to_acc_precomp(spend_public_key, boost::get(o.target), derivation, i); if(received) { money_transfered = o.amount; // may be 0 for ringct outputs @@ -308,6 +308,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s std::deque amount(tx.vout.size()); std::deque mask(tx.vout.size()); int threads = tools::get_max_concurrency(); + 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); if (miner_tx && m_refresh_type == RefreshNoCoinbase) { // assume coinbase isn't for us @@ -316,7 +319,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s { uint64_t money_transfered = 0; bool error = false, received = false; - check_acc_out(m_account.get_keys(), tx.vout[0], tx_pub_key, 0, received, money_transfered, error); + check_acc_out_precomp(keys.m_account_address.m_spend_public_key, tx.vout[0], derivation, 0, received, money_transfered, error); if (error) { r = false; @@ -326,14 +329,13 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s // this assumes that the miner tx pays a single address if (received) { - wallet_generate_key_image_helper(m_account.get_keys(), tx_pub_key, 0, in_ephemeral[0], ki[0]); + wallet_generate_key_image_helper(keys, tx_pub_key, 0, in_ephemeral[0], ki[0]); THROW_WALLET_EXCEPTION_IF(in_ephemeral[0].pub != boost::get(tx.vout[0].target).key, error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key"); outs.push_back(0); if (money_transfered == 0) { - const cryptonote::account_keys& keys = m_account.get_keys(); money_transfered = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, 0, mask[0]); } amount[0] = money_transfered; @@ -349,14 +351,13 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice)); } - const account_keys &keys = m_account.get_keys(); 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) { - ioservice.dispatch(boost::bind(&wallet2::check_acc_out, this, std::cref(keys), std::cref(tx.vout[i]), std::cref(tx_pub_key), i, + ioservice.dispatch(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]))); } KILL_IOSERVICE(); @@ -369,14 +370,13 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s } if (received[i]) { - wallet_generate_key_image_helper(m_account.get_keys(), tx_pub_key, i, in_ephemeral[i], ki[i]); + wallet_generate_key_image_helper(keys, tx_pub_key, i, in_ephemeral[i], ki[i]); THROW_WALLET_EXCEPTION_IF(in_ephemeral[i].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[i] == 0) { - const cryptonote::account_keys& keys = m_account.get_keys(); money_transfered[i] = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]); } tx_money_got_in_outs += money_transfered[i]; @@ -397,13 +397,12 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice)); } - const account_keys &keys = m_account.get_keys(); 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) { - ioservice.dispatch(boost::bind(&wallet2::check_acc_out, this, std::cref(keys), std::cref(tx.vout[i]), std::cref(tx_pub_key), i, + ioservice.dispatch(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]))); } KILL_IOSERVICE(); @@ -417,14 +416,13 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s } if (received[i]) { - wallet_generate_key_image_helper(m_account.get_keys(), tx_pub_key, i, in_ephemeral[i], ki[i]); + wallet_generate_key_image_helper(keys, tx_pub_key, i, in_ephemeral[i], ki[i]); THROW_WALLET_EXCEPTION_IF(in_ephemeral[i].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[i] == 0) { - const cryptonote::account_keys& keys = m_account.get_keys(); money_transfered[i] = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]); } tx_money_got_in_outs += money_transfered[i]; @@ -439,7 +437,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s { uint64_t money_transfered = 0; bool error = false, received = false; - check_acc_out(m_account.get_keys(), tx.vout[i], tx_pub_key, i, received, money_transfered, error); + check_acc_out_precomp(keys.m_account_address.m_spend_public_key, tx.vout[i], derivation, i, received, money_transfered, error); if (error) { r = false; @@ -449,14 +447,13 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s { if (received) { - wallet_generate_key_image_helper(m_account.get_keys(), tx_pub_key, i, in_ephemeral[i], ki[i]); + wallet_generate_key_image_helper(keys, tx_pub_key, i, in_ephemeral[i], ki[i]); THROW_WALLET_EXCEPTION_IF(in_ephemeral[i].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) { - const cryptonote::account_keys& keys = m_account.get_keys(); money_transfered = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]); } amount[i] = money_transfered; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 6cd288ac..e17d4a5a 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -515,7 +515,7 @@ namespace tools void check_genesis(const crypto::hash& genesis_hash) const; //throws bool generate_chacha8_key_from_secret_keys(crypto::chacha8_key &key) const; crypto::hash get_payment_id(const pending_tx &ptx) const; - void check_acc_out(const cryptonote::account_keys &acc, const cryptonote::tx_out &o, const crypto::public_key &tx_pub_key, size_t i, bool &received, uint64_t &money_transfered, bool &error) const; + void check_acc_out_precomp(const crypto::public_key &spend_public_key, const cryptonote::tx_out &o, const crypto::key_derivation &derivation, size_t i, bool &received, uint64_t &money_transfered, bool &error) const; void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const; uint64_t get_upper_tranaction_size_limit(); std::vector get_unspent_amounts_vector();