Skip to content

Commit

Permalink
Review fixes and refactor:
Browse files Browse the repository at this point in the history
1) refactor filtering of validations to specifically avoid
   concurrent checkAccept() calls for the same validation hash.
2) Log when duplicate concurrent inbound ledger and validation requests
   are filtered.
3) RAII for containers that track concurrent inbound ledger and
   validation requests.
4) Comment on when to asynchronously acquire inbound ledgers, which
   is possible to be always OK, but should have further review.
  • Loading branch information
mtrippled committed Aug 29, 2024
1 parent 098546f commit f15ac51
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 18 deletions.
20 changes: 18 additions & 2 deletions src/ripple/app/consensus/RCLValidations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,9 @@ void
handleNewValidation(
Application& app,
std::shared_ptr<STValidation> const& val,
std::string const& source)
std::string const& source,
BypassAccept const bypassAccept,
std::optional<beast::Journal> j)
{
auto const& signingKey = val->getSignerPublic();
auto const& hash = val->getLedgerHash();
Expand All @@ -186,7 +188,21 @@ handleNewValidation(
if (outcome == ValStatus::current)
{
if (val->isTrusted())
app.getLedgerMaster().checkAccept(hash, seq);
{
if (bypassAccept == BypassAccept::TRUE)
{
assert(j.has_value());
if (j.has_value())
{
JLOG(j->trace()) << "Bypassing checkAccept for validation "
<< val->getLedgerHash();
}
}
else
{
app.getLedgerMaster().checkAccept(hash, seq);
}
}
return;
}

Expand Down
8 changes: 7 additions & 1 deletion src/ripple/app/consensus/RCLValidations.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@
#include <ripple/protocol/Protocol.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <ripple/protocol/STValidation.h>
#include <optional>
#include <set>
#include <vector>

namespace ripple {

class Application;

enum class BypassAccept { FALSE, TRUE };

/** Wrapper over STValidation for generic Validation code
Wraps an STValidation for compatibility with the generic validation code.
Expand Down Expand Up @@ -248,7 +252,9 @@ void
handleNewValidation(
Application& app,
std::shared_ptr<STValidation> const& val,
std::string const& source);
std::string const& source,
BypassAccept const bypassAccept = BypassAccept::FALSE,
std::optional<beast::Journal> j = std::nullopt);

} // namespace ripple

Expand Down
8 changes: 6 additions & 2 deletions src/ripple/app/ledger/InboundLedgers.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <ripple/app/ledger/InboundLedger.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <memory>
#include <set>

namespace ripple {

Expand All @@ -37,11 +38,14 @@ class InboundLedgers

virtual ~InboundLedgers() = default;

// VFALCO TODO Should this be called findOrAdd ?
//
// Callers should use this if they possibly need an authoritative
// response immediately.
virtual std::shared_ptr<Ledger const>
acquire(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason) = 0;

// Callers should use this if they are known to be executing on the Job
// Queue. TODO review whether all callers of acquire() can use this
// instead. Inbound ledger acquisition is asynchronous anyway.
virtual void
acquireAsync(
uint256 const& hash,
Expand Down
26 changes: 21 additions & 5 deletions src/ripple/app/ledger/impl/InboundLedgers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <ripple/core/JobQueue.h>
#include <ripple/nodestore/DatabaseShard.h>
#include <ripple/protocol/jss.h>
#include <exception>
#include <memory>
#include <mutex>
#include <vector>
Expand Down Expand Up @@ -156,11 +157,26 @@ class InboundLedgersImp : public InboundLedgers
InboundLedger::Reason reason) override
{
std::unique_lock lock(acquiresMutex_);
if (pendingAcquires_.contains(hash))
return;
pendingAcquires_.insert(hash);
lock.unlock();
acquire(hash, seq, reason);
try
{
if (pendingAcquires_.contains(hash))
return;
pendingAcquires_.insert(hash);
lock.unlock();
acquire(hash, seq, reason);
}
catch (std::exception const& e)
{
JLOG(j_.warn())
<< "Exception thrown for acquiring new inbound ledger "
<< hash << ": " << e.what();
}
catch (...)
{
JLOG(j_.warn())
<< "Unknown exception thrown for acquiring new inbound ledger "
<< hash;
}
lock.lock();
pendingAcquires_.erase(hash);
}
Expand Down
34 changes: 26 additions & 8 deletions src/ripple/app/misc/NetworkOPs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@
#include <boost/asio/steady_timer.hpp>

#include <algorithm>
#include <exception>
#include <mutex>
#include <optional>
#include <set>
#include <string>
#include <tuple>
#include <unordered_map>
Expand Down Expand Up @@ -781,7 +783,7 @@ class NetworkOPsImp final : public NetworkOPs

StateAccounting accounting_{};

std::set<std::pair<PublicKey, uint256>> pendingValidations_;
std::set<uint256> pendingValidations_;
std::mutex validationsMutex_;

private:
Expand Down Expand Up @@ -2312,14 +2314,30 @@ NetworkOPsImp::recvValidation(
<< "recvValidation " << val->getLedgerHash() << " from " << source;

std::unique_lock lock(validationsMutex_);
if (pendingValidations_.contains(
{val->getSignerPublic(), val->getLedgerHash()}))
return false;
pendingValidations_.insert({val->getSignerPublic(), val->getLedgerHash()});
lock.unlock();
handleNewValidation(app_, val, source);
try
{
BypassAccept bypassAccept = BypassAccept::FALSE;
if (pendingValidations_.contains(val->getLedgerHash()))
bypassAccept = BypassAccept::TRUE;
else
pendingValidations_.insert(val->getLedgerHash());
lock.unlock();
handleNewValidation(app_, val, source, bypassAccept, m_journal);
}
catch (std::exception const& e)
{
JLOG(m_journal.warn())
<< "Exception thrown for handling new validation "
<< val->getLedgerHash() << ": " << e.what();
}
catch (...)
{
JLOG(m_journal.warn())
<< "Unknown exception thrown for handling new validation "
<< val->getLedgerHash();
}
lock.lock();
pendingValidations_.erase({val->getSignerPublic(), val->getLedgerHash()});
pendingValidations_.erase(val->getLedgerHash());
lock.unlock();

pubValidation(val);
Expand Down

0 comments on commit f15ac51

Please sign in to comment.