diff --git a/src/ledger/LedgerTxn.cpp b/src/ledger/LedgerTxn.cpp index a450613b5f..43c1ff8657 100644 --- a/src/ledger/LedgerTxn.cpp +++ b/src/ledger/LedgerTxn.cpp @@ -182,10 +182,10 @@ LedgerKeyMeter::canLoad(LedgerKey const& key, size_t entrySizeBytes) const void LedgerKeyMeter::addTxn(SorobanResources const& resources) { - mTxReadBytes.push_back(resources.readBytes); - auto txId = mTxReadBytes.size() - 1; + TxReadBytesPtr txReadBytesPtr = + std::make_shared(resources.readBytes); auto addKeyToTxnMap = [&](auto const& key) { - mLedgerKeyToTxs[key].emplace_back(txId); + mLedgerKeyToTxReadBytes[key].emplace_back(txReadBytesPtr); }; std::for_each(resources.footprint.readOnly.begin(), resources.footprint.readOnly.end(), addKeyToTxnMap); @@ -197,8 +197,8 @@ void LedgerKeyMeter::updateReadQuotasForKey(LedgerKey const& key, size_t entrySizeBytes) { - auto iter = mLedgerKeyToTxs.find(key); - if (iter == mLedgerKeyToTxs.end()) + auto iter = mLedgerKeyToTxReadBytes.find(key); + if (iter == mLedgerKeyToTxReadBytes.end()) { // Key does not belong to the footprint of any transaction. // Ensure this is not a soroban key as they should always be metered. @@ -208,17 +208,16 @@ LedgerKeyMeter::updateReadQuotasForKey(LedgerKey const& key, } // Update the read quota for every transaction containing this key. bool exceedsQuotaForAllTxns = true; - for (auto txn : iter->second) + for (TxReadBytesPtr txReadBytesPtr : iter->second) { - auto& quota = mTxReadBytes.at(txn); - if (quota < entrySizeBytes) + if (*txReadBytesPtr < entrySizeBytes) { - quota = 0; + *txReadBytesPtr = 0; } else { exceedsQuotaForAllTxns = false; - quota -= entrySizeBytes; + *txReadBytesPtr -= entrySizeBytes; } } if (exceedsQuotaForAllTxns) @@ -230,8 +229,8 @@ LedgerKeyMeter::updateReadQuotasForKey(LedgerKey const& key, uint32_t LedgerKeyMeter::maxReadQuotaForKey(LedgerKey const& key) const { - auto iter = mLedgerKeyToTxs.find(key); - if (iter == mLedgerKeyToTxs.end()) + auto iter = mLedgerKeyToTxReadBytes.find(key); + if (iter == mLedgerKeyToTxReadBytes.end()) { // Key does not belong to the footprint of any transaction, // therefore it is not quota-limited. @@ -240,10 +239,9 @@ LedgerKeyMeter::maxReadQuotaForKey(LedgerKey const& key) const key.type() != CONTRACT_DATA); return std::numeric_limits::max(); } - return std::reduce(iter->second.begin(), iter->second.end(), 0, - [&](uint32_t maxReadQuota, size_t const txn) { - return std::max(maxReadQuota, mTxReadBytes.at(txn)); - }); + return **std::max_element( + iter->second.begin(), iter->second.end(), + [&](TxReadBytesPtr a, TxReadBytesPtr b) { return *a < *b; }); } bool diff --git a/src/ledger/LedgerTxn.h b/src/ledger/LedgerTxn.h index 4ccf67a81b..6e755f651e 100644 --- a/src/ledger/LedgerTxn.h +++ b/src/ledger/LedgerTxn.h @@ -350,14 +350,11 @@ class LedgerKeyMeter : public NonMovableOrCopyable private: // Returns the maximum read quota across all transactions with this key. uint32_t maxReadQuotaForKey(LedgerKey const& key) const; - - // Stores the read quota for each transaction. - std::vector mTxReadBytes{}; - // Stores the keys that each transaction will read. i.e. - // mLedgerKeyToTxs[key] is a vector containing the indices of - // mTxReadBytes corresponding to the transactions which have - // the key in their footprint. - UnorderedMap> mLedgerKeyToTxs{}; + using TxReadBytesPtr = std::shared_ptr; + // Stores a mapping from keys to a vector of pointers to the read bytes + // of the transactions that will read the keys. + UnorderedMap> + mLedgerKeyToTxReadBytes{}; // Stores the keys that were not loaded due to insufficient read quota. LedgerKeySet mNotLoadedKeys{}; };