mirror of
https://github.com/monero-project/monero.git
synced 2025-08-23 11:15:16 -04:00
wallet2: speedup large tx construction: batch ringdb lookups
3.3 seconds -> 2.8 seconds on a test case
This commit is contained in:
parent
353cd5355e
commit
38cdf01c64
4 changed files with 58 additions and 5 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue