Stop adding more outputs than bulletproof allows
If more outputs are requested, they are split across multiple transactions. #7322
This commit is contained in:
parent
cb70ae9450
commit
b587ffa1fd
@ -9778,13 +9778,18 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||
|
||||
TX() : weight(0), needed_fee(0) {}
|
||||
|
||||
void add(const cryptonote::tx_destination_entry &de, uint64_t amount, unsigned int original_output_index, bool merge_destinations) {
|
||||
/* Add an output to the transaction.
|
||||
* Returns True if the output was added, False if there are no more available output slots.
|
||||
*/
|
||||
bool add(const cryptonote::tx_destination_entry &de, uint64_t amount, unsigned int original_output_index, bool merge_destinations, size_t max_dsts) {
|
||||
if (merge_destinations)
|
||||
{
|
||||
std::vector<cryptonote::tx_destination_entry>::iterator i;
|
||||
i = std::find_if(dsts.begin(), dsts.end(), [&](const cryptonote::tx_destination_entry &d) { return !memcmp (&d.addr, &de.addr, sizeof(de.addr)); });
|
||||
if (i == dsts.end())
|
||||
{
|
||||
if (dsts.size() >= max_dsts)
|
||||
return false;
|
||||
dsts.push_back(de);
|
||||
i = dsts.end() - 1;
|
||||
i->amount = 0;
|
||||
@ -9797,12 +9802,15 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||
std::string("original_output_index too large: ") + std::to_string(original_output_index) + " > " + std::to_string(dsts.size()));
|
||||
if (original_output_index == dsts.size())
|
||||
{
|
||||
if (dsts.size() >= max_dsts)
|
||||
return false;
|
||||
dsts.push_back(de);
|
||||
dsts.back().amount = 0;
|
||||
}
|
||||
THROW_WALLET_EXCEPTION_IF(memcmp(&dsts[original_output_index].addr, &de.addr, sizeof(de.addr)), error::wallet_internal_error, "Mismatched destination address");
|
||||
dsts[original_output_index].amount += amount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
std::vector<TX> txes;
|
||||
@ -10072,6 +10080,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||
// clear any fake outs we'd already gathered, since we'll need a new set
|
||||
outs.clear();
|
||||
|
||||
bool out_slots_exhausted = false;
|
||||
if (adding_fee)
|
||||
{
|
||||
LOG_PRINT_L2("We need more fee, adding it to fee");
|
||||
@ -10084,29 +10093,48 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||
// we can fully pay that destination
|
||||
LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
|
||||
" for " << print_money(dsts[0].amount));
|
||||
tx.add(dsts[0], dsts[0].amount, original_output_index, m_merge_destinations);
|
||||
if (!tx.add(dsts[0], dsts[0].amount, original_output_index, m_merge_destinations, BULLETPROOF_MAX_OUTPUTS-1))
|
||||
{
|
||||
LOG_PRINT_L2("Didn't pay: ran out of output slots");
|
||||
out_slots_exhausted = true;
|
||||
break;
|
||||
}
|
||||
available_amount -= dsts[0].amount;
|
||||
dsts[0].amount = 0;
|
||||
pop_index(dsts, 0);
|
||||
++original_output_index;
|
||||
}
|
||||
|
||||
if (available_amount > 0 && !dsts.empty() && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) {
|
||||
if (!out_slots_exhausted && available_amount > 0 && !dsts.empty() && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) {
|
||||
// we can partially fill that destination
|
||||
LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
|
||||
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
|
||||
tx.add(dsts[0], available_amount, original_output_index, m_merge_destinations);
|
||||
if (tx.add(dsts[0], available_amount, original_output_index, m_merge_destinations, BULLETPROOF_MAX_OUTPUTS-1))
|
||||
{
|
||||
dsts[0].amount -= available_amount;
|
||||
available_amount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_L2("Didn't pay: ran out of output slots");
|
||||
out_slots_exhausted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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_weight_limit);
|
||||
bool try_tx = false;
|
||||
|
||||
// If the new transaction is full, create it and start a new one
|
||||
if (out_slots_exhausted)
|
||||
{
|
||||
LOG_PRINT_L2("Transaction is full, will create it and start a new tx");
|
||||
try_tx = true;
|
||||
}
|
||||
// if we have preferred picks, but haven't yet used all of them, continue
|
||||
if (preferred_inputs.empty())
|
||||
else if (preferred_inputs.empty())
|
||||
{
|
||||
if (adding_fee)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user