aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwhythat <whythat@protonmail.com>2018-05-06 11:45:04 +0300
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-09-18 11:02:03 +0000
commit4ed30bab500dbe2ad94dcb44a0f198f94615836a (patch)
tree6adc430bb2d0f618fc4d9fd875b7577641e23eae
parentwallet: add 'outputs' option for sweep_* commands (diff)
downloadmonero-4ed30bab500dbe2ad94dcb44a0f198f94615836a.tar.xz
wallet: implement coin splitting for sweep_* 'outputs' option
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
-rw-r--r--src/wallet/wallet2.cpp28
1 files changed, 25 insertions, 3 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index fad904031..0ab1035dd 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -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");
@@ -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);