xrpld
Loading...
Searching...
No Matches
tests/libxrpl/csf/Peer.h
1#pragma once
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/UnorderedContainers.h>
5#include <xrpl/basics/chrono.h>
6#include <xrpl/basics/tagged_integer.h>
7#include <xrpl/beast/utility/Journal.h>
8#include <xrpl/beast/utility/WrappedSink.h>
9#include <xrpl/consensus/Consensus.h>
10#include <xrpl/consensus/ConsensusParms.h>
11#include <xrpl/consensus/ConsensusTypes.h>
12#include <xrpl/consensus/Validations.h>
13#include <xrpl/json/json_value.h>
14#include <xrpl/json/json_writer.h>
15
16#include <boost/container/flat_map.hpp>
17#include <boost/container/flat_set.hpp>
18
19#include <csf/BasicNetwork.h>
20#include <csf/CollectorRef.h>
21#include <csf/Proposal.h>
22#include <csf/Scheduler.h>
23#include <csf/SimTime.h>
24#include <csf/TrustGraph.h>
25#include <csf/Tx.h>
26#include <csf/Validation.h>
27#include <csf/events.h>
28#include <csf/ledgers.h>
29
30#include <algorithm>
31#include <chrono>
32#include <cmath>
33#include <cstddef>
34#include <limits>
35#include <optional>
36#include <string>
37#include <utility>
38#include <vector>
39
40namespace xrpl::test::csf {
41
42namespace bc = boost::container;
43
56struct Peer
57{
65 {
66 public:
68 {
69 }
70
71 Proposal const&
72 proposal() const
73 {
74 return proposal_;
75 }
76
78 getJson() const
79 {
80 return proposal_.getJson();
81 }
82
83 static std::string
85 {
86 return "";
87 }
88
89 private:
91 };
92
97 {
104
109
110 // Return the receive delay for message type M, default is no delay
111 // Received delay is the time from receiving the message to actually
112 // handling it.
113 template <class M>
114 [[nodiscard]] SimDuration
115 onReceive(M const&) const
116 {
117 return SimDuration{};
118 }
119
120 [[nodiscard]] SimDuration
121 onReceive(Validation const&) const
122 {
123 return recvValidation;
124 }
125 };
126
128 {
129 };
130
136 {
138
139 public:
140 struct Mutex
141 {
142 void
144 {
145 }
146
147 void
149 {
150 }
151 };
152
155
157 {
158 }
159
160 [[nodiscard]] NetClock::time_point
161 now() const
162 {
163 return p_.now();
164 }
165
167 acquire(Ledger::ID const& lId)
168 {
169 if (Ledger const* ledger = p_.acquireLedger(lId))
170 return *ledger;
171 return std::nullopt;
172 }
173 };
174
181 using TxSet_t = TxSet;
185
191
196
201
206
211
216
221
226
231
236
241
246
252
253 //-------------------------------------------------------------------------
254 // Store most network messages; these could be purged if memory use ever
255 // becomes problematic
256
261 bc::flat_map<Ledger::ID, std::vector<Proposal>> peerPositions;
265 bc::flat_map<TxSet::ID, TxSet> txSets;
266
267 // Ledgers/TxSets we are acquiring and when that request times out
268 bc::flat_map<Ledger::ID, SimTime> acquiringLedgers;
269 bc::flat_map<TxSet::ID, SimTime> acquiringTxSets;
270
275
280
285
290
294 bool runAsValidator = true;
295
296 // TODO: Consider removing these two, they are only a convenience for tests
297 // Number of proposers in the prior round
299 // Duration of prior round
301
302 // Quorum of validations needed for a ledger to be fully validated
303 // TODO: Use the logic in ValidatorList to set this dynamically
305
307
308 // Simulation parameters
310
315
328 PeerID i,
329 Scheduler& s,
330 LedgerOracle& o,
333 CollectorRefs& c,
334 beast::Journal jIn)
335 : sink(jIn, "Peer " + to_string(i) + ": ")
336 , j(sink)
337 , consensus(s.clock(), *this, j)
338 , id{i}
339 , key{id, 0}
340 , oracle{o}
341 , scheduler{s}
342 , net{n}
343 , trustGraph(tg)
344 , lastClosedLedger{Ledger::MakeGenesis{}}
345 , validations{ValidationParms{}, s.clock(), *this}
346 , fullyValidatedLedger{Ledger::MakeGenesis{}}
347 , collectors{c}
348 {
349 // All peers start from the default constructed genesis ledger
351
352 // nodes always trust themselves . . SHOULD THEY?
353 trustGraph.trust(this, this);
354 }
355
360 template <class T>
361 void
363 {
364 using namespace std::chrono_literals;
365
366 if (when == 0ns)
367 {
368 what();
369 }
370 else
371 {
372 scheduler.in(when, std::forward<T>(what));
373 }
374 }
375
376 // Issue a new event to the collectors
377 template <class E>
378 void
379 issue(E const& event)
380 {
381 // Use the scheduler time and not the peer's (skewed) local time
382 collectors.on(id, scheduler.now(), event);
383 }
384
385 //--------------------------------------------------------------------------
386 // Trust and Network members
387 // Methods for modifying and querying the network and trust graphs from
388 // the perspective of this Peer
389
390 //< Extend trust to a peer
391 void
393 {
394 trustGraph.trust(this, &o);
395 }
396
397 //< Revoke trust from a peer
398 void
400 {
401 trustGraph.untrust(this, &o);
402 }
403
404 //< Check whether we trust a peer
405 bool
407 {
408 return trustGraph.trusts(this, &o);
409 }
410
411 //< Check whether we trust a peer based on its ID
412 bool
413 trusts(PeerID const& oId)
414 {
415 return std::ranges::any_of(
416 trustGraph.trustedPeers(this), [&oId](auto const p) { return p->id == oId; });
417 }
418
428
429 bool
431 {
432 return net.connect(this, &o, dur);
433 }
434
443 bool
445 {
446 return net.disconnect(this, &o);
447 }
448
449 //--------------------------------------------------------------------------
450 // Generic Consensus members
451
452 // Attempt to acquire the Ledger associated with the given ID
453 Ledger const*
454 acquireLedger(Ledger::ID const& ledgerID)
455 {
456 if (auto it = ledgers.find(ledgerID); it != ledgers.end())
457 {
458 return &(it->second);
459 }
460
461 // No peers
462 if (net.links(this).empty())
463 return nullptr;
464
465 // Don't retry if we already are acquiring it and haven't timed out
466 auto aIt = acquiringLedgers.find(ledgerID);
467 if (aIt != acquiringLedgers.end())
468 {
469 if (scheduler.now() < aIt->second)
470 return nullptr;
471 }
472
473 using namespace std::chrono_literals;
474 SimDuration minDuration{10s};
475 for (auto const link : net.links(this))
476 {
477 minDuration = std::min(minDuration, link.data.delay);
478
479 // Send a message to neighbors to find the ledger
480 net.send(this, link.target, [to = link.target, from = this, ledgerID]() {
481 if (auto it = to->ledgers.find(ledgerID); it != to->ledgers.end())
482 {
483 // if the ledger is found, send it back to the original
484 // requesting peer where it is added to the available
485 // ledgers
486 to->net.send(to, from, [from, ledger = it->second]() {
487 from->acquiringLedgers.erase(ledger.id());
488 from->ledgers.emplace(ledger.id(), ledger);
489 });
490 }
491 });
492 }
493 acquiringLedgers[ledgerID] = scheduler.now() + 2 * minDuration;
494 return nullptr;
495 }
496
497 // Attempt to acquire the TxSet associated with the given ID
498 TxSet const*
500 {
501 if (auto it = txSets.find(setId); it != txSets.end())
502 {
503 return &(it->second);
504 }
505
506 // No peers
507 if (net.links(this).empty())
508 return nullptr;
509
510 // Don't retry if we already are acquiring it and haven't timed out
511 auto aIt = acquiringTxSets.find(setId);
512 if (aIt != acquiringTxSets.end())
513 {
514 if (scheduler.now() < aIt->second)
515 return nullptr;
516 }
517
518 using namespace std::chrono_literals;
519 SimDuration minDuration{10s};
520 for (auto const link : net.links(this))
521 {
522 minDuration = std::min(minDuration, link.data.delay);
523 // Send a message to neighbors to find the tx set
524 net.send(this, link.target, [to = link.target, from = this, setId]() {
525 if (auto it = to->txSets.find(setId); it != to->txSets.end())
526 {
527 // If the txSet is found, send it back to the original
528 // requesting peer, where it is handled like a TxSet
529 // that was broadcast over the network
530 to->net.send(to, from, [from, txSet = it->second]() {
531 from->acquiringTxSets.erase(txSet.id());
532 from->handle(txSet);
533 });
534 }
535 });
536 }
537 acquiringTxSets[setId] = scheduler.now() + 2 * minDuration;
538 return nullptr;
539 }
540
541 bool
543 {
544 return !openTxs.empty();
545 }
546
549 {
550 return validations.numTrustedForLedger(prevLedger);
551 }
552
555 {
556 return validations.getNodesAfter(prevLedger, prevLedgerID);
557 }
558
559 Result
560 onClose(Ledger const& prevLedger, NetClock::time_point closeTime, ConsensusMode mode)
561 {
562 issue(CloseLedger{.prevLedger = prevLedger, .txs = openTxs});
563
564 return Result(
565 TxSet{openTxs},
566 Proposal(
567 prevLedger.id(), Proposal::kSeqJoin, TxSet::calcID(openTxs), closeTime, now(), id));
568 }
569
570 void
572 Result const& result,
573 Ledger const& prevLedger,
574 NetClock::duration const& closeResolution,
575 ConsensusCloseTimes const& rawCloseTimes,
576 ConsensusMode const& mode,
577 json::Value const& consensusJson)
578 {
579 onAccept(
580 result, prevLedger, closeResolution, rawCloseTimes, mode, consensusJson, validating());
581 }
582
583 void
585 Result const& result,
586 Ledger const& prevLedger,
587 NetClock::duration const& closeResolution,
588 ConsensusCloseTimes const& rawCloseTimes,
589 ConsensusMode const& mode,
590 json::Value const& consensusJson,
591 bool const validating)
592 {
593 schedule(delays.ledgerAccept, [mode, result, prevLedger, closeResolution, this]() {
594 bool const proposing = mode == ConsensusMode::Proposing;
595 bool const consensusFail = result.state == ConsensusState::MovedOn;
596
597 TxSet const acceptedTxs = injectTxs(prevLedger, result.txns);
598 Ledger const newLedger = oracle.accept(
599 prevLedger, acceptedTxs.txs(), closeResolution, result.position.closeTime());
600 ledgers[newLedger.id()] = newLedger;
601
602 issue(AcceptLedger{.ledger = newLedger, .prior = lastClosedLedger});
603 prevProposers = result.proposers;
604 prevRoundTime = result.roundTime.read();
605 lastClosedLedger = newLedger;
606
607 auto const removed = std::ranges::remove_if(
608 openTxs, [&](Tx const& tx) { return acceptedTxs.exists(tx.id()); });
609 openTxs.erase(removed.begin(), removed.end());
610
611 // Only send validation if the new ledger is compatible with our
612 // fully validated ledger
613 bool const isCompatible = newLedger.isAncestor(fullyValidatedLedger);
614
615 // Can only send one validated ledger per seq
616 if (runAsValidator && isCompatible && !consensusFail &&
617 validations.canValidateSeq(newLedger.seq()))
618 {
619 bool const isFull = proposing;
620
621 Validation const v{newLedger.id(), newLedger.seq(), now(), now(), key, id, isFull};
622 // share the new validation; it is trusted by the receiver
623 share(v);
624 // we trust ourselves
626 }
627
628 checkFullyValidated(newLedger);
629
630 // kick off the next round...
631 // in the actual implementation, this passes back through
632 // network ops
634 // startRound sets the LCL state, so we need to call it once after
635 // the last requested round completes
637 {
638 startRound();
639 }
640 });
641 }
642
643 // Earliest allowed sequence number when checking for ledgers with more
644 // validations than our current ledger
645 Ledger::Seq
647 {
648 return fullyValidatedLedger.seq();
649 }
650
652 getPrevLedger(Ledger::ID const& ledgerID, Ledger const& ledger, ConsensusMode mode)
653 {
654 // only do if we are past the genesis ledger
655 if (ledger.seq() == Ledger::Seq{0})
656 return ledgerID;
657
658 Ledger::ID const netLgr = validations.getPreferred(ledger, earliestAllowedSeq());
659
660 if (netLgr != ledgerID)
661 {
662 JLOG(j.trace()) << json::Compact(validations.getJsonTrie());
663 issue(WrongPrevLedger{.wrong = ledgerID, .right = netLgr});
664 }
665
666 return netLgr;
667 }
668
669 void
670 propose(Proposal const& pos)
671 {
672 share(pos);
673 }
674
675 ConsensusParms const&
676 parms() const
677 {
678 return consensusParms;
679 }
680
681 // Not interested in tracking consensus mode changes for now
682 void
686
687 // Share a message by broadcasting to all connected peers
688 template <class M>
689 void
690 share(M const& m)
691 {
692 issue(Share<M>{m});
693 send(BroadcastMesg<M>{m, router.nextSeq++, this->id}, this->id);
694 }
695
696 // Unwrap the Position and share the raw proposal
697 void
698 share(Position const& p)
699 {
700 share(p.proposal());
701 }
702
703 //--------------------------------------------------------------------------
704 // Validation members
705
709 bool
711 {
712 v.setTrusted();
713 v.setSeen(now());
714 ValStatus const res = validations.add(v.nodeID(), v);
715
716 if (res == ValStatus::Stale)
717 return false;
718
719 // Acquire will try to get from network if not already local
720 if (Ledger const* lgr = acquireLedger(v.ledgerID()))
722 return true;
723 }
724
728 void
730 {
731 // Only consider ledgers newer than our last fully validated ledger
732 if (ledger.seq() <= fullyValidatedLedger.seq())
733 return;
734
735 std::size_t const count = validations.numTrustedForLedger(ledger.id());
736 std::size_t const numTrustedPeers = trustGraph.graph().outDegree(this);
737 quorum = static_cast<std::size_t>(std::ceil(numTrustedPeers * 0.8));
738 if (count >= quorum && ledger.isAncestor(fullyValidatedLedger))
739 {
740 issue(FullyValidateLedger{.ledger = ledger, .prior = fullyValidatedLedger});
741 fullyValidatedLedger = ledger;
742 }
743 }
744
745 //-------------------------------------------------------------------------
746 // Peer messaging members
747
748 // Basic Sequence number router
749 // A message that will be flooded across the network is tagged with a
750 // sequence number by the origin node in a BroadcastMesg. Receivers will
751 // ignore a message as stale if they've already processed a newer sequence
752 // number, or will process and potentially relay the message along.
753 //
754 // The various bool handle(MessageType) members do the actual processing
755 // and should return true if the message should continue to be sent to
756 // peers.
757 //
758 // WARN: This assumes messages are received and processed in the order they
759 // are sent, so that a peer receives a message with seq 1 from node 0
760 // before seq 2 from node 0, etc.
761 // TODO: Break this out into a class and identify type interface to allow
762 // alternate routing strategies
763 template <class M>
770
771 struct Router
772 {
774 bc::flat_map<PeerID, std::size_t> lastObservedSeq;
775 };
776
778
779 // Send a broadcast message to all peers
780 template <class M>
781 void
782 send(BroadcastMesg<M> const& bm, PeerID from)
783 {
784 for (auto const link : net.links(this))
785 {
786 if (link.target->id != from && link.target->id != bm.origin)
787 {
788 // cheat and don't bother sending if we know it has already been
789 // used on the other end
790 if (link.target->router.lastObservedSeq[bm.origin] < bm.seq)
791 {
792 issue(Relay<M>{link.target->id, bm.msg});
793 net.send(this, link.target, [to = link.target, bm, id = this->id] {
794 to->receive(bm, id);
795 });
796 }
797 }
798 }
799 }
800
801 // Receive a shared message, process it and consider continuing to relay it
802 template <class M>
803 void
805 {
806 issue(Receive<M>{from, bm.msg});
807 if (router.lastObservedSeq[bm.origin] < bm.seq)
808 {
809 router.lastObservedSeq[bm.origin] = bm.seq;
810 schedule(delays.onReceive(bm.msg), [this, bm, from] {
811 if (handle(bm.msg))
812 send(bm, from);
813 });
814 }
815 }
816
817 // Type specific receive handlers, return true if the message should
818 // continue to be broadcast to peers
819 bool
820 handle(Proposal const& p)
821 {
822 // Only relay untrusted proposals on the same ledger
823 if (!trusts(p.nodeID()))
824 return p.prevLedger() == lastClosedLedger.id();
825
826 // TODO: This always suppresses relay of peer positions already seen
827 // Should it allow forwarding if for a recent ledger ?
828 auto& dest = peerPositions[p.prevLedger()];
829 if (std::ranges::find(dest, p) != dest.end())
830 return false;
831
832 dest.push_back(p);
833
834 // Rely on consensus to decide whether to relay
835 return consensus.peerProposal(now(), Position{p});
836 }
837
838 bool
839 handle(TxSet const& txs)
840 {
841 bool const inserted = txSets.insert(std::make_pair(txs.id(), txs)).second;
842 if (inserted)
843 consensus.gotTxSet(now(), txs);
844 // relay only if new
845 return inserted;
846 }
847
848 bool
849 handle(Tx const& tx)
850 {
851 // Ignore and suppress relay of transactions already in last ledger
852 TxSetType const& lastClosedTxs = lastClosedLedger.txs();
853 if (lastClosedTxs.contains(tx))
854 return false;
855
856 // only relay if it was new to our open ledger
857 return openTxs.insert(tx).second;
858 }
859
860 bool
862 {
863 // TODO: This is not relaying untrusted validations
864 if (!trusts(v.nodeID()))
865 return false;
866
867 // Will only relay if current
868 return addTrustedValidation(v);
869 }
870
871 bool
873 {
874 return fullyValidatedLedger.seq() > Ledger::Seq{0};
875 }
876
879 {
880 return earliestAllowedSeq();
881 }
882
885 {
887 for (auto const p : trustGraph.trustedPeers(this))
888 keys.insert(p->key);
889 return {quorum, keys};
890 }
891
894 {
895 return validations.laggards(seq, trusted);
896 }
897
898 bool
899 validator() const
900 {
901 return runAsValidator;
902 }
903
904 void
905 updateOperatingMode(std::size_t const positions) const
906 {
907 }
908
909 static bool
911 {
912 // does not matter
913 return false;
914 }
915
916 //--------------------------------------------------------------------------
917 // A locally submitted transaction
918 void
919 submit(Tx const& tx)
920 {
921 issue(SubmitTx{tx});
922 if (handle(tx))
923 share(tx);
924 }
925
926 //--------------------------------------------------------------------------
927 // Simulation "driver" members
928
932 void
934 {
935 consensus.timerEntry(now());
936 // only reschedule if not completed
938 scheduler.in(parms().ledgerGRANULARITY, [this]() { timerEntry(); });
939 }
940
941 // Called to begin the next round
942 void
944 {
945 // Between rounds, we take the majority ledger
946 // In the future, consider taking peer dominant ledger if no validations
947 // yet
949 if (bestLCL == Ledger::ID{0})
950 bestLCL = lastClosedLedger.id();
951
952 issue(StartRound{.bestLedger = bestLCL, .prevLedger = lastClosedLedger});
953
954 // Not yet modeling dynamic UNL.
955 hash_set<PeerID> const nowUntrusted;
956 consensus.startRound(now(), bestLCL, lastClosedLedger, nowUntrusted, runAsValidator, {});
957 }
958
959 // Start the consensus process assuming it is not yet running
960 // This runs forever unless targetLedgers is specified
961 void
963 {
964 // TODO: Expire validations less frequently?
965 validations.expire(j);
966 scheduler.in(parms().ledgerGRANULARITY, [&]() { timerEntry(); });
967 startRound();
968 }
969
971 now() const
972 {
973 // We don't care about the actual epochs, but do want the
974 // generated NetClock time to be well past its epoch to ensure
975 // any subtractions of two NetClock::time_point in the consensus
976 // code are positive. (e.g. proposeFRESHNESS)
977 using namespace std::chrono;
978 using namespace std::chrono_literals;
981 scheduler.now().time_since_epoch() + 86400s + clockSkew));
982 }
983
986 {
987 return consensus.prevLedgerID();
988 }
989
990 //-------------------------------------------------------------------------
991 // Injects a specific transaction when generating the ledger following
992 // the provided sequence. This allows simulating a byzantine failure in
993 // which a node generates the wrong ledger, even when consensus worked
994 // properly.
995 // TODO: Make this more robust
997
1009 TxSet
1010 injectTxs(Ledger prevLedger, TxSet const& src)
1011 {
1012 auto const it = txInjections.find(prevLedger.seq());
1013
1014 if (it == txInjections.end())
1015 return src;
1016 TxSetType res{src.txs()};
1017 res.insert(it->second);
1018
1019 return TxSet{res};
1020 }
1021};
1022
1023} // namespace xrpl::test::csf
T any_of(T... args)
T ceil(T... args)
A generic endpoint for log messages.
Definition Journal.h:44
Wraps a Journal::Sink to prefix its output with a string.
Definition WrappedSink.h:19
Decorator for streaming out compact json.
Represents a JSON value.
Definition json_value.h:117
LedgerId const & prevLedger() const
Get the prior accepted ledger this position is based on.
NodeId const & nodeID() const
Identifying which peer took this position.
std::chrono::milliseconds read() const
Generic implementation of consensus algorithm.
Definition Consensus.h:290
std::chrono::time_point< NetClock > time_point
Definition chrono.h:48
std::chrono::duration< rep, period > duration
Definition chrono.h:47
Maintains current and recent ledger validations.
Peer to peer network simulator.
A container of CollectorRefs.
Oracle maintaining unique ledgers for a simulation.
Definition ledgers.h:249
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition ledgers.h:48
TaggedInteger< std::uint32_t, IdTag > ID
Definition ledgers.h:56
TaggedInteger< std::uint32_t, SeqTag > Seq
Definition ledgers.h:53
bool isAncestor(Ledger const &ancestor) const
Determine whether ancestor is really an ancestor of this ledger.
Definition ledgers.cpp:30
TxSetType const & txs() const
Definition ledgers.h:208
Basic wrapper of a proposed position taken by a peer.
std::optional< Ledger > acquire(Ledger::ID const &lId)
Simulated discrete-event scheduler.
time_point now() const
Return the current network time.
TxSet is a set of transactions to consider including in the ledger.
Definition Tx.h:71
beast::Uhash<>::result_type ID
Definition Tx.h:73
static ID calcID(TxSetType const &txs)
Definition Tx.h:77
ID id() const
Definition Tx.h:139
TxSetType const & txs() const
Definition Tx.h:133
A single transaction.
Definition Tx.h:24
ID const & id() const
Definition Tx.h:40
Validation of a specific ledger by a specific Peer.
Definition Validation.h:32
void setSeen(NetClock::time_point seen)
Definition Validation.h:171
PeerID const & nodeID() const
Definition Validation.h:102
Ledger::ID ledgerID() const
Definition Validation.h:72
T duration_cast(T... args)
T find(T... args)
T forward(T... args)
T insert(T... args)
T make_pair(T... args)
T max(T... args)
T min(T... args)
SimClock::duration SimDuration
Definition SimTime.h:14
std::string to_string(TxSetType const &txs)
Definition Tx.h:213
boost::container::flat_set< Tx > TxSetType
Definition Tx.h:65
TaggedInteger< std::uint32_t, PeerIDTag > PeerID
Definition Validation.h:17
ConsensusProposal< PeerID, Ledger::ID, TxSet::ID > Proposal
Proposal is a position taken in the consensus process and is represented directly from the generic ty...
Definition Proposal.h:14
std::pair< PeerID, std::uint32_t > PeerKey
The current key of a peer.
Definition Validation.h:26
ConsensusMode
Represents how a node currently participates in Consensus.
std::unordered_set< Value, Hash, Pred, Allocator > hash_set
boost::outcome_v2::result< T, std::error_code > Result
Definition b58_utils.h:19
ValStatus
Status of validation we received.
@ Stale
Not current or was older than current from this node.
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
T remove_if(T... args)
Stores the set of initial close times.
Consensus algorithm parameters.
Encapsulates the result of consensus.
ConsensusTimer roundTime
Timing parameters to control validation staleness and expiration.
Definition Validations.h:36
Peer closed the open ledger.
Definition events.h:109
Peer fully validated a new ledger.
Definition events.h:144
Simulated delays in internal peer processing.
std::chrono::milliseconds recvValidation
Delay in processing validations from remote peers.
SimDuration onReceive(Validation const &) const
std::chrono::milliseconds ledgerAccept
Delay in consensus calling doAccept to accepting and issuing validation TODO: This should be a functi...
bc::flat_map< PeerID, std::size_t > lastObservedSeq
ConsensusResult< Peer > Result
Result onClose(Ledger const &prevLedger, NetClock::time_point closeTime, ConsensusMode mode)
std::chrono::seconds clockSkew
Skew of time relative to the common scheduler clock.
void propose(Proposal const &pos)
Ledger::ID prevLedgerID() const
TxSetType openTxs
openTxs that haven't been closed in a ledger yet
void updateOperatingMode(std::size_t const positions) const
void receive(BroadcastMesg< M > const &bm, PeerID from)
ConsensusParms const & parms() const
Ledger::Seq getValidLedgerIndex() const
bc::flat_map< TxSet::ID, TxSet > txSets
TxSet associated with a TxSet::ID.
BasicNetwork< Peer * > & net
Handle to network for sending messages.
int completedLedgers
The number of ledgers this peer has completed.
hash_set< NodeKey_t > trustedKeys
hash_map< Ledger::ID, Ledger > ledgers
Ledgers this node has closed or loaded from the network.
Peer(PeerID i, Scheduler &s, LedgerOracle &o, BasicNetwork< Peer * > &n, TrustGraph< Peer * > &tg, CollectorRefs &c, beast::Journal jIn)
Constructor.
bool runAsValidator
Whether to simulate running as validator or a tracking node.
hash_map< Ledger::Seq, Tx > txInjections
TxSet const * acquireTxSet(TxSet::ID const &setId)
CollectorRefs & collectors
The collectors to report events to.
bool trusts(PeerID const &oId)
TxSet injectTxs(Ledger prevLedger, TxSet const &src)
Inject non-consensus Tx.
Ledger lastClosedLedger
The last ledger closed by this node.
LedgerOracle & oracle
The oracle that manages unique ledgers.
std::pair< std::size_t, hash_set< NodeKey_t > > getQuorumKeys()
Ledger const * acquireLedger(Ledger::ID const &ledgerID)
Ledger Ledger_t
Type definitions for generic consensus.
bc::flat_map< TxSet::ID, SimTime > acquiringTxSets
Ledger::ID getPrevLedger(Ledger::ID const &ledgerID, Ledger const &ledger, ConsensusMode mode)
Consensus< Peer > consensus
Generic consensus.
bool connect(Peer &o, SimDuration dur)
Create network connection.
void onForceAccept(Result const &result, Ledger const &prevLedger, NetClock::duration const &closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, json::Value const &consensusJson)
bool handle(Validation const &v)
void send(BroadcastMesg< M > const &bm, PeerID from)
bool handle(TxSet const &txs)
void checkFullyValidated(Ledger const &ledger)
Check if a new ledger can be deemed fully validated.
bc::flat_map< Ledger::ID, SimTime > acquiringLedgers
void onModeChange(ConsensusMode, ConsensusMode)
NetClock::time_point now() const
TrustGraph< Peer * > & trustGraph
Handle to Trust graph of network.
std::size_t laggards(Ledger::Seq const seq, hash_set< NodeKey_t > &trusted)
bool handle(Proposal const &p)
void timerEntry()
Heartbeat timer call.
void onAccept(Result const &result, Ledger const &prevLedger, NetClock::duration const &closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, json::Value const &consensusJson, bool const validating)
bc::flat_map< Ledger::ID, std::vector< Proposal > > peerPositions
Map from Ledger::ID to vector of Positions with that ledger as the prior ledger.
Validations< ValAdaptor > validations
Validations from trusted nodes.
bool addTrustedValidation(Validation v)
Add a trusted validation and return true if it is worth forwarding.
PeerKey key
Current signing key.
void schedule(std::chrono::nanoseconds when, T &&what)
Schedule the provided callback in when duration, but if when is 0, call immediately.
Scheduler & scheduler
Scheduler of events.
ProcessingDelays delays
Simulated delays to use for internal processing.
void share(Position const &p)
Ledger fullyValidatedLedger
The most recent ledger that has been fully validated by the network from the perspective of this Peer...
beast::WrappedSink sink
Logging support that prefixes messages with the peer ID.
int targetLedgers
The number of ledgers this peer should complete before stopping to run.
std::size_t proposersFinished(Ledger const &prevLedger, Ledger::ID const &prevLedgerID)
std::size_t proposersValidated(Ledger::ID const &prevLedger)
bool disconnect(Peer &o)
Remove a network connection.
Ledger::Seq earliestAllowedSeq() const
std::chrono::milliseconds prevRoundTime
A value received from another peer as part of flooding.
Definition events.h:66
A value relayed to another peer as part of flooding.
Definition events.h:49
A value to be flooded to all other peers starting from this peer.
Definition events.h:37
Peer starts a new consensus round.
Definition events.h:93
A transaction submitted to a peer.
Definition events.h:82
Peer detected a wrong prior ledger during consensus.
Definition events.h:133