xrpld
Loading...
Searching...
No Matches
test/csf/Peer.h
1#pragma once
2
3#include <test/csf/BasicNetwork.h>
4#include <test/csf/CollectorRef.h>
5#include <test/csf/Scheduler.h>
6#include <test/csf/TrustGraph.h>
7#include <test/csf/Tx.h>
8#include <test/csf/Validation.h>
9#include <test/csf/events.h>
10#include <test/csf/ledgers.h>
11
12#include <xrpld/consensus/Consensus.h>
13#include <xrpld/consensus/Validations.h>
14
15#include <xrpl/beast/utility/WrappedSink.h>
16#include <xrpl/protocol/PublicKey.h>
17
18#include <boost/container/flat_map.hpp>
19#include <boost/container/flat_set.hpp>
20
21#include <algorithm>
22
23namespace xrpl::test::csf {
24
25namespace bc = boost::container;
26
38struct Peer
39{
46 {
47 public:
49 {
50 }
51
52 Proposal const&
53 proposal() const
54 {
55 return proposal_;
56 }
57
59 getJson() const
60 {
61 return proposal_.getJson();
62 }
63
64 static std::string
66 {
67 return "";
68 }
69
70 private:
72 };
73
77 {
82
85
86 // Return the receive delay for message type M, default is no delay
87 // Received delay is the time from receiving the message to actually
88 // handling it.
89 template <class M>
90 [[nodiscard]] SimDuration
91 onReceive(M const&) const
92 {
93 return SimDuration{};
94 }
95
96 [[nodiscard]] SimDuration
97 onReceive(Validation const&) const
98 {
99 return recvValidation;
100 }
101 };
102
104 {
105 };
106
111 {
113
114 public:
115 struct Mutex
116 {
117 void
119 {
120 }
121
122 void
124 {
125 }
126 };
127
130
132 {
133 }
134
135 [[nodiscard]] NetClock::time_point
136 now() const
137 {
138 return p_.now();
139 }
140
142 acquire(Ledger::ID const& lId)
143 {
144 if (Ledger const* ledger = p_.acquireLedger(lId))
145 return *ledger;
146 return std::nullopt;
147 }
148 };
149
154 using TxSet_t = TxSet;
158
162
165
168
171
174
177
180
183
186
189
192
195
199
200 //-------------------------------------------------------------------------
201 // Store most network messages; these could be purged if memory use ever
202 // becomes problematic
203
206 bc::flat_map<Ledger::ID, std::vector<Proposal>> peerPositions;
208 bc::flat_map<TxSet::ID, TxSet> txSets;
209
210 // Ledgers/TxSets we are acquiring and when that request times out
211 bc::flat_map<Ledger::ID, SimTime> acquiringLedgers;
212 bc::flat_map<TxSet::ID, SimTime> acquiringTxSets;
213
216
219
222
225
227 bool runAsValidator = true;
228
229 // TODO: Consider removing these two, they are only a convenience for tests
230 // Number of proposers in the prior round
232 // Duration of prior round
234
235 // Quorum of validations needed for a ledger to be fully validated
236 // TODO: Use the logic in ValidatorList to set this dynamically
238
240
241 // Simulation parameters
243
246
259 PeerID i,
260 Scheduler& s,
261 LedgerOracle& o,
264 CollectorRefs& c,
265 beast::Journal jIn)
266 : sink(jIn, "Peer " + to_string(i) + ": ")
267 , j(sink)
268 , consensus(s.clock(), *this, j)
269 , id{i}
270 , key{id, 0}
271 , oracle{o}
272 , scheduler{s}
273 , net{n}
274 , trustGraph(tg)
275 , lastClosedLedger{Ledger::MakeGenesis{}}
276 , validations{ValidationParms{}, s.clock(), *this}
277 , fullyValidatedLedger{Ledger::MakeGenesis{}}
278 , collectors{c}
279 {
280 // All peers start from the default constructed genesis ledger
282
283 // nodes always trust themselves . . SHOULD THEY?
284 trustGraph.trust(this, this);
285 }
286
290 template <class T>
291 void
293 {
294 using namespace std::chrono_literals;
295
296 if (when == 0ns)
297 {
298 what();
299 }
300 else
301 {
302 scheduler.in(when, std::forward<T>(what));
303 }
304 }
305
306 // Issue a new event to the collectors
307 template <class E>
308 void
309 issue(E const& event)
310 {
311 // Use the scheduler time and not the peer's (skewed) local time
312 collectors.on(id, scheduler.now(), event);
313 }
314
315 //--------------------------------------------------------------------------
316 // Trust and Network members
317 // Methods for modifying and querying the network and trust graphs from
318 // the perspective of this Peer
319
320 //< Extend trust to a peer
321 void
323 {
324 trustGraph.trust(this, &o);
325 }
326
327 //< Revoke trust from a peer
328 void
330 {
331 trustGraph.untrust(this, &o);
332 }
333
334 //< Check whether we trust a peer
335 bool
337 {
338 return trustGraph.trusts(this, &o);
339 }
340
341 //< Check whether we trust a peer based on its ID
342 bool
343 trusts(PeerID const& oId)
344 {
345 for (auto const p : trustGraph.trustedPeers(this))
346 {
347 if (p->id == oId)
348 return true;
349 }
350 return false;
351 }
352
361
362 bool
364 {
365 return net.connect(this, &o, dur);
366 }
367
375 bool
377 {
378 return net.disconnect(this, &o);
379 }
380
381 //--------------------------------------------------------------------------
382 // Generic Consensus members
383
384 // Attempt to acquire the Ledger associated with the given ID
385 Ledger const*
386 acquireLedger(Ledger::ID const& ledgerID)
387 {
388 if (auto it = ledgers.find(ledgerID); it != ledgers.end())
389 {
390 return &(it->second);
391 }
392
393 // No peers
394 if (net.links(this).empty())
395 return nullptr;
396
397 // Don't retry if we already are acquiring it and haven't timed out
398 auto aIt = acquiringLedgers.find(ledgerID);
399 if (aIt != acquiringLedgers.end())
400 {
401 if (scheduler.now() < aIt->second)
402 return nullptr;
403 }
404
405 using namespace std::chrono_literals;
406 SimDuration minDuration{10s};
407 for (auto const link : net.links(this))
408 {
409 minDuration = std::min(minDuration, link.data.delay);
410
411 // Send a message to neighbors to find the ledger
412 net.send(this, link.target, [to = link.target, from = this, ledgerID]() {
413 if (auto it = to->ledgers.find(ledgerID); it != to->ledgers.end())
414 {
415 // if the ledger is found, send it back to the original
416 // requesting peer where it is added to the available
417 // ledgers
418 to->net.send(to, from, [from, ledger = it->second]() {
419 from->acquiringLedgers.erase(ledger.id());
420 from->ledgers.emplace(ledger.id(), ledger);
421 });
422 }
423 });
424 }
425 acquiringLedgers[ledgerID] = scheduler.now() + 2 * minDuration;
426 return nullptr;
427 }
428
429 // Attempt to acquire the TxSet associated with the given ID
430 TxSet const*
432 {
433 if (auto it = txSets.find(setId); it != txSets.end())
434 {
435 return &(it->second);
436 }
437
438 // No peers
439 if (net.links(this).empty())
440 return nullptr;
441
442 // Don't retry if we already are acquiring it and haven't timed out
443 auto aIt = acquiringTxSets.find(setId);
444 if (aIt != acquiringTxSets.end())
445 {
446 if (scheduler.now() < aIt->second)
447 return nullptr;
448 }
449
450 using namespace std::chrono_literals;
451 SimDuration minDuration{10s};
452 for (auto const link : net.links(this))
453 {
454 minDuration = std::min(minDuration, link.data.delay);
455 // Send a message to neighbors to find the tx set
456 net.send(this, link.target, [to = link.target, from = this, setId]() {
457 if (auto it = to->txSets.find(setId); it != to->txSets.end())
458 {
459 // If the txSet is found, send it back to the original
460 // requesting peer, where it is handled like a TxSet
461 // that was broadcast over the network
462 to->net.send(to, from, [from, txSet = it->second]() {
463 from->acquiringTxSets.erase(txSet.id());
464 from->handle(txSet);
465 });
466 }
467 });
468 }
469 acquiringTxSets[setId] = scheduler.now() + 2 * minDuration;
470 return nullptr;
471 }
472
473 bool
475 {
476 return !openTxs.empty();
477 }
478
481 {
482 return validations.numTrustedForLedger(prevLedger);
483 }
484
487 {
488 return validations.getNodesAfter(prevLedger, prevLedgerID);
489 }
490
491 Result
492 onClose(Ledger const& prevLedger, NetClock::time_point closeTime, ConsensusMode mode)
493 {
494 issue(CloseLedger{.prevLedger = prevLedger, .txs = openTxs});
495
496 return Result(
497 TxSet{openTxs},
498 Proposal(
499 prevLedger.id(), Proposal::kSeqJoin, TxSet::calcID(openTxs), closeTime, now(), id));
500 }
501
502 void
504 Result const& result,
505 Ledger const& prevLedger,
506 NetClock::duration const& closeResolution,
507 ConsensusCloseTimes const& rawCloseTimes,
508 ConsensusMode const& mode,
509 json::Value const& consensusJson)
510 {
511 onAccept(
512 result, prevLedger, closeResolution, rawCloseTimes, mode, consensusJson, validating());
513 }
514
515 void
517 Result const& result,
518 Ledger const& prevLedger,
519 NetClock::duration const& closeResolution,
520 ConsensusCloseTimes const& rawCloseTimes,
521 ConsensusMode const& mode,
522 json::Value const& consensusJson,
523 bool const validating)
524 {
525 schedule(delays.ledgerAccept, [mode, result, prevLedger, closeResolution, this]() {
526 bool const proposing = mode == ConsensusMode::Proposing;
527 bool const consensusFail = result.state == ConsensusState::MovedOn;
528
529 TxSet const acceptedTxs = injectTxs(prevLedger, result.txns);
530 Ledger const newLedger = oracle.accept(
531 prevLedger, acceptedTxs.txs(), closeResolution, result.position.closeTime());
532 ledgers[newLedger.id()] = newLedger;
533
534 issue(AcceptLedger{.ledger = newLedger, .prior = lastClosedLedger});
535 prevProposers = result.proposers;
536 prevRoundTime = result.roundTime.read();
537 lastClosedLedger = newLedger;
538
539 auto const removed = std::ranges::remove_if(
540 openTxs, [&](Tx const& tx) { return acceptedTxs.exists(tx.id()); });
541 openTxs.erase(removed.begin(), removed.end());
542
543 // Only send validation if the new ledger is compatible with our
544 // fully validated ledger
545 bool const isCompatible = newLedger.isAncestor(fullyValidatedLedger);
546
547 // Can only send one validated ledger per seq
548 if (runAsValidator && isCompatible && !consensusFail &&
549 validations.canValidateSeq(newLedger.seq()))
550 {
551 bool const isFull = proposing;
552
553 Validation const v{newLedger.id(), newLedger.seq(), now(), now(), key, id, isFull};
554 // share the new validation; it is trusted by the receiver
555 share(v);
556 // we trust ourselves
558 }
559
560 checkFullyValidated(newLedger);
561
562 // kick off the next round...
563 // in the actual implementation, this passes back through
564 // network ops
566 // startRound sets the LCL state, so we need to call it once after
567 // the last requested round completes
569 {
570 startRound();
571 }
572 });
573 }
574
575 // Earliest allowed sequence number when checking for ledgers with more
576 // validations than our current ledger
577 Ledger::Seq
579 {
580 return fullyValidatedLedger.seq();
581 }
582
584 getPrevLedger(Ledger::ID const& ledgerID, Ledger const& ledger, ConsensusMode mode)
585 {
586 // only do if we are past the genesis ledger
587 if (ledger.seq() == Ledger::Seq{0})
588 return ledgerID;
589
590 Ledger::ID const netLgr = validations.getPreferred(ledger, earliestAllowedSeq());
591
592 if (netLgr != ledgerID)
593 {
594 JLOG(j.trace()) << json::Compact(validations.getJsonTrie());
595 issue(WrongPrevLedger{.wrong = ledgerID, .right = netLgr});
596 }
597
598 return netLgr;
599 }
600
601 void
602 propose(Proposal const& pos)
603 {
604 share(pos);
605 }
606
607 ConsensusParms const&
608 parms() const
609 {
610 return consensusParms;
611 }
612
613 // Not interested in tracking consensus mode changes for now
614 void
618
619 // Share a message by broadcasting to all connected peers
620 template <class M>
621 void
622 share(M const& m)
623 {
624 issue(Share<M>{m});
625 send(BroadcastMesg<M>{m, router.nextSeq++, this->id}, this->id);
626 }
627
628 // Unwrap the Position and share the raw proposal
629 void
630 share(Position const& p)
631 {
632 share(p.proposal());
633 }
634
635 //--------------------------------------------------------------------------
636 // Validation members
637
639 bool
641 {
642 v.setTrusted();
643 v.setSeen(now());
644 ValStatus const res = validations.add(v.nodeID(), v);
645
646 if (res == ValStatus::Stale)
647 return false;
648
649 // Acquire will try to get from network if not already local
650 if (Ledger const* lgr = acquireLedger(v.ledgerID()))
652 return true;
653 }
654
656 void
658 {
659 // Only consider ledgers newer than our last fully validated ledger
660 if (ledger.seq() <= fullyValidatedLedger.seq())
661 return;
662
663 std::size_t const count = validations.numTrustedForLedger(ledger.id());
664 std::size_t const numTrustedPeers = trustGraph.graph().outDegree(this);
665 quorum = static_cast<std::size_t>(std::ceil(numTrustedPeers * 0.8));
666 if (count >= quorum && ledger.isAncestor(fullyValidatedLedger))
667 {
668 issue(FullyValidateLedger{.ledger = ledger, .prior = fullyValidatedLedger});
669 fullyValidatedLedger = ledger;
670 }
671 }
672
673 //-------------------------------------------------------------------------
674 // Peer messaging members
675
676 // Basic Sequence number router
677 // A message that will be flooded across the network is tagged with a
678 // sequence number by the origin node in a BroadcastMesg. Receivers will
679 // ignore a message as stale if they've already processed a newer sequence
680 // number, or will process and potentially relay the message along.
681 //
682 // The various bool handle(MessageType) members do the actual processing
683 // and should return true if the message should continue to be sent to
684 // peers.
685 //
686 // WARN: This assumes messages are received and processed in the order they
687 // are sent, so that a peer receives a message with seq 1 from node 0
688 // before seq 2 from node 0, etc.
689 // TODO: Break this out into a class and identify type interface to allow
690 // alternate routing strategies
691 template <class M>
698
699 struct Router
700 {
702 bc::flat_map<PeerID, std::size_t> lastObservedSeq;
703 };
704
706
707 // Send a broadcast message to all peers
708 template <class M>
709 void
710 send(BroadcastMesg<M> const& bm, PeerID from)
711 {
712 for (auto const link : net.links(this))
713 {
714 if (link.target->id != from && link.target->id != bm.origin)
715 {
716 // cheat and don't bother sending if we know it has already been
717 // used on the other end
718 if (link.target->router.lastObservedSeq[bm.origin] < bm.seq)
719 {
720 issue(Relay<M>{link.target->id, bm.msg});
721 net.send(this, link.target, [to = link.target, bm, id = this->id] {
722 to->receive(bm, id);
723 });
724 }
725 }
726 }
727 }
728
729 // Receive a shared message, process it and consider continuing to relay it
730 template <class M>
731 void
733 {
734 issue(Receive<M>{from, bm.msg});
735 if (router.lastObservedSeq[bm.origin] < bm.seq)
736 {
737 router.lastObservedSeq[bm.origin] = bm.seq;
738 schedule(delays.onReceive(bm.msg), [this, bm, from] {
739 if (handle(bm.msg))
740 send(bm, from);
741 });
742 }
743 }
744
745 // Type specific receive handlers, return true if the message should
746 // continue to be broadcast to peers
747 bool
748 handle(Proposal const& p)
749 {
750 // Only relay untrusted proposals on the same ledger
751 if (!trusts(p.nodeID()))
752 return p.prevLedger() == lastClosedLedger.id();
753
754 // TODO: This always suppresses relay of peer positions already seen
755 // Should it allow forwarding if for a recent ledger ?
756 auto& dest = peerPositions[p.prevLedger()];
757 if (std::ranges::find(dest, p) != dest.end())
758 return false;
759
760 dest.push_back(p);
761
762 // Rely on consensus to decide whether to relay
763 return consensus.peerProposal(now(), Position{p});
764 }
765
766 bool
767 handle(TxSet const& txs)
768 {
769 bool const inserted = txSets.insert(std::make_pair(txs.id(), txs)).second;
770 if (inserted)
771 consensus.gotTxSet(now(), txs);
772 // relay only if new
773 return inserted;
774 }
775
776 bool
777 handle(Tx const& tx)
778 {
779 // Ignore and suppress relay of transactions already in last ledger
780 TxSetType const& lastClosedTxs = lastClosedLedger.txs();
781 if (lastClosedTxs.contains(tx))
782 return false;
783
784 // only relay if it was new to our open ledger
785 return openTxs.insert(tx).second;
786 }
787
788 bool
790 {
791 // TODO: This is not relaying untrusted validations
792 if (!trusts(v.nodeID()))
793 return false;
794
795 // Will only relay if current
796 return addTrustedValidation(v);
797 }
798
799 bool
801 {
802 return fullyValidatedLedger.seq() > Ledger::Seq{0};
803 }
804
807 {
808 return earliestAllowedSeq();
809 }
810
813 {
815 for (auto const p : trustGraph.trustedPeers(this))
816 keys.insert(p->key);
817 return {quorum, keys};
818 }
819
822 {
823 return validations.laggards(seq, trusted);
824 }
825
826 bool
827 validator() const
828 {
829 return runAsValidator;
830 }
831
832 void
833 updateOperatingMode(std::size_t const positions) const
834 {
835 }
836
837 static bool
839 {
840 // does not matter
841 return false;
842 }
843
844 //--------------------------------------------------------------------------
845 // A locally submitted transaction
846 void
847 submit(Tx const& tx)
848 {
849 issue(SubmitTx{tx});
850 if (handle(tx))
851 share(tx);
852 }
853
854 //--------------------------------------------------------------------------
855 // Simulation "driver" members
856
858 void
860 {
861 consensus.timerEntry(now());
862 // only reschedule if not completed
864 scheduler.in(parms().ledgerGRANULARITY, [this]() { timerEntry(); });
865 }
866
867 // Called to begin the next round
868 void
870 {
871 // Between rounds, we take the majority ledger
872 // In the future, consider taking peer dominant ledger if no validations
873 // yet
875 if (bestLCL == Ledger::ID{0})
876 bestLCL = lastClosedLedger.id();
877
878 issue(StartRound{.bestLedger = bestLCL, .prevLedger = lastClosedLedger});
879
880 // Not yet modeling dynamic UNL.
881 hash_set<PeerID> const nowUntrusted;
882 consensus.startRound(now(), bestLCL, lastClosedLedger, nowUntrusted, runAsValidator, {});
883 }
884
885 // Start the consensus process assuming it is not yet running
886 // This runs forever unless targetLedgers is specified
887 void
889 {
890 // TODO: Expire validations less frequently?
891 validations.expire(j);
892 scheduler.in(parms().ledgerGRANULARITY, [&]() { timerEntry(); });
893 startRound();
894 }
895
897 now() const
898 {
899 // We don't care about the actual epochs, but do want the
900 // generated NetClock time to be well past its epoch to ensure
901 // any subtractions of two NetClock::time_point in the consensus
902 // code are positive. (e.g. proposeFRESHNESS)
903 using namespace std::chrono;
904 using namespace std::chrono_literals;
907 scheduler.now().time_since_epoch() + 86400s + clockSkew));
908 }
909
912 {
913 return consensus.prevLedgerID();
914 }
915
916 //-------------------------------------------------------------------------
917 // Injects a specific transaction when generating the ledger following
918 // the provided sequence. This allows simulating a byzantine failure in
919 // which a node generates the wrong ledger, even when consensus worked
920 // properly.
921 // TODO: Make this more robust
923
934 TxSet
935 injectTxs(Ledger prevLedger, TxSet const& src)
936 {
937 auto const it = txInjections.find(prevLedger.seq());
938
939 if (it == txInjections.end())
940 return src;
941 TxSetType res{src.txs()};
942 res.insert(it->second);
943
944 return TxSet{res};
945 }
946};
947
948} // namespace xrpl::test::csf
T ceil(T... args)
A generic endpoint for log messages.
Definition Journal.h:38
Wraps a Journal::Sink to prefix its output with a string.
Definition WrappedSink.h:16
Decorator for streaming out compact json.
Represents a JSON value.
Definition json_value.h:130
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:278
std::chrono::time_point< NetClock > time_point
Definition chrono.h:46
std::chrono::duration< rep, period > duration
Definition chrono.h:45
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:227
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition ledgers.h:41
TaggedInteger< std::uint32_t, IdTag > ID
Definition ledgers.h:49
TaggedInteger< std::uint32_t, SeqTag > Seq
Definition ledgers.h:46
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:191
Basic wrapper of a proposed position taken by a peer.
static std::string render()
Proposal const & proposal() const
NetClock::time_point now() const
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:62
beast::Uhash<>::result_type ID
Definition Tx.h:64
static ID calcID(TxSetType const &txs)
Definition Tx.h:68
ID id() const
Definition Tx.h:130
TxSetType const & txs() const
Definition Tx.h:124
A single transaction.
Definition Tx.h:21
ID const & id() const
Definition Tx.h:35
Validation of a specific ledger by a specific Peer.
Definition Validation.h:28
void setSeen(NetClock::time_point seen)
Definition Validation.h:167
PeerID const & nodeID() const
Definition Validation.h:98
Ledger::ID ledgerID() const
Definition Validation.h:68
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:199
boost::container::flat_set< Tx > TxSetType
Definition Tx.h:58
TaggedInteger< std::uint32_t, PeerIDTag > PeerID
Definition Validation.h:15
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:13
std::pair< PeerID, std::uint32_t > PeerKey
The current key of a peer.
Definition Validation.h:23
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:17
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:27
Peer closed the open ledger.
Definition events.h:89
Peer fully validated a new ledger.
Definition events.h:118
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
SimDuration onReceive(M const &) const
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.
void share(M const &m)
hash_set< NodeKey_t > trustedKeys
hash_map< Ledger::ID, Ledger > ledgers
Ledgers this node has closed or loaded from the network.
bool haveValidated() const
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)
ConsensusParms consensusParms
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)
void issue(E const &event)
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.
PeerID id
Our unique ID.
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
Validations< ValAdaptor > validations
Validations from trusted nodes.
bool addTrustedValidation(Validation v)
Add a trusted validation and return true if it is worth forwarding.
bool handle(Tx const &tx)
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)
bool hasOpenTransactions() const
static bool validating()
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.
Validation::NodeKey NodeKey
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
void submit(Tx const &tx)
A value received from another peer as part of flooding.
Definition events.h:60
A value relayed to another peer as part of flooding.
Definition events.h:48
A value to be flooded to all other peers starting from this peer.
Definition events.h:39
Peer starts a new consensus round.
Definition events.h:78
A transaction submitted to a peer.
Definition events.h:70
Peer detected a wrong prior ledger during consensus.
Definition events.h:109