rippled
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.validationSET_EXPIRES))
102 seq_ = Seq{0};
103 if (s <= seq_)
104 return false;
105 seq_ = s;
106 when_ = now;
107 return true;
108 }
109
110 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.validationCURRENT_EARLY)) &&
143 (signTime < (now + p.validationCURRENT_WALL)) &&
144 ((seenTime == NetClock::time_point{}) || (seenTime < (now + p.validationCURRENT_LOCAL)));
145}
146
148enum class ValStatus {
150 current,
152 stale,
154 badSeq,
156 multiple,
159};
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 = typename Adaptor::Mutex;
271 using Validation = typename Adaptor::Validation;
272 using Ledger = typename Adaptor::Ledger;
273 using ID = typename Ledger::ID;
274 using Seq = typename Ledger::Seq;
275 using NodeID = typename Validation::NodeID;
276 using NodeKey = typename Validation::NodeKey;
277
279 std::decay_t<std::invoke_result_t<decltype(&Validation::unwrap), Validation>>;
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::lock_guard<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 ++it;
373 }
374 }
375
376 // Update the trie to reflect a new validated ledger
377 void
378 updateTrie(std::lock_guard<Mutex> const&, NodeID const& nodeID, Ledger ledger)
379 {
380 auto const [it, inserted] = lastLedger_.emplace(nodeID, ledger);
381 if (!inserted)
382 {
383 trie_.remove(it->second);
384 it->second = ledger;
385 }
386 trie_.insert(ledger);
387 }
388
402 void
404 std::lock_guard<Mutex> const& lock,
405 NodeID const& nodeID,
406 Validation const& val,
408 {
409 XRPL_ASSERT(val.trusted(), "xrpl::Validations::updateTrie : trusted input validation");
410
411 // Clear any prior acquiring ledger for this node
412 if (prior)
413 {
414 auto it = acquiring_.find(*prior);
415 if (it != acquiring_.end())
416 {
417 it->second.erase(nodeID);
418 if (it->second.empty())
419 acquiring_.erase(it);
420 }
421 }
422
423 checkAcquired(lock);
424
425 std::pair<Seq, ID> const valPair{val.seq(), val.ledgerID()};
426 auto it = acquiring_.find(valPair);
427 if (it != acquiring_.end())
428 {
429 it->second.insert(nodeID);
430 }
431 else
432 {
433 if (std::optional<Ledger> ledger = adaptor_.acquire(val.ledgerID()))
434 updateTrie(lock, nodeID, *ledger);
435 else
436 acquiring_[valPair].insert(nodeID);
437 }
438 }
439
452 template <class F>
453 auto
455 {
456 // Call current to flush any stale validations
457 current(lock, [](auto) {}, [](auto, auto) {});
458 checkAcquired(lock);
459 return f(trie_);
460 }
461
478 template <class Pre, class F>
479 void
480 current(std::lock_guard<Mutex> const& lock, Pre&& pre, F&& f)
481 {
482 NetClock::time_point const t = adaptor_.now();
483 pre(current_.size());
484 auto it = current_.begin();
485 while (it != current_.end())
486 {
487 // Check for staleness
488 if (!isCurrent(parms_, t, it->second.signTime(), it->second.seenTime()))
489 {
490 removeTrie(lock, it->first, it->second);
491 it = current_.erase(it);
492 }
493 else
494 {
495 auto cit = typename decltype(current_)::const_iterator{it};
496 // contains a live record
497 f(cit->first, cit->second);
498 ++it;
499 }
500 }
501 }
502
515 template <class Pre, class F>
516 void
517 byLedger(std::lock_guard<Mutex> const&, ID const& ledgerID, Pre&& pre, F&& f)
518 {
519 auto it = byLedger_.find(ledgerID);
520 if (it != byLedger_.end())
521 {
522 // Update set time since it is being used
523 byLedger_.touch(it);
524 pre(it->second.size());
525 for (auto const& [key, val] : it->second)
526 f(key, val);
527 }
528 }
529
530public:
537 template <class... Ts>
539 ValidationParms const& p,
541 Ts&&... ts)
542 : byLedger_(c), bySequence_(c), parms_(p), adaptor_(std::forward<Ts>(ts)...)
543 {
544 }
545
548 Adaptor const&
549 adaptor() const
550 {
551 return adaptor_;
552 }
553
556 ValidationParms const&
557 parms() const
558 {
559 return parms_;
560 }
561
569 bool
571 {
572 std::lock_guard const lock{mutex_};
573 return localSeqEnforcer_(byLedger_.clock().now(), s, parms_);
574 }
575
585 add(NodeID const& nodeID, Validation const& val)
586 {
587 if (!isCurrent(parms_, adaptor_.now(), val.signTime(), val.seenTime()))
588 return ValStatus::stale;
589
590 {
591 std::lock_guard const lock{mutex_};
592
593 // Check that validation sequence is greater than any non-expired
594 // validations sequence from that validator; if it's not, perform
595 // additional work to detect Byzantine validations
596 auto const now = byLedger_.clock().now();
597
598 auto const [seqit, seqinserted] = bySequence_[val.seq()].emplace(nodeID, val);
599
600 if (!seqinserted)
601 {
602 // Check if the entry we're already tracking was signed
603 // long enough ago that we can disregard it.
604 auto const diff = std::max(seqit->second.signTime(), val.signTime()) -
605 std::min(seqit->second.signTime(), val.signTime());
606
607 if (diff > parms_.validationCURRENT_WALL &&
608 val.signTime() > seqit->second.signTime())
609 seqit->second = val;
610 }
611
612 // Enforce monotonically increasing sequences for validations
613 // by a given node, and run the active Byzantine detector:
614 if (auto& enf = seqEnforcers_[nodeID]; !enf(now, val.seq(), parms_))
615 {
616 // If the validation is for the same sequence as one we are
617 // tracking, check it closely:
618 if (seqit->second.seq() == val.seq())
619 {
620 // Two validations for the same sequence but for different
621 // ledgers. This could be the result of misconfiguration
622 // but it can also mean a Byzantine validator.
623 if (seqit->second.ledgerID() != val.ledgerID())
625
626 // Two validations for the same sequence and for the same
627 // ledger with different sign times. This could be the
628 // result of a misconfiguration but it can also mean a
629 // Byzantine validator.
630 if (seqit->second.signTime() != val.signTime())
632
633 // Two validations for the same sequence but with different
634 // cookies. This is probably accidental misconfiguration.
635 if (seqit->second.cookie() != val.cookie())
636 return ValStatus::multiple;
637 }
638
639 return ValStatus::badSeq;
640 }
641
642 byLedger_[val.ledgerID()].insert_or_assign(nodeID, val);
643
644 auto const [it, inserted] = current_.emplace(nodeID, val);
645 if (!inserted)
646 {
647 // Replace existing only if this one is newer
648 Validation const& oldVal = it->second;
649 if (val.signTime() > oldVal.signTime())
650 {
651 std::pair<Seq, ID> old(oldVal.seq(), oldVal.ledgerID());
652 it->second = val;
653 if (val.trusted())
654 updateTrie(lock, nodeID, val, old);
655 }
656 else
657 return ValStatus::stale;
658 }
659 else if (val.trusted())
660 {
661 updateTrie(lock, nodeID, val, std::nullopt);
662 }
663 }
664
665 return ValStatus::current;
666 }
667
674 void
675 setSeqToKeep(Seq const& low, Seq const& high)
676 {
677 std::lock_guard const lock{mutex_};
678 XRPL_ASSERT(low < high, "xrpl::Validations::setSeqToKeep : valid inputs");
679 toKeep_ = {low, high};
680 }
681
687 void
689 {
690 auto const start = std::chrono::steady_clock::now();
691 {
692 std::lock_guard const lock{mutex_};
693 if (toKeep_)
694 {
695 // We only need to refresh the keep range when it's just about
696 // to expire. Track the next time we need to refresh.
697 static std::chrono::steady_clock::time_point refreshTime;
698 if (auto const now = byLedger_.clock().now(); refreshTime <= now)
699 {
700 // The next refresh time is shortly before the expiration
701 // time from now.
703
704 for (auto i = byLedger_.begin(); i != byLedger_.end(); ++i)
705 {
706 auto const& validationMap = i->second;
707 if (!validationMap.empty())
708 {
709 auto const seq = validationMap.begin()->second.seq();
710 if (toKeep_->low_ <= seq && seq < toKeep_->high_)
711 {
712 byLedger_.touch(i);
713 }
714 }
715 }
716
717 for (auto i = bySequence_.begin(); i != bySequence_.end(); ++i)
718 {
719 if (toKeep_->low_ <= i->first && i->first < toKeep_->high_)
720 {
721 bySequence_.touch(i);
722 }
723 }
724 }
725 }
726
729 }
730 JLOG(j.debug()) << "Validations sets sweep lock duration "
731 << std::chrono::duration_cast<std::chrono::milliseconds>(
733 .count()
734 << "ms";
735 }
736
746 void
747 trustChanged(hash_set<NodeID> const& added, hash_set<NodeID> const& removed)
748 {
749 std::lock_guard const lock{mutex_};
750
751 for (auto& [nodeId, validation] : current_)
752 {
753 if (added.find(nodeId) != added.end())
754 {
755 validation.setTrusted();
756 updateTrie(lock, nodeId, validation, std::nullopt);
757 }
758 else if (removed.find(nodeId) != removed.end())
759 {
760 validation.setUntrusted();
761 removeTrie(lock, nodeId, validation);
762 }
763 }
764
765 for (auto& [_, validationMap] : byLedger_)
766 {
767 (void)_;
768 for (auto& [nodeId, validation] : validationMap)
769 {
770 if (added.find(nodeId) != added.end())
771 {
772 validation.setTrusted();
773 }
774 else if (removed.find(nodeId) != removed.end())
775 {
776 validation.setUntrusted();
777 }
778 }
779 }
780 }
781
784 {
785 std::lock_guard const lock{mutex_};
786 return trie_.getJson();
787 }
788
802 getPreferred(Ledger const& curr)
803 {
804 std::lock_guard const lock{mutex_};
805 std::optional<SpanTip<Ledger>> preferred = withTrie(lock, [this](LedgerTrie<Ledger>& trie) {
806 return trie.getPreferred(localSeqEnforcer_.largest());
807 });
808 // No trusted validations to determine branch
809 if (!preferred)
810 {
811 // fall back to majority over acquiring ledgers
812 auto it = std::max_element(
813 acquiring_.begin(), acquiring_.end(), [](auto const& a, auto const& b) {
814 std::pair<Seq, ID> const& aKey = a.first;
815 typename hash_set<NodeID>::size_type const& aSize = a.second.size();
816 std::pair<Seq, ID> const& bKey = b.first;
817 typename hash_set<NodeID>::size_type const& bSize = b.second.size();
818 // order by number of trusted peers validating that ledger
819 // break ties with ledger ID
820 return std::tie(aSize, aKey.second) < std::tie(bSize, bKey.second);
821 });
822 if (it != acquiring_.end())
823 return it->first;
824 return std::nullopt;
825 }
826
827 // If we are the parent of the preferred ledger, stick with our
828 // current ledger since we might be about to generate it
829 if (preferred->seq == curr.seq() + Seq{1} && preferred->ancestor(curr.seq()) == curr.id())
830 return std::make_pair(curr.seq(), curr.id());
831
832 // A ledger ahead of us is preferred regardless of whether it is
833 // a descendant of our working ledger or it is on a different chain
834 if (preferred->seq > curr.seq())
835 return std::make_pair(preferred->seq, preferred->id);
836
837 // Only switch to earlier or same sequence number
838 // if it is a different chain.
839 if (curr[preferred->seq] != preferred->id)
840 return std::make_pair(preferred->seq, preferred->id);
841
842 // Stick with current ledger
843 return std::make_pair(curr.seq(), curr.id());
844 }
845
855 ID
856 getPreferred(Ledger const& curr, Seq minValidSeq)
857 {
859 if (preferred && preferred->first >= minValidSeq)
860 return preferred->second;
861 return curr.id();
862 }
863
880 ID
881 getPreferredLCL(Ledger const& lcl, Seq minSeq, hash_map<ID, std::uint32_t> const& peerCounts)
882 {
884
885 // Trusted validations exist, but stick with local preferred ledger if
886 // preferred is in the past
887 if (preferred)
888 return (preferred->first >= minSeq) ? preferred->second : lcl.id();
889
890 // Otherwise, rely on peer ledgers
891 auto it = std::max_element(peerCounts.begin(), peerCounts.end(), [](auto& a, auto& b) {
892 // Prefer larger counts, then larger ids on ties
893 // (max_element expects this to return true if a < b)
894 return std::tie(a.second, a.first) < std::tie(b.second, b.first);
895 });
896
897 if (it != peerCounts.end())
898 return it->first;
899 return lcl.id();
900 }
901
914 getNodesAfter(Ledger const& ledger, ID const& ledgerID)
915 {
916 std::lock_guard const lock{mutex_};
917
918 // Use trie if ledger is the right one
919 if (ledger.id() == ledgerID)
920 return withTrie(lock, [&ledger](LedgerTrie<Ledger>& trie) {
921 return trie.branchSupport(ledger) - trie.tipSupport(ledger);
922 });
923
924 // Count parent ledgers as fallback
925 return std::count_if(lastLedger_.begin(), lastLedger_.end(), [&ledgerID](auto const& it) {
926 auto const& curr = it.second;
927 return curr.seq() > Seq{0} && curr[curr.seq() - Seq{1}] == ledgerID;
928 });
929 }
930
937 {
939 std::lock_guard const lock{mutex_};
940 current(
941 lock,
942 [&](std::size_t numValidations) { ret.reserve(numValidations); },
943 [&](NodeID const&, Validation const& v) {
944 if (v.trusted() && v.full())
945 ret.push_back(v.unwrap());
946 });
947 return ret;
948 }
949
954 auto
956 {
958 std::lock_guard const lock{mutex_};
959 current(
960 lock,
961 [&](std::size_t numValidations) { ret.reserve(numValidations); },
962 [&](NodeID const& nid, Validation const&) { ret.insert(nid); });
963
964 return ret;
965 }
966
973 numTrustedForLedger(ID const& ledgerID)
974 {
975 std::size_t count = 0;
976 std::lock_guard const lock{mutex_};
977 byLedger(
978 lock,
979 ledgerID,
980 [&](std::size_t) {}, // nothing to reserve
981 [&](NodeID const&, Validation const& v) {
982 if (v.trusted() && v.full())
983 ++count;
984 });
985 return count;
986 }
987
995 getTrustedForLedger(ID const& ledgerID, Seq const& seq)
996 {
998 std::lock_guard const lock{mutex_};
999 byLedger(
1000 lock,
1001 ledgerID,
1002 [&](std::size_t numValidations) { res.reserve(numValidations); },
1003 [&](NodeID const&, Validation const& v) {
1004 if (v.trusted() && v.full() && v.seq() == seq)
1005 res.emplace_back(v.unwrap());
1006 });
1007
1008 return res;
1009 }
1010
1018 fees(ID const& ledgerID, std::uint32_t baseFee)
1019 {
1021 std::lock_guard const lock{mutex_};
1022 byLedger(
1023 lock,
1024 ledgerID,
1025 [&](std::size_t numValidations) { res.reserve(numValidations); },
1026 [&](NodeID const&, Validation const& v) {
1027 if (v.trusted() && v.full())
1028 {
1029 std::optional<std::uint32_t> loadFee = v.loadFee();
1030 if (loadFee)
1031 res.push_back(*loadFee);
1032 else
1033 res.push_back(baseFee);
1034 }
1035 });
1036 return res;
1037 }
1038
1041 void
1043 {
1044 std::lock_guard const lock{mutex_};
1045 current_.clear();
1046 }
1047
1064 laggards(Seq const seq, hash_set<NodeKey>& trustedKeys)
1065 {
1066 std::size_t laggards = 0;
1067
1068 current(
1069 std::lock_guard{mutex_},
1070 [](std::size_t) {},
1071 [&](NodeID const&, Validation const& v) {
1072 if (adaptor_.now() < v.seenTime() + parms_.validationFRESHNESS &&
1073 trustedKeys.find(v.key()) != trustedKeys.end())
1074 {
1075 trustedKeys.erase(v.key());
1076 if (seq > v.seq())
1077 ++laggards;
1078 }
1079 });
1080
1081 return laggards;
1082 }
1083
1086 {
1087 std::lock_guard const lock{mutex_};
1088 return current_.size();
1089 }
1090
1093 {
1094 std::lock_guard const lock{mutex_};
1095 return seqEnforcers_.size();
1096 }
1097
1100 {
1101 std::lock_guard const lock{mutex_};
1102 return byLedger_.size();
1103 }
1104
1107 {
1108 std::lock_guard const lock{mutex_};
1109 return bySequence_.size();
1110 }
1111};
1112
1113} // namespace xrpl
T begin(T... args)
Represents a JSON value.
Definition json_value.h:130
A generic endpoint for log messages.
Definition Journal.h:40
Stream debug() const
Definition Journal.h:301
Abstract interface to a clock.
Associative container where each element is also indexed by time.
Ancestry trie of ledgers.
Definition LedgerTrie.h:324
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
Definition LedgerTrie.h:568
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
Definition LedgerTrie.h:582
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
Definition LedgerTrie.h:656
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
Maintains current and recent ledger 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.
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.
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.
typename Adaptor::Mutex Mutex
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.
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 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.
void checkAcquired(std::lock_guard< Mutex > const &lock)
ValidationParms const & parms() const
Return the validation timing parameters.
void current(std::lock_guard< Mutex > const &lock, Pre &&pre, F &&f)
Iterate current validations.
void removeTrie(std::lock_guard< Mutex > const &, NodeID const &nodeID, Validation const &val)
hash_map< NodeID, Validation > current_
hash_map< NodeID, SeqEnforcer< Seq > > seqEnforcers_
Adaptor const & adaptor() const
Return the adaptor instance.
beast::aged_unordered_map< Seq, hash_map< NodeID, Validation >, std::chrono::steady_clock, beast::uhash<> > bySequence_
hash_map< NodeID, Ledger > lastLedger_
auto withTrie(std::lock_guard< Mutex > const &lock, F &&f)
Use the trie for a calculation.
SeqEnforcer< Seq > localSeqEnforcer_
Json::Value getJsonTrie() const
std::size_t sizeOfCurrentCache() const
std::optional< std::pair< Seq, ID > > getPreferred(Ledger const &curr)
Return the sequence number and ID of the preferred working ledger.
typename Validation::NodeKey NodeKey
void flush()
Flush all current validations.
std::vector< WrappedValidationType > currentTrusted()
Get the currently trusted full validations.
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)
void setSeqToKeep(Seq const &low, Seq const &high)
Set the range [low, high) of validations to keep from expire.
Validations(ValidationParms const &p, beast::abstract_clock< std::chrono::steady_clock > &c, Ts &&... ts)
Constructor.
ValidationParms const parms_
void updateTrie(std::lock_guard< Mutex > const &, NodeID const &nodeID, Ledger ledger)
std::size_t sizeOfByLedgerCache() const
typename Adaptor::Validation Validation
typename Ledger::Seq Seq
std::size_t sizeOfBySequenceCache() const
typename Ledger::ID ID
typename Validation::NodeID NodeID
typename Adaptor::Ledger Ledger
std::size_t sizeOfSeqEnforcersCache() const
std::optional< KeepRange > toKeep_
void expire(beast::Journal &j)
Expire old validation sets.
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 ...
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.
void updateTrie(std::lock_guard< Mutex > const &lock, NodeID const &nodeID, Validation const &val, std::optional< std::pair< Seq, ID > > prior)
Process a new validation.
hash_map< std::pair< Seq, ID >, hash_set< NodeID > > acquiring_
T count_if(T... args)
T emplace_back(T... args)
T end(T... args)
T erase(T... args)
T find(T... args)
T insert(T... args)
T is_same_v
T make_pair(T... args)
T max_element(T... args)
T max(T... args)
T min(T... args)
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.
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::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:602
ValStatus
Status of validation we received.
@ badSeq
A validation violates the increasing seq requirement.
@ stale
Not current or was older than current from this node.
@ current
This was a new validation and was added.
@ conflicting
Multiple validations by a validator for different ledgers.
@ multiple
Multiple validations by a validator for the same ledger.
Dir::const_iterator const_iterator
Definition Dir.cpp:5
@ validation
validation for signing
@ stale
Sequence is too old.
T push_back(T... args)
T reserve(T... args)
Timing parameters to control validation staleness and expiration.
Definition Validations.h:27
std::chrono::seconds validationFRESHNESS
How long we consider a validation fresh.
Definition Validations.h:69
std::chrono::seconds validationSET_EXPIRES
Duration a set of validations for a given ledger hash remain valid.
Definition Validations.h:59
std::chrono::seconds validationCURRENT_EARLY
Duration pre-close in which validations are acceptable.
Definition Validations.h:51
std::chrono::seconds validationCURRENT_LOCAL
Duration a validation remains current after first observed.
Definition Validations.h:44
std::chrono::seconds validationCURRENT_WALL
The number of seconds a validation remains current after its ledger's close time.
Definition Validations.h:36