diff options
author | Crypto City <cryptocity@example.com> | 2021-11-05 19:18:10 +0000 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2022-05-13 17:43:22 +0000 |
commit | 38cdf01c643df677a0c65b8932d62c3f6eb4e62b (patch) | |
tree | fa9b08fcfcbb2d98ac2095d0f4a38fbee715dfad /src/wallet/wallet2.cpp | |
parent | wallet2: speedup large tx construction: no pointless clsag generation (diff) | |
download | monero-38cdf01c643df677a0c65b8932d62c3f6eb4e62b.tar.xz |
wallet2: speedup large tx construction: batch ringdb lookups
3.3 seconds -> 2.8 seconds on a test case
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r-- | src/wallet/wallet2.cpp | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index e77e3bafd..3df67aac1 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7606,6 +7606,14 @@ bool wallet2::get_ring(const crypto::chacha_key &key, const crypto::key_image &k catch (const std::exception &e) { return false; } } +bool wallet2::get_rings(const crypto::chacha_key &key, const std::vector<crypto::key_image> &key_images, std::vector<std::vector<uint64_t>> &outs) +{ + if (!m_ringdb) + return false; + try { return m_ringdb->get_rings(key, key_images, outs); } + catch (const std::exception &e) { return false; } +} + bool wallet2::get_rings(const crypto::hash &txid, std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &outs) { for (auto i: m_confirmed_txs) @@ -8126,6 +8134,25 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> } } + std::vector<crypto::key_image> ring_key_images; + ring_key_images.reserve(selected_transfers.size()); + std::unordered_map<crypto::key_image, std::vector<uint64_t>> existing_rings; + for(size_t idx: selected_transfers) + { + const transfer_details &td = m_transfers[idx]; + if (td.m_key_image_known && !td.m_key_image_partial) + ring_key_images.push_back(td.m_key_image); + } + if (!ring_key_images.empty()) + { + std::vector<std::vector<uint64_t>> all_outs; + if (get_rings(get_ringdb_key(), ring_key_images, all_outs)) + { + for (size_t i = 0; i < ring_key_images.size(); ++i) + existing_rings[ring_key_images[i]] = std::move(all_outs[i]); + } + } + // we ask for more, to have spares if some outputs are still locked size_t base_requested_outputs_count = (size_t)((fake_outputs_count + 1) * 1.5 + 1); LOG_PRINT_L2("base_requested_outputs_count: " << base_requested_outputs_count); @@ -8248,9 +8275,12 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> // if we have a known ring, use it if (td.m_key_image_known && !td.m_key_image_partial) { - std::vector<uint64_t> ring; - if (get_ring(get_ringdb_key(), td.m_key_image, ring)) + + const auto it = existing_rings.find(td.m_key_image); + const bool has_ring = it != existing_rings.end(); + if (has_ring) { + const std::vector<uint64_t> &ring = it->second; MINFO("This output has a known ring, reusing (size " << ring.size() << ")"); THROW_WALLET_EXCEPTION_IF(ring.size() > fake_outputs_count + 1, error::wallet_internal_error, "An output in this transaction was previously spent on another chain with ring size " + @@ -8520,9 +8550,10 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> // then pick outs from an existing ring, if any if (td.m_key_image_known && !td.m_key_image_partial) { - std::vector<uint64_t> ring; - if (get_ring(get_ringdb_key(), td.m_key_image, ring)) + const auto it = existing_rings.find(td.m_key_image); + if (it != existing_rings.end()) { + const std::vector<uint64_t> &ring = it->second; for (uint64_t out: ring) { if (out < num_outs) |