rippled
Loading...
Searching...
No Matches
Validations.h
1#ifndef XRPL_CONSENSUS_VALIDATIONS_H_INCLUDED
2#define XRPL_CONSENSUS_VALIDATIONS_H_INCLUDED
3
4#include <xrpld/consensus/LedgerTrie.h>
5
6#include <xrpl/basics/Log.h>
7#include <xrpl/basics/UnorderedContainers.h>
8#include <xrpl/basics/chrono.h>
9#include <xrpl/beast/container/aged_container_utility.h>
10#include <xrpl/beast/container/aged_unordered_map.h>
11#include <xrpl/protocol/PublicKey.h>
12
13#include <mutex>
14#include <optional>
15#include <type_traits>
16#include <utility>
17#include <vector>
18
19namespace ripple {
20
72
79template <class Seq>
81{
82 using time_point = std::chrono::steady_clock::time_point;
83 Seq seq_{0};
85
86public:
99 bool
101 {
102 if (now > (when_ + p.validationSET_EXPIRES))
103 seq_ = Seq{0};
104 if (s <= seq_)
105 return false;
106 seq_ = s;
107 when_ = now;
108 return true;
109 }
110
111 Seq
112 largest() const
113 {
114 return seq_;
115 }
116};
117
129inline bool
131 ValidationParms const& p,
133 NetClock::time_point signTime,
134 NetClock::time_point seenTime)
135{
136 // Because this can be called on untrusted, possibly
137 // malicious validations, we do our math in a way
138 // that avoids any chance of overflowing or underflowing
139 // the signing time. All of the expressions below are
140 // promoted from unsigned 32 bit to signed 64 bit prior
141 // to computation.
142
143 return (signTime > (now - p.validationCURRENT_EARLY)) &&
144 (signTime < (now + p.validationCURRENT_WALL)) &&
145 ((seenTime == NetClock::time_point{}) ||
146 (seenTime < (now + p.validationCURRENT_LOCAL)));
147}
148
150enum class ValStatus {
152 current,
154 stale,
156 badSeq,
158 multiple,
161};
162
163inline std::string
165{
166 switch (m)
167 {
169 return "current";
170 case ValStatus::stale:
171 return "stale";
173 return "badSeq";
175 return "multiple";
177 return "conflicting";
178 default:
179 return "unknown";
180 }
181}
182
269template <class Adaptor>
271{
272 using Mutex = typename Adaptor::Mutex;
273 using Validation = typename Adaptor::Validation;
274 using Ledger = typename Adaptor::Ledger;
275 using ID = typename Ledger::ID;
276 using Seq = typename Ledger::Seq;
277 using NodeID = typename Validation::NodeID;
278 using NodeKey = typename Validation::NodeKey;
279
281 std::invoke_result_t<decltype(&Validation::unwrap), Validation>>;
282
283 // Manages concurrent access to members
284 mutable Mutex mutex_;
285
286 // Validations from currently listed and trusted nodes (partial and full)
288
289 // Used to enforce the largest validation invariant for the local node
291
292 // Sequence of the largest validation received from each node
294
297 ID,
302
303 // Partial and full validations indexed by sequence
305 Seq,
310
311 // A range [low_, high_) of validations to keep from expire
313 {
316 };
318
319 // Represents the ancestry of validated ledgers
321
322 // Last (validated) ledger successfully acquired. If in this map, it is
323 // accounted for in the trie.
325
326 // Set of ledgers being acquired from the network
328
329 // Parameters to determine validation staleness
331
332 // Adaptor instance
333 // Is NOT managed by the mutex_ above
334 Adaptor adaptor_;
335
336private:
337 // Remove support of a validated ledger
338 void
341 NodeID const& nodeID,
342 Validation const& val)
343 {
344 {
345 auto it =
346 acquiring_.find(std::make_pair(val.seq(), val.ledgerID()));
347 if (it != acquiring_.end())
348 {
349 it->second.erase(nodeID);
350 if (it->second.empty())
351 acquiring_.erase(it);
352 }
353 }
354 {
355 auto it = lastLedger_.find(nodeID);
356 if (it != lastLedger_.end() && it->second.id() == val.ledgerID())
357 {
358 trie_.remove(it->second);
359 lastLedger_.erase(nodeID);
360 }
361 }
362 }
363
364 // Check if any pending acquire ledger requests are complete
365 void
367 {
368 for (auto it = acquiring_.begin(); it != acquiring_.end();)
369 {
370 if (std::optional<Ledger> ledger =
371 adaptor_.acquire(it->first.second))
372 {
373 for (NodeID const& nodeID : it->second)
374 updateTrie(lock, nodeID, *ledger);
375
376 it = acquiring_.erase(it);
377 }
378 else
379 ++it;
380 }
381 }
382
383 // Update the trie to reflect a new validated ledger
384 void
387 NodeID const& nodeID,
388 Ledger ledger)
389 {
390 auto const [it, inserted] = lastLedger_.emplace(nodeID, ledger);
391 if (!inserted)
392 {
393 trie_.remove(it->second);
394 it->second = ledger;
395 }
396 trie_.insert(ledger);
397 }
398
412 void
414 std::lock_guard<Mutex> const& lock,
415 NodeID const& nodeID,
416 Validation const& val,
418 {
419 XRPL_ASSERT(
420 val.trusted(),
421 "ripple::Validations::updateTrie : trusted input validation");
422
423 // Clear any prior acquiring ledger for this node
424 if (prior)
425 {
426 auto it = acquiring_.find(*prior);
427 if (it != acquiring_.end())
428 {
429 it->second.erase(nodeID);
430 if (it->second.empty())
431 acquiring_.erase(it);
432 }
433 }
434
435 checkAcquired(lock);
436
437 std::pair<Seq, ID> valPair{val.seq(), val.ledgerID()};
438 auto it = acquiring_.find(valPair);
439 if (it != acquiring_.end())
440 {
441 it->second.insert(nodeID);
442 }
443 else
444 {
445 if (std::optional<Ledger> ledger = adaptor_.acquire(val.ledgerID()))
446 updateTrie(lock, nodeID, *ledger);
447 else
448 acquiring_[valPair].insert(nodeID);
449 }
450 }
451
464 template <class F>
465 auto
467 {
468 // Call current to flush any stale validations
469 current(lock, [](auto) {}, [](auto, auto) {});
470 checkAcquired(lock);
471 return f(trie_);
472 }
473
490 template <class Pre, class F>
491 void
492 current(std::lock_guard<Mutex> const& lock, Pre&& pre, F&& f)
493 {
495 pre(current_.size());
496 auto it = current_.begin();
497 while (it != current_.end())
498 {
499 // Check for staleness
500 if (!isCurrent(
501 parms_, t, it->second.signTime(), it->second.seenTime()))
502 {
503 removeTrie(lock, it->first, it->second);
504 it = current_.erase(it);
505 }
506 else
507 {
508 auto cit = typename decltype(current_)::const_iterator{it};
509 // contains a live record
510 f(cit->first, cit->second);
511 ++it;
512 }
513 }
514 }
515
528 template <class Pre, class F>
529 void
532 ID const& ledgerID,
533 Pre&& pre,
534 F&& f)
535 {
536 auto it = byLedger_.find(ledgerID);
537 if (it != byLedger_.end())
538 {
539 // Update set time since it is being used
540 byLedger_.touch(it);
541 pre(it->second.size());
542 for (auto const& [key, val] : it->second)
543 f(key, val);
544 }
545 }
546
547public:
554 template <class... Ts>
556 ValidationParms const& p,
558 Ts&&... ts)
559 : byLedger_(c)
560 , bySequence_(c)
561 , parms_(p)
562 , adaptor_(std::forward<Ts>(ts)...)
563 {
564 }
565
568 Adaptor const&
569 adaptor() const
570 {
571 return adaptor_;
572 }
573
576 ValidationParms const&
577 parms() const
578 {
579 return parms_;
580 }
581
589 bool
591 {
593 return localSeqEnforcer_(byLedger_.clock().now(), s, parms_);
594 }
595
605 add(NodeID const& nodeID, Validation const& val)
606 {
607 if (!isCurrent(parms_, adaptor_.now(), val.signTime(), val.seenTime()))
608 return ValStatus::stale;
609
610 {
612
613 // Check that validation sequence is greater than any non-expired
614 // validations sequence from that validator; if it's not, perform
615 // additional work to detect Byzantine validations
616 auto const now = byLedger_.clock().now();
617
618 auto const [seqit, seqinserted] =
619 bySequence_[val.seq()].emplace(nodeID, val);
620
621 if (!seqinserted)
622 {
623 // Check if the entry we're already tracking was signed
624 // long enough ago that we can disregard it.
625 auto const diff =
626 std::max(seqit->second.signTime(), val.signTime()) -
627 std::min(seqit->second.signTime(), val.signTime());
628
629 if (diff > parms_.validationCURRENT_WALL &&
630 val.signTime() > seqit->second.signTime())
631 seqit->second = val;
632 }
633
634 // Enforce monotonically increasing sequences for validations
635 // by a given node, and run the active Byzantine detector:
636 if (auto& enf = seqEnforcers_[nodeID]; !enf(now, val.seq(), parms_))
637 {
638 // If the validation is for the same sequence as one we are
639 // tracking, check it closely:
640 if (seqit->second.seq() == val.seq())
641 {
642 // Two validations for the same sequence but for different
643 // ledgers. This could be the result of misconfiguration
644 // but it can also mean a Byzantine validator.
645 if (seqit->second.ledgerID() != val.ledgerID())
647
648 // Two validations for the same sequence and for the same
649 // ledger with different sign times. This could be the
650 // result of a misconfiguration but it can also mean a
651 // Byzantine validator.
652 if (seqit->second.signTime() != val.signTime())
654
655 // Two validations for the same sequence but with different
656 // cookies. This is probably accidental misconfiguration.
657 if (seqit->second.cookie() != val.cookie())
658 return ValStatus::multiple;
659 }
660
661 return ValStatus::badSeq;
662 }
663
664 byLedger_[val.ledgerID()].insert_or_assign(nodeID, val);
665
666 auto const [it, inserted] = current_.emplace(nodeID, val);
667 if (!inserted)
668 {
669 // Replace existing only if this one is newer
670 Validation& oldVal = it->second;
671 if (val.signTime() > oldVal.signTime())
672 {
673 std::pair<Seq, ID> old(oldVal.seq(), oldVal.ledgerID());
674 it->second = val;
675 if (val.trusted())
676 updateTrie(lock, nodeID, val, old);
677 }
678 else
679 return ValStatus::stale;
680 }
681 else if (val.trusted())
682 {
683 updateTrie(lock, nodeID, val, std::nullopt);
684 }
685 }
686
687 return ValStatus::current;
688 }
689
696 void
697 setSeqToKeep(Seq const& low, Seq const& high)
698 {
700 XRPL_ASSERT(
701 low < high, "ripple::Validations::setSeqToKeep : valid inputs");
702 toKeep_ = {low, high};
703 }
704
710 void
712 {
713 auto const start = std::chrono::steady_clock::now();
714 {
716 if (toKeep_)
717 {
718 // We only need to refresh the keep range when it's just about
719 // to expire. Track the next time we need to refresh.
720 static std::chrono::steady_clock::time_point refreshTime;
721 if (auto const now = byLedger_.clock().now();
722 refreshTime <= now)
723 {
724 // The next refresh time is shortly before the expiration
725 // time from now.
726 refreshTime = now + parms_.validationSET_EXPIRES -
728
729 for (auto i = byLedger_.begin(); i != byLedger_.end(); ++i)
730 {
731 auto const& validationMap = i->second;
732 if (!validationMap.empty())
733 {
734 auto const seq =
735 validationMap.begin()->second.seq();
736 if (toKeep_->low_ <= seq && seq < toKeep_->high_)
737 {
738 byLedger_.touch(i);
739 }
740 }
741 }
742
743 for (auto i = bySequence_.begin(); i != bySequence_.end();
744 ++i)
745 {
746 if (toKeep_->low_ <= i->first &&
747 i->first < toKeep_->high_)
748 {
749 bySequence_.touch(i);
750 }
751 }
752 }
753 }
754
757 }
758 JLOG(j.debug())
759 << "Validations sets sweep lock duration "
760 << std::chrono::duration_cast<std::chrono::milliseconds>(
762 .count()
763 << "ms";
764 }
765
775 void
776 trustChanged(hash_set<NodeID> const& added, hash_set<NodeID> const& removed)
777 {
779
780 for (auto& [nodeId, validation] : current_)
781 {
782 if (added.find(nodeId) != added.end())
783 {
784 validation.setTrusted();
785 updateTrie(lock, nodeId, validation, std::nullopt);
786 }
787 else if (removed.find(nodeId) != removed.end())
788 {
789 validation.setUntrusted();
790 removeTrie(lock, nodeId, validation);
791 }
792 }
793
794 for (auto& [_, validationMap] : byLedger_)
795 {
796 (void)_;
797 for (auto& [nodeId, validation] : validationMap)
798 {
799 if (added.find(nodeId) != added.end())
800 {
801 validation.setTrusted();
802 }
803 else if (removed.find(nodeId) != removed.end())
804 {
805 validation.setUntrusted();
806 }
807 }
808 }
809 }
810
813 {
815 return trie_.getJson();
816 }
817
831 getPreferred(Ledger const& curr)
832 {
835 withTrie(lock, [this](LedgerTrie<Ledger>& trie) {
836 return trie.getPreferred(localSeqEnforcer_.largest());
837 });
838 // No trusted validations to determine branch
839 if (!preferred)
840 {
841 // fall back to majority over acquiring ledgers
842 auto it = std::max_element(
843 acquiring_.begin(),
844 acquiring_.end(),
845 [](auto const& a, auto const& b) {
846 std::pair<Seq, ID> const& aKey = a.first;
847 typename hash_set<NodeID>::size_type const& aSize =
848 a.second.size();
849 std::pair<Seq, ID> const& bKey = b.first;
850 typename hash_set<NodeID>::size_type const& bSize =
851 b.second.size();
852 // order by number of trusted peers validating that ledger
853 // break ties with ledger ID
854 return std::tie(aSize, aKey.second) <
855 std::tie(bSize, bKey.second);
856 });
857 if (it != acquiring_.end())
858 return it->first;
859 return std::nullopt;
860 }
861
862 // If we are the parent of the preferred ledger, stick with our
863 // current ledger since we might be about to generate it
864 if (preferred->seq == curr.seq() + Seq{1} &&
865 preferred->ancestor(curr.seq()) == curr.id())
866 return std::make_pair(curr.seq(), curr.id());
867
868 // A ledger ahead of us is preferred regardless of whether it is
869 // a descendant of our working ledger or it is on a different chain
870 if (preferred->seq > curr.seq())
871 return std::make_pair(preferred->seq, preferred->id);
872
873 // Only switch to earlier or same sequence number
874 // if it is a different chain.
875 if (curr[preferred->seq] != preferred->id)
876 return std::make_pair(preferred->seq, preferred->id);
877
878 // Stick with current ledger
879 return std::make_pair(curr.seq(), curr.id());
880 }
881
891 ID
892 getPreferred(Ledger const& curr, Seq minValidSeq)
893 {
895 if (preferred && preferred->first >= minValidSeq)
896 return preferred->second;
897 return curr.id();
898 }
899
916 ID
918 Ledger const& lcl,
919 Seq minSeq,
920 hash_map<ID, std::uint32_t> const& peerCounts)
921 {
923
924 // Trusted validations exist, but stick with local preferred ledger if
925 // preferred is in the past
926 if (preferred)
927 return (preferred->first >= minSeq) ? preferred->second : lcl.id();
928
929 // Otherwise, rely on peer ledgers
930 auto it = std::max_element(
931 peerCounts.begin(), peerCounts.end(), [](auto& a, auto& b) {
932 // Prefer larger counts, then larger ids on ties
933 // (max_element expects this to return true if a < b)
934 return std::tie(a.second, a.first) <
935 std::tie(b.second, b.first);
936 });
937
938 if (it != peerCounts.end())
939 return it->first;
940 return lcl.id();
941 }
942
955 getNodesAfter(Ledger const& ledger, ID const& ledgerID)
956 {
958
959 // Use trie if ledger is the right one
960 if (ledger.id() == ledgerID)
961 return withTrie(lock, [&ledger](LedgerTrie<Ledger>& trie) {
962 return trie.branchSupport(ledger) - trie.tipSupport(ledger);
963 });
964
965 // Count parent ledgers as fallback
966 return std::count_if(
967 lastLedger_.begin(),
968 lastLedger_.end(),
969 [&ledgerID](auto const& it) {
970 auto const& curr = it.second;
971 return curr.seq() > Seq{0} &&
972 curr[curr.seq() - Seq{1}] == ledgerID;
973 });
974 }
975
982 {
984 std::lock_guard lock{mutex_};
985 current(
986 lock,
987 [&](std::size_t numValidations) { ret.reserve(numValidations); },
988 [&](NodeID const&, Validation const& v) {
989 if (v.trusted() && v.full())
990 ret.push_back(v.unwrap());
991 });
992 return ret;
993 }
994
999 auto
1001 {
1002 hash_set<NodeID> ret;
1003 std::lock_guard lock{mutex_};
1004 current(
1005 lock,
1006 [&](std::size_t numValidations) { ret.reserve(numValidations); },
1007 [&](NodeID const& nid, Validation const&) { ret.insert(nid); });
1008
1009 return ret;
1010 }
1011
1018 numTrustedForLedger(ID const& ledgerID)
1019 {
1020 std::size_t count = 0;
1021 std::lock_guard lock{mutex_};
1022 byLedger(
1023 lock,
1024 ledgerID,
1025 [&](std::size_t) {}, // nothing to reserve
1026 [&](NodeID const&, Validation const& v) {
1027 if (v.trusted() && v.full())
1028 ++count;
1029 });
1030 return count;
1031 }
1032
1040 getTrustedForLedger(ID const& ledgerID, Seq const& seq)
1041 {
1043 std::lock_guard lock{mutex_};
1044 byLedger(
1045 lock,
1046 ledgerID,
1047 [&](std::size_t numValidations) { res.reserve(numValidations); },
1048 [&](NodeID const&, Validation const& v) {
1049 if (v.trusted() && v.full() && v.seq() == seq)
1050 res.emplace_back(v.unwrap());
1051 });
1052
1053 return res;
1054 }
1055
1063 fees(ID const& ledgerID, std::uint32_t baseFee)
1064 {
1066 std::lock_guard lock{mutex_};
1067 byLedger(
1068 lock,
1069 ledgerID,
1070 [&](std::size_t numValidations) { res.reserve(numValidations); },
1071 [&](NodeID const&, Validation const& v) {
1072 if (v.trusted() && v.full())
1073 {
1074 std::optional<std::uint32_t> loadFee = v.loadFee();
1075 if (loadFee)
1076 res.push_back(*loadFee);
1077 else
1078 res.push_back(baseFee);
1079 }
1080 });
1081 return res;
1082 }
1083
1086 void
1088 {
1089 std::lock_guard lock{mutex_};
1090 current_.clear();
1091 }
1092
1109 laggards(Seq const seq, hash_set<NodeKey>& trustedKeys)
1110 {
1111 std::size_t laggards = 0;
1112
1113 current(
1114 std::lock_guard{mutex_},
1115 [](std::size_t) {},
1116 [&](NodeID const&, Validation const& v) {
1117 if (adaptor_.now() <
1118 v.seenTime() + parms_.validationFRESHNESS &&
1119 trustedKeys.find(v.key()) != trustedKeys.end())
1120 {
1121 trustedKeys.erase(v.key());
1122 if (seq > v.seq())
1123 ++laggards;
1124 }
1125 });
1126
1127 return laggards;
1128 }
1129
1132 {
1133 std::lock_guard lock{mutex_};
1134 return current_.size();
1135 }
1136
1139 {
1140 std::lock_guard lock{mutex_};
1141 return seqEnforcers_.size();
1142 }
1143
1146 {
1147 std::lock_guard lock{mutex_};
1148 return byLedger_.size();
1149 }
1150
1153 {
1154 std::lock_guard lock{mutex_};
1155 return bySequence_.size();
1156 }
1157};
1158
1159} // namespace ripple
1160#endif
T begin(T... args)
Represents a JSON value.
Definition json_value.h:131
A generic endpoint for log messages.
Definition Journal.h:41
Stream debug() const
Definition Journal.h:309
Abstract interface to a clock.
Associative container where each element is also indexed by time.
Ancestry trie of ledgers.
Definition LedgerTrie.h:332
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
Definition LedgerTrie.h:578
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
Definition LedgerTrie.h:666
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
Definition LedgerTrie.h:592
Enforce validation increasing sequence requirement.
Definition Validations.h:81
Seq largest() const
bool operator()(time_point now, Seq s, ValidationParms const &p)
Try advancing the largest observed validation ledger sequence.
std::chrono::steady_clock::time_point time_point
Definition Validations.h:82
Maintains current and recent ledger validations.
void current(std::lock_guard< Mutex > const &lock, Pre &&pre, F &&f)
Iterate current validations.
std::size_t sizeOfByLedgerCache() const
auto withTrie(std::lock_guard< Mutex > const &lock, F &&f)
Use the trie for a calculation.
hash_map< NodeID, Ledger > lastLedger_
std::optional< std::pair< Seq, ID > > getPreferred(Ledger const &curr)
Return the sequence number and ID of the preferred working ledger.
typename Ledger::Seq Seq
typename Adaptor::Mutex Mutex
typename Adaptor::Validation Validation
Adaptor const & adaptor() const
Return the adaptor instance.
Validations(ValidationParms const &p, beast::abstract_clock< std::chrono::steady_clock > &c, Ts &&... ts)
Constructor.
void removeTrie(std::lock_guard< Mutex > const &, NodeID const &nodeID, Validation const &val)
std::size_t sizeOfCurrentCache() const
hash_map< NodeID, SeqEnforcer< Seq > > seqEnforcers_
Json::Value getJsonTrie() const
typename Validation::NodeKey NodeKey
SeqEnforcer< Seq > localSeqEnforcer_
std::size_t numTrustedForLedger(ID const &ledgerID)
Count the number of trusted full validations for the given ledger.
hash_map< std::pair< Seq, ID >, hash_set< NodeID > > acquiring_
typename Validation::NodeID NodeID
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 ...
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)
hash_map< NodeID, Validation > current_
void updateTrie(std::lock_guard< Mutex > const &, NodeID const &nodeID, Ledger ledger)
void flush()
Flush all current validations.
LedgerTrie< Ledger > trie_
ValidationParms const & parms() const
Return the validation timing parameters.
auto getCurrentNodeIDs() -> hash_set< NodeID >
Get the set of node ids associated with current validations.
std::optional< KeepRange > toKeep_
ValidationParms const parms_
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::vector< WrappedValidationType > getTrustedForLedger(ID const &ledgerID, Seq const &seq)
Get trusted full validations for a specific ledger.
typename Adaptor::Ledger 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.
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 sizeOfSeqEnforcersCache() const
beast::aged_unordered_map< Seq, hash_map< NodeID, Validation >, std::chrono::steady_clock, beast::uhash<> > bySequence_
void trustChanged(hash_set< NodeID > const &added, hash_set< NodeID > const &removed)
Update trust status of validations.
std::vector< WrappedValidationType > currentTrusted()
Get the currently trusted full validations.
typename Ledger::ID ID
ID getPreferred(Ledger const &curr, Seq minValidSeq)
Get the ID of the preferred working ledger that exceeds a minimum valid ledger sequence number.
std::size_t sizeOfBySequenceCache() const
void checkAcquired(std::lock_guard< Mutex > const &lock)
void setSeqToKeep(Seq const &low, Seq const &high)
Set the range [low, high) of validations to keep from expire.
bool canValidateSeq(Seq const s)
Return whether the local node can issue a validation for the given sequence number.
ValStatus add(NodeID const &nodeID, Validation const &val)
Add a new validation.
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.
void expire(beast::Journal &j)
Expire old validation sets.
std::vector< std::uint32_t > fees(ID const &ledgerID, std::uint32_t baseFee)
Returns fees reported by trusted full validators in the given ledger.
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.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
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.
@ stale
Sequence is too old.
Dir::const_iterator const_iterator
Definition Dir.cpp:5
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
@ validation
validation for signing
STL namespace.
T push_back(T... args)
T reserve(T... args)
Timing parameters to control validation staleness and expiration.
Definition Validations.h:28
std::chrono::seconds validationCURRENT_LOCAL
Duration a validation remains current after first observed.
Definition Validations.h:45
std::chrono::seconds validationFRESHNESS
How long we consider a validation fresh.
Definition Validations.h:70
std::chrono::seconds validationSET_EXPIRES
Duration a set of validations for a given ledger hash remain valid.
Definition Validations.h:60
std::chrono::seconds validationCURRENT_WALL
The number of seconds a validation remains current after its ledger's close time.
Definition Validations.h:37
std::chrono::seconds validationCURRENT_EARLY
Duration pre-close in which validations are acceptable.
Definition Validations.h:52