rippled
Loading...
Searching...
No Matches
test/csf/Peer.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_TEST_CSF_PEER_H_INCLUDED
21#define RIPPLE_TEST_CSF_PEER_H_INCLUDED
22
23#include <test/csf/CollectorRef.h>
24#include <test/csf/Scheduler.h>
25#include <test/csf/TrustGraph.h>
26#include <test/csf/Tx.h>
27#include <test/csf/Validation.h>
28#include <test/csf/events.h>
29#include <test/csf/ledgers.h>
30
31#include <xrpld/consensus/Consensus.h>
32#include <xrpld/consensus/Validations.h>
33
34#include <xrpl/beast/utility/WrappedSink.h>
35#include <xrpl/protocol/PublicKey.h>
36
37#include <boost/container/flat_map.hpp>
38#include <boost/container/flat_set.hpp>
39
40#include <algorithm>
41
42namespace ripple {
43namespace test {
44namespace csf {
45
46namespace bc = boost::container;
47
59struct Peer
60{
67 {
68 public:
70 {
71 }
72
73 Proposal const&
74 proposal() const
75 {
76 return proposal_;
77 }
78
80 getJson() const
81 {
82 return proposal_.getJson();
83 }
84
86 render() const
87 {
88 return "";
89 }
90
91 private:
93 };
94
98 {
103
106
107 // Return the receive delay for message type M, default is no delay
108 // Received delay is the time from receiving the message to actually
109 // handling it.
110 template <class M>
112 onReceive(M const&) const
113 {
114 return SimDuration{};
115 }
116
118 onReceive(Validation const&) const
119 {
120 return recvValidation;
121 }
122 };
123
125 {
126 };
127
132 {
134
135 public:
136 struct Mutex
137 {
138 void
140 {
141 }
142
143 void
145 {
146 }
147 };
148
151
153 {
154 }
155
157 now() const
158 {
159 return p_.now();
160 }
161
163 acquire(Ledger::ID const& lId)
164 {
165 if (Ledger const* ledger = p_.acquireLedger(lId))
166 return *ledger;
167 return std::nullopt;
168 }
169 };
170
175 using TxSet_t = TxSet;
179
183
186
189
192
195
198
201
204
207
210
213
216
220
221 //-------------------------------------------------------------------------
222 // Store most network messages; these could be purged if memory use ever
223 // becomes problematic
224
227 bc::flat_map<Ledger::ID, std::vector<Proposal>> peerPositions;
229 bc::flat_map<TxSet::ID, TxSet> txSets;
230
231 // Ledgers/TxSets we are acquiring and when that request times out
232 bc::flat_map<Ledger::ID, SimTime> acquiringLedgers;
233 bc::flat_map<TxSet::ID, SimTime> acquiringTxSets;
234
237
240
243
246
248 bool runAsValidator = true;
249
250 // TODO: Consider removing these two, they are only a convenience for tests
251 // Number of proposers in the prior round
253 // Duration of prior round
255
256 // Quorum of validations needed for a ledger to be fully validated
257 // TODO: Use the logic in ValidatorList to set this dynamically
259
261
262 // Simulation parameters
264
267
280 PeerID i,
281 Scheduler& s,
282 LedgerOracle& o,
285 CollectorRefs& c,
286 beast::Journal jIn)
287 : sink(jIn, "Peer " + to_string(i) + ": ")
288 , j(sink)
289 , consensus(s.clock(), *this, j)
290 , id{i}
291 , key{id, 0}
292 , oracle{o}
293 , scheduler{s}
294 , net{n}
295 , trustGraph(tg)
296 , lastClosedLedger{Ledger::MakeGenesis{}}
297 , validations{ValidationParms{}, s.clock(), *this}
298 , fullyValidatedLedger{Ledger::MakeGenesis{}}
299 , collectors{c}
300 {
301 // All peers start from the default constructed genesis ledger
303
304 // nodes always trust themselves . . SHOULD THEY?
305 trustGraph.trust(this, this);
306 }
307
311 template <class T>
312 void
314 {
315 using namespace std::chrono_literals;
316
317 if (when == 0ns)
318 what();
319 else
320 scheduler.in(when, std::forward<T>(what));
321 }
322
323 // Issue a new event to the collectors
324 template <class E>
325 void
326 issue(E const& event)
327 {
328 // Use the scheduler time and not the peer's (skewed) local time
329 collectors.on(id, scheduler.now(), event);
330 }
331
332 //--------------------------------------------------------------------------
333 // Trust and Network members
334 // Methods for modifying and querying the network and trust graphs from
335 // the perspective of this Peer
336
337 //< Extend trust to a peer
338 void
340 {
341 trustGraph.trust(this, &o);
342 }
343
344 //< Revoke trust from a peer
345 void
347 {
348 trustGraph.untrust(this, &o);
349 }
350
351 //< Check whether we trust a peer
352 bool
354 {
355 return trustGraph.trusts(this, &o);
356 }
357
358 //< Check whether we trust a peer based on its ID
359 bool
360 trusts(PeerID const& oId)
361 {
362 for (auto const p : trustGraph.trustedPeers(this))
363 if (p->id == oId)
364 return true;
365 return false;
366 }
367
377 bool
379 {
380 return net.connect(this, &o, dur);
381 }
382
390 bool
392 {
393 return net.disconnect(this, &o);
394 }
395
396 //--------------------------------------------------------------------------
397 // Generic Consensus members
398
399 // Attempt to acquire the Ledger associated with the given ID
400 Ledger const*
401 acquireLedger(Ledger::ID const& ledgerID)
402 {
403 if (auto it = ledgers.find(ledgerID); it != ledgers.end())
404 {
405 return &(it->second);
406 }
407
408 // No peers
409 if (net.links(this).empty())
410 return nullptr;
411
412 // Don't retry if we already are acquiring it and haven't timed out
413 auto aIt = acquiringLedgers.find(ledgerID);
414 if (aIt != acquiringLedgers.end())
415 {
416 if (scheduler.now() < aIt->second)
417 return nullptr;
418 }
419
420 using namespace std::chrono_literals;
421 SimDuration minDuration{10s};
422 for (auto const link : net.links(this))
423 {
424 minDuration = std::min(minDuration, link.data.delay);
425
426 // Send a messsage to neighbors to find the ledger
427 net.send(
428 this, link.target, [to = link.target, from = this, ledgerID]() {
429 if (auto it = to->ledgers.find(ledgerID);
430 it != to->ledgers.end())
431 {
432 // if the ledger is found, send it back to the original
433 // requesting peer where it is added to the available
434 // ledgers
435 to->net.send(to, from, [from, ledger = it->second]() {
436 from->acquiringLedgers.erase(ledger.id());
437 from->ledgers.emplace(ledger.id(), ledger);
438 });
439 }
440 });
441 }
442 acquiringLedgers[ledgerID] = scheduler.now() + 2 * minDuration;
443 return nullptr;
444 }
445
446 // Attempt to acquire the TxSet associated with the given ID
447 TxSet const*
449 {
450 if (auto it = txSets.find(setId); it != txSets.end())
451 {
452 return &(it->second);
453 }
454
455 // No peers
456 if (net.links(this).empty())
457 return nullptr;
458
459 // Don't retry if we already are acquiring it and haven't timed out
460 auto aIt = acquiringTxSets.find(setId);
461 if (aIt != acquiringTxSets.end())
462 {
463 if (scheduler.now() < aIt->second)
464 return nullptr;
465 }
466
467 using namespace std::chrono_literals;
468 SimDuration minDuration{10s};
469 for (auto const link : net.links(this))
470 {
471 minDuration = std::min(minDuration, link.data.delay);
472 // Send a message to neighbors to find the tx set
473 net.send(
474 this, link.target, [to = link.target, from = this, setId]() {
475 if (auto it = to->txSets.find(setId);
476 it != to->txSets.end())
477 {
478 // If the txSet is found, send it back to the original
479 // requesting peer, where it is handled like a TxSet
480 // that was broadcast over the network
481 to->net.send(to, from, [from, txSet = it->second]() {
482 from->acquiringTxSets.erase(txSet.id());
483 from->handle(txSet);
484 });
485 }
486 });
487 }
488 acquiringTxSets[setId] = scheduler.now() + 2 * minDuration;
489 return nullptr;
490 }
491
492 bool
494 {
495 return !openTxs.empty();
496 }
497
500 {
501 return validations.numTrustedForLedger(prevLedger);
502 }
503
505 proposersFinished(Ledger const& prevLedger, Ledger::ID const& prevLedgerID)
506 {
507 return validations.getNodesAfter(prevLedger, prevLedgerID);
508 }
509
510 Result
512 Ledger const& prevLedger,
513 NetClock::time_point closeTime,
514 ConsensusMode mode)
515 {
516 issue(CloseLedger{prevLedger, openTxs});
517
518 return Result(
519 TxSet{openTxs},
520 Proposal(
521 prevLedger.id(),
522 Proposal::seqJoin,
523 TxSet::calcID(openTxs),
524 closeTime,
525 now(),
526 id));
527 }
528
529 void
531 Result const& result,
532 Ledger const& prevLedger,
533 NetClock::duration const& closeResolution,
534 ConsensusCloseTimes const& rawCloseTimes,
535 ConsensusMode const& mode,
536 Json::Value&& consensusJson)
537 {
538 onAccept(
539 result,
540 prevLedger,
541 closeResolution,
542 rawCloseTimes,
543 mode,
544 std::move(consensusJson),
545 validating());
546 }
547
548 void
550 Result const& result,
551 Ledger const& prevLedger,
552 NetClock::duration const& closeResolution,
553 ConsensusCloseTimes const& rawCloseTimes,
554 ConsensusMode const& mode,
555 Json::Value&& consensusJson,
556 bool const validating)
557 {
558 schedule(delays.ledgerAccept, [=, this]() {
559 bool const proposing = mode == ConsensusMode::proposing;
560 bool const consensusFail = result.state == ConsensusState::MovedOn;
561
562 TxSet const acceptedTxs = injectTxs(prevLedger, result.txns);
563 Ledger const newLedger = oracle.accept(
564 prevLedger,
565 acceptedTxs.txs(),
566 closeResolution,
567 result.position.closeTime());
568 ledgers[newLedger.id()] = newLedger;
569
570 issue(AcceptLedger{newLedger, lastClosedLedger});
571 prevProposers = result.proposers;
572 prevRoundTime = result.roundTime.read();
573 lastClosedLedger = newLedger;
574
575 auto const it = std::remove_if(
576 openTxs.begin(), openTxs.end(), [&](Tx const& tx) {
577 return acceptedTxs.exists(tx.id());
578 });
579 openTxs.erase(it, openTxs.end());
580
581 // Only send validation if the new ledger is compatible with our
582 // fully validated ledger
583 bool const isCompatible =
584 newLedger.isAncestor(fullyValidatedLedger);
585
586 // Can only send one validated ledger per seq
587 if (runAsValidator && isCompatible && !consensusFail &&
588 validations.canValidateSeq(newLedger.seq()))
589 {
590 bool isFull = proposing;
591
592 Validation v{
593 newLedger.id(),
594 newLedger.seq(),
595 now(),
596 now(),
597 key,
598 id,
599 isFull};
600 // share the new validation; it is trusted by the receiver
601 share(v);
602 // we trust ourselves
603 addTrustedValidation(v);
604 }
605
606 checkFullyValidated(newLedger);
607
608 // kick off the next round...
609 // in the actual implementation, this passes back through
610 // network ops
611 ++completedLedgers;
612 // startRound sets the LCL state, so we need to call it once after
613 // the last requested round completes
614 if (completedLedgers <= targetLedgers)
615 {
616 startRound();
617 }
618 });
619 }
620
621 // Earliest allowed sequence number when checking for ledgers with more
622 // validations than our current ledger
623 Ledger::Seq
625 {
626 return fullyValidatedLedger.seq();
627 }
628
631 Ledger::ID const& ledgerID,
632 Ledger const& ledger,
633 ConsensusMode mode)
634 {
635 // only do if we are past the genesis ledger
636 if (ledger.seq() == Ledger::Seq{0})
637 return ledgerID;
638
639 Ledger::ID const netLgr =
640 validations.getPreferred(ledger, earliestAllowedSeq());
641
642 if (netLgr != ledgerID)
643 {
644 JLOG(j.trace()) << Json::Compact(validations.getJsonTrie());
645 issue(WrongPrevLedger{ledgerID, netLgr});
646 }
647
648 return netLgr;
649 }
650
651 void
652 propose(Proposal const& pos)
653 {
654 share(pos);
655 }
656
657 ConsensusParms const&
658 parms() const
659 {
660 return consensusParms;
661 }
662
663 // Not interested in tracking consensus mode changes for now
664 void
668
669 // Share a message by broadcasting to all connected peers
670 template <class M>
671 void
672 share(M const& m)
673 {
674 issue(Share<M>{m});
675 send(BroadcastMesg<M>{m, router.nextSeq++, this->id}, this->id);
676 }
677
678 // Unwrap the Position and share the raw proposal
679 void
680 share(Position const& p)
681 {
682 share(p.proposal());
683 }
684
685 //--------------------------------------------------------------------------
686 // Validation members
687
689 bool
691 {
692 v.setTrusted();
693 v.setSeen(now());
694 ValStatus const res = validations.add(v.nodeID(), v);
695
696 if (res == ValStatus::stale)
697 return false;
698
699 // Acquire will try to get from network if not already local
700 if (Ledger const* lgr = acquireLedger(v.ledgerID()))
701 checkFullyValidated(*lgr);
702 return true;
703 }
704
706 void
708 {
709 // Only consider ledgers newer than our last fully validated ledger
710 if (ledger.seq() <= fullyValidatedLedger.seq())
711 return;
712
713 std::size_t const count = validations.numTrustedForLedger(ledger.id());
714 std::size_t const numTrustedPeers = trustGraph.graph().outDegree(this);
715 quorum = static_cast<std::size_t>(std::ceil(numTrustedPeers * 0.8));
716 if (count >= quorum && ledger.isAncestor(fullyValidatedLedger))
717 {
718 issue(FullyValidateLedger{ledger, fullyValidatedLedger});
719 fullyValidatedLedger = ledger;
720 }
721 }
722
723 //-------------------------------------------------------------------------
724 // Peer messaging members
725
726 // Basic Sequence number router
727 // A message that will be flooded across the network is tagged with a
728 // sequence number by the origin node in a BroadcastMesg. Receivers will
729 // ignore a message as stale if they've already processed a newer sequence
730 // number, or will process and potentially relay the message along.
731 //
732 // The various bool handle(MessageType) members do the actual processing
733 // and should return true if the message should continue to be sent to
734 // peers.
735 //
736 // WARN: This assumes messages are received and processed in the order they
737 // are sent, so that a peer receives a message with seq 1 from node 0
738 // before seq 2 from node 0, etc.
739 // TODO: Break this out into a class and identify type interface to allow
740 // alternate routing strategies
741 template <class M>
748
749 struct Router
750 {
751 std::size_t nextSeq = 1;
752 bc::flat_map<PeerID, std::size_t> lastObservedSeq;
753 };
754
756
757 // Send a broadcast message to all peers
758 template <class M>
759 void
760 send(BroadcastMesg<M> const& bm, PeerID from)
761 {
762 for (auto const link : net.links(this))
763 {
764 if (link.target->id != from && link.target->id != bm.origin)
765 {
766 // cheat and don't bother sending if we know it has already been
767 // used on the other end
768 if (link.target->router.lastObservedSeq[bm.origin] < bm.seq)
769 {
770 issue(Relay<M>{link.target->id, bm.mesg});
771 net.send(
772 this,
773 link.target,
774 [to = link.target, bm, id = this->id] {
775 to->receive(bm, id);
776 });
777 }
778 }
779 }
780 }
781
782 // Receive a shared message, process it and consider continuing to relay it
783 template <class M>
784 void
786 {
787 issue(Receive<M>{from, bm.mesg});
788 if (router.lastObservedSeq[bm.origin] < bm.seq)
789 {
790 router.lastObservedSeq[bm.origin] = bm.seq;
791 schedule(delays.onReceive(bm.mesg), [this, bm, from] {
792 if (handle(bm.mesg))
793 send(bm, from);
794 });
795 }
796 }
797
798 // Type specific receive handlers, return true if the message should
799 // continue to be broadcast to peers
800 bool
801 handle(Proposal const& p)
802 {
803 // Only relay untrusted proposals on the same ledger
804 if (!trusts(p.nodeID()))
805 return p.prevLedger() == lastClosedLedger.id();
806
807 // TODO: This always suppresses relay of peer positions already seen
808 // Should it allow forwarding if for a recent ledger ?
809 auto& dest = peerPositions[p.prevLedger()];
810 if (std::find(dest.begin(), dest.end(), p) != dest.end())
811 return false;
812
813 dest.push_back(p);
814
815 // Rely on consensus to decide whether to relay
816 return consensus.peerProposal(now(), Position{p});
817 }
818
819 bool
820 handle(TxSet const& txs)
821 {
822 bool const inserted =
823 txSets.insert(std::make_pair(txs.id(), txs)).second;
824 if (inserted)
825 consensus.gotTxSet(now(), txs);
826 // relay only if new
827 return inserted;
828 }
829
830 bool
831 handle(Tx const& tx)
832 {
833 // Ignore and suppress relay of transactions already in last ledger
834 TxSetType const& lastClosedTxs = lastClosedLedger.txs();
835 if (lastClosedTxs.find(tx) != lastClosedTxs.end())
836 return false;
837
838 // only relay if it was new to our open ledger
839 return openTxs.insert(tx).second;
840 }
841
842 bool
844 {
845 // TODO: This is not relaying untrusted validations
846 if (!trusts(v.nodeID()))
847 return false;
848
849 // Will only relay if current
850 return addTrustedValidation(v);
851 }
852
853 bool
855 {
856 return fullyValidatedLedger.seq() > Ledger::Seq{0};
857 }
858
861 {
862 return earliestAllowedSeq();
863 }
864
867 {
869 for (auto const p : trustGraph.trustedPeers(this))
870 keys.insert(p->key);
871 return {quorum, keys};
872 }
873
876 {
877 return validations.laggards(seq, trusted);
878 }
879
880 bool
881 validator() const
882 {
883 return runAsValidator;
884 }
885
886 void
887 updateOperatingMode(std::size_t const positions) const
888 {
889 }
890
891 bool
893 {
894 // does not matter
895 return false;
896 }
897
898 //--------------------------------------------------------------------------
899 // A locally submitted transaction
900 void
901 submit(Tx const& tx)
902 {
903 issue(SubmitTx{tx});
904 if (handle(tx))
905 share(tx);
906 }
907
908 //--------------------------------------------------------------------------
909 // Simulation "driver" members
910
912 void
914 {
915 consensus.timerEntry(now());
916 // only reschedule if not completed
917 if (completedLedgers < targetLedgers)
918 scheduler.in(parms().ledgerGRANULARITY, [this]() { timerEntry(); });
919 }
920
921 // Called to begin the next round
922 void
924 {
925 // Between rounds, we take the majority ledger
926 // In the future, consider taking peer dominant ledger if no validations
927 // yet
928 Ledger::ID bestLCL =
929 validations.getPreferred(lastClosedLedger, earliestAllowedSeq());
930 if (bestLCL == Ledger::ID{0})
931 bestLCL = lastClosedLedger.id();
932
933 issue(StartRound{bestLCL, lastClosedLedger});
934
935 // Not yet modeling dynamic UNL.
936 hash_set<PeerID> nowUntrusted;
937 consensus.startRound(
938 now(), bestLCL, lastClosedLedger, nowUntrusted, runAsValidator, {});
939 }
940
941 // Start the consensus process assuming it is not yet running
942 // This runs forever unless targetLedgers is specified
943 void
945 {
946 // TODO: Expire validations less frequently?
947 validations.expire(j);
948 scheduler.in(parms().ledgerGRANULARITY, [&]() { timerEntry(); });
949 startRound();
950 }
951
953 now() const
954 {
955 // We don't care about the actual epochs, but do want the
956 // generated NetClock time to be well past its epoch to ensure
957 // any subtractions of two NetClock::time_point in the consensus
958 // code are positive. (e.g. proposeFRESHNESS)
959 using namespace std::chrono;
960 using namespace std::chrono_literals;
961 return NetClock::time_point(duration_cast<NetClock::duration>(
962 scheduler.now().time_since_epoch() + 86400s + clockSkew));
963 }
964
967 {
968 return consensus.prevLedgerID();
969 }
970
971 //-------------------------------------------------------------------------
972 // Injects a specific transaction when generating the ledger following
973 // the provided sequence. This allows simulating a byzantine failure in
974 // which a node generates the wrong ledger, even when consensus worked
975 // properly.
976 // TODO: Make this more robust
978
989 TxSet
990 injectTxs(Ledger prevLedger, TxSet const& src)
991 {
992 auto const it = txInjections.find(prevLedger.seq());
993
994 if (it == txInjections.end())
995 return src;
996 TxSetType res{src.txs()};
997 res.insert(it->second);
998
999 return TxSet{res};
1000 }
1001};
1002
1003} // namespace csf
1004} // namespace test
1005} // namespace ripple
1006#endif
T ceil(T... args)
Decorator for streaming out compact json.
Represents a JSON value.
Definition json_value.h:149
A generic endpoint for log messages.
Definition Journal.h:60
Wraps a Journal::Sink to prefix its output with a string.
Definition WrappedSink.h:34
LedgerID_t const & prevLedger() const
Get the prior accepted ledger this position is based on.
NodeID_t const & nodeID() const
Identifying which peer took this position.
Json::Value getJson() const
Get JSON representation for debugging.
std::chrono::milliseconds read() const
Generic implementation of consensus algorithm.
Definition Consensus.h:298
std::chrono::time_point< NetClock > time_point
Definition chrono.h:69
Maintains current and recent ledger validations.
std::size_t numTrustedForLedger(ID const &ledgerID)
Count the number of trusted full validations for the given ledger.
std::size_t getNodesAfter(Ledger const &ledger, ID const &ledgerID)
Count the number of current trusted validators working on a ledger after the specified one.
bool canValidateSeq(Seq const s)
Return whether the local node can issue a validation for the given sequence number.
Peer to peer network simulator.
void send(Peer const &from, Peer const &to, Function &&f)
Send a message to a peer.
auto links(Peer const &from)
Return the range of active links.
A container of CollectorRefs.
void on(PeerID node, SimTime when, E const &e)
Oracle maintaining unique ledgers for a simulation.
Definition ledgers.h:250
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition ledgers.h:64
bool isAncestor(Ledger const &ancestor) const
Determine whether ancestor is really an ancestor of this ledger.
Definition ledgers.cpp:40
Basic wrapper of a proposed position taken by a peer.
Proposal const & proposal() const
Generic Validations adaptor that simply ignores recently stale validations.
std::optional< Ledger > acquire(Ledger::ID const &lId)
NetClock::time_point now() const
Simulated discrete-event scheduler.
time_point now() const
Return the current network time.
cancel_token in(duration const &delay, Function &&f)
Schedule an event after a specified duration passes.
TxSet is a set of transactions to consider including in the ledger.
Definition Tx.h:83
TxSetType const & txs() const
Definition Tx.h:144
ID id() const
Definition Tx.h:150
beast::uhash<>::result_type ID
Definition Tx.h:85
Tx const * find(Tx::ID const &txId) const
Definition Tx.h:135
A single transaction.
Definition Tx.h:42
Validation of a specific ledger by a specific Peer.
Definition Validation.h:50
Ledger::Seq seq() const
Definition Validation.h:96
Ledger::ID ledgerID() const
Definition Validation.h:90
void setSeen(NetClock::time_point seen)
Definition Validation.h:197
PeerID const & nodeID() const
Definition Validation.h:120
T end(T... args)
T find(T... args)
T insert(T... args)
T is_same_v
T make_pair(T... args)
T max(T... args)
T min(T... args)
std::pair< PeerID, std::uint32_t > PeerKey
The current key of a peer.
Definition Validation.h:45
tagged_integer< std::uint32_t, PeerIDTag > PeerID
Definition Validation.h:37
typename SimClock::duration SimDuration
Definition SimTime.h:36
boost::container::flat_set< Tx > TxSetType
Definition Tx.h:79
std::string to_string(TxSetType const &txs)
Definition Tx.h:215
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
ConsensusMode
Represents how a node currently participates in Consensus.
@ proposing
We are normal participant in consensus and propose our position.
boost::outcome_v2::result< T, std::error_code > Result
Definition b58_utils.h:37
ValStatus
Status of validation we received.
@ stale
Not current or was older than current from this node.
T remove_if(T... args)
Stores the set of initial close times.
Consensus algorithm parameters.
Encapsulates the result of consensus.
Timing parameters to control validation staleness and expiration.
Definition Validations.h:47
Peer closed the open ledger.
Definition events.h:111
Peer fully validated a new ledger.
Definition events.h:140
Simulated delays in internal peer processing.
SimDuration onReceive(M const &) const
std::chrono::milliseconds ledgerAccept
Delay in consensus calling doAccept to accepting and issuing validation TODO: This should be a functi...
std::chrono::milliseconds recvValidation
Delay in processing validations from remote peers.
SimDuration onReceive(Validation const &) const
bc::flat_map< PeerID, std::size_t > lastObservedSeq
A single peer in the simulation.
bool handle(TxSet const &txs)
bc::flat_map< Ledger::ID, std::vector< Proposal > > peerPositions
Map from Ledger::ID to vector of Positions with that ledger as the prior ledger.
void propose(Proposal const &pos)
bool addTrustedValidation(Validation v)
Add a trusted validation and return true if it is worth forwarding.
bool hasOpenTransactions() const
bool handle(Validation const &v)
Ledger const * acquireLedger(Ledger::ID const &ledgerID)
Consensus< Peer > consensus
Generic consensus.
void receive(BroadcastMesg< M > const &bm, PeerID from)
BasicNetwork< Peer * > & net
Handle to network for sending messages.
void onAccept(Result const &result, Ledger const &prevLedger, NetClock::duration const &closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, Json::Value &&consensusJson, bool const validating)
void checkFullyValidated(Ledger const &ledger)
Check if a new ledger can be deemed fully validated.
hash_set< NodeKey_t > trustedKeys
std::pair< std::size_t, hash_set< NodeKey_t > > getQuorumKeys()
hash_map< Ledger::ID, Ledger > ledgers
Ledgers this node has closed or loaded from the network.
Ledger::Seq earliestAllowedSeq() const
TrustGraph< Peer * > & trustGraph
Handle to Trust graph of network.
void send(BroadcastMesg< M > const &bm, PeerID from)
LedgerOracle & oracle
The oracle that manages unique ledgers.
TxSetType openTxs
openTxs that haven't been closed in a ledger yet
bool connect(Peer &o, SimDuration dur)
Create network connection.
void timerEntry()
Heartbeat timer call.
Ledger lastClosedLedger
The last ledger closed by this node.
std::size_t laggards(Ledger::Seq const seq, hash_set< NodeKey_t > &trusted)
PeerKey key
Current signing key.
hash_map< Ledger::Seq, Tx > txInjections
CollectorRefs & collectors
The collectors to report events to.
Result onClose(Ledger const &prevLedger, NetClock::time_point closeTime, ConsensusMode mode)
ConsensusParms const & parms() const
void issue(E const &event)
void updateOperatingMode(std::size_t const positions) const
bc::flat_map< Ledger::ID, SimTime > acquiringLedgers
void onForceAccept(Result const &result, Ledger const &prevLedger, NetClock::duration const &closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, Json::Value &&consensusJson)
ProcessingDelays delays
Simulated delays to use for internal processing.
std::size_t proposersFinished(Ledger const &prevLedger, Ledger::ID const &prevLedgerID)
Ledger fullyValidatedLedger
The most recent ledger that has been fully validated by the network from the perspective of this Peer...
bc::flat_map< TxSet::ID, TxSet > txSets
TxSet associated with a TxSet::ID.
Peer(PeerID i, Scheduler &s, LedgerOracle &o, BasicNetwork< Peer * > &n, TrustGraph< Peer * > &tg, CollectorRefs &c, beast::Journal jIn)
Constructor.
TxSet const * acquireTxSet(TxSet::ID const &setId)
PeerID id
Our unique ID.
bc::flat_map< TxSet::ID, SimTime > acquiringTxSets
bool trusts(PeerID const &oId)
Ledger::ID prevLedgerID() const
Scheduler & scheduler
Scheduler of events.
int targetLedgers
The number of ledgers this peer should complete before stopping to run.
ConsensusParms consensusParms
beast::WrappedSink sink
Logging support that prefixes messages with the peer ID.
bool disconnect(Peer &o)
Remove a network connection.
std::chrono::seconds clockSkew
Skew of time relative to the common scheduler clock.
std::size_t proposersValidated(Ledger::ID const &prevLedger)
Ledger::ID getPrevLedger(Ledger::ID const &ledgerID, Ledger const &ledger, ConsensusMode mode)
bool handle(Proposal const &p)
void onModeChange(ConsensusMode, ConsensusMode)
int completedLedgers
The number of ledgers this peer has completed.
Validations< ValAdaptor > validations
Validations from trusted nodes.
TxSet injectTxs(Ledger prevLedger, TxSet const &src)
Inject non-consensus Tx.
bool runAsValidator
Whether to simulate running as validator or a tracking node.
bool handle(Tx const &tx)
void schedule(std::chrono::nanoseconds when, T &&what)
Schedule the provided callback in when duration, but if when is 0, call immediately.
void share(Position const &p)
std::chrono::milliseconds prevRoundTime
Ledger::Seq getValidLedgerIndex() const
void submit(Tx const &tx)
void share(M const &m)
NetClock::time_point now() const
A value received from another peer as part of flooding.
Definition events.h:82
A value relayed to another peer as part of flooding.
Definition events.h:70
A value to be flooded to all other peers starting from this peer.
Definition events.h:61
Peer starts a new consensus round.
Definition events.h:100
A transaction submitted to a peer.
Definition events.h:92
Peer detected a wrong prior ledger during consensus.
Definition events.h:131
Set the sequence number on a JTx.
Definition seq.h:34