mirror of
https://github.com/monero-project/monero.git
synced 2024-10-01 11:49:47 -04:00
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
67ba733de1
commit
76824bf827
@ -9768,13 +9768,18 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
|
|
||||||
TX() : weight(0), needed_fee(0) {}
|
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)
|
if (merge_destinations)
|
||||||
{
|
{
|
||||||
std::vector<cryptonote::tx_destination_entry>::iterator i;
|
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)); });
|
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 (i == dsts.end())
|
||||||
{
|
{
|
||||||
|
if (dsts.size() >= max_dsts)
|
||||||
|
return false;
|
||||||
dsts.push_back(de);
|
dsts.push_back(de);
|
||||||
i = dsts.end() - 1;
|
i = dsts.end() - 1;
|
||||||
i->amount = 0;
|
i->amount = 0;
|
||||||
@ -9787,12 +9792,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()));
|
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 (original_output_index == dsts.size())
|
||||||
{
|
{
|
||||||
|
if (dsts.size() >= max_dsts)
|
||||||
|
return false;
|
||||||
dsts.push_back(de);
|
dsts.push_back(de);
|
||||||
dsts.back().amount = 0;
|
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");
|
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;
|
dsts[original_output_index].amount += amount;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::vector<TX> txes;
|
std::vector<TX> txes;
|
||||||
@ -10062,6 +10070,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
|
// clear any fake outs we'd already gathered, since we'll need a new set
|
||||||
outs.clear();
|
outs.clear();
|
||||||
|
|
||||||
|
bool out_slots_exhausted = false;
|
||||||
if (adding_fee)
|
if (adding_fee)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("We need more fee, adding it to fee");
|
LOG_PRINT_L2("We need more fee, adding it to fee");
|
||||||
@ -10074,29 +10083,48 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
// 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_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
|
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));
|
" 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;
|
available_amount -= dsts[0].amount;
|
||||||
dsts[0].amount = 0;
|
dsts[0].amount = 0;
|
||||||
pop_index(dsts, 0);
|
pop_index(dsts, 0);
|
||||||
++original_output_index;
|
++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
|
// 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) <<
|
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));
|
" 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;
|
dsts[0].amount -= available_amount;
|
||||||
available_amount = 0;
|
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
|
// 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_weight_limit);
|
<< upper_transaction_weight_limit);
|
||||||
bool try_tx = false;
|
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 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)
|
if (adding_fee)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user