simplewallet: warn about correlations if print-ring-members is not set

The warning about spending more than one output with similar creation
time was skipped if print-ring-members was not set, and it defaults to
false, which means most people probably aren't getting this warning if
they spend correlated outputs.

Reported by SeventhAlpaca.
pull/241/head
moneromooo-monero 4 years ago
parent 72262b348a
commit 9989cb087e
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3

@ -6064,11 +6064,14 @@ std::pair<std::string, std::string> simple_wallet::show_outputs_line(const std::
return std::make_pair(ostr.str(), ring_str); return std::make_pair(ostr.str(), ring_str);
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending_tx>& ptx_vector, std::ostream& ostr) bool simple_wallet::process_ring_members(const std::vector<tools::wallet2::pending_tx>& ptx_vector, std::ostream& ostr, bool verbose)
{ {
uint32_t version; uint32_t version;
if (!try_connect_to_daemon(false, &version)) if (!try_connect_to_daemon(false, &version))
{
fail_msg_writer() << tr("failed to connect to daemon");
return false; return false;
}
// available for RPC version 1.4 or higher // available for RPC version 1.4 or higher
if (version < MAKE_CORE_RPC_VERSION(1, 4)) if (version < MAKE_CORE_RPC_VERSION(1, 4))
return true; return true;
@ -6084,7 +6087,8 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
{ {
const cryptonote::transaction& tx = ptx_vector[n].tx; const cryptonote::transaction& tx = ptx_vector[n].tx;
const tools::wallet2::tx_construction_data& construction_data = ptx_vector[n].construction_data; const tools::wallet2::tx_construction_data& construction_data = ptx_vector[n].construction_data;
ostr << boost::format(tr("\nTransaction %llu/%llu: txid=%s")) % (n + 1) % ptx_vector.size() % cryptonote::get_transaction_hash(tx); if (verbose)
ostr << boost::format(tr("\nTransaction %llu/%llu: txid=%s")) % (n + 1) % ptx_vector.size() % cryptonote::get_transaction_hash(tx);
// for each input // for each input
std::vector<uint64_t> spent_key_height(tx.vin.size()); std::vector<uint64_t> spent_key_height(tx.vin.size());
std::vector<crypto::hash> spent_key_txid (tx.vin.size()); std::vector<crypto::hash> spent_key_txid (tx.vin.size());
@ -6105,7 +6109,8 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
} }
const cryptonote::tx_source_entry& source = *sptr; const cryptonote::tx_source_entry& source = *sptr;
ostr << boost::format(tr("\nInput %llu/%llu (%s): amount=%s")) % (i + 1) % tx.vin.size() % epee::string_tools::pod_to_hex(in_key.k_image) % print_money(source.amount); if (verbose)
ostr << boost::format(tr("\nInput %llu/%llu (%s): amount=%s")) % (i + 1) % tx.vin.size() % epee::string_tools::pod_to_hex(in_key.k_image) % print_money(source.amount);
// convert relative offsets of ring member keys into absolute offsets (indices) associated with the amount // convert relative offsets of ring member keys into absolute offsets (indices) associated with the amount
std::vector<uint64_t> absolute_offsets = cryptonote::relative_output_offsets_to_absolute(in_key.key_offsets); std::vector<uint64_t> absolute_offsets = cryptonote::relative_output_offsets_to_absolute(in_key.key_offsets);
// get block heights from which those ring member keys originated // get block heights from which those ring member keys originated
@ -6135,7 +6140,8 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
return false; return false;
} }
} }
ostr << tr("\nOriginating block heights: "); if (verbose)
ostr << tr("\nOriginating block heights: ");
spent_key_height[i] = res.outs[source.real_output].height; spent_key_height[i] = res.outs[source.real_output].height;
spent_key_txid [i] = res.outs[source.real_output].txid; spent_key_txid [i] = res.outs[source.real_output].txid;
std::vector<uint64_t> heights(absolute_offsets.size(), 0); std::vector<uint64_t> heights(absolute_offsets.size(), 0);
@ -6144,7 +6150,8 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
heights[j] = res.outs[j].height; heights[j] = res.outs[j].height;
} }
std::pair<std::string, std::string> ring_str = show_outputs_line(heights, blockchain_height, source.real_output); std::pair<std::string, std::string> ring_str = show_outputs_line(heights, blockchain_height, source.real_output);
ostr << ring_str.first << tr("\n|") << ring_str.second << tr("|\n"); if (verbose)
ostr << ring_str.first << tr("\n|") << ring_str.second << tr("|\n");
} }
// warn if rings contain keys originating from the same tx or temporally very close block heights // warn if rings contain keys originating from the same tx or temporally very close block heights
bool are_keys_from_same_tx = false; bool are_keys_from_same_tx = false;
@ -6163,7 +6170,7 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
ostr ostr
<< tr("\nWarning: Some input keys being spent are from ") << tr("\nWarning: Some input keys being spent are from ")
<< (are_keys_from_same_tx ? tr("the same transaction") : tr("blocks that are temporally very close")) << (are_keys_from_same_tx ? tr("the same transaction") : tr("blocks that are temporally very close"))
<< tr(", which can break the anonymity of ring signature. Make sure this is intentional!"); << tr(", which can break the anonymity of ring signatures. Make sure this is intentional!");
} }
ostr << ENDL; ostr << ENDL;
} }
@ -6604,11 +6611,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
float days = locked_blocks / 720.0f; float days = locked_blocks / 720.0f;
prompt << boost::format(tr(".\nThis transaction (including %s change) will unlock on block %llu, in approximately %s days (assuming 2 minutes per block)")) % cryptonote::print_money(change) % ((unsigned long long)unlock_block) % days; prompt << boost::format(tr(".\nThis transaction (including %s change) will unlock on block %llu, in approximately %s days (assuming 2 minutes per block)")) % cryptonote::print_money(change) % ((unsigned long long)unlock_block) % days;
} }
if (m_wallet->print_ring_members()) if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
{ return false;
if (!print_ring_members(ptx_vector, prompt))
return false;
}
bool default_ring_size = true; bool default_ring_size = true;
for (const auto &ptx: ptx_vector) for (const auto &ptx: ptx_vector)
{ {
@ -7064,7 +7068,7 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector<st
if (subaddr_indices.size() > 1) if (subaddr_indices.size() > 1)
prompt << tr("WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy.\n"); prompt << tr("WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy.\n");
} }
if (m_wallet->print_ring_members() && !print_ring_members(ptx_vector, prompt)) if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
return true; return true;
if (ptx_vector.size() > 1) { if (ptx_vector.size() > 1) {
prompt << boost::format(tr("Sweeping %s in %llu transactions for a total fee of %s. Is this okay?")) % prompt << boost::format(tr("Sweeping %s in %llu transactions for a total fee of %s. Is this okay?")) %
@ -7308,7 +7312,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
uint64_t total_fee = ptx_vector[0].fee; uint64_t total_fee = ptx_vector[0].fee;
uint64_t total_sent = m_wallet->get_transfer_details(ptx_vector[0].selected_transfers.front()).amount(); uint64_t total_sent = m_wallet->get_transfer_details(ptx_vector[0].selected_transfers.front()).amount();
std::ostringstream prompt; std::ostringstream prompt;
if (!print_ring_members(ptx_vector, prompt)) if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
return true; return true;
prompt << boost::format(tr("Sweeping %s for a total fee of %s. Is this okay?")) % prompt << boost::format(tr("Sweeping %s for a total fee of %s. Is this okay?")) %
print_money(total_sent) % print_money(total_sent) %

@ -270,7 +270,7 @@ namespace cryptonote
bool accept_loaded_tx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx, const std::string &extra_message = std::string()); bool accept_loaded_tx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx, const std::string &extra_message = std::string());
bool accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs); bool accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs);
bool accept_loaded_tx(const tools::wallet2::signed_tx_set &txs); bool accept_loaded_tx(const tools::wallet2::signed_tx_set &txs);
bool print_ring_members(const std::vector<tools::wallet2::pending_tx>& ptx_vector, std::ostream& ostr); bool process_ring_members(const std::vector<tools::wallet2::pending_tx>& ptx_vector, std::ostream& ostr, bool verbose);
std::string get_prompt() const; std::string get_prompt() const;
bool print_seed(bool encrypted); bool print_seed(bool encrypted);
void key_images_sync_intern(); void key_images_sync_intern();

Loading…
Cancel
Save