3#include <xrpld/consensus/LedgerTrie.h>
5#include <xrpl/basics/Log.h>
6#include <xrpl/basics/UnorderedContainers.h>
7#include <xrpl/basics/chrono.h>
8#include <xrpl/beast/container/aged_container_utility.h>
9#include <xrpl/beast/container/aged_unordered_map.h>
10#include <xrpl/protocol/PublicKey.h>
81 using time_point = std::chrono::steady_clock::time_point;
175 return "conflicting";
267template <
class Adaptor>
343 it->second.erase(nodeID);
344 if (it->second.empty())
352 trie_.remove(it->second);
366 for (
NodeID const& nodeID : it->second)
382 auto const [it, inserted] =
lastLedger_.emplace(nodeID, ledger);
385 trie_.remove(it->second);
388 trie_.insert(ledger);
411 XRPL_ASSERT(val.
trusted(),
"xrpl::Validations::updateTrie : trusted input validation");
419 it->second.erase(nodeID);
420 if (it->second.empty())
431 it->second.insert(nodeID);
463 current(lock, [](
auto) {}, [](
auto,
auto) {});
484 template <
class Pre,
class F>
494 if (!
isCurrent(
parms_, t, it->second.signTime(), it->second.seenTime()))
503 f(cit->first, cit->second);
521 template <
class Pre,
class F>
530 pre(it->second.size());
531 for (
auto const& [key, val] : it->second)
543 template <
class... Ts>
602 auto const now =
byLedger_.clock().now();
604 auto const [seqit, seqinserted] =
bySequence_[val.
seq()].emplace(nodeID, val);
613 if (diff >
parms_.validationCurrentWall &&
614 val.
signTime() > seqit->second.signTime())
624 if (seqit->second.seq() == val.
seq())
629 if (seqit->second.ledgerID() != val.
ledgerID())
636 if (seqit->second.signTime() != val.
signTime())
641 if (seqit->second.cookie() != val.
cookie())
650 auto const [it, inserted] =
current_.emplace(nodeID, val);
686 XRPL_ASSERT(low < high,
"xrpl::Validations::setSeqToKeep : valid inputs");
705 static std::chrono::steady_clock::time_point kRefreshTime;
706 if (
auto const now =
byLedger_.clock().now(); kRefreshTime <= now)
710 kRefreshTime = now +
parms_.validationSetExpires -
parms_.validationFRESHNESS;
714 auto const& validationMap = i->second;
715 if (!validationMap.empty())
717 auto const seq = validationMap.begin()->second.seq();
718 if (
toKeep_->low <= seq && seq < toKeep_->high)
738 JLOG(j.
debug()) <<
"Validations sets sweep lock duration "
759 for (
auto& [nodeId, validation] :
current_)
761 if (added.
find(nodeId) != added.
end())
763 validation.setTrusted();
764 updateTrie(lock, nodeId, validation, std::nullopt);
766 else if (removed.
find(nodeId) != removed.
end())
768 validation.setUntrusted();
773 for (
auto& [_, validationMap] :
byLedger_)
776 for (
auto& [nodeId, validation] : validationMap)
778 if (added.
find(nodeId) != added.
end())
780 validation.setTrusted();
782 else if (removed.
find(nodeId) != removed.
end())
784 validation.setUntrusted();
794 return trie_.getJson();
836 if (preferred->seq == curr.
seq() +
Seq{1} && preferred->ancestor(curr.
seq()) == curr.
id())
841 if (preferred->seq > curr.
seq())
846 if (curr[preferred->seq] != preferred->id)
866 if (preferred && preferred->first >= minValidSeq)
867 return preferred->second;
895 return (preferred->first >= minSeq) ? preferred->second : lcl.
id();
904 if (it != peerCounts.
end())
926 if (ledger.
id() == ledgerID)
935 auto const& curr = it.second;
936 return curr.seq() >
Seq{0} && curr[curr.seq() -
Seq{1}] == ledgerID;
953 if (v.trusted() && v.full())
991 if (v.trusted() && v.full())
1013 if (v.trusted() && v.full() && v.seq() == seq)
1036 if (v.trusted() && v.full())
1085 if (
adaptor_.now() < v.seenTime() +
parms_.validationFRESHNESS &&
1086 trustedKeys.
find(v.key()) != trustedKeys.
end())
1088 trustedKeys.
erase(v.key());
Abstract interface to a clock.
A generic endpoint for log messages.
Ancestry trie of ledgers.
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
std::chrono::time_point< NetClock > time_point
Seq seq() const
The sequence (index) of the ledger.
ID id() const
The ID (hash) of the ledger.
std::uint32_t seq() const
Validated ledger's sequence number (0 if none).
bool trusted() const
Whether the validation is considered trusted.
NetClock::time_point seenTime() const
Validated ledger's first seen time.
std::uint64_t cookie() const
Get the cookie specified in the validation (0 if not set).
NetClock::time_point signTime() const
Validation's signing time.
std::shared_ptr< STValidation > unwrap() const
Extract the underlying STValidation being wrapped.
uint256 ledgerID() const
Validated ledger's hash.
Enforce validation increasing sequence requirement.
std::chrono::steady_clock::time_point time_point
bool operator()(time_point now, Seq s, ValidationParms const &p)
Try advancing the largest observed validation ledger sequence.
void updateTrie(std::scoped_lock< Mutex > const &, NodeID const &nodeID, Ledger ledger)
ID getPreferredLCL(Ledger const &lcl, Seq minSeq, hash_map< ID, std::uint32_t > const &peerCounts)
Determine the preferred last closed ledger for the next consensus round.
std::size_t getNodesAfter(Ledger const &ledger, ID const &ledgerID)
Count the number of current trusted validators working on a ledger after the specified one.
void expire(beast::Journal const &j)
Expire old validation sets.
bool canValidateSeq(Seq const s)
Return whether the local node can issue a validation for the given sequence number.
LedgerTrie< Ledger > trie_
auto getCurrentNodeIDs() -> hash_set< NodeID >
Get the set of node ids associated with current validations.
std::size_t numTrustedForLedger(ID const &ledgerID)
Count the number of trusted full validations for the given ledger.
std::vector< WrappedValidationType > getTrustedForLedger(ID const &ledgerID, Seq const &seq)
Get trusted full validations for a specific ledger.
ValStatus add(NodeID const &nodeID, Validation const &val)
Add a new validation.
void trustChanged(hash_set< NodeID > const &added, hash_set< NodeID > const &removed)
Update trust status of validations.
ValidationParms const & parms() const
Return the validation timing parameters.
void checkAcquired(std::scoped_lock< Mutex > const &lock)
hash_map< NodeID, Validation > current_
hash_map< NodeID, SeqEnforcer< Seq > > seqEnforcers_
RCLValidationsAdaptor::Mutex Mutex
Adaptor const & adaptor() const
Return the adaptor instance.
hash_map< NodeID, Ledger > lastLedger_
SeqEnforcer< Seq > localSeqEnforcer_
beast::aged_unordered_map< Seq, hash_map< NodeID, Validation >, std::chrono::steady_clock, beast::Uhash<> > bySequence_
std::size_t sizeOfCurrentCache() const
void updateTrie(std::scoped_lock< Mutex > const &lock, NodeID const &nodeID, Validation const &val, std::optional< std::pair< Seq, ID > > prior)
Process a new validation.
beast::aged_unordered_map< ID, hash_map< NodeID, Validation >, std::chrono::steady_clock, beast::Uhash<> > byLedger_
std::optional< std::pair< Seq, ID > > getPreferred(Ledger const &curr)
Return the sequence number and ID of the preferred working ledger.
void flush()
Flush all current validations.
std::vector< WrappedValidationType > currentTrusted()
Get the currently trusted full validations.
void setSeqToKeep(Seq const &low, Seq const &high)
Set the range [low, high) of validations to keep from expire.
auto withTrie(std::scoped_lock< Mutex > const &lock, F &&f)
Use the trie for a calculation.
ValidationParms const parms_
std::size_t sizeOfByLedgerCache() const
RCLValidationsAdaptor::Validation Validation
std::size_t sizeOfBySequenceCache() const
json::Value getJsonTrie() const
std::decay_t< std::invoke_result_t< decltype(&Validation::unwrap), Validation > > WrappedValidationType
void removeTrie(std::scoped_lock< Mutex > const &, NodeID const &nodeID, Validation const &val)
Validations(ValidationParms const &p, beast::AbstractClock< std::chrono::steady_clock > &c, Ts &&... ts)
Constructor.
std::size_t sizeOfSeqEnforcersCache() const
std::optional< KeepRange > toKeep_
std::size_t laggards(Seq const seq, hash_set< NodeKey > &trustedKeys)
Return quantity of lagging proposers, and remove online proposers for purposes of evaluating whether ...
void byLedger(std::scoped_lock< Mutex > const &, ID const &ledgerID, Pre &&pre, F &&f)
Iterate current validations.
Validation::NodeID NodeID
ID getPreferred(Ledger const &curr, Seq minValidSeq)
Get the ID of the preferred working ledger that exceeds a minimum valid ledger sequence number.
RCLValidationsAdaptor adaptor_
std::vector< std::uint32_t > fees(ID const &ledgerID, std::uint32_t baseFee)
Returns fees reported by trusted full validators in the given ledger.
Validation::NodeKey NodeKey
RCLValidationsAdaptor::Ledger Ledger
hash_map< std::pair< Seq, ID >, hash_set< NodeID > > acquiring_
T duration_cast(T... args)
T emplace_back(T... args)
std::enable_if_t< IsAgedContainer< AgedContainer >::value, std::size_t > expire(AgedContainer &c, std::chrono::duration< Rep, Period > const &age)
Expire aged container items past the specified age.
detail::AgedUnorderedContainer< false, true, Key, T, Clock, Hash, KeyEqual, Allocator > aged_unordered_map
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
std::unordered_set< Value, Hash, Pred, Allocator > hash_set
@ Current
The current working ledger (open, not yet closed).
std::string to_string(BaseUInt< Bits, Tag > const &a)
ValStatus
Status of validation we received.
@ Current
This was a new validation and was added.
@ BadSeq
A validation violates the increasing seq requirement.
@ Conflicting
Multiple validations by a validator for different ledgers.
@ Multiple
Multiple validations by a validator for the same ledger.
@ Stale
Not current or was older than current from this node.
Dir::ConstIterator const_iterator
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
@ Stale
Sequence is too old.
Timing parameters to control validation staleness and expiration.
std::chrono::seconds validationCurrentEarly
Duration pre-close in which validations are acceptable.
std::chrono::seconds validationCurrentLocal
Duration a validation remains current after first observed.
std::chrono::seconds validationSetExpires
Duration a set of validations for a given ledger hash remain valid.
ValidationParms()=default
std::chrono::seconds validationFRESHNESS
How long we consider a validation fresh.
std::chrono::seconds validationCurrentWall
The number of seconds a validation remains current after its ledger's close time.