From d86ae2bec6737ca1c1f85b3a8395a4a241659a72 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 7 Jan 2017 16:06:07 +0000 Subject: wallet2: reuse fake outs when adjusting fee on transfer This avoids indirectly leaking the real output to the daemon, and is faster. This will still happen for more complex cases, especially when cancelling a tx and "re-rolling" it. --- src/wallet/wallet2.cpp | 66 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 21 deletions(-) (limited to 'src/wallet/wallet2.cpp') diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 8badebbfa..1d990d6d5 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3400,8 +3400,7 @@ std::vector wallet2::create_transactions(std::vector -void wallet2::get_outs(std::vector> &outs, const std::list &selected_transfers, size_t fake_outputs_count) +void wallet2::get_outs(std::vector> &outs, const std::list &selected_transfers, size_t fake_outputs_count) { LOG_PRINT_L2("fake_outputs_count: " << fake_outputs_count); outs.clear(); @@ -3492,6 +3491,7 @@ void wallet2::get_outs(std::vector> &outs, const std::list> &outs, const std::list()); + outs.push_back(std::vector()); outs.back().reserve(fake_outputs_count + 1); const rct::key mask = td.is_rct() ? rct::commit(td.amount(), td.m_mask) : rct::zeroCommit(td.amount()); @@ -3616,7 +3616,7 @@ void wallet2::get_outs(std::vector> &outs, const std::list(a) < std::get<0>(b); }); + std::sort(outs.back().begin(), outs.back().end(), [](const get_outs_entry &a, const get_outs_entry &b) { return std::get<0>(a) < std::get<0>(b); }); } base += requested_outputs_count; } @@ -3627,7 +3627,7 @@ void wallet2::get_outs(std::vector> &outs, const std::list v; + std::vector v; const rct::key mask = td.is_rct() ? rct::commit(td.amount(), td.m_mask) : rct::zeroCommit(td.amount()); v.push_back(std::make_tuple(td.m_global_output_index, boost::get(td.m_tx.vout[td.m_internal_output_index].target).key, mask)); outs.push_back(v); @@ -3636,7 +3636,8 @@ void wallet2::get_outs(std::vector> &outs, const std::list -void wallet2::transfer_selected(const std::vector& dsts, const std::list selected_transfers, size_t fake_outputs_count, +void wallet2::transfer_selected(const std::vector& dsts, const std::list selected_transfers, size_t fake_outputs_count, + std::vector> &outs, uint64_t unlock_time, uint64_t fee, const std::vector& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx) { using namespace cryptonote; @@ -3666,11 +3667,11 @@ void wallet2::transfer_selected(const std::vector entry; - std::vector> outs; - get_outs(outs, selected_transfers, fake_outputs_count); // may throw + if (outs.empty()) + get_outs(outs, selected_transfers, fake_outputs_count); // may throw //prepare inputs + LOG_PRINT_L2("preparing outputs"); typedef cryptonote::tx_source_entry::output_entry tx_output_entry; size_t i = 0, out_index = 0; std::vector sources; @@ -3713,6 +3714,7 @@ void wallet2::transfer_selected(const std::vector dsts, const std::list selected_transfers, size_t fake_outputs_count, + std::vector> &outs, uint64_t unlock_time, uint64_t fee, const std::vector& extra, cryptonote::transaction& tx, pending_tx &ptx) { using namespace cryptonote; @@ -3782,7 +3788,7 @@ void wallet2::transfer_selected_rct(std::vector entry; - std::vector> outs; - get_outs(outs, selected_transfers, fake_outputs_count); // may throw + if (outs.empty()) + get_outs(outs, selected_transfers, fake_outputs_count); // may throw //prepare inputs + LOG_PRINT_L2("preparing outputs"); size_t i = 0, out_index = 0; std::vector sources; BOOST_FOREACH(size_t idx, selected_transfers) @@ -3853,6 +3859,7 @@ void wallet2::transfer_selected_rct(std::vector splitted_dsts = dsts; @@ -3864,9 +3871,11 @@ void wallet2::transfer_selected_rct(std::vector bool { @@ -3887,6 +3899,7 @@ void wallet2::transfer_selected_rct(std::vector wallet2::create_transactions_2(std::vector> outs; // for rct, since we don't see the amounts, we will try to make all transactions // look the same, with 1 or 2 inputs, and 2 outputs. One input is preferable, as // this prevents linking to another by provenance analysis, but two is ok if we // try to pick outputs not from the same block. We will get two outputs, one for // the destination, and one for change. + LOG_PRINT_L2("checking preferred"); std::vector prefered_inputs; uint64_t rct_outs_needed = 2 * (fake_outs_count + 1); rct_outs_needed += 100; // some fudge factor since we don't know how many are locked @@ -4128,6 +4144,7 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_from(const crypton std::vector txes; uint64_t needed_fee, available_for_fee = 0; uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit(); + std::vector> outs; const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0); const bool use_new_fee = use_fork_rules(3, -720 * 14); @@ -4386,6 +4407,9 @@ std::vector wallet2::create_transactions_from(const crypton uint64_t available_amount = td.amount(); accumulated_outputs += available_amount; + // clear any fake outs we'd already gathered, since we'll need a new set + outs.clear(); + // here, check if we need to sent tx and start a new one LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit " << upper_transaction_size_limit); @@ -4407,10 +4431,10 @@ std::vector wallet2::create_transactions_from(const crypton LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " destinations and " << tx.selected_transfers.size() << " outputs"); if (use_rct) - transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, unlock_time, needed_fee, extra, + transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, test_tx, test_ptx); else - transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, unlock_time, needed_fee, extra, + transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); auto txBlob = t_serializable_object_to_blob(test_ptx.tx); needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier); @@ -4424,10 +4448,10 @@ std::vector wallet2::create_transactions_from(const crypton LOG_PRINT_L2("We made a tx, adjusting fee and saving it"); tx.dsts[0].amount = available_for_fee - needed_fee; if (use_rct) - transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, unlock_time, needed_fee, extra, + transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, test_tx, test_ptx); else - transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, unlock_time, needed_fee, extra, + transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); txBlob = t_serializable_object_to_blob(test_ptx.tx); needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier); -- cgit v1.2.3