From 20f71527690e8ccb8faeccdca72e1a76431b2cfd Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 22 Jan 2017 15:12:13 +0000 Subject: [PATCH] wallet2: fix sending a rct tx with a single output available This would have tried to send a second output to make the tx look like the 2/2 ideal, but it would not fail to find one because picking an output from preferred_inputs priority list did not remove it from the unused tranfer/dust outputs, so it would try to send the same output twice. While there, I also added a check to avoid sending a second input if it's related to the first. Better 1/2 than linking inputs, I think. --- src/wallet/wallet2.cpp | 53 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c08b16a5..4348b8a6 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -87,6 +87,8 @@ using namespace cryptonote; #define FEE_ESTIMATE_GRACE_BLOCKS 10 // estimate fee valid for that many blocks +#define SECOND_OUTPUT_RELATEDNESS_THRESHOLD 0.0f + #define KILL_IOSERVICE() \ do { \ work.reset(); \ @@ -2720,6 +2722,19 @@ namespace vec.pop_back(); return res; } + + template + void pop_if_present(std::vector& vec, T e) + { + for (size_t i = 0; i < vec.size(); ++i) + { + if (e == vec[i]) + { + pop_index (vec, i); + return; + } + } + } } //---------------------------------------------------------------------------------------------------- // This returns a handwavy estimation of how much two outputs are related @@ -4028,6 +4043,17 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money) co return picks; } +static bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector &unused_transfers_indices, const std::vector &unused_dust_indices) +{ + if (!use_rct) + return false; + if (n_transfers > 1) + return false; + if (unused_dust_indices.empty() && unused_transfers_indices.empty()) + return false; + return true; +} + // Another implementation of transaction creation that is hopefully better // While there is anything left to pay, it goes through random outputs and tries // to fill the next destination/amount. If it fully fills it, it will use the @@ -4152,9 +4178,19 @@ std::vector wallet2::create_transactions_2(std::vector 0) || adding_fee || (use_rct && txes.back().selected_transfers.size() == 1)) { + while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), unused_transfers_indices, unused_dust_indices)) { TX &tx = txes.back(); + LOG_PRINT_L2("Start of loop with " << unused_transfers_indices.size() << " " << unused_dust_indices.size()); + LOG_PRINT_L2("unused_transfers_indices:"); + for (auto t: unused_transfers_indices) + LOG_PRINT_L2(" " << t); + LOG_PRINT_L2("unused_dust_indices:"); + for (auto t: unused_dust_indices) + LOG_PRINT_L2(" " << t); + LOG_PRINT_L2("dsts size " << dsts.size() << ", first " << (dsts.empty() ? -1 : dsts[0].amount)); + LOG_PRINT_L2("adding_fee " << adding_fee << ", use_rct " << use_rct); + // if we need to spend money and don't have any left, we fail if (unused_dust_indices.empty() && unused_transfers_indices.empty()) { LOG_PRINT_L2("No more outputs to choose from"); @@ -4167,9 +4203,20 @@ std::vector wallet2::create_transactions_2(std::vector SECOND_OUTPUT_RELATEDNESS_THRESHOLD) + { + LOG_PRINT_L2("Second outout was not strictly needed, and relatedness " << relatedness << ", not adding"); + break; + } + } else idx = pop_best_value(unused_transfers_indices.empty() ? unused_dust_indices : unused_transfers_indices, tx.selected_transfers); const transfer_details &td = m_transfers[idx];