From 58cceaad7102c8e1c7130c47fa22cdb50eab97e8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 11 Jun 2018 12:01:41 +0100 Subject: [PATCH] wallet2: fix double counting outs if the tx pubkey is duplicated --- src/wallet/wallet2.cpp | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 1a1537e62..b080172e0 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1172,6 +1172,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote // Don't try to extract tx public key if tx has no ouputs size_t pk_index = 0; std::vector tx_scan_info(tx.vout.size()); + std::unordered_set public_keys_seen; while (!tx.vout.empty()) { // if tx.vout is not empty, we loop through all tx pubkeys @@ -1192,6 +1193,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote error::wallet_internal_error, "tx_cache_data is out of sync"); } + if (public_keys_seen.find(pub_key_field.pub_key) != public_keys_seen.end()) + { + MWARNING("The same transaction pubkey is present more than once, ignoring extra instance"); + continue; + } + public_keys_seen.insert(pub_key_field.pub_key); + int num_vouts_received = 0; tx_pub_key = pub_key_field.pub_key; tools::threadpool& tpool = tools::threadpool::getInstance(); @@ -1216,16 +1224,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote memcpy(&derivation, rct::identity().bytes, sizeof(derivation)); } - // additional tx pubkeys and derivations for multi-destination transfers involving one or more subaddresses - if (find_tx_extra_field_by_type(tx_extra_fields, additional_tx_pub_keys)) + if (pk_index == 1) { - for (size_t i = 0; i < additional_tx_pub_keys.data.size(); ++i) + // additional tx pubkeys and derivations for multi-destination transfers involving one or more subaddresses + if (find_tx_extra_field_by_type(tx_extra_fields, additional_tx_pub_keys)) { - additional_derivations.push_back({}); - if (!hwdev.generate_key_derivation(additional_tx_pub_keys.data[i], keys.m_view_secret_key, additional_derivations.back())) + for (size_t i = 0; i < additional_tx_pub_keys.data.size(); ++i) { - MWARNING("Failed to generate key derivation from additional tx pubkey in " << txid << ", skipping"); - memcpy(&additional_derivations.back(), rct::identity().bytes, sizeof(crypto::key_derivation)); + additional_derivations.push_back({}); + if (!hwdev.generate_key_derivation(additional_tx_pub_keys.data[i], keys.m_view_secret_key, additional_derivations.back())) + { + MWARNING("Failed to generate key derivation from additional tx pubkey in " << txid << ", skipping"); + memcpy(&additional_derivations.back(), rct::identity().bytes, sizeof(crypto::key_derivation)); + } } } } @@ -1236,10 +1247,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote error::wallet_internal_error, "pk_index out of range of tx_cache_data"); is_out_data_ptr = &tx_cache_data.primary[pk_index - 1]; derivation = tx_cache_data.primary[pk_index - 1].derivation; - for (size_t n = 0; n < tx_cache_data.additional.size(); ++n) + if (pk_index == 1) { - additional_tx_pub_keys.data.push_back(tx_cache_data.additional[n].pkey); - additional_derivations.push_back(tx_cache_data.additional[n].derivation); + for (size_t n = 0; n < tx_cache_data.additional.size(); ++n) + { + additional_tx_pub_keys.data.push_back(tx_cache_data.additional[n].pkey); + additional_derivations.push_back(tx_cache_data.additional[n].derivation); + } } }