aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r--src/wallet/wallet2.cpp45
1 files changed, 36 insertions, 9 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 592d529be..45f991b81 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -2772,9 +2772,8 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
{
if (tx_cache_data[i].empty())
continue;
- tpool.submit(&waiter, [&hwdev, &gender, &tx_cache_data, i]() {
+ tpool.submit(&waiter, [&gender, &tx_cache_data, i]() {
auto &slot = tx_cache_data[i];
- boost::unique_lock<hw::device> hwdev_lock(hwdev);
for (auto &iod: slot.primary)
gender(iod);
for (auto &iod: slot.additional)
@@ -9809,13 +9808,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;
@@ -9828,12 +9832,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;
@@ -10103,6 +10110,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");
@@ -10115,20 +10123,32 @@ 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);
- dsts[0].amount -= available_amount;
- available_amount = 0;
+ 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;
+ }
}
}
@@ -10136,8 +10156,15 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
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)
{