touch keys

This commit is contained in:
Richard Holland
2025-04-15 13:50:12 +10:00
parent 2fb5c92140
commit cac869fe7e
7 changed files with 85 additions and 3 deletions

View File

@@ -128,4 +128,20 @@ HashRouter::shouldRelay(uint256 const& key)
return s.releasePeerSet();
}
void
HashRouter::setTouchedKeys(uint256 const& id, std::set<uint256>&& k)
{
std::unique_lock<std::shared_mutex> lock(touchedKeysMutex_);
touchedKeysMap_.insert_or_assign(id, std::move(k));
}
std::optional<std::reference_wrapper<const std::set<uint256>>>
HashRouter::getTouchedKeys(uint256 const& id)
{
std::shared_lock<std::shared_mutex> lock(touchedKeysMutex_);
if (auto it = touchedKeysMap_.find(id); it != touchedKeysMap_.end())
return std::cref(it->second);
return std::nullopt;
}
} // namespace ripple

View File

@@ -27,6 +27,8 @@
#include <ripple/beast/container/aged_unordered_map.h>
#include <optional>
#include <set>
#include <shared_mutex>
namespace ripple {
@@ -195,6 +197,12 @@ public:
int
getFlags(uint256 const& key);
void
setTouchedKeys(uint256 const& id, std::set<uint256>&& k);
std::optional<std::reference_wrapper<const std::set<uint256>>>
getTouchedKeys(uint256 const& id);
/** Determines whether the hashed item should be relayed.
Effects:
@@ -217,6 +225,9 @@ private:
std::mutex mutable mutex_;
mutable std::shared_mutex touchedKeysMutex_;
std::map<uint256, std::set<uint256>> touchedKeysMap_;
// Stores all suppressed hashes and their expiration time
beast::aged_unordered_map<
uint256,

View File

@@ -31,6 +31,7 @@
#include <boost/intrusive/set.hpp>
#include <optional>
#include <vector>
#include <set>
namespace ripple {
@@ -105,13 +106,13 @@ public:
FeeLevel64 minimumEscalationMultiplier = baseLevel * 500;
/// Minimum number of transactions to allow into the ledger
/// before escalation, regardless of the prior ledger's size.
std::uint32_t minimumTxnInLedger = 32;
std::uint32_t minimumTxnInLedger = 5000;
/// Like @ref minimumTxnInLedger for standalone mode.
/// Primarily so that tests don't need to worry about queuing.
std::uint32_t minimumTxnInLedgerSA = 1000;
/// Number of transactions per ledger that fee escalation "works
/// towards".
std::uint32_t targetTxnInLedger = 1000;
std::uint32_t targetTxnInLedger = 10000;
/** Optional maximum allowed value of transactions per ledger before
fee escalation kicks in. By default, the maximum is an emergent
property of network, validator, and consensus performance. This

View File

@@ -30,6 +30,7 @@
#include <algorithm>
#include <limits>
#include <numeric>
#include <set>
namespace ripple {
@@ -739,10 +740,17 @@ TxQ::apply(
STAmountSO stAmountSO{view.rules().enabled(fixSTAmountCanonicalize)};
NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)};
auto const transactionID = tx->getTransactionID();
// See if the transaction paid a high enough fee that it can go straight
// into the ledger.
view.getAndResetKeysTouched();
if (auto directApplied = tryDirectApply(app, view, tx, flags, j))
{
app.getHashRouter().setTouchedKeys(
transactionID, view.getAndResetKeysTouched());
return *directApplied;
}
// If we get past tryDirectApply() without returning then we expect
// one of the following to occur:
@@ -841,7 +849,6 @@ TxQ::apply(
// is allowed in the TxQ:
// 1. If the account's queue is empty or
// 2. If the blocker replaces the only entry in the account's queue.
auto const transactionID = tx->getTransactionID();
if (pfresult.consequences.isBlocker())
{
if (acctTxCount > 1)
@@ -1207,6 +1214,8 @@ TxQ::apply(
{
OpenView sandbox(open_ledger, &view, view.rules());
sandbox.getAndResetKeysTouched();
auto result = tryClearAccountQueueUpThruTx(
app,
sandbox,
@@ -1219,6 +1228,10 @@ TxQ::apply(
flags,
metricsSnapshot,
j);
app.getHashRouter().setTouchedKeys(
transactionID, sandbox.getAndResetKeysTouched());
if (result.second)
{
sandbox.apply(view);
@@ -1657,11 +1670,16 @@ TxQ::accept(Application& app, OpenView& view)
JLOG(j_.trace()) << "Applying queued transaction "
<< candidateIter->txID << " to open ledger.";
view.getAndResetKeysTouched();
auto const [txnResult, didApply] =
candidateIter->apply(app, view, j_);
if (didApply)
{
app.getHashRouter().setTouchedKeys(
candidateIter->txID, view.getAndResetKeysTouched());
// Remove the candidate from the queue
JLOG(j_.debug())
<< "Queued transaction " << candidateIter->txID

View File

@@ -99,6 +99,12 @@ private:
bool open_ = true;
public:
std::set<uint256>
getAndResetKeysTouched()
{
return items_.getAndResetKeysTouched();
}
OpenView() = delete;
OpenView&
operator=(OpenView&&) = delete;

View File

@@ -35,6 +35,9 @@ namespace detail {
// Helper class that buffers raw modifications
class RawStateTable
{
private:
mutable std::set<uint256> keysTouched_;
public:
using key_type = ReadView::key_type;
// Initial size for the monotonic_buffer_resource used for allocations
@@ -98,6 +101,19 @@ public:
std::unique_ptr<ReadView::sles_type::iter_base>
slesUpperBound(ReadView const& base, uint256 const& key) const;
// each time a key is read or written it will be placed in the keysTouched_
// set.
std::set<uint256>
getAndResetKeysTouched()
{
std::set<uint256> out;
out.swap(keysTouched_);
std::cout << "--------------\n";
for (auto const& k : out)
std::cout << "getAndResetKeysTouched: " << to_string(k) << "\n";
return out;
}
private:
enum class Action {
erase,

View File

@@ -173,6 +173,8 @@ RawStateTable::apply(RawView& to) const
to.rawReplace(item.sle);
break;
}
keysTouched_.emplace(elem.first);
}
}
@@ -180,6 +182,9 @@ bool
RawStateTable::exists(ReadView const& base, Keylet const& k) const
{
assert(k.key.isNonZero());
keysTouched_.insert(k.key);
auto const iter = items_.find(k.key);
if (iter == items_.end())
return base.exists(k);
@@ -227,12 +232,18 @@ RawStateTable::succ(
// what we got from the parent.
if (last && next >= last)
return std::nullopt;
if (next.has_value())
keysTouched_.insert(*next);
return next;
}
void
RawStateTable::erase(std::shared_ptr<SLE> const& sle)
{
keysTouched_.insert(sle->key());
// The base invariant is checked during apply
auto const result = items_.emplace(
std::piecewise_construct,
@@ -259,6 +270,7 @@ RawStateTable::erase(std::shared_ptr<SLE> const& sle)
void
RawStateTable::insert(std::shared_ptr<SLE> const& sle)
{
keysTouched_.insert(sle->key());
auto const result = items_.emplace(
std::piecewise_construct,
std::forward_as_tuple(sle->key()),
@@ -284,6 +296,7 @@ RawStateTable::insert(std::shared_ptr<SLE> const& sle)
void
RawStateTable::replace(std::shared_ptr<SLE> const& sle)
{
keysTouched_.insert(sle->key());
auto const result = items_.emplace(
std::piecewise_construct,
std::forward_as_tuple(sle->key()),
@@ -306,6 +319,7 @@ RawStateTable::replace(std::shared_ptr<SLE> const& sle)
std::shared_ptr<SLE const>
RawStateTable::read(ReadView const& base, Keylet const& k) const
{
keysTouched_.insert(k.key);
auto const iter = items_.find(k.key);
if (iter == items_.end())
return base.read(k);