aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-07-08 11:01:13 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-07-08 12:56:51 +0100
commitfc39d3b23ce6762834b58b52b204f080b6b3288f (patch)
treed63355c60f2bed1c8850f51cf9697453f3217030 /src/wallet
parentMerge pull request #4094 (diff)
downloadmonero-fc39d3b23ce6762834b58b52b204f080b6b3288f.tar.xz
wallet2: ensure outputs are processed only once
This should be proof against any way one might get to multiple processing, such as generating the same derivation from the same pubkey, etc
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/wallet2.cpp31
-rw-r--r--src/wallet/wallet2.h1
2 files changed, 18 insertions, 14 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index d99371673..40a43b8e7 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1057,6 +1057,16 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio
tx_scan_info.error = false;
}
//----------------------------------------------------------------------------------------------------
+void wallet2::check_acc_out_precomp_once(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, const is_out_data *is_out_data, tx_scan_info_t &tx_scan_info, bool &already_seen) const
+{
+ tx_scan_info.received = boost::none;
+ if (already_seen)
+ return;
+ check_acc_out_precomp(o, derivation, additional_derivations, i, is_out_data, tx_scan_info);
+ if (tx_scan_info.received)
+ already_seen = true;
+}
+//----------------------------------------------------------------------------------------------------
static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &derivation, unsigned int i, rct::key & mask, hw::device &hwdev)
{
crypto::secret_key scalar1;
@@ -1173,7 +1183,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_t> tx_scan_info(tx.vout.size());
- std::unordered_set<crypto::public_key> public_keys_seen;
+ std::deque<bool> output_found(tx.vout.size(), false);
while (!tx.vout.empty())
{
// if tx.vout is not empty, we loop through all tx pubkeys
@@ -1194,13 +1204,6 @@ 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();
@@ -1264,7 +1267,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
else if (miner_tx && m_refresh_type == RefreshOptimizeCoinbase)
{
- check_acc_out_precomp(tx.vout[0], derivation, additional_derivations, 0, is_out_data_ptr, tx_scan_info[0]);
+ check_acc_out_precomp_once(tx.vout[0], derivation, additional_derivations, 0, is_out_data_ptr, tx_scan_info[0], output_found[0]);
THROW_WALLET_EXCEPTION_IF(tx_scan_info[0].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
// this assumes that the miner tx pays a single address
@@ -1274,8 +1277,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
// 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(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
- std::cref(is_out_data_ptr), std::ref(tx_scan_info[i])), true);
+ tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
+ std::cref(is_out_data_ptr), std::ref(tx_scan_info[i]), std::ref(output_found[i])), true);
}
waiter.wait(&tpool);
// then scan all outputs from 0
@@ -1297,8 +1300,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
{
for (size_t i = 0; i < tx.vout.size(); ++i)
{
- tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
- std::cref(is_out_data_ptr), std::ref(tx_scan_info[i])), true);
+ tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
+ std::cref(is_out_data_ptr), std::ref(tx_scan_info[i]), std::ref(output_found[i])), true);
}
waiter.wait(&tpool);
@@ -1319,7 +1322,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
{
for (size_t i = 0; i < tx.vout.size(); ++i)
{
- check_acc_out_precomp(tx.vout[i], derivation, additional_derivations, i, is_out_data_ptr, tx_scan_info[i]);
+ check_acc_out_precomp_once(tx.vout[i], derivation, additional_derivations, i, is_out_data_ptr, tx_scan_info[i], output_found[i]);
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
if (tx_scan_info[i].received)
{
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index d33d8258b..4d22b6915 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1181,6 +1181,7 @@ namespace tools
crypto::hash get_payment_id(const pending_tx &ptx) const;
void check_acc_out_precomp(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const;
void check_acc_out_precomp(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, const is_out_data *is_out_data, tx_scan_info_t &tx_scan_info) const;
+ void check_acc_out_precomp_once(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, const is_out_data *is_out_data, tx_scan_info_t &tx_scan_info, bool &already_seen) const;
void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const;
uint64_t get_upper_transaction_size_limit() const;
std::vector<uint64_t> get_unspent_amounts_vector() const;