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#ifndef RIPPLE_TEST_CSF_PEER_H_INCLUDED
20#define RIPPLE_TEST_CSF_PEER_H_INCLUDED
21
22#include <test/csf/CollectorRef.h>
23#include <test/csf/Scheduler.h>
24#include <test/csf/TrustGraph.h>
25#include <test/csf/Tx.h>
26#include <test/csf/Validation.h>
27#include <test/csf/events.h>
28#include <test/csf/ledgers.h>
29#include <xrpld/consensus/Consensus.h>
30#include <xrpld/consensus/Validations.h>
31#include <xrpl/beast/utility/WrappedSink.h>
32#include <xrpl/protocol/PublicKey.h>
33#include <boost/container/flat_map.hpp>
34#include <boost/container/flat_set.hpp>
35#include <algorithm>
36
37namespace ripple {
38namespace test {
39namespace csf {
40
41namespace bc = boost::container;
42
54struct Peer
55{
62 {
63 public:
65 {
66 }
67
68 Proposal const&
69 proposal() const
70 {
71 return proposal_;
72 }
73
75 getJson() const
76 {
77 return proposal_.getJson();
78 }
79
81 render() const
82 {
83 return "";
84 }
85
86 private:
88 };
89
93 {
98
101
102 // Return the receive delay for message type M, default is no delay
103 // Received delay is the time from receiving the message to actually
104 // handling it.
105 template <class M>
107 onReceive(M const&) const
108 {
109 return SimDuration{};
110 }
111
113 onReceive(Validation const&) const
114 {
115 return recvValidation;
116 }
117 };
118
123 {
125
126 public:
127 struct Mutex
128 {
129 void
131 {
132 }
133
134 void
136 {
137 }
138 };
139
142
144 {
145 }
146
148 now() const
149 {
150 return p_.now();
151 }
152
154 acquire(Ledger::ID const& lId)
155 {
156 if (Ledger const* ledger = p_.acquireLedger(lId))
157 return *ledger;
158 return std::nullopt;
159 }
160 };
161
166 using TxSet_t = TxSet;
170
174
177
180
183
186
189
192
195
198
201
204
207
211
212 //-------------------------------------------------------------------------
213 // Store most network messages; these could be purged if memory use ever
214 // becomes problematic
215
218 bc::flat_map<Ledger::ID, std::vector<Proposal>> peerPositions;
220 bc::flat_map<TxSet::ID, TxSet> txSets;
221
222 // Ledgers/TxSets we are acquiring and when that request times out
223 bc::flat_map<Ledger::ID, SimTime> acquiringLedgers;
224 bc::flat_map<TxSet::ID, SimTime> acquiringTxSets;
225
228
231
234
237
239 bool runAsValidator = true;
240
241 // TODO: Consider removing these two, they are only a convenience for tests
242 // Number of proposers in the prior round
244 // Duration of prior round
246
247 // Quorum of validations needed for a ledger to be fully validated
248 // TODO: Use the logic in ValidatorList to set this dynamically
250
252
253 // Simulation parameters
255
258
271 PeerID i,
272 Scheduler& s,
273 LedgerOracle& o,
276 CollectorRefs& c,
277 beast::Journal jIn)
278 : sink(jIn, "Peer " + to_string(i) + ": ")
279 , j(sink)
280 , consensus(s.clock(), *this, j)
281 , id{i}
282 , key{id, 0}
283 , oracle{o}
284 , scheduler{s}
285 , net{n}
286 , trustGraph(tg)
287 , lastClosedLedger{Ledger::MakeGenesis{}}
288 , validations{ValidationParms{}, s.clock(), *this}
289 , fullyValidatedLedger{Ledger::MakeGenesis{}}
290 , collectors{c}
291 {
292 // All peers start from the default constructed genesis ledger
294
295 // nodes always trust themselves . . SHOULD THEY?
296 trustGraph.trust(this, this);
297 }
298
302 template <class T>
303 void
305 {
306 using namespace std::chrono_literals;
307
308 if (when == 0ns)
309 what();
310 else
311 scheduler.in(when, std::forward<T>(what));
312 }
313
314 // Issue a new event to the collectors
315 template <class E>
316 void
317 issue(E const& event)
318 {
319 // Use the scheduler time and not the peer's (skewed) local time
320 collectors.on(id, scheduler.now(), event);
321 }
322
323 //--------------------------------------------------------------------------
324 // Trust and Network members
325 // Methods for modifying and querying the network and trust graphs from
326 // the perspective of this Peer
327
328 //< Extend trust to a peer
329 void
331 {
332 trustGraph.trust(this, &o);
333 }
334
335 //< Revoke trust from a peer
336 void
338 {
339 trustGraph.untrust(this, &o);
340 }
341
342 //< Check whether we trust a peer
343 bool
345 {
346 return trustGraph.trusts(this, &o);
347 }
348
349 //< Check whether we trust a peer based on its ID
350 bool
351 trusts(PeerID const& oId)
352 {
353 for (auto const p : trustGraph.trustedPeers(this))
354 if (p->id == oId)
355 return true;
356 return false;
357 }
358
368 bool
370 {
371 return net.connect(this, &o, dur);
372 }
373
381 bool
383 {
384 return net.disconnect(this, &o);
385 }
386
387 //--------------------------------------------------------------------------
388 // Generic Consensus members
389
390 // Attempt to acquire the Ledger associated with the given ID
391 Ledger const*
392 acquireLedger(Ledger::ID const& ledgerID)
393 {
394 if (auto it = ledgers.find(ledgerID); it != ledgers.end())
395 {
396 return &(it->second);
397 }
398
399 // No peers
400 if (net.links(this).empty())
401 return nullptr;
402
403 // Don't retry if we already are acquiring it and haven't timed out
404 auto aIt = acquiringLedgers.find(ledgerID);
405 if (aIt != acquiringLedgers.end())
406 {
407 if (scheduler.now() < aIt->second)
408 return nullptr;
409 }
410
411 using namespace std::chrono_literals;
412 SimDuration minDuration{10s};
413 for (auto const link : net.links(this))
414 {
415 minDuration = std::min(minDuration, link.data.delay);
416
417 // Send a messsage to neighbors to find the ledger
418 net.send(
419 this, link.target, [to = link.target, from = this, ledgerID]() {
420 if (auto it = to->ledgers.find(ledgerID);
421 it != to->ledgers.end())
422 {
423 // if the ledger is found, send it back to the original
424 // requesting peer where it is added to the available
425 // ledgers
426 to->net.send(to, from, [from, ledger = it->second]() {
427 from->acquiringLedgers.erase(ledger.id());
428 from->ledgers.emplace(ledger.id(), ledger);
429 });
430 }
431 });
432 }
433 acquiringLedgers[ledgerID] = scheduler.now() + 2 * minDuration;
434 return nullptr;
435 }
436
437 // Attempt to acquire the TxSet associated with the given ID
438 TxSet const*
440 {
441 if (auto it = txSets.find(setId); it != txSets.end())
442 {
443 return &(it->second);
444 }
445
446 // No peers
447 if (net.links(this).empty())
448 return nullptr;
449
450 // Don't retry if we already are acquiring it and haven't timed out
451 auto aIt = acquiringTxSets.find(setId);
452 if (aIt != acquiringTxSets.end())
453 {
454 if (scheduler.now() < aIt->second)
455 return nullptr;
456 }
457
458 using namespace std::chrono_literals;
459 SimDuration minDuration{10s};
460 for (auto const link : net.links(this))
461 {
462 minDuration = std::min(minDuration, link.data.delay);
463 // Send a message to neighbors to find the tx set
464 net.send(
465 this, link.target, [to = link.target, from = this, setId]() {
466 if (auto it = to->txSets.find(setId);
467 it != to->txSets.end())
468 {
469 // If the txSet is found, send it back to the original
470 // requesting peer, where it is handled like a TxSet
471 // that was broadcast over the network
472 to->net.send(to, from, [from, txSet = it->second]() {
473 from->acquiringTxSets.erase(txSet.id());
474 from->handle(txSet);
475 });
476 }
477 });
478 }
479 acquiringTxSets[setId] = scheduler.now() + 2 * minDuration;
480 return nullptr;
481 }
482
483 bool
485 {
486 return !openTxs.empty();
487 }
488
491 {
492 return validations.numTrustedForLedger(prevLedger);
493 }
494
496 proposersFinished(Ledger const& prevLedger, Ledger::ID const& prevLedgerID)
497 {
498 return validations.getNodesAfter(prevLedger, prevLedgerID);
499 }
500
501 Result
503 Ledger const& prevLedger,
504 NetClock::time_point closeTime,
505 ConsensusMode mode)
506 {
507 issue(CloseLedger{prevLedger, openTxs});
508
509 return Result(
510 TxSet{openTxs},
511 Proposal(
512 prevLedger.id(),
513 Proposal::seqJoin,
514 TxSet::calcID(openTxs),
515 closeTime,
516 now(),
517 id));
518 }
519
520 void
522 Result const& result,
523 Ledger const& prevLedger,
524 NetClock::duration const& closeResolution,
525 ConsensusCloseTimes const& rawCloseTimes,
526 ConsensusMode const& mode,
527 Json::Value&& consensusJson)
528 {
529 onAccept(
530 result,
531 prevLedger,
532 closeResolution,
533 rawCloseTimes,
534 mode,
535 std::move(consensusJson));
536 }
537
538 void
540 Result const& result,
541 Ledger const& prevLedger,
542 NetClock::duration const& closeResolution,
543 ConsensusCloseTimes const& rawCloseTimes,
544 ConsensusMode const& mode,
545 Json::Value&& consensusJson)
546 {
547 schedule(delays.ledgerAccept, [=, this]() {
548 const bool proposing = mode == ConsensusMode::proposing;
549 const bool consensusFail = result.state == ConsensusState::MovedOn;
550
551 TxSet const acceptedTxs = injectTxs(prevLedger, result.txns);
552 Ledger const newLedger = oracle.accept(
553 prevLedger,
554 acceptedTxs.txs(),
555 closeResolution,
556 result.position.closeTime());
557 ledgers[newLedger.id()] = newLedger;
558
559 issue(AcceptLedger{newLedger, lastClosedLedger});
560 prevProposers = result.proposers;
561 prevRoundTime = result.roundTime.read();
562 lastClosedLedger = newLedger;
563
564 auto const it = std::remove_if(
565 openTxs.begin(), openTxs.end(), [&](Tx const& tx) {
566 return acceptedTxs.exists(tx.id());
567 });
568 openTxs.erase(it, openTxs.end());
569
570 // Only send validation if the new ledger is compatible with our
571 // fully validated ledger
572 bool const isCompatible =
573 newLedger.isAncestor(fullyValidatedLedger);
574
575 // Can only send one validated ledger per seq
576 if (runAsValidator && isCompatible && !consensusFail &&
577 validations.canValidateSeq(newLedger.seq()))
578 {
579 bool isFull = proposing;
580
581 Validation v{
582 newLedger.id(),
583 newLedger.seq(),
584 now(),
585 now(),
586 key,
587 id,
588 isFull};
589 // share the new validation; it is trusted by the receiver
590 share(v);
591 // we trust ourselves
592 addTrustedValidation(v);
593 }
594
595 checkFullyValidated(newLedger);
596
597 // kick off the next round...
598 // in the actual implementation, this passes back through
599 // network ops
600 ++completedLedgers;
601 // startRound sets the LCL state, so we need to call it once after
602 // the last requested round completes
603 if (completedLedgers <= targetLedgers)
604 {
605 startRound();
606 }
607 });
608 }
609
610 // Earliest allowed sequence number when checking for ledgers with more
611 // validations than our current ledger
612 Ledger::Seq
614 {
615 return fullyValidatedLedger.seq();
616 }
617
620 Ledger::ID const& ledgerID,
621 Ledger const& ledger,
622 ConsensusMode mode)
623 {
624 // only do if we are past the genesis ledger
625 if (ledger.seq() == Ledger::Seq{0})
626 return ledgerID;
627
628 Ledger::ID const netLgr =
629 validations.getPreferred(ledger, earliestAllowedSeq());
630
631 if (netLgr != ledgerID)
632 {
633 JLOG(j.trace()) << Json::Compact(validations.getJsonTrie());
634 issue(WrongPrevLedger{ledgerID, netLgr});
635 }
636
637 return netLgr;
638 }
639
640 void
641 propose(Proposal const& pos)
642 {
643 share(pos);
644 }
645
646 ConsensusParms const&
647 parms() const
648 {
649 return consensusParms;
650 }
651
652 // Not interested in tracking consensus mode changes for now
653 void
655 {
656 }
657
658 // Share a message by broadcasting to all connected peers
659 template <class M>
660 void
661 share(M const& m)
662 {
663 issue(Share<M>{m});
664 send(BroadcastMesg<M>{m, router.nextSeq++, this->id}, this->id);
665 }
666
667 // Unwrap the Position and share the raw proposal
668 void
669 share(Position const& p)
670 {
671 share(p.proposal());
672 }
673
674 //--------------------------------------------------------------------------
675 // Validation members
676
678 bool
680 {
681 v.setTrusted();
682 v.setSeen(now());
683 ValStatus const res = validations.add(v.nodeID(), v);
684
685 if (res == ValStatus::stale)
686 return false;
687
688 // Acquire will try to get from network if not already local
689 if (Ledger const* lgr = acquireLedger(v.ledgerID()))
690 checkFullyValidated(*lgr);
691 return true;
692 }
693
695 void
697 {
698 // Only consider ledgers newer than our last fully validated ledger
699 if (ledger.seq() <= fullyValidatedLedger.seq())
700 return;
701
702 std::size_t const count = validations.numTrustedForLedger(ledger.id());
703 std::size_t const numTrustedPeers = trustGraph.graph().outDegree(this);
704 quorum = static_cast<std::size_t>(std::ceil(numTrustedPeers * 0.8));
705 if (count >= quorum && ledger.isAncestor(fullyValidatedLedger))
706 {
707 issue(FullyValidateLedger{ledger, fullyValidatedLedger});
708 fullyValidatedLedger = ledger;
709 }
710 }
711
712 //-------------------------------------------------------------------------
713 // Peer messaging members
714
715 // Basic Sequence number router
716 // A message that will be flooded across the network is tagged with a
717 // sequence number by the origin node in a BroadcastMesg. Receivers will
718 // ignore a message as stale if they've already processed a newer sequence
719 // number, or will process and potentially relay the message along.
720 //
721 // The various bool handle(MessageType) members do the actual processing
722 // and should return true if the message should continue to be sent to
723 // peers.
724 //
725 // WARN: This assumes messages are received and processed in the order they
726 // are sent, so that a peer receives a message with seq 1 from node 0
727 // before seq 2 from node 0, etc.
728 // TODO: Break this out into a class and identify type interface to allow
729 // alternate routing strategies
730 template <class M>
732 {
736 };
737
738 struct Router
739 {
740 std::size_t nextSeq = 1;
741 bc::flat_map<PeerID, std::size_t> lastObservedSeq;
742 };
743
745
746 // Send a broadcast message to all peers
747 template <class M>
748 void
749 send(BroadcastMesg<M> const& bm, PeerID from)
750 {
751 for (auto const link : net.links(this))
752 {
753 if (link.target->id != from && link.target->id != bm.origin)
754 {
755 // cheat and don't bother sending if we know it has already been
756 // used on the other end
757 if (link.target->router.lastObservedSeq[bm.origin] < bm.seq)
758 {
759 issue(Relay<M>{link.target->id, bm.mesg});
760 net.send(
761 this,
762 link.target,
763 [to = link.target, bm, id = this->id] {
764 to->receive(bm, id);
765 });
766 }
767 }
768 }
769 }
770
771 // Receive a shared message, process it and consider continuing to relay it
772 template <class M>
773 void
775 {
776 issue(Receive<M>{from, bm.mesg});
777 if (router.lastObservedSeq[bm.origin] < bm.seq)
778 {
779 router.lastObservedSeq[bm.origin] = bm.seq;
780 schedule(delays.onReceive(bm.mesg), [this, bm, from] {
781 if (handle(bm.mesg))
782 send(bm, from);
783 });
784 }
785 }
786
787 // Type specific receive handlers, return true if the message should
788 // continue to be broadcast to peers
789 bool
790 handle(Proposal const& p)
791 {
792 // Only relay untrusted proposals on the same ledger
793 if (!trusts(p.nodeID()))
794 return p.prevLedger() == lastClosedLedger.id();
795
796 // TODO: This always suppresses relay of peer positions already seen
797 // Should it allow forwarding if for a recent ledger ?
798 auto& dest = peerPositions[p.prevLedger()];
799 if (std::find(dest.begin(), dest.end(), p) != dest.end())
800 return false;
801
802 dest.push_back(p);
803
804 // Rely on consensus to decide whether to relay
805 return consensus.peerProposal(now(), Position{p});
806 }
807
808 bool
809 handle(TxSet const& txs)
810 {
811 bool const inserted =
812 txSets.insert(std::make_pair(txs.id(), txs)).second;
813 if (inserted)
814 consensus.gotTxSet(now(), txs);
815 // relay only if new
816 return inserted;
817 }
818
819 bool
820 handle(Tx const& tx)
821 {
822 // Ignore and suppress relay of transactions already in last ledger
823 TxSetType const& lastClosedTxs = lastClosedLedger.txs();
824 if (lastClosedTxs.find(tx) != lastClosedTxs.end())
825 return false;
826
827 // only relay if it was new to our open ledger
828 return openTxs.insert(tx).second;
829 }
830
831 bool
833 {
834 // TODO: This is not relaying untrusted validations
835 if (!trusts(v.nodeID()))
836 return false;
837
838 // Will only relay if current
839 return addTrustedValidation(v);
840 }
841
842 bool
844 {
845 return fullyValidatedLedger.seq() > Ledger::Seq{0};
846 }
847
850 {
851 return earliestAllowedSeq();
852 }
853
856 {
858 for (auto const p : trustGraph.trustedPeers(this))
859 keys.insert(p->key);
860 return {quorum, keys};
861 }
862
865 {
866 return validations.laggards(seq, trusted);
867 }
868
869 bool
870 validator() const
871 {
872 return runAsValidator;
873 }
874
875 void
876 updateOperatingMode(std::size_t const positions) const
877 {
878 }
879
880 //--------------------------------------------------------------------------
881 // A locally submitted transaction
882 void
883 submit(Tx const& tx)
884 {
885 issue(SubmitTx{tx});
886 if (handle(tx))
887 share(tx);
888 }
889
890 //--------------------------------------------------------------------------
891 // Simulation "driver" members
892
894 void
896 {
897 consensus.timerEntry(now());
898 // only reschedule if not completed
899 if (completedLedgers < targetLedgers)
900 scheduler.in(parms().ledgerGRANULARITY, [this]() { timerEntry(); });
901 }
902
903 // Called to begin the next round
904 void
906 {
907 // Between rounds, we take the majority ledger
908 // In the future, consider taking peer dominant ledger if no validations
909 // yet
910 Ledger::ID bestLCL =
911 validations.getPreferred(lastClosedLedger, earliestAllowedSeq());
912 if (bestLCL == Ledger::ID{0})
913 bestLCL = lastClosedLedger.id();
914
915 issue(StartRound{bestLCL, lastClosedLedger});
916
917 // Not yet modeling dynamic UNL.
918 hash_set<PeerID> nowUntrusted;
919 consensus.startRound(
920 now(), bestLCL, lastClosedLedger, nowUntrusted, runAsValidator);
921 }
922
923 // Start the consensus process assuming it is not yet running
924 // This runs forever unless targetLedgers is specified
925 void
927 {
928 // TODO: Expire validations less frequently?
929 validations.expire(j);
930 scheduler.in(parms().ledgerGRANULARITY, [&]() { timerEntry(); });
931 startRound();
932 }
933
935 now() const
936 {
937 // We don't care about the actual epochs, but do want the
938 // generated NetClock time to be well past its epoch to ensure
939 // any subtractions of two NetClock::time_point in the consensus
940 // code are positive. (e.g. proposeFRESHNESS)
941 using namespace std::chrono;
942 using namespace std::chrono_literals;
943 return NetClock::time_point(duration_cast<NetClock::duration>(
944 scheduler.now().time_since_epoch() + 86400s + clockSkew));
945 }
946
949 {
950 return consensus.prevLedgerID();
951 }
952
953 //-------------------------------------------------------------------------
954 // Injects a specific transaction when generating the ledger following
955 // the provided sequence. This allows simulating a byzantine failure in
956 // which a node generates the wrong ledger, even when consensus worked
957 // properly.
958 // TODO: Make this more robust
960
971 TxSet
972 injectTxs(Ledger prevLedger, TxSet const& src)
973 {
974 auto const it = txInjections.find(prevLedger.seq());
975
976 if (it == txInjections.end())
977 return src;
978 TxSetType res{src.txs()};
979 res.insert(it->second);
980
981 return TxSet{res};
982 }
983};
984
985} // namespace csf
986} // namespace test
987} // namespace ripple
988#endif
T ceil(T... args)
Decorator for streaming out compact json.
Definition: json_writer.h:317
Represents a JSON value.
Definition: json_value.h:147
A generic endpoint for log messages.
Definition: Journal.h:59
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:288
std::chrono::time_point< NetClock > time_point
Definition: chrono.h:70
Maintains current and recent ledger validations.
Definition: Validations.h:289
std::size_t numTrustedForLedger(ID const &ledgerID)
Count the number of trusted full validations for the given ledger.
Definition: Validations.h:1036
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.
Definition: Validations.h:973
bool canValidateSeq(Seq const s)
Return whether the local node can issue a validation for the given sequence number.
Definition: Validations.h:608
Peer to peer network simulator.
Definition: BasicNetwork.h:84
void send(Peer const &from, Peer const &to, Function &&f)
Send a message to a peer.
Definition: BasicNetwork.h:237
auto links(Peer const &from)
Return the range of active links.
Definition: BasicNetwork.h:185
A container of CollectorRefs.
Definition: CollectorRef.h:324
void on(PeerID node, SimTime when, E const &e)
Definition: CollectorRef.h:337
Oracle maintaining unique ledgers for a simulation.
Definition: ledgers.h:245
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition: ledgers.h:59
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.
Definition: test/csf/Peer.h:62
Proposal const & proposal() const
Definition: test/csf/Peer.h:69
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:79
TxSetType const & txs() const
Definition: Tx.h:140
ID id() const
Definition: Tx.h:146
beast::uhash<>::result_type ID
Definition: Tx.h:81
Tx const * find(Tx::ID const &txId) const
Definition: Tx.h:131
A single transaction.
Definition: Tx.h:38
Validation of a specific ledger by a specific Peer.
Definition: Validation.h:48
Ledger::Seq seq() const
Definition: Validation.h:94
Ledger::ID ledgerID() const
Definition: Validation.h:88
void setSeen(NetClock::time_point seen)
Definition: Validation.h:195
PeerID const & nodeID() const
Definition: Validation.h:118
T end(T... args)
T find(T... args)
T insert(T... args)
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:43
tagged_integer< std::uint32_t, PeerIDTag > PeerID
Definition: Validation.h:35
typename SimClock::duration SimDuration
Definition: SimTime.h:35
boost::container::flat_set< Tx > TxSetType
Definition: Tx.h:75
std::string to_string(TxSetType const &txs)
Definition: Tx.h:211
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
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:38
ValStatus
Status of validation we received.
Definition: Validations.h:168
@ 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.
ConsensusTimer roundTime
Timing parameters to control validation staleness and expiration.
Definition: Validations.h:46
Peer closed the open ledger.
Definition: events.h:109
Peer fully validated a new ledger.
Definition: events.h:138
Simulated delays in internal peer processing.
Definition: test/csf/Peer.h:93
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...
Definition: test/csf/Peer.h:97
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.
Definition: test/csf/Peer.h:55
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 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
void onAccept(Result const &result, Ledger const &prevLedger, NetClock::duration const &closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, Json::Value &&consensusJson)
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 haveValidated() const
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:80
A value relayed to another peer as part of flooding.
Definition: events.h:68
A value to be flooded to all other peers starting from this peer.
Definition: events.h:59
Peer starts a new consensus round.
Definition: events.h:98
A transaction submitted to a peer.
Definition: events.h:90
Peer detected a wrong prior ledger during consensus.
Definition: events.h:129
Set the sequence number on a JTx.
Definition: seq.h:34