blockchain: limit offsets cache size

(cherry picked from commit d232dc09c55104f011133425f22a1c0e4e0b21ee)
This commit is contained in:
j-berman
2026-10-04 18:50:23 -04:00
committed by such-gitea
parent 7ff4a5567a
commit 39647836f4
+28 -1
View File
@@ -155,6 +155,8 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
std::vector<uint64_t> absolute_offsets = relative_output_offsets_to_absolute(tx_in_to_key.key_offsets); std::vector<uint64_t> absolute_offsets = relative_output_offsets_to_absolute(tx_in_to_key.key_offsets);
std::vector<output_data_t> outputs; std::vector<output_data_t> outputs;
// We check the m_scan_table cache, but note it may not have the entry.
// We have to read the db in that case.
bool found = false; bool found = false;
auto it = m_scan_table.find(tx_prefix_hash); auto it = m_scan_table.find(tx_prefix_hash);
if (it != m_scan_table.end()) if (it != m_scan_table.end())
@@ -5336,6 +5338,14 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
std::map<uint64_t, std::vector<output_data_t>> tx_map; std::map<uint64_t, std::vector<output_data_t>> tx_map;
std::vector<std::pair<cryptonote::transaction, crypto::hash>> txes(total_txs); std::vector<std::pair<cryptonote::transaction, crypto::hash>> txes(total_txs);
// We want to target max memory usage for offsets here to 100mb. We'll have output_data_t
// per offset in memory for m_scan_table and tx_map (hence the 2*sizeof(output_data_t)).
// If m_scan_table doesn't have an offset entry while handling an incoming block, that's
// ok. It should cache miss and just do the db read(s) when handling the block.
// Note: we might go over the target max offsets a little, but that's ok.
// TODO: return early once we're past the FCMP++ fork.
constexpr std::size_t TARGET_MAX_OFFSETS_FOR_SCAN_TABLE_CACHE = 100000000/*100MB*/ / (2*sizeof(output_data_t));
#define SCAN_TABLE_QUIT(m) \ #define SCAN_TABLE_QUIT(m) \
do { \ do { \
MERROR_VER(m) ;\ MERROR_VER(m) ;\
@@ -5345,10 +5355,13 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
// generate sorted tables for all amounts and absolute offsets // generate sorted tables for all amounts and absolute offsets
size_t tx_index = 0, block_index = 0; size_t tx_index = 0, block_index = 0;
size_t n_total_offsets = 0;
for (const auto &entry : blocks_entry) for (const auto &entry : blocks_entry)
{ {
if (m_cancel) if (m_cancel)
return false; return false;
if (n_total_offsets >= TARGET_MAX_OFFSETS_FOR_SCAN_TABLE_CACHE)
break;
for (const auto &tx_blob : entry.txs) for (const auto &tx_blob : entry.txs)
{ {
@@ -5391,8 +5404,16 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
// no need to check for duplicate here. // no need to check for duplicate here.
auto absolute_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets); auto absolute_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
for (const auto & offset : absolute_offsets) for (const auto & offset : absolute_offsets)
{
offset_map[in_to_key.amount].push_back(offset); offset_map[in_to_key.amount].push_back(offset);
++n_total_offsets;
}
}
if (n_total_offsets >= TARGET_MAX_OFFSETS_FOR_SCAN_TABLE_CACHE)
{
MWARNING("Preparing large batch to sync, we exceeded our cache limit");
break;
} }
} }
++block_index; ++block_index;
@@ -5438,10 +5459,13 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
// now generate a table for each tx_prefix and k_image hashes // now generate a table for each tx_prefix and k_image hashes
tx_index = 0; tx_index = 0;
bool reached_end_of_cache = false;
for (const auto &entry : blocks_entry) for (const auto &entry : blocks_entry)
{ {
if (m_cancel) if (m_cancel)
return false; return false;
if (reached_end_of_cache)
break;
for (size_t i = 0; i < entry.txs.size(); ++i) for (size_t i = 0; i < entry.txs.size(); ++i)
{ {
@@ -5453,7 +5477,10 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
auto its = m_scan_table.find(tx_prefix_hash); auto its = m_scan_table.find(tx_prefix_hash);
if (its == m_scan_table.end()) if (its == m_scan_table.end())
SCAN_TABLE_QUIT("Tx not found on scan table from incoming blocks."); {
reached_end_of_cache = true;
break;
}
for (const auto &txin : tx.vin) for (const auto &txin : tx.vin)
{ {