Skip to content

Commit

Permalink
wallet: implement coin splitting for sweep_* 'outputs' option
Browse files Browse the repository at this point in the history
Implemented strategy splits total amount into N equal parts,
where N is a specified number of outputs. If N > 1, dummy
change output is NOT created.

rebased by moneromooo
  • Loading branch information
rodentrabies authored and moneromooo-monero committed Sep 18, 2018
1 parent 24f5239 commit 4ed30ba
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions src/wallet/wallet2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8532,7 +8532,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton

needed_fee = estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, base_fee, fee_multiplier, fee_quantization_mask);

tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress));
// add N - 1 outputs for correct initial fee estimation
for (size_t i = 0; i < ((outputs > 1) ? outputs - 1 : outputs); ++i)
tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress));

LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " destinations and " <<
tx.selected_transfers.size() << " outputs");
Expand All @@ -8544,15 +8546,35 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
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(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
available_for_fee = test_ptx.fee + test_ptx.dests[0].amount + test_ptx.change_dts.amount;
available_for_fee = test_ptx.fee + test_ptx.change_dts.amount;
for (auto &dt: test_ptx.dests)
available_for_fee += dt.amount;
LOG_PRINT_L2("Made a " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(available_for_fee) << " available for fee (" <<
print_money(needed_fee) << " needed)");

// add last output, missed for fee estimation
if (outputs > 1)
tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress));

THROW_WALLET_EXCEPTION_IF(needed_fee > available_for_fee, error::wallet_internal_error, "Transaction cannot pay for itself");

do {
LOG_PRINT_L2("We made a tx, adjusting fee and saving it");
tx.dsts[0].amount = available_for_fee - needed_fee;
// distribute total transferred amount between outputs
uint64_t amount_transferred = available_for_fee - needed_fee;
uint64_t dt_amount = amount_transferred / outputs;
// residue is distributed as one atomic unit per output until it reaches zero
uint64_t residue = amount_transferred % outputs;
for (auto &dt: tx.dsts)
{
uint64_t dt_residue = 0;
if (residue > 0)
{
dt_residue = 1;
residue -= 1;
}
dt.amount = dt_amount + dt_residue;
}
if (use_rct)
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
test_tx, test_ptx, range_proof_type);
Expand Down

0 comments on commit 4ed30ba

Please sign in to comment.