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
This commit is contained in:
parent
24f5239693
commit
4ed30bab50
|
@ -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);
|
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 " <<
|
LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " destinations and " <<
|
||||||
tx.selected_transfers.size() << " outputs");
|
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);
|
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);
|
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);
|
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 (" <<
|
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)");
|
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");
|
THROW_WALLET_EXCEPTION_IF(needed_fee > available_for_fee, error::wallet_internal_error, "Transaction cannot pay for itself");
|
||||||
|
|
||||||
do {
|
do {
|
||||||
LOG_PRINT_L2("We made a tx, adjusting fee and saving it");
|
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)
|
if (use_rct)
|
||||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, 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, range_proof_type);
|
test_tx, test_ptx, range_proof_type);
|
||||||
|
|
Loading…
Reference in New Issue