mirror of
https://codeberg.org/anoncontributorxmr/monero.git
synced 2024-12-24 14:17:46 +00:00
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.
This commit is contained in:
parent
b06c1abaa6
commit
a970a4e3cf
4 changed files with 22 additions and 17 deletions
|
@ -876,6 +876,13 @@ namespace cryptonote
|
||||||
return pk == out_key.key;
|
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<size_t>& outs, uint64_t& money_transfered)
|
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered)
|
||||||
{
|
{
|
||||||
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
|
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
|
||||||
|
|
|
@ -115,6 +115,7 @@ namespace cryptonote
|
||||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id);
|
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 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(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<size_t>& outs, uint64_t& money_transfered);
|
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered);
|
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||||
bool get_tx_fee(const transaction& tx, uint64_t & fee);
|
bool get_tx_fee(const transaction& tx, uint64_t & fee);
|
||||||
|
|
|
@ -195,7 +195,7 @@ void wallet2::set_unspent(size_t idx)
|
||||||
td.m_spent_height = 0;
|
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))
|
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");
|
LOG_ERROR("wrong type id in transaction out");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
received = is_out_to_acc(acc, boost::get<txout_to_key>(o.target), tx_pub_key, i);
|
received = is_out_to_acc_precomp(spend_public_key, boost::get<txout_to_key>(o.target), derivation, i);
|
||||||
if(received)
|
if(received)
|
||||||
{
|
{
|
||||||
money_transfered = o.amount; // may be 0 for ringct outputs
|
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<uint64_t> amount(tx.vout.size());
|
std::deque<uint64_t> amount(tx.vout.size());
|
||||||
std::deque<rct::key> mask(tx.vout.size());
|
std::deque<rct::key> mask(tx.vout.size());
|
||||||
int threads = tools::get_max_concurrency();
|
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)
|
if (miner_tx && m_refresh_type == RefreshNoCoinbase)
|
||||||
{
|
{
|
||||||
// assume coinbase isn't for us
|
// 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;
|
uint64_t money_transfered = 0;
|
||||||
bool error = false, received = false;
|
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)
|
if (error)
|
||||||
{
|
{
|
||||||
r = false;
|
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
|
// this assumes that the miner tx pays a single address
|
||||||
if (received)
|
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<cryptonote::txout_to_key>(tx.vout[0].target).key,
|
THROW_WALLET_EXCEPTION_IF(in_ephemeral[0].pub != boost::get<cryptonote::txout_to_key>(tx.vout[0].target).key,
|
||||||
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
||||||
|
|
||||||
outs.push_back(0);
|
outs.push_back(0);
|
||||||
if (money_transfered == 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]);
|
money_transfered = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, 0, mask[0]);
|
||||||
}
|
}
|
||||||
amount[0] = money_transfered;
|
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));
|
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
|
||||||
}
|
}
|
||||||
|
|
||||||
const account_keys &keys = m_account.get_keys();
|
|
||||||
std::vector<uint64_t> money_transfered(tx.vout.size());
|
std::vector<uint64_t> money_transfered(tx.vout.size());
|
||||||
std::deque<bool> error(tx.vout.size());
|
std::deque<bool> error(tx.vout.size());
|
||||||
std::deque<bool> received(tx.vout.size());
|
std::deque<bool> received(tx.vout.size());
|
||||||
// the first one was already checked
|
// the first one was already checked
|
||||||
for (size_t i = 1; i < tx.vout.size(); ++i)
|
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])));
|
std::ref(received[i]), std::ref(money_transfered[i]), std::ref(error[i])));
|
||||||
}
|
}
|
||||||
KILL_IOSERVICE();
|
KILL_IOSERVICE();
|
||||||
|
@ -369,14 +370,13 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
}
|
}
|
||||||
if (received[i])
|
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<cryptonote::txout_to_key>(tx.vout[i].target).key,
|
THROW_WALLET_EXCEPTION_IF(in_ephemeral[i].pub != boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key,
|
||||||
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
||||||
|
|
||||||
outs.push_back(i);
|
outs.push_back(i);
|
||||||
if (money_transfered[i] == 0)
|
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]);
|
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];
|
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));
|
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
|
||||||
}
|
}
|
||||||
|
|
||||||
const account_keys &keys = m_account.get_keys();
|
|
||||||
std::vector<uint64_t> money_transfered(tx.vout.size());
|
std::vector<uint64_t> money_transfered(tx.vout.size());
|
||||||
std::deque<bool> error(tx.vout.size());
|
std::deque<bool> error(tx.vout.size());
|
||||||
std::deque<bool> received(tx.vout.size());
|
std::deque<bool> received(tx.vout.size());
|
||||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
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])));
|
std::ref(received[i]), std::ref(money_transfered[i]), std::ref(error[i])));
|
||||||
}
|
}
|
||||||
KILL_IOSERVICE();
|
KILL_IOSERVICE();
|
||||||
|
@ -417,14 +416,13 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
}
|
}
|
||||||
if (received[i])
|
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<cryptonote::txout_to_key>(tx.vout[i].target).key,
|
THROW_WALLET_EXCEPTION_IF(in_ephemeral[i].pub != boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key,
|
||||||
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
||||||
|
|
||||||
outs.push_back(i);
|
outs.push_back(i);
|
||||||
if (money_transfered[i] == 0)
|
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]);
|
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];
|
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;
|
uint64_t money_transfered = 0;
|
||||||
bool error = false, received = false;
|
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)
|
if (error)
|
||||||
{
|
{
|
||||||
r = false;
|
r = false;
|
||||||
|
@ -449,14 +447,13 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
{
|
{
|
||||||
if (received)
|
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<cryptonote::txout_to_key>(tx.vout[i].target).key,
|
THROW_WALLET_EXCEPTION_IF(in_ephemeral[i].pub != boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key,
|
||||||
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
|
||||||
|
|
||||||
outs.push_back(i);
|
outs.push_back(i);
|
||||||
if (money_transfered == 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, i, mask[i]);
|
money_transfered = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]);
|
||||||
}
|
}
|
||||||
amount[i] = money_transfered;
|
amount[i] = money_transfered;
|
||||||
|
|
|
@ -515,7 +515,7 @@ namespace tools
|
||||||
void check_genesis(const crypto::hash& genesis_hash) const; //throws
|
void check_genesis(const crypto::hash& genesis_hash) const; //throws
|
||||||
bool generate_chacha8_key_from_secret_keys(crypto::chacha8_key &key) const;
|
bool generate_chacha8_key_from_secret_keys(crypto::chacha8_key &key) const;
|
||||||
crypto::hash get_payment_id(const pending_tx &ptx) 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;
|
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();
|
uint64_t get_upper_tranaction_size_limit();
|
||||||
std::vector<uint64_t> get_unspent_amounts_vector();
|
std::vector<uint64_t> get_unspent_amounts_vector();
|
||||||
|
|
Loading…
Reference in a new issue