xrpld
Loading...
Searching...
No Matches
Validations.h
1#pragma once
2
3#include <xrpld/consensus/LedgerTrie.h>
4
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>
11
12#include <mutex>
13#include <optional>
14#include <type_traits>
15#include <utility>
16#include <vector>
17
18namespace xrpl {
19
71
78template <class Seq>
80{
81 using time_point = std::chrono::steady_clock::time_point;
82 Seq seq_{0};
84
85public:
98 bool
100 {
101 if (now > (when_ + p.validationSetExpires))
102 seq_ = Seq{0};
103 if (s <= seq_)
104 return false;
105 seq_ = s;
106 when_ = now;
107 return true;
108 }
109
110 [[nodiscard]] Seq
111 largest() const
112 {
113 return seq_;
114 }
115};
116
128inline bool
130 ValidationParms const& p,
132 NetClock::time_point signTime,
133 NetClock::time_point seenTime)
134{
135 // Because this can be called on untrusted, possibly
136 // malicious validations, we do our math in a way
137 // that avoids any chance of overflowing or underflowing
138 // the signing time. All of the expressions below are
139 // promoted from unsigned 32 bit to signed 64 bit prior
140 // to computation.
141
142 return (signTime > (now - p.validationCurrentEarly)) &&
143 (signTime < (now + p.validationCurrentWall)) &&
144 ((seenTime == NetClock::time_point{}) || (seenTime < (now + p.validationCurrentLocal)));
145}
146
160
161inline std::string
163{
164 switch (m)
165 {
167 return "current";
168 case ValStatus::Stale:
169 return "stale";
171 return "badSeq";
173 return "multiple";
175 return "conflicting";
176 default:
177 return "unknown";
178 }
179}
180
267template <class Adaptor>
269{
270 using Mutex = Adaptor::Mutex;
271 using Validation = Adaptor::Validation;
272 using Ledger = Adaptor::Ledger;
273 using ID = Ledger::ID;
277
280
281 // Manages concurrent access to members
282 mutable Mutex mutex_;
283
284 // Validations from currently listed and trusted nodes (partial and full)
286
287 // Used to enforce the largest validation invariant for the local node
289
290 // Sequence of the largest validation received from each node
292
295 ID,
300
301 // Partial and full validations indexed by sequence
303 Seq,
308
309 // A range [low_, high_) of validations to keep from expire
311 {
314 };
316
317 // Represents the ancestry of validated ledgers
319
320 // Last (validated) ledger successfully acquired. If in this map, it is
321 // accounted for in the trie.
323
324 // Set of ledgers being acquired from the network
326
327 // Parameters to determine validation staleness
329
330 // Adaptor instance
331 // Is NOT managed by the mutex_ above
332 Adaptor adaptor_;
333
334private:
335 // Remove support of a validated ledger
336 void
337 removeTrie(std::scoped_lock<Mutex> const&, NodeID const& nodeID, Validation const& val)
338 {
339 {
340 auto it = acquiring_.find(std::make_pair(val.seq(), val.ledgerID()));
341 if (it != acquiring_.end())
342 {
343 it->second.erase(nodeID);
344 if (it->second.empty())
345 acquiring_.erase(it);
346 }
347 }
348 {
349 auto it = lastLedger_.find(nodeID);
350 if (it != lastLedger_.end() && it->second.id() == val.ledgerID())
351 {
352 trie_.remove(it->second);
353 lastLedger_.erase(nodeID);
354 }
355 }
356 }
357
358 // Check if any pending acquire ledger requests are complete
359 void
361 {
362 for (auto it = acquiring_.begin(); it != acquiring_.end();)
363 {
364 if (std::optional<Ledger> ledger = adaptor_.acquire(it->first.second))
365 {
366 for (NodeID const& nodeID : it->second)
367 updateTrie(lock, nodeID, *ledger);
368
369 it = acquiring_.erase(it);
370 }
371 else
372 {
373 ++it;
374 }
375 }
376 }
377
378 // Update the trie to reflect a new validated ledger
379 void
380 updateTrie(std::scoped_lock<Mutex> const&, NodeID const& nodeID, Ledger ledger)
381 {
382 auto const [it, inserted] = lastLedger_.emplace(nodeID, ledger);
383 if (!inserted)
384 {
385 trie_.remove(it->second);
386 it->second = ledger;
387 }
388 trie_.insert(ledger);
389 }
390
404 void
406 std::scoped_lock<Mutex> const& lock,
407 NodeID const& nodeID,
408 Validation const& val,
410 {
411 XRPL_ASSERT(val.trusted(), "xrpl::Validations::updateTrie : trusted input validation");
412
413 // Clear any prior acquiring ledger for this node
414 if (prior)
415 {
416 auto it = acquiring_.find(*prior);
417 if (it != acquiring_.end())
418 {
419 it->second.erase(nodeID);
420 if (it->second.empty())
421 acquiring_.erase(it);
422 }
423 }
424
425 checkAcquired(lock);
426
427 std::pair<Seq, ID> const valPair{val.seq(), val.ledgerID()};
428 auto it = acquiring_.find(valPair);
429 if (it != acquiring_.end())
430 {
431 it->second.insert(nodeID);
432 }
433 else
434 {
435 if (std::optional<Ledger> ledger = adaptor_.acquire(val.ledgerID()))
436 {
437 updateTrie(lock, nodeID, *ledger);
438 }
439 else
440 {
441 acquiring_[valPair].insert(nodeID);
442 }
443 }
444 }
445
458 template <class F>
459 auto
461 {
462 // Call current to flush any stale validations
463 current(lock, [](auto) {}, [](auto, auto) {});
464 checkAcquired(lock);
465 return f(trie_);
466 }
467
483
484 template <class Pre, class F>
485 void
486 current(std::scoped_lock<Mutex> const& lock, Pre&& pre, F&& f)
487 {
488 NetClock::time_point const t = adaptor_.now();
489 pre(current_.size());
490 auto it = current_.begin();
491 while (it != current_.end())
492 {
493 // Check for staleness
494 if (!isCurrent(parms_, t, it->second.signTime(), it->second.seenTime()))
495 {
496 removeTrie(lock, it->first, it->second);
497 it = current_.erase(it);
498 }
499 else
500 {
501 auto cit = typename decltype(current_)::const_iterator{it};
502 // contains a live record
503 f(cit->first, cit->second);
504 ++it;
505 }
506 }
507 }
508
521 template <class Pre, class F>
522 void
523 byLedger(std::scoped_lock<Mutex> const&, ID const& ledgerID, Pre&& pre, F&& f)
524 {
525 auto it = byLedger_.find(ledgerID);
526 if (it != byLedger_.end())
527 {
528 // Update set time since it is being used
529 byLedger_.touch(it);
530 pre(it->second.size());
531 for (auto const& [key, val] : it->second)
532 f(key, val);
533 }
534 }
535
536public:
543 template <class... Ts>
545 ValidationParms const& p,
547 Ts&&... ts)
548 : byLedger_(c), bySequence_(c), parms_(p), adaptor_(std::forward<Ts>(ts)...)
549 {
550 }
551
554 Adaptor const&
555 adaptor() const
556 {
557 return adaptor_;
558 }
559
562 ValidationParms const&
563 parms() const
564 {
565 return parms_;
566 }
567
575 bool
577 {
578 std::scoped_lock const lock{mutex_};
579 return localSeqEnforcer_(byLedger_.clock().now(), s, parms_);
580 }
581
591 add(NodeID const& nodeID, Validation const& val)
592 {
593 if (!isCurrent(parms_, adaptor_.now(), val.signTime(), val.seenTime()))
594 return ValStatus::Stale;
595
596 {
597 std::scoped_lock const lock{mutex_};
598
599 // Check that validation sequence is greater than any non-expired
600 // validations sequence from that validator; if it's not, perform
601 // additional work to detect Byzantine validations
602 auto const now = byLedger_.clock().now();
603
604 auto const [seqit, seqinserted] = bySequence_[val.seq()].emplace(nodeID, val);
605
606 if (!seqinserted)
607 {
608 // Check if the entry we're already tracking was signed
609 // long enough ago that we can disregard it.
610 auto const diff = std::max(seqit->second.signTime(), val.signTime()) -
611 std::min(seqit->second.signTime(), val.signTime());
612
613 if (diff > parms_.validationCurrentWall &&
614 val.signTime() > seqit->second.signTime())
615 seqit->second = val;
616 }
617
618 // Enforce monotonically increasing sequences for validations
619 // by a given node, and run the active Byzantine detector:
620 if (auto& enf = seqEnforcers_[nodeID]; !enf(now, val.seq(), parms_))
621 {
622 // If the validation is for the same sequence as one we are
623 // tracking, check it closely:
624 if (seqit->second.seq() == val.seq())
625 {
626 // Two validations for the same sequence but for different
627 // ledgers. This could be the result of misconfiguration
628 // but it can also mean a Byzantine validator.
629 if (seqit->second.ledgerID() != val.ledgerID())
631
632 // Two validations for the same sequence and for the same
633 // ledger with different sign times. This could be the
634 // result of a misconfiguration but it can also mean a
635 // Byzantine validator.
636 if (seqit->second.signTime() != val.signTime())
638
639 // Two validations for the same sequence but with different
640 // cookies. This is probably accidental misconfiguration.
641 if (seqit->second.cookie() != val.cookie())
642 return ValStatus::Multiple;
643 }
644
645 return ValStatus::BadSeq;
646 }
647
648 byLedger_[val.ledgerID()].insert_or_assign(nodeID, val);
649
650 auto const [it, inserted] = current_.emplace(nodeID, val);
651 if (!inserted)
652 {
653 // Replace existing only if this one is newer
654 Validation const& oldVal = it->second;
655 if (val.signTime() > oldVal.signTime())
656 {
657 std::pair<Seq, ID> old(oldVal.seq(), oldVal.ledgerID());
658 it->second = val;
659 if (val.trusted())
660 updateTrie(lock, nodeID, val, old);
661 }
662 else
663 {
664 return ValStatus::Stale;
665 }
666 }
667 else if (val.trusted())
668 {
669 updateTrie(lock, nodeID, val, std::nullopt);
670 }
671 }
672
673 return ValStatus::Current;
674 }
675
682 void
683 setSeqToKeep(Seq const& low, Seq const& high)
684 {
685 std::scoped_lock const lock{mutex_};
686 XRPL_ASSERT(low < high, "xrpl::Validations::setSeqToKeep : valid inputs");
687 toKeep_ = {low, high};
688 }
689
695 void
697 {
698 auto const start = std::chrono::steady_clock::now();
699 {
700 std::scoped_lock const lock{mutex_};
701 if (toKeep_)
702 {
703 // We only need to refresh the keep range when it's just about
704 // to expire. Track the next time we need to refresh.
705 static std::chrono::steady_clock::time_point kRefreshTime;
706 if (auto const now = byLedger_.clock().now(); kRefreshTime <= now)
707 {
708 // The next refresh time is shortly before the expiration
709 // time from now.
710 kRefreshTime = now + parms_.validationSetExpires - parms_.validationFRESHNESS;
711
712 for (auto i = byLedger_.begin(); i != byLedger_.end(); ++i)
713 {
714 auto const& validationMap = i->second;
715 if (!validationMap.empty())
716 {
717 auto const seq = validationMap.begin()->second.seq();
718 if (toKeep_->low <= seq && seq < toKeep_->high)
719 {
720 byLedger_.touch(i);
721 }
722 }
723 }
724
725 for (auto i = bySequence_.begin(); i != bySequence_.end(); ++i)
726 {
727 if (toKeep_->low <= i->first && i->first < toKeep_->high)
728 {
729 bySequence_.touch(i);
730 }
731 }
732 }
733 }
734
735 beast::expire(byLedger_, parms_.validationSetExpires);
736 beast::expire(bySequence_, parms_.validationSetExpires);
737 }
738 JLOG(j.debug()) << "Validations sets sweep lock duration "
741 .count()
742 << "ms";
743 }
744
754 void
755 trustChanged(hash_set<NodeID> const& added, hash_set<NodeID> const& removed)
756 {
757 std::scoped_lock const lock{mutex_};
758
759 for (auto& [nodeId, validation] : current_)
760 {
761 if (added.find(nodeId) != added.end())
762 {
763 validation.setTrusted();
764 updateTrie(lock, nodeId, validation, std::nullopt);
765 }
766 else if (removed.find(nodeId) != removed.end())
767 {
768 validation.setUntrusted();
769 removeTrie(lock, nodeId, validation);
770 }
771 }
772
773 for (auto& [_, validationMap] : byLedger_)
774 {
775 (void)_;
776 for (auto& [nodeId, validation] : validationMap)
777 {
778 if (added.find(nodeId) != added.end())
779 {
780 validation.setTrusted();
781 }
782 else if (removed.find(nodeId) != removed.end())
783 {
784 validation.setUntrusted();
785 }
786 }
787 }
788 }
789
792 {
793 std::scoped_lock const lock{mutex_};
794 return trie_.getJson();
795 }
796
810 getPreferred(Ledger const& curr)
811 {
812 std::scoped_lock const lock{mutex_};
813 std::optional<SpanTip<Ledger>> preferred = withTrie(lock, [this](LedgerTrie<Ledger>& trie) {
814 return trie.getPreferred(localSeqEnforcer_.largest());
815 });
816 // No trusted validations to determine branch
817 if (!preferred)
818 {
819 // fall back to majority over acquiring ledgers
820 auto it = std::ranges::max_element(acquiring_, [](auto const& a, auto const& b) {
821 std::pair<Seq, ID> const& aKey = a.first;
822 typename hash_set<NodeID>::size_type const& aSize = a.second.size();
823 std::pair<Seq, ID> const& bKey = b.first;
824 typename hash_set<NodeID>::size_type const& bSize = b.second.size();
825 // order by number of trusted peers validating that ledger
826 // break ties with ledger ID
827 return std::tie(aSize, aKey.second) < std::tie(bSize, bKey.second);
828 });
829 if (it != acquiring_.end())
830 return it->first;
831 return std::nullopt;
832 }
833
834 // If we are the parent of the preferred ledger, stick with our
835 // current ledger since we might be about to generate it
836 if (preferred->seq == curr.seq() + Seq{1} && preferred->ancestor(curr.seq()) == curr.id())
837 return std::make_pair(curr.seq(), curr.id());
838
839 // A ledger ahead of us is preferred regardless of whether it is
840 // a descendant of our working ledger or it is on a different chain
841 if (preferred->seq > curr.seq())
842 return std::make_pair(preferred->seq, preferred->id);
843
844 // Only switch to earlier or same sequence number
845 // if it is a different chain.
846 if (curr[preferred->seq] != preferred->id)
847 return std::make_pair(preferred->seq, preferred->id);
848
849 // Stick with current ledger
850 return std::make_pair(curr.seq(), curr.id());
851 }
852
862 ID
863 getPreferred(Ledger const& curr, Seq minValidSeq)
864 {
866 if (preferred && preferred->first >= minValidSeq)
867 return preferred->second;
868 return curr.id();
869 }
870
887 ID
888 getPreferredLCL(Ledger const& lcl, Seq minSeq, hash_map<ID, std::uint32_t> const& peerCounts)
889 {
891
892 // Trusted validations exist, but stick with local preferred ledger if
893 // preferred is in the past
894 if (preferred)
895 return (preferred->first >= minSeq) ? preferred->second : lcl.id();
896
897 // Otherwise, rely on peer ledgers
898 auto it = std::ranges::max_element(peerCounts, [](auto const& a, auto const& b) {
899 // Prefer larger counts, then larger ids on ties
900 // (max_element expects this to return true if a < b)
901 return std::tie(a.second, a.first) < std::tie(b.second, b.first);
902 });
903
904 if (it != peerCounts.end())
905 return it->first;
906 return lcl.id();
907 }
908
921 getNodesAfter(Ledger const& ledger, ID const& ledgerID)
922 {
923 std::scoped_lock const lock{mutex_};
924
925 // Use trie if ledger is the right one
926 if (ledger.id() == ledgerID)
927 {
928 return withTrie(lock, [&ledger](LedgerTrie<Ledger>& trie) {
929 return trie.branchSupport(ledger) - trie.tipSupport(ledger);
930 });
931 }
932
933 // Count parent ledgers as fallback
934 return std::ranges::count_if(lastLedger_, [&ledgerID](auto const& it) {
935 auto const& curr = it.second;
936 return curr.seq() > Seq{0} && curr[curr.seq() - Seq{1}] == ledgerID;
937 });
938 }
939
946 {
948 std::scoped_lock const lock{mutex_};
949 current(
950 lock,
951 [&](std::size_t numValidations) { ret.reserve(numValidations); },
952 [&](NodeID const&, Validation const& v) {
953 if (v.trusted() && v.full())
954 ret.push_back(v.unwrap());
955 });
956 return ret;
957 }
958
963 auto
965 {
967 std::scoped_lock const lock{mutex_};
968 current(
969 lock,
970 [&](std::size_t numValidations) { ret.reserve(numValidations); },
971 [&](NodeID const& nid, Validation const&) { ret.insert(nid); });
972
973 return ret;
974 }
975
982 numTrustedForLedger(ID const& ledgerID)
983 {
984 std::size_t count = 0;
985 std::scoped_lock const lock{mutex_};
986 byLedger(
987 lock,
988 ledgerID,
989 [&](std::size_t) {}, // nothing to reserve
990 [&](NodeID const&, Validation const& v) {
991 if (v.trusted() && v.full())
992 ++count;
993 });
994 return count;
995 }
996
1004 getTrustedForLedger(ID const& ledgerID, Seq const& seq)
1005 {
1007 std::scoped_lock const lock{mutex_};
1008 byLedger(
1009 lock,
1010 ledgerID,
1011 [&](std::size_t numValidations) { res.reserve(numValidations); },
1012 [&](NodeID const&, Validation const& v) {
1013 if (v.trusted() && v.full() && v.seq() == seq)
1014 res.emplace_back(v.unwrap());
1015 });
1016
1017 return res;
1018 }
1019
1027 fees(ID const& ledgerID, std::uint32_t baseFee)
1028 {
1030 std::scoped_lock const lock{mutex_};
1031 byLedger(
1032 lock,
1033 ledgerID,
1034 [&](std::size_t numValidations) { res.reserve(numValidations); },
1035 [&](NodeID const&, Validation const& v) {
1036 if (v.trusted() && v.full())
1037 {
1038 std::optional<std::uint32_t> loadFee = v.loadFee();
1039 if (loadFee)
1040 {
1041 res.push_back(*loadFee);
1042 }
1043 else
1044 {
1045 res.push_back(baseFee);
1046 }
1047 }
1048 });
1049 return res;
1050 }
1051
1054 void
1056 {
1057 std::scoped_lock const lock{mutex_};
1058 current_.clear();
1059 }
1060
1077 laggards(Seq const seq, hash_set<NodeKey>& trustedKeys)
1078 {
1080
1081 current(
1083 [](std::size_t) {},
1084 [&](NodeID const&, Validation const& v) {
1085 if (adaptor_.now() < v.seenTime() + parms_.validationFRESHNESS &&
1086 trustedKeys.find(v.key()) != trustedKeys.end())
1087 {
1088 trustedKeys.erase(v.key());
1089 if (seq > v.seq())
1090 ++laggards;
1091 }
1092 });
1093
1094 return laggards;
1095 }
1096
1099 {
1100 std::scoped_lock const lock{mutex_};
1101 return current_.size();
1102 }
1103
1106 {
1107 std::scoped_lock const lock{mutex_};
1108 return seqEnforcers_.size();
1109 }
1110
1113 {
1114 std::scoped_lock const lock{mutex_};
1115 return byLedger_.size();
1116 }
1117
1120 {
1121 std::scoped_lock const lock{mutex_};
1122 return bySequence_.size();
1123 }
1124};
1125
1126} // namespace xrpl
Abstract interface to a clock.
A generic endpoint for log messages.
Definition Journal.h:38
Stream debug() const
Definition Journal.h:297
Represents a JSON value.
Definition json_value.h:130
Ancestry trie of ledgers.
Definition LedgerTrie.h:323
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
Definition LedgerTrie.h:569
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
Definition LedgerTrie.h:583
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
Definition LedgerTrie.h:657
std::chrono::time_point< NetClock > time_point
Definition chrono.h:46
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).
xrpl::PublicKey NodeKey
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.
Definition Validations.h:80
std::chrono::steady_clock::time_point time_point
Definition Validations.h:81
bool operator()(time_point now, Seq s, ValidationParms const &p)
Try advancing the largest observed validation ledger sequence.
Definition Validations.h:99
Seq largest() const
time_point when_
Definition Validations.h:83
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.
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_
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.
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::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.
ID getPreferred(Ledger const &curr, Seq minValidSeq)
Get the ID of the preferred working ledger that exceeds a minimum valid ledger sequence number.
std::vector< std::uint32_t > fees(ID const &ledgerID, std::uint32_t baseFee)
Returns fees reported by trusted full validators in the given ledger.
RCLValidationsAdaptor::Ledger Ledger
hash_map< std::pair< Seq, ID >, hash_set< NodeID > > acquiring_
T count_if(T... args)
T duration_cast(T... args)
T emplace_back(T... args)
T end(T... args)
T erase(T... args)
T find(T... args)
T insert(T... args)
T make_pair(T... args)
T max_element(T... args)
T max(T... args)
T min(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
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
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)
Definition base_uint.h:633
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
Definition Dir.cpp:16
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
@ Stale
Sequence is too old.
Definition Manifest.h:200
T push_back(T... args)
T reserve(T... args)
Timing parameters to control validation staleness and expiration.
Definition Validations.h:27
std::chrono::seconds validationCurrentEarly
Duration pre-close in which validations are acceptable.
Definition Validations.h:51
std::chrono::seconds validationCurrentLocal
Duration a validation remains current after first observed.
Definition Validations.h:44
std::chrono::seconds validationSetExpires
Duration a set of validations for a given ledger hash remain valid.
Definition Validations.h:59
std::chrono::seconds validationFRESHNESS
How long we consider a validation fresh.
Definition Validations.h:69
std::chrono::seconds validationCurrentWall
The number of seconds a validation remains current after its ledger's close time.
Definition Validations.h:36
T tie(T... args)