rippled
Loading...
Searching...
No Matches
Validations.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2017 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_CONSENSUS_VALIDATIONS_H_INCLUDED
21#define RIPPLE_CONSENSUS_VALIDATIONS_H_INCLUDED
22
23#include <xrpld/consensus/LedgerTrie.h>
24
25#include <xrpl/basics/Log.h>
26#include <xrpl/basics/UnorderedContainers.h>
27#include <xrpl/basics/chrono.h>
28#include <xrpl/beast/container/aged_container_utility.h>
29#include <xrpl/beast/container/aged_unordered_map.h>
30#include <xrpl/protocol/PublicKey.h>
31
32#include <mutex>
33#include <optional>
34#include <type_traits>
35#include <utility>
36#include <vector>
37
38namespace ripple {
39
91
98template <class Seq>
100{
101 using time_point = std::chrono::steady_clock::time_point;
102 Seq seq_{0};
104
105public:
118 bool
120 {
121 if (now > (when_ + p.validationSET_EXPIRES))
122 seq_ = Seq{0};
123 if (s <= seq_)
124 return false;
125 seq_ = s;
126 when_ = now;
127 return true;
128 }
129
130 Seq
131 largest() const
132 {
133 return seq_;
134 }
135};
136
148inline bool
150 ValidationParms const& p,
152 NetClock::time_point signTime,
153 NetClock::time_point seenTime)
154{
155 // Because this can be called on untrusted, possibly
156 // malicious validations, we do our math in a way
157 // that avoids any chance of overflowing or underflowing
158 // the signing time. All of the expressions below are
159 // promoted from unsigned 32 bit to signed 64 bit prior
160 // to computation.
161
162 return (signTime > (now - p.validationCURRENT_EARLY)) &&
163 (signTime < (now + p.validationCURRENT_WALL)) &&
164 ((seenTime == NetClock::time_point{}) ||
165 (seenTime < (now + p.validationCURRENT_LOCAL)));
166}
167
169enum class ValStatus {
171 current,
173 stale,
175 badSeq,
177 multiple,
180};
181
182inline std::string
184{
185 switch (m)
186 {
188 return "current";
189 case ValStatus::stale:
190 return "stale";
192 return "badSeq";
194 return "multiple";
196 return "conflicting";
197 default:
198 return "unknown";
199 }
200}
201
288template <class Adaptor>
290{
291 using Mutex = typename Adaptor::Mutex;
292 using Validation = typename Adaptor::Validation;
293 using Ledger = typename Adaptor::Ledger;
294 using ID = typename Ledger::ID;
295 using Seq = typename Ledger::Seq;
296 using NodeID = typename Validation::NodeID;
297 using NodeKey = typename Validation::NodeKey;
298
300 std::invoke_result_t<decltype(&Validation::unwrap), Validation>>;
301
302 // Manages concurrent access to members
303 mutable Mutex mutex_;
304
305 // Validations from currently listed and trusted nodes (partial and full)
307
308 // Used to enforce the largest validation invariant for the local node
310
311 // Sequence of the largest validation received from each node
313
316 ID,
321
322 // Partial and full validations indexed by sequence
324 Seq,
329
330 // A range [low_, high_) of validations to keep from expire
332 {
335 };
337
338 // Represents the ancestry of validated ledgers
340
341 // Last (validated) ledger successfully acquired. If in this map, it is
342 // accounted for in the trie.
344
345 // Set of ledgers being acquired from the network
347
348 // Parameters to determine validation staleness
350
351 // Adaptor instance
352 // Is NOT managed by the mutex_ above
353 Adaptor adaptor_;
354
355private:
356 // Remove support of a validated ledger
357 void
360 NodeID const& nodeID,
361 Validation const& val)
362 {
363 {
364 auto it =
365 acquiring_.find(std::make_pair(val.seq(), val.ledgerID()));
366 if (it != acquiring_.end())
367 {
368 it->second.erase(nodeID);
369 if (it->second.empty())
370 acquiring_.erase(it);
371 }
372 }
373 {
374 auto it = lastLedger_.find(nodeID);
375 if (it != lastLedger_.end() && it->second.id() == val.ledgerID())
376 {
377 trie_.remove(it->second);
378 lastLedger_.erase(nodeID);
379 }
380 }
381 }
382
383 // Check if any pending acquire ledger requests are complete
384 void
386 {
387 for (auto it = acquiring_.begin(); it != acquiring_.end();)
388 {
389 if (std::optional<Ledger> ledger =
390 adaptor_.acquire(it->first.second))
391 {
392 for (NodeID const& nodeID : it->second)
393 updateTrie(lock, nodeID, *ledger);
394
395 it = acquiring_.erase(it);
396 }
397 else
398 ++it;
399 }
400 }
401
402 // Update the trie to reflect a new validated ledger
403 void
406 NodeID const& nodeID,
407 Ledger ledger)
408 {
409 auto const [it, inserted] = lastLedger_.emplace(nodeID, ledger);
410 if (!inserted)
411 {
412 trie_.remove(it->second);
413 it->second = ledger;
414 }
415 trie_.insert(ledger);
416 }
417
431 void
433 std::lock_guard<Mutex> const& lock,
434 NodeID const& nodeID,
435 Validation const& val,
437 {
438 XRPL_ASSERT(
439 val.trusted(),
440 "ripple::Validations::updateTrie : trusted input validation");
441
442 // Clear any prior acquiring ledger for this node
443 if (prior)
444 {
445 auto it = acquiring_.find(*prior);
446 if (it != acquiring_.end())
447 {
448 it->second.erase(nodeID);
449 if (it->second.empty())
450 acquiring_.erase(it);
451 }
452 }
453
454 checkAcquired(lock);
455
456 std::pair<Seq, ID> valPair{val.seq(), val.ledgerID()};
457 auto it = acquiring_.find(valPair);
458 if (it != acquiring_.end())
459 {
460 it->second.insert(nodeID);
461 }
462 else
463 {
464 if (std::optional<Ledger> ledger = adaptor_.acquire(val.ledgerID()))
465 updateTrie(lock, nodeID, *ledger);
466 else
467 acquiring_[valPair].insert(nodeID);
468 }
469 }
470
483 template <class F>
484 auto
486 {
487 // Call current to flush any stale validations
488 current(lock, [](auto) {}, [](auto, auto) {});
489 checkAcquired(lock);
490 return f(trie_);
491 }
492
509 template <class Pre, class F>
510 void
511 current(std::lock_guard<Mutex> const& lock, Pre&& pre, F&& f)
512 {
514 pre(current_.size());
515 auto it = current_.begin();
516 while (it != current_.end())
517 {
518 // Check for staleness
519 if (!isCurrent(
520 parms_, t, it->second.signTime(), it->second.seenTime()))
521 {
522 removeTrie(lock, it->first, it->second);
523 it = current_.erase(it);
524 }
525 else
526 {
527 auto cit = typename decltype(current_)::const_iterator{it};
528 // contains a live record
529 f(cit->first, cit->second);
530 ++it;
531 }
532 }
533 }
534
547 template <class Pre, class F>
548 void
551 ID const& ledgerID,
552 Pre&& pre,
553 F&& f)
554 {
555 auto it = byLedger_.find(ledgerID);
556 if (it != byLedger_.end())
557 {
558 // Update set time since it is being used
559 byLedger_.touch(it);
560 pre(it->second.size());
561 for (auto const& [key, val] : it->second)
562 f(key, val);
563 }
564 }
565
566public:
573 template <class... Ts>
575 ValidationParms const& p,
577 Ts&&... ts)
578 : byLedger_(c)
579 , bySequence_(c)
580 , parms_(p)
581 , adaptor_(std::forward<Ts>(ts)...)
582 {
583 }
584
587 Adaptor const&
588 adaptor() const
589 {
590 return adaptor_;
591 }
592
595 ValidationParms const&
596 parms() const
597 {
598 return parms_;
599 }
600
608 bool
610 {
612 return localSeqEnforcer_(byLedger_.clock().now(), s, parms_);
613 }
614
624 add(NodeID const& nodeID, Validation const& val)
625 {
626 if (!isCurrent(parms_, adaptor_.now(), val.signTime(), val.seenTime()))
627 return ValStatus::stale;
628
629 {
631
632 // Check that validation sequence is greater than any non-expired
633 // validations sequence from that validator; if it's not, perform
634 // additional work to detect Byzantine validations
635 auto const now = byLedger_.clock().now();
636
637 auto const [seqit, seqinserted] =
638 bySequence_[val.seq()].emplace(nodeID, val);
639
640 if (!seqinserted)
641 {
642 // Check if the entry we're already tracking was signed
643 // long enough ago that we can disregard it.
644 auto const diff =
645 std::max(seqit->second.signTime(), val.signTime()) -
646 std::min(seqit->second.signTime(), val.signTime());
647
648 if (diff > parms_.validationCURRENT_WALL &&
649 val.signTime() > seqit->second.signTime())
650 seqit->second = val;
651 }
652
653 // Enforce monotonically increasing sequences for validations
654 // by a given node, and run the active Byzantine detector:
655 if (auto& enf = seqEnforcers_[nodeID]; !enf(now, val.seq(), parms_))
656 {
657 // If the validation is for the same sequence as one we are
658 // tracking, check it closely:
659 if (seqit->second.seq() == val.seq())
660 {
661 // Two validations for the same sequence but for different
662 // ledgers. This could be the result of misconfiguration
663 // but it can also mean a Byzantine validator.
664 if (seqit->second.ledgerID() != val.ledgerID())
666
667 // Two validations for the same sequence and for the same
668 // ledger with different sign times. This could be the
669 // result of a misconfiguration but it can also mean a
670 // Byzantine validator.
671 if (seqit->second.signTime() != val.signTime())
673
674 // Two validations for the same sequence but with different
675 // cookies. This is probably accidental misconfiguration.
676 if (seqit->second.cookie() != val.cookie())
677 return ValStatus::multiple;
678 }
679
680 return ValStatus::badSeq;
681 }
682
683 byLedger_[val.ledgerID()].insert_or_assign(nodeID, val);
684
685 auto const [it, inserted] = current_.emplace(nodeID, val);
686 if (!inserted)
687 {
688 // Replace existing only if this one is newer
689 Validation& oldVal = it->second;
690 if (val.signTime() > oldVal.signTime())
691 {
692 std::pair<Seq, ID> old(oldVal.seq(), oldVal.ledgerID());
693 it->second = val;
694 if (val.trusted())
695 updateTrie(lock, nodeID, val, old);
696 }
697 else
698 return ValStatus::stale;
699 }
700 else if (val.trusted())
701 {
702 updateTrie(lock, nodeID, val, std::nullopt);
703 }
704 }
705
706 return ValStatus::current;
707 }
708
715 void
716 setSeqToKeep(Seq const& low, Seq const& high)
717 {
719 XRPL_ASSERT(
720 low < high, "ripple::Validations::setSeqToKeep : valid inputs");
721 toKeep_ = {low, high};
722 }
723
729 void
731 {
732 auto const start = std::chrono::steady_clock::now();
733 {
735 if (toKeep_)
736 {
737 // We only need to refresh the keep range when it's just about
738 // to expire. Track the next time we need to refresh.
739 static std::chrono::steady_clock::time_point refreshTime;
740 if (auto const now = byLedger_.clock().now();
741 refreshTime <= now)
742 {
743 // The next refresh time is shortly before the expiration
744 // time from now.
745 refreshTime = now + parms_.validationSET_EXPIRES -
747
748 for (auto i = byLedger_.begin(); i != byLedger_.end(); ++i)
749 {
750 auto const& validationMap = i->second;
751 if (!validationMap.empty())
752 {
753 auto const seq =
754 validationMap.begin()->second.seq();
755 if (toKeep_->low_ <= seq && seq < toKeep_->high_)
756 {
757 byLedger_.touch(i);
758 }
759 }
760 }
761
762 for (auto i = bySequence_.begin(); i != bySequence_.end();
763 ++i)
764 {
765 if (toKeep_->low_ <= i->first &&
766 i->first < toKeep_->high_)
767 {
768 bySequence_.touch(i);
769 }
770 }
771 }
772 }
773
776 }
777 JLOG(j.debug())
778 << "Validations sets sweep lock duration "
779 << std::chrono::duration_cast<std::chrono::milliseconds>(
781 .count()
782 << "ms";
783 }
784
794 void
795 trustChanged(hash_set<NodeID> const& added, hash_set<NodeID> const& removed)
796 {
798
799 for (auto& [nodeId, validation] : current_)
800 {
801 if (added.find(nodeId) != added.end())
802 {
803 validation.setTrusted();
804 updateTrie(lock, nodeId, validation, std::nullopt);
805 }
806 else if (removed.find(nodeId) != removed.end())
807 {
808 validation.setUntrusted();
809 removeTrie(lock, nodeId, validation);
810 }
811 }
812
813 for (auto& [_, validationMap] : byLedger_)
814 {
815 (void)_;
816 for (auto& [nodeId, validation] : validationMap)
817 {
818 if (added.find(nodeId) != added.end())
819 {
820 validation.setTrusted();
821 }
822 else if (removed.find(nodeId) != removed.end())
823 {
824 validation.setUntrusted();
825 }
826 }
827 }
828 }
829
832 {
834 return trie_.getJson();
835 }
836
850 getPreferred(Ledger const& curr)
851 {
854 withTrie(lock, [this](LedgerTrie<Ledger>& trie) {
855 return trie.getPreferred(localSeqEnforcer_.largest());
856 });
857 // No trusted validations to determine branch
858 if (!preferred)
859 {
860 // fall back to majority over acquiring ledgers
861 auto it = std::max_element(
862 acquiring_.begin(),
863 acquiring_.end(),
864 [](auto const& a, auto const& b) {
865 std::pair<Seq, ID> const& aKey = a.first;
866 typename hash_set<NodeID>::size_type const& aSize =
867 a.second.size();
868 std::pair<Seq, ID> const& bKey = b.first;
869 typename hash_set<NodeID>::size_type const& bSize =
870 b.second.size();
871 // order by number of trusted peers validating that ledger
872 // break ties with ledger ID
873 return std::tie(aSize, aKey.second) <
874 std::tie(bSize, bKey.second);
875 });
876 if (it != acquiring_.end())
877 return it->first;
878 return std::nullopt;
879 }
880
881 // If we are the parent of the preferred ledger, stick with our
882 // current ledger since we might be about to generate it
883 if (preferred->seq == curr.seq() + Seq{1} &&
884 preferred->ancestor(curr.seq()) == curr.id())
885 return std::make_pair(curr.seq(), curr.id());
886
887 // A ledger ahead of us is preferred regardless of whether it is
888 // a descendant of our working ledger or it is on a different chain
889 if (preferred->seq > curr.seq())
890 return std::make_pair(preferred->seq, preferred->id);
891
892 // Only switch to earlier or same sequence number
893 // if it is a different chain.
894 if (curr[preferred->seq] != preferred->id)
895 return std::make_pair(preferred->seq, preferred->id);
896
897 // Stick with current ledger
898 return std::make_pair(curr.seq(), curr.id());
899 }
900
910 ID
911 getPreferred(Ledger const& curr, Seq minValidSeq)
912 {
914 if (preferred && preferred->first >= minValidSeq)
915 return preferred->second;
916 return curr.id();
917 }
918
935 ID
937 Ledger const& lcl,
938 Seq minSeq,
939 hash_map<ID, std::uint32_t> const& peerCounts)
940 {
942
943 // Trusted validations exist, but stick with local preferred ledger if
944 // preferred is in the past
945 if (preferred)
946 return (preferred->first >= minSeq) ? preferred->second : lcl.id();
947
948 // Otherwise, rely on peer ledgers
949 auto it = std::max_element(
950 peerCounts.begin(), peerCounts.end(), [](auto& a, auto& b) {
951 // Prefer larger counts, then larger ids on ties
952 // (max_element expects this to return true if a < b)
953 return std::tie(a.second, a.first) <
954 std::tie(b.second, b.first);
955 });
956
957 if (it != peerCounts.end())
958 return it->first;
959 return lcl.id();
960 }
961
974 getNodesAfter(Ledger const& ledger, ID const& ledgerID)
975 {
977
978 // Use trie if ledger is the right one
979 if (ledger.id() == ledgerID)
980 return withTrie(lock, [&ledger](LedgerTrie<Ledger>& trie) {
981 return trie.branchSupport(ledger) - trie.tipSupport(ledger);
982 });
983
984 // Count parent ledgers as fallback
985 return std::count_if(
986 lastLedger_.begin(),
987 lastLedger_.end(),
988 [&ledgerID](auto const& it) {
989 auto const& curr = it.second;
990 return curr.seq() > Seq{0} &&
991 curr[curr.seq() - Seq{1}] == ledgerID;
992 });
993 }
994
1001 {
1003 std::lock_guard lock{mutex_};
1004 current(
1005 lock,
1006 [&](std::size_t numValidations) { ret.reserve(numValidations); },
1007 [&](NodeID const&, Validation const& v) {
1008 if (v.trusted() && v.full())
1009 ret.push_back(v.unwrap());
1010 });
1011 return ret;
1012 }
1013
1018 auto
1020 {
1021 hash_set<NodeID> ret;
1022 std::lock_guard lock{mutex_};
1023 current(
1024 lock,
1025 [&](std::size_t numValidations) { ret.reserve(numValidations); },
1026 [&](NodeID const& nid, Validation const&) { ret.insert(nid); });
1027
1028 return ret;
1029 }
1030
1037 numTrustedForLedger(ID const& ledgerID)
1038 {
1039 std::size_t count = 0;
1040 std::lock_guard lock{mutex_};
1041 byLedger(
1042 lock,
1043 ledgerID,
1044 [&](std::size_t) {}, // nothing to reserve
1045 [&](NodeID const&, Validation const& v) {
1046 if (v.trusted() && v.full())
1047 ++count;
1048 });
1049 return count;
1050 }
1051
1059 getTrustedForLedger(ID const& ledgerID, Seq const& seq)
1060 {
1062 std::lock_guard lock{mutex_};
1063 byLedger(
1064 lock,
1065 ledgerID,
1066 [&](std::size_t numValidations) { res.reserve(numValidations); },
1067 [&](NodeID const&, Validation const& v) {
1068 if (v.trusted() && v.full() && v.seq() == seq)
1069 res.emplace_back(v.unwrap());
1070 });
1071
1072 return res;
1073 }
1074
1082 fees(ID const& ledgerID, std::uint32_t baseFee)
1083 {
1085 std::lock_guard lock{mutex_};
1086 byLedger(
1087 lock,
1088 ledgerID,
1089 [&](std::size_t numValidations) { res.reserve(numValidations); },
1090 [&](NodeID const&, Validation const& v) {
1091 if (v.trusted() && v.full())
1092 {
1093 std::optional<std::uint32_t> loadFee = v.loadFee();
1094 if (loadFee)
1095 res.push_back(*loadFee);
1096 else
1097 res.push_back(baseFee);
1098 }
1099 });
1100 return res;
1101 }
1102
1105 void
1107 {
1108 std::lock_guard lock{mutex_};
1109 current_.clear();
1110 }
1111
1128 laggards(Seq const seq, hash_set<NodeKey>& trustedKeys)
1129 {
1130 std::size_t laggards = 0;
1131
1132 current(
1133 std::lock_guard{mutex_},
1134 [](std::size_t) {},
1135 [&](NodeID const&, Validation const& v) {
1136 if (adaptor_.now() <
1137 v.seenTime() + parms_.validationFRESHNESS &&
1138 trustedKeys.find(v.key()) != trustedKeys.end())
1139 {
1140 trustedKeys.erase(v.key());
1141 if (seq > v.seq())
1142 ++laggards;
1143 }
1144 });
1145
1146 return laggards;
1147 }
1148
1151 {
1152 std::lock_guard lock{mutex_};
1153 return current_.size();
1154 }
1155
1158 {
1159 std::lock_guard lock{mutex_};
1160 return seqEnforcers_.size();
1161 }
1162
1165 {
1166 std::lock_guard lock{mutex_};
1167 return byLedger_.size();
1168 }
1169
1172 {
1173 std::lock_guard lock{mutex_};
1174 return bySequence_.size();
1175 }
1176};
1177
1178} // namespace ripple
1179#endif
T begin(T... args)
Represents a JSON value.
Definition json_value.h:149
A generic endpoint for log messages.
Definition Journal.h:60
Stream debug() const
Definition Journal.h:328
Abstract interface to a clock.
Associative container where each element is also indexed by time.
Ancestry trie of ledgers.
Definition LedgerTrie.h:351
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
Definition LedgerTrie.h:597
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
Definition LedgerTrie.h:685
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
Definition LedgerTrie.h:611
Enforce validation increasing sequence requirement.
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
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:25
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:24
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
@ 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:47
std::chrono::seconds validationCURRENT_LOCAL
Duration a validation remains current after first observed.
Definition Validations.h:64
std::chrono::seconds validationFRESHNESS
How long we consider a validation fresh.
Definition Validations.h:89
std::chrono::seconds validationSET_EXPIRES
Duration a set of validations for a given ledger hash remain valid.
Definition Validations.h:79
std::chrono::seconds validationCURRENT_WALL
The number of seconds a validation remains current after its ledger's close time.
Definition Validations.h:56
std::chrono::seconds validationCURRENT_EARLY
Duration pre-close in which validations are acceptable.
Definition Validations.h:71