rippled
Loading...
Searching...
No Matches
LedgerReplay_test.cpp
1#include <test/jtx.h>
2#include <test/jtx/envconfig.h>
3
4#include <xrpld/app/ledger/BuildLedger.h>
5#include <xrpld/app/ledger/LedgerMaster.h>
6#include <xrpld/app/ledger/LedgerReplay.h>
7#include <xrpld/app/ledger/LedgerReplayTask.h>
8#include <xrpld/app/ledger/LedgerReplayer.h>
9#include <xrpld/app/ledger/detail/LedgerDeltaAcquire.h>
10#include <xrpld/app/ledger/detail/LedgerReplayMsgHandler.h>
11#include <xrpld/app/ledger/detail/SkipListAcquire.h>
12#include <xrpld/overlay/PeerSet.h>
13#include <xrpld/overlay/detail/PeerImp.h>
14
15#include <xrpl/basics/Slice.h>
16
17#include <chrono>
18#include <thread>
19
20namespace xrpl {
21namespace test {
22
24{
25 void
26 run() override
27 {
28 testcase("Replay ledger");
29
30 using namespace jtx;
31
32 // Build a ledger normally
33 auto const alice = Account("alice");
34 auto const bob = Account("bob");
35
36 Env env(*this);
37 env.fund(XRP(100000), alice, bob);
38 env.close();
39
41 auto const lastClosed = ledgerMaster.getClosedLedger();
42 auto const lastClosedParent = ledgerMaster.getLedgerByHash(lastClosed->header().parentHash);
43
44 auto const replayed = buildLedger(
45 LedgerReplay(lastClosedParent, lastClosed), tapNONE, env.app(), env.journal);
46
47 BEAST_EXPECT(replayed->header().hash == lastClosed->header().hash);
48 }
49};
50
52 Good,
53 DropAll,
54};
55
62{
63public:
71 virtual ~MagicInboundLedgers() = default;
72
75 {
77 return {};
78 if (auto l = ledgerSource.getLedgerByHash(hash); l)
79 {
81 return l;
82 }
83
84 return {};
85 }
86
87 virtual void
89 {
90 }
91
93 find(LedgerHash const& hash) override
94 {
95 return {};
96 }
97
98 virtual bool
100 LedgerHash const& ledgerHash,
103 {
104 return false;
105 }
106
107 virtual void
111
112 virtual void
114 {
115 }
116
117 virtual bool
118 isFailure(uint256 const& h) override
119 {
120 return false;
121 }
122
123 virtual void
124 clearFailures() override
125 {
126 }
127
128 virtual Json::Value
129 getInfo() override
130 {
131 return {};
132 }
133
134 virtual std::size_t
135 fetchRate() override
136 {
137 return 0;
138 }
139
140 virtual void
142 {
143 }
144
145 virtual void
146 gotFetchPack() override
147 {
148 }
149 virtual void
150 sweep() override
151 {
152 }
153
154 virtual void
155 stop() override
156 {
157 }
158
159 virtual size_t
160 cacheSize() override
161 {
162 return 0;
163 }
164
168};
169
170enum class PeerFeature {
172 None,
173};
174
180class TestPeer : public Peer
181{
182public:
183 TestPeer(bool enableLedgerReplay)
184 : ledgerReplayEnabled_(enableLedgerReplay)
186 {
187 }
188
189 void
191 {
192 }
194 getRemoteAddress() const override
195 {
196 return {};
197 }
198 void
199 charge(Resource::Charge const& fee, std::string const& context = {}) override
200 {
201 }
202 id_t
203 id() const override
204 {
205 return 1234;
206 }
207 bool
208 cluster() const override
209 {
210 return false;
211 }
212 bool
213 isHighLatency() const override
214 {
215 return false;
216 }
217 int
218 getScore(bool) const override
219 {
220 return 0;
221 }
222 PublicKey const&
223 getNodePublic() const override
224 {
225 return nodePublicKey_;
226 }
228 json() override
229 {
230 return {};
231 }
232 bool
238 publisherListSequence(PublicKey const&) const override
239 {
240 return {};
241 }
242 void
244 {
245 }
246 uint256 const&
247 getClosedLedgerHash() const override
248 {
249 static uint256 const hash{};
250 return hash;
251 }
252 bool
253 hasLedger(uint256 const& hash, std::uint32_t seq) const override
254 {
255 return true;
256 }
257 void
258 ledgerRange(std::uint32_t& minSeq, std::uint32_t& maxSeq) const override
259 {
260 }
261 bool
262 hasTxSet(uint256 const& hash) const override
263 {
264 return false;
265 }
266 void
267 cycleStatus() override
268 {
269 }
270 bool
272 {
273 return false;
274 }
275 bool
276 compressionEnabled() const override
277 {
278 return false;
279 }
280 void
281 sendTxQueue() override
282 {
283 }
284 void
285 addTxQueue(uint256 const&) override
286 {
287 }
288 void
289 removeTxQueue(uint256 const&) override
290 {
291 }
292 bool
293 txReduceRelayEnabled() const override
294 {
295 return false;
296 }
297
298 std::string const&
299 fingerprint() const override
300 {
301 return fingerprint_;
302 }
303
307};
308
309enum class PeerSetBehavior {
310 Good,
311 Drop50,
312 DropAll,
315 Repeat,
316};
317
324struct TestPeerSet : public PeerSet
325{
329 PeerSetBehavior bhvr,
330 bool enableLedgerReplay)
331 : local(me)
332 , remote(other)
333 , dummyPeer(std::make_shared<TestPeer>(enableLedgerReplay))
334 , behavior(bhvr)
335 {
336 }
337
338 void
340 std::size_t limit,
341 std::function<bool(std::shared_ptr<Peer> const&)> hasItem,
342 std::function<void(std::shared_ptr<Peer> const&)> onPeerAdded) override
343 {
344 hasItem(dummyPeer);
345 onPeerAdded(dummyPeer);
346 }
347
348 void
350 ::google::protobuf::Message const& msg,
351 protocol::MessageType type,
352 std::shared_ptr<Peer> const& peer) override
353 {
354 int dropRate = 0;
356 {
357 dropRate = 50;
358 }
360 {
361 dropRate = 100;
362 }
363
364 if (((rand() % 100) + 1) <= dropRate)
365 return;
366
367 switch (type)
368 {
369 case protocol::mtPROOF_PATH_REQ: {
371 return;
373 dynamic_cast<protocol::TMProofPathRequest const&>(msg));
379 break;
380 }
381 case protocol::mtREPLAY_DELTA_REQ: {
383 return;
385 dynamic_cast<protocol::TMReplayDeltaRequest const&>(msg));
391 break;
392 }
393 default:
394 return;
395 }
396 }
397
399 getPeerIds() const override
400 {
401 static std::set<Peer::id_t> const emptyPeers;
402 return emptyPeers;
403 }
404
409};
410
441
447{
449 {
451 int initAccounts = 10;
452 int initAmount = 1'000'000;
454 int txAmount = 10;
455 };
456
458 : env(suite)
459 , app(env.app())
460 , ledgerMaster(env.app().getLedgerMaster())
461 , msgHandler(env.app(), env.app().getLedgerReplayer())
462 , param(p)
463 {
464 assert(param.initLedgers > 0);
468 }
469
473 void
474 createAccounts(int newAccounts)
475 {
476 auto fundedAccounts = accounts.size();
477 for (int i = 0; i < newAccounts; ++i)
478 {
479 accounts.emplace_back("alice_" + std::to_string(fundedAccounts + i));
481 }
482 env.close();
483 }
484
488 void
489 sendPayments(int newTxes)
490 {
491 int fundedAccounts = accounts.size();
492 assert(fundedAccounts >= newTxes);
494
495 // somewhat random but reproducible
496 int r = ledgerMaster.getClosedLedger()->seq() * 7;
497 int fromIdx = 0;
498 int toIdx = 0;
499 auto updateIdx = [&]() {
500 assert(fundedAccounts > senders.size());
501 fromIdx = (fromIdx + r) % fundedAccounts;
502 while (senders.contains(fromIdx))
503 fromIdx = (fromIdx + 1) % fundedAccounts;
504 senders.insert(fromIdx);
505 toIdx = (toIdx + r * 2) % fundedAccounts;
506 if (toIdx == fromIdx)
507 toIdx = (toIdx + 1) % fundedAccounts;
508 };
509
510 for (int i = 0; i < newTxes; ++i)
511 {
512 updateIdx();
513 env(pay(accounts[fromIdx],
514 accounts[toIdx],
515 jtx::drops(ledgerMaster.getClosedLedger()->fees().base) +
520 }
521 env.close();
522 }
523
527 void
529 {
530 for (int i = 0; i < param.initLedgers - 1; ++i)
531 {
533 }
534 }
535
542};
543
544enum class TaskStatus {
545 Failed,
546 Completed,
547 NotDone,
548 NotExist,
549};
550
559{
560public:
563 LedgerServer& server,
567 : env(suite, jtx::envconfig(), nullptr, beast::severities::kDisabled)
568 , app(env.app())
569 , ledgerMaster(env.app().getLedgerMaster())
570 , inboundLedgers(server.app.getLedgerMaster(), ledgerMaster, inboundBhvr)
571 , serverMsgHandler(server.app, server.app.getLedgerReplayer())
573 , replayer(
574 env.app(),
576 std::make_unique<TestPeerSetBuilder>(
579 behavior,
580 peerFeature))
581 {
582 }
583
584 void
589
590 bool
591 haveLedgers(uint256 const& finishLedgerHash, int totalReplay)
592 {
593 uint256 hash = finishLedgerHash;
594 int i = 0;
595 for (; i < totalReplay; ++i)
596 {
597 auto const l = ledgerMaster.getLedgerByHash(hash);
598 if (!l)
599 return false;
600 hash = l->header().parentHash;
601 }
602 return true;
603 }
604
605 bool
606 waitForLedgers(uint256 const& finishLedgerHash, int totalReplay)
607 {
608 int const totalRound = 100;
609 for (int i = 0; i < totalRound; ++i)
610 {
611 if (haveLedgers(finishLedgerHash, totalReplay))
612 return true;
613 if (i < totalRound - 1)
615 }
616 return false;
617 }
618
619 bool
621 {
622 int const totalRound = 100;
623 for (int i = 0; i < totalRound; ++i)
624 {
625 bool allDone = true;
626 {
628 for (auto const& t : replayer.tasks_)
629 {
630 if (!t->finished())
631 {
632 allDone = false;
633 break;
634 }
635 }
636 }
637 if (allDone)
638 return true;
639 if (i < totalRound - 1)
641 }
642 return false;
643 }
644
647 {
649 return replayer.tasks_;
650 }
651
653 findTask(uint256 const& hash, int totalReplay)
654 {
656 auto i = std::find_if(replayer.tasks_.begin(), replayer.tasks_.end(), [&](auto const& t) {
657 return t->parameter_.finishHash_ == hash && t->parameter_.totalLedgers_ == totalReplay;
658 });
659 if (i == replayer.tasks_.end())
660 return {};
661 return *i;
662 }
663
666 {
668 return replayer.deltas_.size();
669 }
670
673 {
675 return replayer.skipLists_.size();
676 }
677
678 bool
680 {
682 return replayer.tasks_.size() == tasks && replayer.skipLists_.size() == skipLists &&
683 replayer.deltas_.size() == deltas;
684 }
685
688 {
690 auto i = replayer.skipLists_.find(hash);
691 if (i == replayer.skipLists_.end())
692 return {};
693 return i->second.lock();
694 }
695
698 {
700 auto i = replayer.deltas_.find(hash);
701 if (i == replayer.deltas_.end())
702 return {};
703 return i->second.lock();
704 }
705
706 template <typename T>
709 {
710 if (t->failed_)
711 return TaskStatus::Failed;
712 if (t->complete_)
714 return TaskStatus::NotDone;
715 }
716
717 bool
720 TaskStatus taskExpect,
721 TaskStatus skiplistExpect,
722 std::vector<TaskStatus> const& deltaExpects)
723 {
724 if (taskStatus(task) == taskExpect)
725 {
726 if (taskStatus(task->skipListAcquirer_) == skiplistExpect)
727 {
728 if (task->deltas_.size() == deltaExpects.size())
729 {
730 for (int i = 0; i < deltaExpects.size(); ++i)
731 {
732 if (taskStatus(task->deltas_[i]) != deltaExpects[i])
733 return false;
734 }
735 return true;
736 }
737 }
738 }
739 return false;
740 }
741
742 bool
744 uint256 const& hash,
745 int totalReplay,
746 TaskStatus taskExpect,
747 TaskStatus skiplistExpect,
748 std::vector<TaskStatus> const& deltaExpects)
749 {
750 auto t = findTask(hash, totalReplay);
751 if (!t)
752 {
753 return taskExpect == TaskStatus::NotExist;
754 }
755
756 return asExpected(t, taskExpect, skiplistExpect, deltaExpects);
757 }
758
759 bool
761 uint256 const& hash,
762 int totalReplay,
763 TaskStatus taskExpect,
764 TaskStatus skiplistExpect,
765 std::vector<TaskStatus> const& deltaExpects)
766 {
767 auto t = findTask(hash, totalReplay);
768 if (!t)
769 {
770 return taskExpect == TaskStatus::NotExist;
771 }
772
773 return asExpected(t, taskExpect, skiplistExpect, deltaExpects);
774 }
775
776 bool
778 uint256 const& hash,
779 int totalReplay,
780 TaskStatus taskExpect,
781 TaskStatus skiplistExpect,
782 std::vector<TaskStatus> const& deltaExpects)
783 {
784 if (!waitForDone())
785 return false;
786
787 return checkStatus(hash, totalReplay, taskExpect, skiplistExpect, deltaExpects);
788 }
789
797};
798
799using namespace beast::severities;
800void
802 LedgerServer& server,
803 LedgerReplayClient& client,
804 beast::severities::Severity level = Severity::kTrace)
805{
806 server.app.getLogs().threshold(level);
807 client.app.getLogs().threshold(level);
808}
809// logAll(net.server, net.client);
810
811/*
812 * Create a LedgerServer and a LedgerReplayClient
813 */
815{
818 LedgerServer::Parameter const& param,
822 : server(suite, param), client(suite, server, behavior, inboundBhvr, peerFeature)
823 {
824 // logAll(server, client);
825 }
828};
829
856{
857 void
859 {
860 testcase("ProofPath");
861 LedgerServer server(*this, {1});
862 auto const l = server.ledgerMaster.getClosedLedger();
863
864 {
865 // request, missing key
867 request->set_ledgerhash(l->header().hash.data(), l->header().hash.size());
868 request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE);
870 server.msgHandler.processProofPathRequest(request));
871 BEAST_EXPECT(reply->has_error());
872 BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply));
873 }
874 {
875 // request, wrong hash
877 request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE);
878 request->set_key(keylet::skip().key.data(), keylet::skip().key.size());
879 uint256 hash(1234567);
880 request->set_ledgerhash(hash.data(), hash.size());
882 server.msgHandler.processProofPathRequest(request));
883 BEAST_EXPECT(reply->has_error());
884 }
885
886 {
887 // good request
889 request->set_ledgerhash(l->header().hash.data(), l->header().hash.size());
890 request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE);
891 request->set_key(keylet::skip().key.data(), keylet::skip().key.size());
892 // generate response
894 server.msgHandler.processProofPathRequest(request));
895 BEAST_EXPECT(!reply->has_error());
896 BEAST_EXPECT(server.msgHandler.processProofPathResponse(reply));
897
898 {
899 // bad reply
900 // bad header
901 std::string r(reply->ledgerheader());
902 r.back()--;
903 reply->set_ledgerheader(r);
904 BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply));
905 r.back()++;
906 reply->set_ledgerheader(r);
907 BEAST_EXPECT(server.msgHandler.processProofPathResponse(reply));
908 // bad proof path
909 reply->mutable_path()->RemoveLast();
910 BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply));
911 }
912 }
913 }
914
915 void
917 {
918 testcase("ReplayDelta");
919 LedgerServer server(*this, {1});
920 auto const l = server.ledgerMaster.getClosedLedger();
921
922 {
923 // request, missing hash
926 server.msgHandler.processReplayDeltaRequest(request));
927 BEAST_EXPECT(reply->has_error());
928 BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply));
929 // request, wrong hash
930 uint256 hash(1234567);
931 request->set_ledgerhash(hash.data(), hash.size());
933 server.msgHandler.processReplayDeltaRequest(request));
934 BEAST_EXPECT(reply->has_error());
935 BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply));
936 }
937
938 {
939 // good request
941 request->set_ledgerhash(l->header().hash.data(), l->header().hash.size());
943 server.msgHandler.processReplayDeltaRequest(request));
944 BEAST_EXPECT(!reply->has_error());
945 BEAST_EXPECT(server.msgHandler.processReplayDeltaResponse(reply));
946
947 {
948 // bad reply
949 // bad header
950 std::string r(reply->ledgerheader());
951 r.back()--;
952 reply->set_ledgerheader(r);
953 BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply));
954 r.back()++;
955 reply->set_ledgerheader(r);
956 BEAST_EXPECT(server.msgHandler.processReplayDeltaResponse(reply));
957 // bad txns
958 reply->mutable_transaction()->RemoveLast();
959 BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply));
960 }
961 }
962 }
963
964 void
966 {
967 testcase("TaskParameter");
968
969 auto makeSkipList = [](int count) -> std::vector<uint256> {
971 sList.reserve(count);
972 for (int i = 0; i < count; ++i)
973 sList.emplace_back(i);
974 return sList;
975 };
976
978 BEAST_EXPECT(!tp10.update(uint256(777), 5, makeSkipList(10)));
979 BEAST_EXPECT(!tp10.update(uint256(10), 5, makeSkipList(8)));
980 BEAST_EXPECT(tp10.update(uint256(10), 10, makeSkipList(10)));
981
982 // can merge to self
983 BEAST_EXPECT(tp10.canMergeInto(tp10));
984
985 // smaller task
987
988 BEAST_EXPECT(tp9.canMergeInto(tp10));
989 BEAST_EXPECT(!tp10.canMergeInto(tp9));
990
991 tp9.totalLedgers_++;
992 BEAST_EXPECT(!tp9.canMergeInto(tp10));
993 tp9.totalLedgers_--;
994 BEAST_EXPECT(tp9.canMergeInto(tp10));
995
997 BEAST_EXPECT(!tp9.canMergeInto(tp10));
999 BEAST_EXPECT(tp9.canMergeInto(tp10));
1000
1001 tp9.finishHash_ = uint256(1234);
1002 BEAST_EXPECT(!tp9.canMergeInto(tp10));
1003 tp9.finishHash_ = uint256(9);
1004 BEAST_EXPECT(tp9.canMergeInto(tp10));
1005
1006 // larger task
1008 BEAST_EXPECT(tp20.update(uint256(20), 20, makeSkipList(20)));
1009 BEAST_EXPECT(tp10.canMergeInto(tp20));
1010 BEAST_EXPECT(tp9.canMergeInto(tp20));
1011 BEAST_EXPECT(!tp20.canMergeInto(tp10));
1012 BEAST_EXPECT(!tp20.canMergeInto(tp9));
1013 }
1014
1015 void
1017 {
1018 testcase("config test");
1019 {
1020 Config const c;
1021 BEAST_EXPECT(c.LEDGER_REPLAY == false);
1022 }
1023
1024 {
1025 Config c;
1026 std::string const toLoad(R"rippleConfig(
1027[ledger_replay]
10281
1029)rippleConfig");
1030 c.loadFromString(toLoad);
1031 BEAST_EXPECT(c.LEDGER_REPLAY == true);
1032 }
1033
1034 {
1035 Config c;
1036 std::string const toLoad = (R"rippleConfig(
1037[ledger_replay]
10380
1039)rippleConfig");
1040 c.loadFromString(toLoad);
1041 BEAST_EXPECT(c.LEDGER_REPLAY == false);
1042 }
1043 }
1044
1045 void
1047 {
1048 testcase("handshake test");
1049 auto handshake = [&](bool client, bool server, bool expecting) -> bool {
1050 auto request = xrpl::makeRequest(true, false, client, false, false);
1051 http_request_type http_request;
1052 http_request.version(request.version());
1053 http_request.base() = request.base();
1054 bool const serverResult =
1055 peerFeatureEnabled(http_request, FEATURE_LEDGER_REPLAY, server);
1056 if (serverResult != expecting)
1057 return false;
1058
1059 beast::IP::Address const addr = boost::asio::ip::make_address("172.1.1.100");
1060 jtx::Env serverEnv(*this);
1061 serverEnv.app().config().LEDGER_REPLAY = server;
1062 auto http_resp = xrpl::makeResponse(
1063 true, http_request, addr, addr, uint256{1}, 1, {1, 0}, serverEnv.app());
1064 auto const clientResult = peerFeatureEnabled(http_resp, FEATURE_LEDGER_REPLAY, client);
1065 return clientResult == expecting;
1066 };
1067
1068 BEAST_EXPECT(handshake(false, false, false));
1069 BEAST_EXPECT(handshake(false, true, false));
1070 BEAST_EXPECT(handshake(true, false, false));
1071 BEAST_EXPECT(handshake(true, true, true));
1072 }
1073
1074 void
1075 testAllLocal(int totalReplay)
1076 {
1077 testcase("local node has all the ledgers");
1078 auto psBhvr = PeerSetBehavior::DropAll;
1079 auto ilBhvr = InboundLedgersBehavior::DropAll;
1080 auto peerFeature = PeerFeature::None;
1081
1082 NetworkOfTwo net(*this, {totalReplay + 1}, psBhvr, ilBhvr, peerFeature);
1083
1084 auto l = net.server.ledgerMaster.getClosedLedger();
1085 uint256 const finalHash = l->header().hash;
1086 for (int i = 0; i < totalReplay; ++i)
1087 {
1088 BEAST_EXPECT(l);
1089 if (l)
1090 {
1091 net.client.ledgerMaster.storeLedger(l);
1092 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1093 }
1094 else
1095 {
1096 break;
1097 }
1098 }
1099
1100 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1101
1102 std::vector<TaskStatus> const deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1103 BEAST_EXPECT(net.client.waitAndCheckStatus(
1104 finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses));
1105
1106 // sweep
1107 net.client.replayer.sweep();
1108 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1109 }
1110
1111 void
1112 testAllInboundLedgers(int totalReplay)
1113 {
1114 testcase("all the ledgers from InboundLedgers");
1115 NetworkOfTwo net(
1116 *this,
1117 {totalReplay + 1},
1121
1122 auto l = net.server.ledgerMaster.getClosedLedger();
1123 uint256 const finalHash = l->header().hash;
1124 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1125
1126 std::vector<TaskStatus> const deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1127 BEAST_EXPECT(net.client.waitAndCheckStatus(
1128 finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses));
1129
1130 // sweep() cleans up skipLists_ and deltas_ by removing entries whose
1131 // weak_ptr can no longer be locked. Those weak_ptrs expire only when the
1132 // last shared_ptr holder releases the sub-task. The sole owner is the
1133 // LedgerReplayTask, but a JobQueue worker thread may still hold a
1134 // temporary shared_ptr to a sub-task (from wptr.lock()) while executing
1135 // the timer job that drove the task to completion. If sweep() runs before
1136 // that thread unwinds, the weak_ptr is still lockable and the map entry
1137 // is not removed. We retry until the worker thread finishes.
1138 auto waitForSweep = [&net]() {
1139 for (auto numAttempts = 0; numAttempts < 20; ++numAttempts)
1140 {
1141 net.client.replayer.sweep();
1142 if (net.client.countsAsExpected(0, 0, 0))
1143 {
1144 return true;
1145 }
1147 }
1148 return false;
1149 };
1150 BEAST_EXPECT(waitForSweep());
1151 }
1152
1153 void
1154 testPeerSetBehavior(PeerSetBehavior peerSetBehavior, int totalReplay = 4)
1155 {
1156 switch (peerSetBehavior)
1157 {
1159 testcase("good network");
1160 break;
1162 testcase("network drops 50% messages");
1163 break;
1165 testcase("network repeats all messages");
1166 break;
1167 default:
1168 return;
1169 }
1170
1171 NetworkOfTwo net(
1172 *this,
1173 {totalReplay + 1},
1174 peerSetBehavior,
1177
1178 // feed client with start ledger since InboundLedgers drops all
1179 auto l = net.server.ledgerMaster.getClosedLedger();
1180 uint256 const finalHash = l->header().hash;
1181 for (int i = 0; i < totalReplay - 1; ++i)
1182 {
1183 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1184 }
1185 net.client.ledgerMaster.storeLedger(l);
1186
1187 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1188
1189 std::vector<TaskStatus> const deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1190 BEAST_EXPECT(net.client.waitAndCheckStatus(
1191 finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses));
1192 BEAST_EXPECT(net.client.waitForLedgers(finalHash, totalReplay));
1193
1194 // sweep
1195 net.client.replayer.sweep();
1196 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1197 }
1198
1199 void
1201 {
1202 testcase("stop before timeout");
1203 int const totalReplay = 3;
1204 NetworkOfTwo net(
1205 *this,
1206 {totalReplay + 1},
1210
1211 auto l = net.server.ledgerMaster.getClosedLedger();
1212 uint256 const finalHash = l->header().hash;
1213 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1214
1215 std::vector<TaskStatus> const deltaStatuses;
1216 BEAST_EXPECT(net.client.checkStatus(
1217 finalHash, totalReplay, TaskStatus::NotDone, TaskStatus::NotDone, deltaStatuses));
1218
1219 BEAST_EXPECT(net.client.countsAsExpected(1, 1, 0));
1220 net.client.replayer.stop();
1221 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1222 }
1223
1224 void
1226 {
1227 testcase("SkipListAcquire bad reply");
1228 int const totalReplay = 3;
1229 NetworkOfTwo net(
1230 *this,
1231 {totalReplay + 1 + 1},
1235
1236 auto l = net.server.ledgerMaster.getClosedLedger();
1237 uint256 const finalHash = l->header().hash;
1238 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1239
1240 auto skipList = net.client.findSkipListAcquire(finalHash);
1241
1242 std::uint8_t payload[55] = {0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08, 0xB2};
1243 auto item = make_shamapitem(uint256(12345), Slice(payload, sizeof(payload)));
1244 skipList->processData(l->seq(), item);
1245
1246 std::vector<TaskStatus> const deltaStatuses;
1247 BEAST_EXPECT(net.client.waitAndCheckStatus(
1248 finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses));
1249
1250 // add another task
1251 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay + 1);
1252 BEAST_EXPECT(net.client.waitAndCheckStatus(
1253 finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses));
1254 BEAST_EXPECT(net.client.countsAsExpected(2, 1, 0));
1255 }
1256
1257 void
1259 {
1260 testcase("LedgerDeltaAcquire bad reply");
1261 int const totalReplay = 3;
1262 NetworkOfTwo net(
1263 *this,
1264 {totalReplay + 1},
1268
1269 auto l = net.server.ledgerMaster.getClosedLedger();
1270 uint256 const finalHash = l->header().hash;
1271 net.client.ledgerMaster.storeLedger(l);
1272 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1273
1274 auto delta = net.client.findLedgerDeltaAcquire(l->header().parentHash);
1275 delta->processData(
1276 l->header(), // wrong ledger info
1278 BEAST_EXPECT(net.client.taskStatus(delta) == TaskStatus::Failed);
1279 BEAST_EXPECT(
1280 net.client.taskStatus(net.client.findTask(finalHash, totalReplay)) ==
1282
1283 // add another task
1284 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay + 1);
1285 BEAST_EXPECT(
1286 net.client.taskStatus(net.client.findTask(finalHash, totalReplay + 1)) ==
1288 }
1289
1290 void
1292 {
1293 testcase("Overlap tasks");
1294 int const totalReplay = 5;
1295 NetworkOfTwo net(
1296 *this,
1297 {(totalReplay * 3) + 1},
1301 auto l = net.server.ledgerMaster.getClosedLedger();
1302 uint256 const finalHash = l->header().hash;
1303 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1304 std::vector<TaskStatus> deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1305 BEAST_EXPECT(net.client.waitAndCheckStatus(
1306 finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses));
1307 BEAST_EXPECT(net.client.waitForLedgers(finalHash, totalReplay));
1308
1309 // same range, same reason
1310 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1311 BEAST_EXPECT(net.client.countsAsExpected(1, 1, totalReplay - 1));
1312 // same range, different reason
1313 net.client.replayer.replay(InboundLedger::Reason::CONSENSUS, finalHash, totalReplay);
1314 BEAST_EXPECT(net.client.countsAsExpected(2, 1, totalReplay - 1));
1315
1316 // no overlap
1317 for (int i = 0; i < totalReplay + 2; ++i)
1318 {
1319 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1320 }
1321 auto finalHash_early = l->header().hash;
1322 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash_early, totalReplay);
1323 BEAST_EXPECT(net.client.waitAndCheckStatus(
1324 finalHash_early,
1325 totalReplay,
1328 deltaStatuses)); // deltaStatuses no change
1329 BEAST_EXPECT(net.client.waitForLedgers(finalHash_early, totalReplay));
1330 BEAST_EXPECT(net.client.countsAsExpected(3, 2, 2 * (totalReplay - 1)));
1331
1332 // partial overlap
1333 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1334 auto finalHash_moreEarly = l->header().parentHash;
1335 net.client.replayer.replay(
1336 InboundLedger::Reason::GENERIC, finalHash_moreEarly, totalReplay);
1337 BEAST_EXPECT(net.client.waitAndCheckStatus(
1338 finalHash_moreEarly,
1339 totalReplay,
1342 deltaStatuses)); // deltaStatuses no change
1343 BEAST_EXPECT(net.client.waitForLedgers(finalHash_moreEarly, totalReplay));
1344 BEAST_EXPECT(net.client.countsAsExpected(4, 3, (2 * (totalReplay - 1)) + 2));
1345
1346 // cover
1347 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay * 3);
1348 deltaStatuses = std::vector<TaskStatus>((totalReplay * 3) - 1, TaskStatus::Completed);
1349 BEAST_EXPECT(net.client.waitAndCheckStatus(
1350 finalHash,
1351 totalReplay * 3,
1354 deltaStatuses)); // deltaStatuses changed
1355 BEAST_EXPECT(net.client.waitForLedgers(finalHash, totalReplay * 3));
1356 BEAST_EXPECT(net.client.countsAsExpected(5, 3, (totalReplay * 3) - 1));
1357
1358 // sweep
1359 net.client.replayer.sweep();
1360 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1361 }
1362
1363 void
1384};
1385
1387{
1388 void
1390 {
1391 testcase("SkipListAcquire timeout");
1392 int const totalReplay = 3;
1393 NetworkOfTwo net(
1394 *this,
1395 {totalReplay + 1},
1399
1400 auto l = net.server.ledgerMaster.getClosedLedger();
1401 uint256 const finalHash = l->header().hash;
1402 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1403
1404 std::vector<TaskStatus> const deltaStatuses;
1405 BEAST_EXPECT(net.client.waitAndCheckStatus(
1406 finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses));
1407
1408 // sweep
1409 BEAST_EXPECT(net.client.countsAsExpected(1, 1, 0));
1410 net.client.replayer.sweep();
1411 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1412 }
1413
1414 void
1416 {
1417 testcase("LedgerDeltaAcquire timeout");
1418 int const totalReplay = 3;
1419 NetworkOfTwo net(
1420 *this,
1421 {totalReplay + 1},
1425
1426 auto l = net.server.ledgerMaster.getClosedLedger();
1427 uint256 const finalHash = l->header().hash;
1428 net.client.ledgerMaster.storeLedger(l);
1429 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1430
1431 std::vector<TaskStatus> deltaStatuses(totalReplay - 1, TaskStatus::Failed);
1432 deltaStatuses.back() = TaskStatus::Completed; // in client ledgerMaster
1433 BEAST_EXPECT(net.client.waitAndCheckStatus(
1434 finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Completed, deltaStatuses));
1435
1436 // sweep
1437 BEAST_EXPECT(net.client.countsAsExpected(1, 1, totalReplay - 1));
1438 net.client.replayer.sweep();
1439 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1440 }
1441
1442 void
1443 run() override
1444 {
1447 }
1448};
1449
1451{
1452 void
1453 run() override
1454 {
1455 testcase("Acquire 1000 ledgers");
1456 int const totalReplay = 250;
1457 int const rounds = 4;
1458 NetworkOfTwo net(
1459 *this,
1460 {(totalReplay * rounds) + 1},
1464
1465 std::vector<uint256> finishHashes;
1466 auto l = net.server.ledgerMaster.getClosedLedger();
1467 for (int i = 0; i < rounds; ++i)
1468 {
1469 finishHashes.push_back(l->header().hash);
1470 for (int j = 0; j < totalReplay; ++j)
1471 {
1472 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1473 }
1474 }
1475 BEAST_EXPECT(finishHashes.size() == rounds);
1476
1477 for (int i = 0; i < rounds; ++i)
1478 {
1479 net.client.replayer.replay(
1480 InboundLedger::Reason::GENERIC, finishHashes[i], totalReplay);
1481 }
1482
1483 std::vector<TaskStatus> const deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1484 for (int i = 0; i < rounds; ++i)
1485 {
1486 BEAST_EXPECT(net.client.waitAndCheckStatus(
1487 finishHashes[i],
1488 totalReplay,
1491 deltaStatuses));
1492 }
1493
1494 BEAST_EXPECT(net.client.waitForLedgers(finishHashes[0], totalReplay * rounds));
1495 BEAST_EXPECT(net.client.countsAsExpected(rounds, rounds, rounds * (totalReplay - 1)));
1496
1497 // sweep
1498 net.client.replayer.sweep();
1499 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1500 }
1501};
1502
1503BEAST_DEFINE_TESTSUITE(LedgerReplay, app, xrpl);
1504BEAST_DEFINE_TESTSUITE_PRIO(LedgerReplayer, app, xrpl, 1);
1505BEAST_DEFINE_TESTSUITE(LedgerReplayerTimeout, app, xrpl);
1506BEAST_DEFINE_TESTSUITE_MANUAL(LedgerReplayerLong, app, xrpl);
1507
1508} // namespace test
1509} // namespace xrpl
T back(T... args)
Represents a JSON value.
Definition json_value.h:130
A version-independent IP address and port combination.
Definition IPEndpoint.h:18
A testsuite class.
Definition suite.h:51
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:150
virtual Config & config()=0
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition Config.cpp:452
bool LEDGER_REPLAY
Definition Config.h:208
Manages the lifetime of inbound ledgers.
bool storeLedger(std::shared_ptr< Ledger const > ledger)
std::shared_ptr< Ledger const > getClosedLedger()
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
bool processProofPathResponse(std::shared_ptr< protocol::TMProofPathResponse > const &msg)
Process TMProofPathResponse.
protocol::TMProofPathResponse processProofPathRequest(std::shared_ptr< protocol::TMProofPathRequest > const &msg)
Process TMProofPathRequest and return TMProofPathResponse.
bool processReplayDeltaResponse(std::shared_ptr< protocol::TMReplayDeltaResponse > const &msg)
Process TMReplayDeltaResponse.
protocol::TMReplayDeltaResponse processReplayDeltaRequest(std::shared_ptr< protocol::TMReplayDeltaRequest > const &msg)
Process TMReplayDeltaRequest and return TMReplayDeltaResponse.
bool update(uint256 const &hash, std::uint32_t seq, std::vector< uint256 > const &sList)
fill all the fields that was not filled during construction
bool canMergeInto(TaskParameter const &existingTask) const
check if this task can be merged into an existing task
Manages the lifetime of ledger replay tasks.
hash_map< uint256, std::weak_ptr< SkipListAcquire > > skipLists_
std::vector< std::shared_ptr< LedgerReplayTask > > tasks_
hash_map< uint256, std::weak_ptr< LedgerDeltaAcquire > > deltas_
beast::severities::Severity threshold() const
Definition Log.cpp:140
Supports data retrieval by managing a set of peers.
Definition PeerSet.h:20
Represents a peer connection in the overlay.
std::uint32_t id_t
Uniquely identifies a peer.
A public key.
Definition PublicKey.h:42
A consumption charge.
Definition Charge.h:10
virtual LedgerMaster & getLedgerMaster()=0
virtual Logs & getLogs()=0
An immutable linear range of bytes.
Definition Slice.h:26
pointer data()
Definition base_uint.h:101
static constexpr std::size_t size()
Definition base_uint.h:499
Ledger replay client side.
TaskStatus taskStatus(std::shared_ptr< T > const &t)
std::vector< std::shared_ptr< LedgerReplayTask > > getTasks()
bool asExpected(uint256 const &hash, int totalReplay, TaskStatus taskExpect, TaskStatus skiplistExpect, std::vector< TaskStatus > const &deltaExpects)
LedgerReplayMsgHandler clientMsgHandler
bool haveLedgers(uint256 const &finishLedgerHash, int totalReplay)
void addLedger(std::shared_ptr< Ledger const > const &l)
std::shared_ptr< SkipListAcquire > findSkipListAcquire(uint256 const &hash)
bool countsAsExpected(std::size_t tasks, std::size_t skipLists, std::size_t deltas)
bool waitForLedgers(uint256 const &finishLedgerHash, int totalReplay)
LedgerReplayMsgHandler serverMsgHandler
LedgerReplayClient(beast::unit_test::suite &suite, LedgerServer &server, PeerSetBehavior behavior=PeerSetBehavior::Good, InboundLedgersBehavior inboundBhvr=InboundLedgersBehavior::Good, PeerFeature peerFeature=PeerFeature::LedgerReplayEnabled)
bool waitAndCheckStatus(uint256 const &hash, int totalReplay, TaskStatus taskExpect, TaskStatus skiplistExpect, std::vector< TaskStatus > const &deltaExpects)
bool asExpected(std::shared_ptr< LedgerReplayTask > const &task, TaskStatus taskExpect, TaskStatus skiplistExpect, std::vector< TaskStatus > const &deltaExpects)
std::shared_ptr< LedgerReplayTask > findTask(uint256 const &hash, int totalReplay)
bool checkStatus(uint256 const &hash, int totalReplay, TaskStatus taskExpect, TaskStatus skiplistExpect, std::vector< TaskStatus > const &deltaExpects)
std::shared_ptr< LedgerDeltaAcquire > findLedgerDeltaAcquire(uint256 const &hash)
Simulate a network InboundLedgers.
virtual size_t cacheSize() override
virtual void logFailure(uint256 const &h, std::uint32_t seq) override
MagicInboundLedgers(LedgerMaster &ledgerSource, LedgerMaster &ledgerSink, InboundLedgersBehavior bhvr)
virtual void gotFetchPack() override
virtual ~MagicInboundLedgers()=default
virtual void acquireAsync(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason reason) override
virtual void clearFailures() override
virtual bool gotLedgerData(LedgerHash const &ledgerHash, std::shared_ptr< Peer >, std::shared_ptr< protocol::TMLedgerData >) override
virtual std::shared_ptr< Ledger const > acquire(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason) override
virtual Json::Value getInfo() override
virtual std::size_t fetchRate() override
Returns the rate of historical ledger fetches per minute.
virtual std::shared_ptr< InboundLedger > find(LedgerHash const &hash) override
virtual void onLedgerFetched() override
Called when a complete ledger is obtained.
virtual bool isFailure(uint256 const &h) override
virtual void gotStaleData(std::shared_ptr< protocol::TMLedgerData > packet) override
LedgerReplayMsgHandler & remote
TestPeerSetBuilder(LedgerReplayMsgHandler &me, LedgerReplayMsgHandler &other, PeerSetBehavior bhvr, PeerFeature peerFeature)
std::unique_ptr< PeerSet > build() override
Simulate a network peer.
uint256 const & getClosedLedgerHash() const override
std::optional< std::size_t > publisherListSequence(PublicKey const &) const override
bool supportsFeature(ProtocolFeature f) const override
PublicKey const & getNodePublic() const override
beast::IP::Endpoint getRemoteAddress() const override
std::string const & fingerprint() const override
void ledgerRange(std::uint32_t &minSeq, std::uint32_t &maxSeq) const override
bool compressionEnabled() const override
void charge(Resource::Charge const &fee, std::string const &context={}) override
Adjust this peer's load balance based on the type of load imposed.
Json::Value json() override
bool hasLedger(uint256 const &hash, std::uint32_t seq) const override
bool txReduceRelayEnabled() const override
TestPeer(bool enableLedgerReplay)
id_t id() const override
bool hasTxSet(uint256 const &hash) const override
int getScore(bool) const override
bool isHighLatency() const override
bool cluster() const override
Returns true if this connection is a member of the cluster.
void addTxQueue(uint256 const &) override
Aggregate transaction's hash.
void removeTxQueue(uint256 const &) override
Remove hash from the transactions' hashes queue.
void send(std::shared_ptr< Message > const &m) override
void sendTxQueue() override
Send aggregated transactions' hashes.
bool hasRange(std::uint32_t uMin, std::uint32_t uMax) override
void setPublisherListSequence(PublicKey const &, std::size_t const) override
Immutable cryptographic account descriptor.
Definition Account.h:19
A transaction testing environment.
Definition Env.h:122
Application & app()
Definition Env.h:259
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:100
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:270
beast::Journal const journal
Definition Env.h:163
Set the fee on a JTx.
Definition fee.h:17
Set the regular signature on a JTx.
Definition sig.h:15
T contains(T... args)
T emplace_back(T... args)
T find_if(T... args)
T insert(T... args)
T is_same_v
boost::asio::ip::address Address
Definition IPAddress.h:19
A namespace for easy access to logging severity values.
Definition Journal.h:10
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:12
STL namespace.
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition Indexes.cpp:177
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:95
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:11
static autofill_t const autofill
Definition tags.h:22
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:34
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
static uint256 ledgerHash(LedgerHeader const &info)
void logAll(LedgerServer &server, LedgerReplayClient &client, beast::severities::Severity level=Severity::kTrace)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
KeyType
Definition KeyType.h:8
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
Definition SHAMapItem.h:139
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:12
auto makeRequest(bool crawlPublic, bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled) -> request_type
Make outbound http request.
base_uint< 256 > uint256
Definition base_uint.h:531
bool peerFeatureEnabled(headers const &request, std::string const &feature, std::string value, bool config)
Check if a feature should be enabled for a peer.
Definition Handshake.h:171
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
std::shared_ptr< Ledger > buildLedger(std::shared_ptr< Ledger const > const &parent, NetClock::time_point closeTime, bool const closeTimeCorrect, NetClock::duration closeResolution, Application &app, CanonicalTXSet &txns, std::set< TxID > &failedTxs, beast::Journal j)
Build a new ledger by applying consensus transactions.
@ tapNONE
Definition ApplyView.h:11
http_response_type makeResponse(bool crawlPublic, http_request_type const &req, beast::IP::Address public_ip, beast::IP::Address remote_ip, uint256 const &sharedValue, std::optional< std::uint32_t > networkID, ProtocolVersion protocol, Application &app)
Make http response.
@ ledgerMaster
ledger master data for signing
static constexpr char FEATURE_LEDGER_REPLAY[]
Definition Handshake.h:124
T push_back(T... args)
T reserve(T... args)
T size(T... args)
T sleep_for(T... args)
uint256 key
Definition Keylet.h:20
void run() override
Runs the suite.
void run() override
Runs the suite.
Test cases: LedgerReplayer_test: – process TMProofPathRequest and TMProofPathResponse – process TMRep...
void run() override
Runs the suite.
void testPeerSetBehavior(PeerSetBehavior peerSetBehavior, int totalReplay=4)
void testAllInboundLedgers(int totalReplay)
Utility class for (1) creating ledgers with txns and (2) providing the ledgers via the ledgerMaster.
std::vector< jtx::Account > accounts
LedgerServer(beast::unit_test::suite &suite, Parameter const &p)
void createLedgerHistory()
create ledger history
LedgerReplayMsgHandler msgHandler
void createAccounts(int newAccounts)
NetworkOfTwo(beast::unit_test::suite &suite, LedgerServer::Parameter const &param, PeerSetBehavior behavior=PeerSetBehavior::Good, InboundLedgersBehavior inboundBhvr=InboundLedgersBehavior::Good, PeerFeature peerFeature=PeerFeature::LedgerReplayEnabled)
Simulate a peerSet that supplies peers to ledger replay subtasks.
std::set< Peer::id_t > const & getPeerIds() const override
get the set of ids of previously added peers
LedgerReplayMsgHandler & local
std::shared_ptr< TestPeer > dummyPeer
TestPeerSet(LedgerReplayMsgHandler &me, LedgerReplayMsgHandler &other, PeerSetBehavior bhvr, bool enableLedgerReplay)
void sendRequest(::google::protobuf::Message const &msg, protocol::MessageType type, std::shared_ptr< Peer > const &peer) override
LedgerReplayMsgHandler & remote
void addPeers(std::size_t limit, std::function< bool(std::shared_ptr< Peer > const &)> hasItem, std::function< void(std::shared_ptr< Peer > const &)> onPeerAdded) override
Try add more peers.
Set the sequence number on a JTx.
Definition seq.h:14
T to_string(T... args)