mirror of
https://github.com/monero-project/monero.git
synced 2024-10-01 11:49:47 -04:00
wallet2: minimize the number of construct_tx calls
This commit is contained in:
parent
9d505d26b8
commit
0b726be703
@ -455,6 +455,59 @@ void drop_from_short_history(std::list<crypto::hash> &short_chain_history, size_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size)
|
||||||
|
{
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
// tx prefix
|
||||||
|
|
||||||
|
// first few bytes
|
||||||
|
size += 1 + 6;
|
||||||
|
|
||||||
|
// vin
|
||||||
|
size += n_inputs * (1+6+(mixin+1)*2+32);
|
||||||
|
|
||||||
|
// vout
|
||||||
|
size += n_outputs * (6+32);
|
||||||
|
|
||||||
|
// extra
|
||||||
|
size += extra_size;
|
||||||
|
|
||||||
|
// rct signatures
|
||||||
|
|
||||||
|
// type
|
||||||
|
size += 1;
|
||||||
|
|
||||||
|
// rangeSigs
|
||||||
|
size += (2*64*32+32+64*32) * n_outputs;
|
||||||
|
|
||||||
|
// MGs
|
||||||
|
size += n_inputs * (64 * (mixin+1) + 32);
|
||||||
|
|
||||||
|
// mixRing - not serialized, can be reconstructed
|
||||||
|
/* size += 2 * 32 * (mixin+1) * n_inputs; */
|
||||||
|
|
||||||
|
// pseudoOuts
|
||||||
|
size += 32 * n_inputs;
|
||||||
|
// ecdhInfo
|
||||||
|
size += 2 * 32 * n_outputs;
|
||||||
|
// outPk - only commitment is saved
|
||||||
|
size += 32 * n_outputs;
|
||||||
|
// txnFee
|
||||||
|
size += 4;
|
||||||
|
|
||||||
|
LOG_PRINT_L2("estimated rct tx size for " << n_inputs << " with ring size " << (mixin+1) << " and " << n_outputs << ": " << size << " (" << ((32 * n_inputs/*+1*/) + 2 * 32 * (mixin+1) * n_inputs + 32 * n_outputs) << " saved)");
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size)
|
||||||
|
{
|
||||||
|
if (use_rct)
|
||||||
|
return estimate_rct_tx_size(n_inputs, mixin, n_outputs + 1, extra_size);
|
||||||
|
else
|
||||||
|
return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES + extra_size;
|
||||||
|
}
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|
||||||
namespace tools
|
namespace tools
|
||||||
@ -3990,7 +4043,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<crypto
|
|||||||
pending_tx ptx;
|
pending_tx ptx;
|
||||||
|
|
||||||
// loop until fee is met without increasing tx size to next KB boundary.
|
// loop until fee is met without increasing tx size to next KB boundary.
|
||||||
uint64_t needed_fee = 0;
|
const size_t estimated_tx_size = estimate_tx_size(false, unused_transfers_indices.size(), fake_outs_count, dst_vector.size(), extra.size());
|
||||||
|
uint64_t needed_fee = calculate_fee(fee_per_kb, estimated_tx_size, fee_multiplier);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
transfer(dst_vector, fake_outs_count, unused_transfers_indices, unlock_time, needed_fee, extra, tx, ptx, trusted_daemon);
|
transfer(dst_vector, fake_outs_count, unused_transfers_indices, unlock_time, needed_fee, extra, tx, ptx, trusted_daemon);
|
||||||
@ -4725,59 +4779,6 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
|||||||
LOG_PRINT_L2("transfer_selected_rct done");
|
LOG_PRINT_L2("transfer_selected_rct done");
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs)
|
|
||||||
{
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
// tx prefix
|
|
||||||
|
|
||||||
// first few bytes
|
|
||||||
size += 1 + 6;
|
|
||||||
|
|
||||||
// vin
|
|
||||||
size += n_inputs * (1+6+(mixin+1)*2+32);
|
|
||||||
|
|
||||||
// vout
|
|
||||||
size += n_outputs * (6+32);
|
|
||||||
|
|
||||||
// extra
|
|
||||||
size += 40;
|
|
||||||
|
|
||||||
// rct signatures
|
|
||||||
|
|
||||||
// type
|
|
||||||
size += 1;
|
|
||||||
|
|
||||||
// rangeSigs
|
|
||||||
size += (2*64*32+32+64*32) * n_outputs;
|
|
||||||
|
|
||||||
// MGs
|
|
||||||
size += n_inputs * (64 * (mixin+1) + 32);
|
|
||||||
|
|
||||||
// mixRing - not serialized, can be reconstructed
|
|
||||||
/* size += 2 * 32 * (mixin+1) * n_inputs; */
|
|
||||||
|
|
||||||
// pseudoOuts
|
|
||||||
size += 32 * n_inputs;
|
|
||||||
// ecdhInfo
|
|
||||||
size += 2 * 32 * n_outputs;
|
|
||||||
// outPk - only commitment is saved
|
|
||||||
size += 32 * n_outputs;
|
|
||||||
// txnFee
|
|
||||||
size += 4;
|
|
||||||
|
|
||||||
LOG_PRINT_L2("estimated rct tx size for " << n_inputs << " with ring size " << (mixin+1) << " and " << n_outputs << ": " << size << " (" << ((32 * n_inputs/*+1*/) + 2 * 32 * (mixin+1) * n_inputs + 32 * n_outputs) << " saved)");
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs)
|
|
||||||
{
|
|
||||||
if (use_rct)
|
|
||||||
return estimate_rct_tx_size(n_inputs, mixin, n_outputs + 1);
|
|
||||||
else
|
|
||||||
return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices) const
|
std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices) const
|
||||||
{
|
{
|
||||||
std::vector<size_t> picks;
|
std::vector<size_t> picks;
|
||||||
@ -4785,19 +4786,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
|
|||||||
|
|
||||||
LOG_PRINT_L2("pick_preferred_rct_inputs: needed_money " << print_money(needed_money));
|
LOG_PRINT_L2("pick_preferred_rct_inputs: needed_money " << print_money(needed_money));
|
||||||
|
|
||||||
// try to find a rct input of enough size
|
// try to find two outputs
|
||||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
|
||||||
{
|
|
||||||
const transfer_details& td = m_transfers[i];
|
|
||||||
if (!td.m_spent && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
|
|
||||||
{
|
|
||||||
LOG_PRINT_L2("We can use " << i << " alone: " << print_money(td.amount()));
|
|
||||||
picks.push_back(i);
|
|
||||||
return picks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// then try to find two outputs
|
|
||||||
// this could be made better by picking one of the outputs to be a small one, since those
|
// this could be made better by picking one of the outputs to be a small one, since those
|
||||||
// are less useful since often below the needed money, so if one can be used in a pair,
|
// are less useful since often below the needed money, so if one can be used in a pair,
|
||||||
// it gets rid of it for the future
|
// it gets rid of it for the future
|
||||||
@ -5551,7 +5540,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
{
|
{
|
||||||
// this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
|
// this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
|
||||||
// will get us a known fee.
|
// will get us a known fee.
|
||||||
uint64_t estimated_fee = calculate_fee(fee_per_kb, estimate_rct_tx_size(2, fake_outs_count + 1, 2), fee_multiplier);
|
uint64_t estimated_fee = calculate_fee(fee_per_kb, estimate_rct_tx_size(2, fake_outs_count, 2, extra.size()), fee_multiplier);
|
||||||
preferred_inputs = pick_preferred_rct_inputs(needed_money + estimated_fee, subaddr_account, subaddr_indices);
|
preferred_inputs = pick_preferred_rct_inputs(needed_money + estimated_fee, subaddr_account, subaddr_indices);
|
||||||
if (!preferred_inputs.empty())
|
if (!preferred_inputs.empty())
|
||||||
{
|
{
|
||||||
@ -5588,7 +5577,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
unsigned int original_output_index = 0;
|
unsigned int original_output_index = 0;
|
||||||
std::vector<size_t>* unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second;
|
std::vector<size_t>* unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second;
|
||||||
std::vector<size_t>* unused_dust_indices = &unused_dust_indices_per_subaddr[0].second;
|
std::vector<size_t>* unused_dust_indices = &unused_dust_indices_per_subaddr[0].second;
|
||||||
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)) {
|
while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) {
|
||||||
TX &tx = txes.back();
|
TX &tx = txes.back();
|
||||||
|
|
||||||
LOG_PRINT_L2("Start of loop with " << unused_transfers_indices->size() << " " << unused_dust_indices->size());
|
LOG_PRINT_L2("Start of loop with " << unused_transfers_indices->size() << " " << unused_dust_indices->size());
|
||||||
@ -5606,7 +5595,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
// get a random unspent output and use it to pay part (or all) of the current destination (and maybe next one, etc)
|
// get a random unspent output and use it to pay part (or all) of the current destination (and maybe next one, etc)
|
||||||
// This could be more clever, but maybe at the cost of making probabilistic inferences easier
|
// This could be more clever, but maybe at the cost of making probabilistic inferences easier
|
||||||
size_t idx;
|
size_t idx;
|
||||||
if ((dsts.empty() || dsts[0].amount == 0) && !adding_fee) {
|
if (!preferred_inputs.empty()) {
|
||||||
|
idx = pop_back(preferred_inputs);
|
||||||
|
pop_if_present(*unused_transfers_indices, idx);
|
||||||
|
pop_if_present(*unused_dust_indices, idx);
|
||||||
|
} else if ((dsts.empty() || dsts[0].amount == 0) && !adding_fee) {
|
||||||
// the "make rct txes 2/2" case - we pick a small value output to "clean up" the wallet too
|
// the "make rct txes 2/2" case - we pick a small value output to "clean up" the wallet too
|
||||||
std::vector<size_t> indices = get_only_rct(*unused_dust_indices, *unused_transfers_indices);
|
std::vector<size_t> indices = get_only_rct(*unused_dust_indices, *unused_transfers_indices);
|
||||||
idx = pop_best_value(indices, tx.selected_transfers, true);
|
idx = pop_best_value(indices, tx.selected_transfers, true);
|
||||||
@ -5629,10 +5622,6 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
}
|
}
|
||||||
pop_if_present(*unused_transfers_indices, idx);
|
pop_if_present(*unused_transfers_indices, idx);
|
||||||
pop_if_present(*unused_dust_indices, idx);
|
pop_if_present(*unused_dust_indices, idx);
|
||||||
} else if (!preferred_inputs.empty()) {
|
|
||||||
idx = pop_back(preferred_inputs);
|
|
||||||
pop_if_present(*unused_transfers_indices, idx);
|
|
||||||
pop_if_present(*unused_dust_indices, idx);
|
|
||||||
} else
|
} else
|
||||||
idx = pop_best_value(unused_transfers_indices->empty() ? *unused_dust_indices : *unused_transfers_indices, tx.selected_transfers);
|
idx = pop_best_value(unused_transfers_indices->empty() ? *unused_dust_indices : *unused_transfers_indices, tx.selected_transfers);
|
||||||
|
|
||||||
@ -5654,7 +5643,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()) < TX_SIZE_TARGET(upper_transaction_size_limit))
|
while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size()) < TX_SIZE_TARGET(upper_transaction_size_limit))
|
||||||
{
|
{
|
||||||
// we can fully pay that destination
|
// we can fully pay that destination
|
||||||
LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
|
LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
|
||||||
@ -5666,7 +5655,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
++original_output_index;
|
++original_output_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (available_amount > 0 && !dsts.empty() && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()) < TX_SIZE_TARGET(upper_transaction_size_limit)) {
|
if (available_amount > 0 && !dsts.empty() && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size()) < TX_SIZE_TARGET(upper_transaction_size_limit)) {
|
||||||
// we can partially fill that destination
|
// we can partially fill that destination
|
||||||
LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
|
LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
|
||||||
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
|
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
|
||||||
@ -5679,26 +5668,31 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
// here, check if we need to sent tx and start a new one
|
// 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 "
|
LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit "
|
||||||
<< upper_transaction_size_limit);
|
<< upper_transaction_size_limit);
|
||||||
bool try_tx;
|
bool try_tx = false;
|
||||||
if (adding_fee)
|
// if we have preferred picks, but haven't yet used all of them, continue
|
||||||
|
if (preferred_inputs.empty())
|
||||||
{
|
{
|
||||||
/* might not actually be enough if adding this output bumps size to next kB, but we need to try */
|
if (adding_fee)
|
||||||
try_tx = available_for_fee >= needed_fee;
|
{
|
||||||
}
|
/* might not actually be enough if adding this output bumps size to next kB, but we need to try */
|
||||||
else
|
try_tx = available_for_fee >= needed_fee;
|
||||||
{
|
}
|
||||||
const size_t estimated_rct_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size());
|
else
|
||||||
try_tx = dsts.empty() || (estimated_rct_tx_size >= TX_SIZE_TARGET(upper_transaction_size_limit));
|
{
|
||||||
|
const size_t estimated_rct_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size());
|
||||||
|
try_tx = dsts.empty() || (estimated_rct_tx_size >= TX_SIZE_TARGET(upper_transaction_size_limit));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try_tx) {
|
if (try_tx) {
|
||||||
cryptonote::transaction test_tx;
|
cryptonote::transaction test_tx;
|
||||||
pending_tx test_ptx;
|
pending_tx test_ptx;
|
||||||
|
|
||||||
needed_fee = 0;
|
const size_t estimated_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size());
|
||||||
|
needed_fee = calculate_fee(fee_per_kb, estimated_tx_size, fee_multiplier);
|
||||||
|
|
||||||
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() << " outputs and " <<
|
||||||
tx.selected_transfers.size() << " outputs");
|
tx.selected_transfers.size() << " inputs");
|
||||||
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);
|
test_tx, test_ptx);
|
||||||
@ -5740,8 +5734,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("We made a tx, adjusting fee and saving it");
|
LOG_PRINT_L2("We made a tx, adjusting fee and saving it, we need " << print_money(needed_fee) << " and we have " << print_money(test_ptx.fee));
|
||||||
do {
|
while (needed_fee > test_ptx.fee) {
|
||||||
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);
|
test_tx, test_ptx);
|
||||||
@ -5752,7 +5746,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier);
|
needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier);
|
||||||
LOG_PRINT_L2("Made an attempt at a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
|
LOG_PRINT_L2("Made an attempt at a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
|
||||||
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
||||||
} while (needed_fee > test_ptx.fee);
|
}
|
||||||
|
|
||||||
LOG_PRINT_L2("Made a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
|
LOG_PRINT_L2("Made a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
|
||||||
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
||||||
@ -5934,14 +5928,15 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
// here, check if we need to sent tx and start a new one
|
// 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 "
|
LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit "
|
||||||
<< upper_transaction_size_limit);
|
<< upper_transaction_size_limit);
|
||||||
const size_t estimated_rct_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 1);
|
const size_t estimated_rct_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 1, extra.size());
|
||||||
bool try_tx = (unused_dust_indices.empty() && unused_transfers_indices.empty()) || ( estimated_rct_tx_size >= TX_SIZE_TARGET(upper_transaction_size_limit));
|
bool try_tx = (unused_dust_indices.empty() && unused_transfers_indices.empty()) || ( estimated_rct_tx_size >= TX_SIZE_TARGET(upper_transaction_size_limit));
|
||||||
|
|
||||||
if (try_tx) {
|
if (try_tx) {
|
||||||
cryptonote::transaction test_tx;
|
cryptonote::transaction test_tx;
|
||||||
pending_tx test_ptx;
|
pending_tx test_ptx;
|
||||||
|
|
||||||
needed_fee = 0;
|
const size_t estimated_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size());
|
||||||
|
needed_fee = calculate_fee(fee_per_kb, estimated_tx_size, fee_multiplier);
|
||||||
|
|
||||||
tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress));
|
tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress));
|
||||||
|
|
||||||
@ -5961,7 +5956,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
|
|
||||||
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 {
|
while (needed_fee > test_ptx.fee) {
|
||||||
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;
|
tx.dsts[0].amount = available_for_fee - needed_fee;
|
||||||
if (use_rct)
|
if (use_rct)
|
||||||
@ -5974,7 +5969,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier);
|
needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier);
|
||||||
LOG_PRINT_L2("Made an attempt at a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
|
LOG_PRINT_L2("Made an attempt at a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
|
||||||
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
||||||
} while (needed_fee > test_ptx.fee);
|
}
|
||||||
|
|
||||||
LOG_PRINT_L2("Made a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
|
LOG_PRINT_L2("Made a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
|
||||||
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
|
||||||
|
Loading…
Reference in New Issue
Block a user