20 #ifndef RIPPLE_CONSENSUS_VALIDATIONS_H_INCLUDED
21 #define RIPPLE_CONSENSUS_VALIDATIONS_H_INCLUDED
23 #include <ripple/basics/Log.h>
24 #include <ripple/basics/UnorderedContainers.h>
25 #include <ripple/basics/chrono.h>
26 #include <ripple/beast/container/aged_container_utility.h>
27 #include <ripple/beast/container/aged_unordered_map.h>
28 #include <ripple/consensus/LedgerTrie.h>
29 #include <ripple/protocol/PublicKey.h>
30 #include <boost/optional.hpp>
98 using time_point = std::chrono::steady_clock::time_point;
191 return "conflicting";
283 template <
class Adaptor>
286 using Mutex =
typename Adaptor::Mutex;
289 using ID =
typename Ledger::ID;
290 using Seq =
typename Ledger::Seq;
291 using NodeID =
typename Validation::NodeID;
358 it->second.erase(nodeID);
359 if (it->second.empty())
365 if (it !=
lastLedger_.end() && it->second.id() == val.ledgerID())
367 trie_.remove(it->second);
379 if (boost::optional<Ledger> ledger =
382 for (
NodeID const& nodeID : it->second)
399 auto const [it, inserted] =
lastLedger_.emplace(nodeID, ledger);
402 trie_.remove(it->second);
405 trie_.insert(ledger);
428 assert(val.trusted());
436 it->second.erase(nodeID);
437 if (it->second.empty())
448 it->second.insert(nodeID);
452 if (boost::optional<Ledger> ledger =
478 lock, [](
auto) {}, [](
auto,
auto) {});
499 template <
class Pre,
class F>
510 parms_, t, it->second.signTime(), it->second.seenTime()))
519 f(cit->first, cit->second);
537 template <
class Pre,
class F>
550 pre(it->second.size());
551 for (
auto const& [key, val] : it->second)
563 template <
class... Ts>
625 auto const now =
byLedger_.clock().now();
627 auto const [seqit, seqinserted] =
635 std::max(seqit->second.signTime(), val.signTime()) -
636 std::min(seqit->second.signTime(), val.signTime());
639 val.signTime() > seqit->second.signTime())
649 if (seqit->second.seq() == val.seq())
654 if (seqit->second.ledgerID() != val.ledgerID())
659 if (seqit->second.cookie() != val.cookie())
666 byLedger_[val.ledgerID()].insert_or_assign(nodeID, val);
668 auto const [it, inserted] =
current_.emplace(nodeID, val);
673 if (val.signTime() > oldVal.signTime())
683 else if (val.trusted())
716 auto const& validationMap = i->second;
717 if (!validationMap.empty() &&
718 validationMap.begin()->second.seq() >=
toKeep_)
753 if (added.
find(nodeId) != added.
end())
758 else if (removed.
find(nodeId) != removed.
end())
765 for (
auto& [_, validationMap] :
byLedger_)
768 for (
auto& [nodeId,
validation] : validationMap)
770 if (added.
find(nodeId) != added.
end())
774 else if (removed.
find(nodeId) != removed.
end())
786 return trie_.getJson();
801 boost::optional<std::pair<Seq, ID>>
805 boost::optional<SpanTip<Ledger>> preferred =
816 [](
auto const& a,
auto const& b) {
817 std::pair<Seq, ID> const& aKey = a.first;
818 typename hash_set<NodeID>::size_type const& aSize =
820 std::pair<Seq, ID> const& bKey = b.first;
821 typename hash_set<NodeID>::size_type const& bSize =
825 return std::tie(aSize, aKey.second) <
826 std::tie(bSize, bKey.second);
835 if (preferred->seq == curr.seq() +
Seq{1} &&
836 preferred->ancestor(curr.seq()) == curr.id())
841 if (preferred->seq > curr.seq())
846 if (curr[preferred->seq] != preferred->id)
865 boost::optional<std::pair<Seq, ID>> preferred =
getPreferred(curr);
866 if (preferred && preferred->first >= minValidSeq)
867 return preferred->second;
893 boost::optional<std::pair<Seq, ID>> preferred =
getPreferred(lcl);
898 return (preferred->first >= minSeq) ? preferred->second : lcl.id();
902 peerCounts.
begin(), peerCounts.
end(), [](
auto& a,
auto& b) {
905 return std::tie(a.second, a.first) <
906 std::tie(b.second, b.first);
909 if (it != peerCounts.
end())
931 if (ledger.id() == ledgerID)
940 [&ledgerID](
auto const& it) {
941 auto const& curr = it.second;
942 return curr.seq() > Seq{0} &&
943 curr[curr.seq() -
Seq{1}] == ledgerID;
960 if (v.trusted() && v.full())
998 if (v.trusted() && v.full())
1019 if (v.trusted() && v.full())
1042 if (v.trusted() && v.full())
1044 boost::optional<std::uint32_t> loadFee = v.loadFee();
1087 if (adaptor_.now() <
1088 v.seenTime() + parms_.validationFRESHNESS &&
1089 trustedKeys.
find(v.key()) != trustedKeys.
end())
1091 trustedKeys.
erase(v.key());
void expire()
Expire old validation sets.
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
boost::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
typename ripple::test::csf::Peer::ValAdaptor ::Validation Validation
hash_map< NodeID, SeqEnforcer< Seq > > seqEnforcers_
Enforce validation increasing sequence requirement.
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 ...
std::vector< std::uint32_t > fees(ID const &ledgerID, std::uint32_t baseFee)
Returns fees reported by trusted full validators in the given ledger.
hash_map< NodeID, Ledger > lastLedger_
Validations(ValidationParms const &p, beast::abstract_clock< std::chrono::steady_clock > &c, Ts &&... ts)
Constructor.
void trustChanged(hash_set< NodeID > const &added, hash_set< NodeID > const &removed)
Update trust status of validations.
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.
LedgerTrie< Ledger > trie_
beast::aged_unordered_map< Seq, hash_map< NodeID, Validation >, std::chrono::steady_clock, beast::uhash<> > bySequence_
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
auto withTrie(std::lock_guard< Mutex > const &lock, F &&f)
Use the trie for a calculation.
void current(std::lock_guard< Mutex > const &lock, Pre &&pre, F &&f)
Iterate current validations.
void byLedger(std::lock_guard< Mutex > const &, ID const &ledgerID, Pre &&pre, F &&f)
Iterate the set of validations associated with a given ledger id.
ValStatus
Status of newly received validation.
std::chrono::seconds validationCURRENT_EARLY
Duration pre-close in which validations are acceptable.
void setSeqToKeep(Seq const &s)
Set the smallest sequence number of validations to keep from expire.
beast::aged_unordered_map< ID, hash_map< NodeID, Validation >, std::chrono::steady_clock, beast::uhash<> > byLedger_
Validations from listed nodes, indexed by ledger id (partial and full)
std::string to_string(ListDisposition disposition)
void checkAcquired(std::lock_guard< Mutex > const &lock)
ValidationParms const & parms() const
Return the validation timing parameters.
Json::Value getJsonTrie() const
void updateTrie(std::lock_guard< Mutex > const &lock, NodeID const &nodeID, Validation const &val, boost::optional< std::pair< Seq, ID >> prior)
Process a new validation.
@ badSeq
A validation violates the increasing seq requirement.
boost::optional< std::pair< Seq, ID > > getPreferred(Ledger const &curr)
Return the sequence number and ID of the preferred working ledger.
ValStatus add(NodeID const &nodeID, Validation const &val)
Add a new validation.
typename ripple::test::csf::Peer::ValAdaptor ::Mutex Mutex
std::chrono::steady_clock::time_point time_point
hash_map< std::pair< Seq, ID >, hash_set< NodeID > > acquiring_
typename Validation::NodeKey NodeKey
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
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.
std::size_t numTrustedForLedger(ID const &ledgerID)
Count the number of trusted full validations for the given ledger.
typename Validation::NodeID NodeID
@ multiple
Multiple validations for the same ledger from multiple validators.
@ stale
Not current or was older than current from this node.
@ current
This was a new validation and was added.
std::chrono::seconds validationCURRENT_LOCAL
Duration a validation remains current after first observed.
bool canValidateSeq(Seq const s)
Return whether the local node can issue a validation for the given sequence number.
@ validation
validation for signing
std::enable_if< is_aged_container< AgedContainer >::value, std::size_t >::type expire(AgedContainer &c, std::chrono::duration< Rep, Period > const &age)
Expire aged container items past the specified age.
boost::optional< Seq > toKeep_
std::chrono::seconds validationCURRENT_WALL
The number of seconds a validation remains current after its ledger's close time.
bool operator()(time_point now, Seq s, ValidationParms const &p)
Try advancing the largest observed validation ledger sequence.
std::vector< WrappedValidationType > getTrustedForLedger(ID const &ledgerID)
Get trusted full validations for a specific ledger.
ID getPreferred(Ledger const &curr, Seq minValidSeq)
Get the ID of the preferred working ledger that exceeds a minimum valid ledger sequence number.
void flush()
Flush all current validations.
void updateTrie(std::lock_guard< Mutex > const &, NodeID const &nodeID, Ledger ledger)
@ conflicting
Multiple validations for different ledgers by a single validator.
SeqEnforcer< Seq > localSeqEnforcer_
Associative container where each element is also indexed by time.
T emplace_back(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Ancestry trie of ledgers.
std::chrono::seconds validationFRESHNESS
How long we consider a validation fresh.
std::chrono::seconds validationSET_EXPIRES
Duration a set of validations for a given ledger hash remain valid.
const ValidationParms parms_
typename ripple::test::csf::Peer::ValAdaptor ::Ledger Ledger
auto getCurrentNodeIDs() -> hash_set< NodeID >
Get the set of node ids associated with current validations.
ValidationParms()=default
void removeTrie(std::lock_guard< Mutex > const &, NodeID const &nodeID, Validation const &val)
Adaptor const & adaptor() const
Return the adaptor instance.
Timing parameters to control validation staleness and expiration.
std::vector< WrappedValidationType > currentTrusted()
Get the currently trusted full validations.
hash_map< NodeID, Validation > current_