diff options
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r-- | src/wallet/wallet2.cpp | 45 |
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) { |