xrpld
Loading...
Searching...
No Matches
LedgerReplay_test.cpp
1#include <test/jtx/Account.h>
2#include <test/jtx/Env.h>
3#include <test/jtx/amount.h>
4#include <test/jtx/envconfig.h>
5#include <test/jtx/fee.h>
6#include <test/jtx/pay.h>
7#include <test/jtx/seq.h>
8#include <test/jtx/sig.h>
9#include <test/jtx/tags.h>
10
11#include <xrpld/app/ledger/BuildLedger.h>
12#include <xrpld/app/ledger/InboundLedger.h>
13#include <xrpld/app/ledger/LedgerMaster.h>
14#include <xrpld/app/ledger/LedgerReplay.h>
15#include <xrpld/app/ledger/LedgerReplayTask.h>
16#include <xrpld/app/ledger/LedgerReplayer.h>
17#include <xrpld/app/ledger/detail/LedgerDeltaAcquire.h>
18#include <xrpld/app/ledger/detail/LedgerReplayMsgHandler.h>
19#include <xrpld/app/ledger/detail/SkipListAcquire.h>
20#include <xrpld/core/Config.h>
21#include <xrpld/overlay/Message.h>
22#include <xrpld/overlay/Peer.h>
23#include <xrpld/overlay/PeerSet.h>
24#include <xrpld/overlay/detail/Handshake.h>
25
26#include <xrpl/basics/Slice.h>
27#include <xrpl/basics/base_uint.h>
28#include <xrpl/beast/net/IPAddress.h>
29#include <xrpl/beast/net/IPEndpoint.h>
30#include <xrpl/beast/unit_test/suite.h>
31#include <xrpl/beast/utility/Journal.h>
32#include <xrpl/json/json_value.h>
33#include <xrpl/ledger/ApplyView.h>
34#include <xrpl/protocol/Indexes.h>
35#include <xrpl/protocol/KeyType.h>
36#include <xrpl/protocol/PublicKey.h>
37#include <xrpl/protocol/RippleLedgerHash.h>
38#include <xrpl/protocol/SecretKey.h>
39#include <xrpl/resource/Charge.h>
40#include <xrpl/server/Handoff.h>
41#include <xrpl/shamap/SHAMapItem.h>
42
43#include <boost/asio/ip/address.hpp>
44
45#include <google/protobuf/message.h>
46
47#include <xrpl.pb.h>
48
49#include <algorithm>
50#include <cassert>
51#include <chrono>
52#include <cstddef>
53#include <cstdint>
54#include <cstdlib>
55#include <functional>
56#include <map>
57#include <memory>
58#include <mutex>
59#include <optional>
60#include <set>
61#include <string>
62#include <thread>
63#include <unordered_set>
64#include <vector>
65
66namespace xrpl::test {
67
69{
70 void
71 run() override
72 {
73 testcase("Replay ledger");
74
75 using namespace jtx;
76
77 // Build a ledger normally
78 auto const alice = Account("alice");
79 auto const bob = Account("bob");
80
81 Env env(*this);
82 env.fund(XRP(100000), alice, bob);
83 env.close();
84
85 LedgerMaster& ledgerMaster = env.app().getLedgerMaster();
86 auto const lastClosed = ledgerMaster.getClosedLedger();
87 auto const lastClosedParent = ledgerMaster.getLedgerByHash(lastClosed->header().parentHash);
88
89 auto const replayed = buildLedger(
90 LedgerReplay(lastClosedParent, lastClosed), TapNone, env.app(), env.journal);
91
92 BEAST_EXPECT(replayed->header().hash == lastClosed->header().hash);
93 }
94};
95
100
107{
108public:
116 ~MagicInboundLedgers() override = default;
117
120 {
122 return {};
123 if (auto l = ledgerSource.getLedgerByHash(hash); l)
124 {
125 ledgerSink.storeLedger(l);
126 return l;
127 }
128
129 return {};
130 }
131
132 void
133 acquireAsync(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason reason) override
134 {
135 }
136
138 find(LedgerHash const& hash) override
139 {
140 return {};
141 }
142
143 bool
145 LedgerHash const& ledgerHash,
148 {
149 return false;
150 }
151
152 void
156
157 void
158 logFailure(uint256 const& h, std::uint32_t seq) override
159 {
160 }
161
162 bool
163 isFailure(uint256 const& h) override
164 {
165 return false;
166 }
167
168 void
169 clearFailures() override
170 {
171 }
172
174 getInfo() override
175 {
176 return {};
177 }
178
180 fetchRate() override
181 {
182 return 0;
183 }
184
185 void
187 {
188 }
189
190 void
191 gotFetchPack() override
192 {
193 }
194 void
195 sweep() override
196 {
197 }
198
199 void
200 stop() override
201 {
202 }
203
204 size_t
205 cacheSize() override
206 {
207 return 0;
208 }
209
213};
214
219
225class TestPeer : public Peer
226{
227public:
228 TestPeer(bool enableLedgerReplay)
229 : ledgerReplayEnabled_(enableLedgerReplay)
231 {
232 }
233
234 void
236 {
237 }
238 [[nodiscard]] beast::IP::Endpoint
239 getRemoteAddress() const override
240 {
241 return {};
242 }
243 void
244 charge(Resource::Charge const& fee, std::string const& context = {}) override
245 {
246 }
247 [[nodiscard]] id_t
248 id() const override
249 {
250 return 1234;
251 }
252 [[nodiscard]] bool
253 cluster() const override
254 {
255 return false;
256 }
257 [[nodiscard]] bool
258 isHighLatency() const override
259 {
260 return false;
261 }
262 [[nodiscard]] int
263 getScore(bool) const override
264 {
265 return 0;
266 }
267 [[nodiscard]] PublicKey const&
268 getNodePublic() const override
269 {
270 return nodePublicKey_;
271 }
273 json() override
274 {
275 return {};
276 }
277 [[nodiscard]] bool
282 [[nodiscard]] std::optional<std::size_t>
283 publisherListSequence(PublicKey const&) const override
284 {
285 return {};
286 }
287 void
289 {
290 }
291 [[nodiscard]] uint256 const&
292 getClosedLedgerHash() const override
293 {
294 static uint256 const kHash{};
295 return kHash;
296 }
297 [[nodiscard]] bool
298 hasLedger(uint256 const& hash, std::uint32_t seq) const override
299 {
300 return true;
301 }
302 void
303 ledgerRange(std::uint32_t& minSeq, std::uint32_t& maxSeq) const override
304 {
305 }
306 [[nodiscard]] bool
307 hasTxSet(uint256 const& hash) const override
308 {
309 return false;
310 }
311 void
312 cycleStatus() override
313 {
314 }
315 bool
317 {
318 return false;
319 }
320 [[nodiscard]] bool
321 compressionEnabled() const override
322 {
323 return false;
324 }
325 void
326 sendTxQueue() override
327 {
328 }
329 void
330 addTxQueue(uint256 const&) override
331 {
332 }
333 void
334 removeTxQueue(uint256 const&) override
335 {
336 }
337 [[nodiscard]] bool
338 txReduceRelayEnabled() const override
339 {
340 return false;
341 }
342
343 [[nodiscard]] std::string const&
344 fingerprint() const override
345 {
346 return fingerprint_;
347 }
348
349 // NOLINTBEGIN(readability-identifier-naming)
353 // NOLINTEND(readability-identifier-naming)
354};
355
364
371struct TestPeerSet : public PeerSet
372{
376 PeerSetBehavior bhvr,
377 bool enableLedgerReplay)
378 : local(me)
379 , remote(other)
380 , dummyPeer(std::make_shared<TestPeer>(enableLedgerReplay))
381 , behavior(bhvr)
382 {
383 }
384
385 void
387 std::size_t limit,
388 std::function<bool(std::shared_ptr<Peer> const&)> hasItem,
389 std::function<void(std::shared_ptr<Peer> const&)> onPeerAdded) override
390 {
391 hasItem(dummyPeer);
392 onPeerAdded(dummyPeer);
393 }
394
395 void
397 ::google::protobuf::Message const& msg,
398 protocol::MessageType type,
399 std::shared_ptr<Peer> const& peer) override
400 {
401 int dropRate = 0;
403 {
404 dropRate = 50;
405 }
407 {
408 dropRate = 100;
409 }
410
411 if (((rand() % 100) + 1) <= dropRate)
412 return;
413
414 switch (type)
415 {
416 case protocol::mtPROOF_PATH_REQ: {
418 return;
420 dynamic_cast<protocol::TMProofPathRequest const&>(msg));
422 remote.processProofPathRequest(request));
423 local.processProofPathResponse(reply);
425 local.processProofPathResponse(reply);
426 break;
427 }
428 case protocol::mtREPLAY_DELTA_REQ: {
430 return;
432 dynamic_cast<protocol::TMReplayDeltaRequest const&>(msg));
434 remote.processReplayDeltaRequest(request));
435 local.processReplayDeltaResponse(reply);
437 local.processReplayDeltaResponse(reply);
438 break;
439 }
440 default:
441 return;
442 }
443 }
444
445 [[nodiscard]] std::set<Peer::id_t> const&
446 getPeerIds() const override
447 {
448 static std::set<Peer::id_t> const kEmptyPeers;
449 return kEmptyPeers;
450 }
451
456};
457
488
494{
496 {
498 int initAccounts = 10;
499 int initAmount = 1'000'000;
501 int txAmount = 10;
502 };
503
505 : env(suite)
506 , app(env.app())
507 , ledgerMaster(env.app().getLedgerMaster())
508 , msgHandler(env.app(), env.app().getLedgerReplayer())
509 , param(p)
510 {
511 assert(param.initLedgers > 0);
512 createAccounts(param.initAccounts);
514 app.getLogs().threshold(beast::Severity::Warning);
515 }
516
520 void
521 createAccounts(int newAccounts)
522 {
523 auto fundedAccounts = accounts.size();
524 for (int i = 0; i < newAccounts; ++i)
525 {
526 accounts.emplace_back("alice_" + std::to_string(fundedAccounts + i));
527 env.fund(jtx::XRP(param.initAmount), accounts.back());
528 }
529 env.close();
530 }
531
535 void
536 sendPayments(int newTxes)
537 {
538 int fundedAccounts = accounts.size();
539 assert(fundedAccounts >= newTxes);
541
542 // somewhat random but reproducible
543 int r = ledgerMaster.getClosedLedger()->seq() * 7;
544 int fromIdx = 0;
545 int toIdx = 0;
546 auto updateIdx = [&]() {
547 assert(fundedAccounts > senders.size());
548 fromIdx = (fromIdx + r) % fundedAccounts;
549 while (senders.contains(fromIdx))
550 fromIdx = (fromIdx + 1) % fundedAccounts;
551 senders.insert(fromIdx);
552 toIdx = (toIdx + (r * 2)) % fundedAccounts;
553 if (toIdx == fromIdx)
554 toIdx = (toIdx + 1) % fundedAccounts;
555 };
556
557 for (int i = 0; i < newTxes; ++i)
558 {
559 updateIdx();
560 env(pay(accounts[fromIdx],
561 accounts[toIdx],
562 jtx::drops(ledgerMaster.getClosedLedger()->fees().base) +
563 jtx::XRP(param.txAmount)),
567 }
568 env.close();
569 }
570
574 void
576 {
577 for (int i = 0; i < param.initLedgers - 1; ++i)
578 {
579 sendPayments(param.numTxPerLedger);
580 }
581 }
582
589};
590
597
606{
607public:
610 LedgerServer& server,
614 : env(suite, jtx::envconfig(), nullptr, beast::Severity::Disabled)
615 , app(env.app())
616 , ledgerMaster(env.app().getLedgerMaster())
617 , inboundLedgers(server.app.getLedgerMaster(), ledgerMaster, inboundBhvr)
618 , serverMsgHandler(server.app, server.app.getLedgerReplayer())
620 , replayer(
621 env.app(),
623 std::make_unique<TestPeerSetBuilder>(
626 behavior,
627 peerFeature))
628 {
629 }
630
631 void
633 {
634 ledgerMaster.storeLedger(l);
635 }
636
637 bool
638 haveLedgers(uint256 const& finishLedgerHash, int totalReplay)
639 {
640 uint256 hash = finishLedgerHash;
641 int i = 0;
642 for (; i < totalReplay; ++i)
643 {
644 auto const l = ledgerMaster.getLedgerByHash(hash);
645 if (!l)
646 return false;
647 hash = l->header().parentHash;
648 }
649 return true;
650 }
651
652 bool
653 waitForLedgers(uint256 const& finishLedgerHash, int totalReplay)
654 {
655 int const totalRound = 100;
656 for (int i = 0; i < totalRound; ++i)
657 {
658 if (haveLedgers(finishLedgerHash, totalReplay))
659 return true;
660 if (i < totalRound - 1)
662 }
663 return false;
664 }
665
666 bool
668 {
669 int const totalRound = 100;
670 for (int i = 0; i < totalRound; ++i)
671 {
672 bool allDone = true;
673 {
674 std::unique_lock<std::mutex> const lock(replayer.mtx_);
675 for (auto const& t : replayer.tasks_)
676 {
677 if (!t->finished())
678 {
679 allDone = false;
680 break;
681 }
682 }
683 }
684 if (allDone)
685 return true;
686 if (i < totalRound - 1)
688 }
689 return false;
690 }
691
694 {
695 std::unique_lock<std::mutex> const lock(replayer.mtx_);
696 return replayer.tasks_;
697 }
698
700 findTask(uint256 const& hash, int totalReplay)
701 {
702 std::unique_lock<std::mutex> const lock(replayer.mtx_);
703 auto i = std::ranges::find_if(replayer.tasks_, [&](auto const& t) {
704 return t->parameter_.finishHash == hash && t->parameter_.totalLedgers == totalReplay;
705 });
706 if (i == replayer.tasks_.end())
707 return {};
708 return *i;
709 }
710
713 {
714 std::unique_lock<std::mutex> const lock(replayer.mtx_);
715 return replayer.deltas_.size();
716 }
717
720 {
721 std::unique_lock<std::mutex> const lock(replayer.mtx_);
722 return replayer.skipLists_.size();
723 }
724
725 bool
727 {
728 std::unique_lock<std::mutex> const lock(replayer.mtx_);
729 return replayer.tasks_.size() == tasks && replayer.skipLists_.size() == skipLists &&
730 replayer.deltas_.size() == deltas;
731 }
732
735 {
736 std::unique_lock<std::mutex> const lock(replayer.mtx_);
737 auto i = replayer.skipLists_.find(hash);
738 if (i == replayer.skipLists_.end())
739 return {};
740 return i->second.lock();
741 }
742
745 {
746 std::unique_lock<std::mutex> const lock(replayer.mtx_);
747 auto i = replayer.deltas_.find(hash);
748 if (i == replayer.deltas_.end())
749 return {};
750 return i->second.lock();
751 }
752
753 template <typename T>
756 {
757 if (t->failed_)
758 return TaskStatus::Failed;
759 if (t->complete_)
761 return TaskStatus::NotDone;
762 }
763
764 bool
767 TaskStatus taskExpect,
768 TaskStatus skiplistExpect,
769 std::vector<TaskStatus> const& deltaExpects)
770 {
771 if (taskStatus(task) == taskExpect)
772 {
773 if (taskStatus(task->skipListAcquirer_) == skiplistExpect)
774 {
775 if (task->deltas_.size() == deltaExpects.size())
776 {
777 for (int i = 0; i < deltaExpects.size(); ++i)
778 {
779 if (taskStatus(task->deltas_[i]) != deltaExpects[i])
780 return false;
781 }
782 return true;
783 }
784 }
785 }
786 return false;
787 }
788
789 bool
791 uint256 const& hash,
792 int totalReplay,
793 TaskStatus taskExpect,
794 TaskStatus skiplistExpect,
795 std::vector<TaskStatus> const& deltaExpects)
796 {
797 auto t = findTask(hash, totalReplay);
798 if (!t)
799 {
800 return taskExpect == TaskStatus::NotExist;
801 }
802
803 return asExpected(t, taskExpect, skiplistExpect, deltaExpects);
804 }
805
806 bool
808 uint256 const& hash,
809 int totalReplay,
810 TaskStatus taskExpect,
811 TaskStatus skiplistExpect,
812 std::vector<TaskStatus> const& deltaExpects)
813 {
814 auto t = findTask(hash, totalReplay);
815 if (!t)
816 {
817 return taskExpect == TaskStatus::NotExist;
818 }
819
820 return asExpected(t, taskExpect, skiplistExpect, deltaExpects);
821 }
822
823 bool
825 uint256 const& hash,
826 int totalReplay,
827 TaskStatus taskExpect,
828 TaskStatus skiplistExpect,
829 std::vector<TaskStatus> const& deltaExpects)
830 {
831 if (!waitForDone())
832 return false;
833
834 return checkStatus(hash, totalReplay, taskExpect, skiplistExpect, deltaExpects);
835 }
836
844};
845
846using beast::Severity;
847void
848logAll(LedgerServer& server, LedgerReplayClient& client, beast::Severity level = Severity::Trace)
849{
850 server.app.getLogs().threshold(level);
851 client.app.getLogs().threshold(level);
852}
853// logAll(net.server, net.client);
854
855/*
856 * Create a LedgerServer and a LedgerReplayClient
857 */
859{
862 LedgerServer::Parameter const& param,
866 : server(suite, param), client(suite, server, behavior, inboundBhvr, peerFeature)
867 {
868 // logAll(server, client);
869 }
872};
873
898
900{
901 void
903 {
904 testcase("ProofPath");
905 LedgerServer server(*this, {.initLedgers = 1});
906 auto const l = server.ledgerMaster.getClosedLedger();
907
908 {
909 // request, missing key
911 request->set_ledgerhash(l->header().hash.data(), l->header().hash.size());
912 request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE);
914 server.msgHandler.processProofPathRequest(request));
915 BEAST_EXPECT(reply->has_error());
916 BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply));
917 }
918 {
919 // request, wrong hash
921 request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE);
922 request->set_key(keylet::skip().key.data(), keylet::skip().key.size());
923 uint256 hash(1234567);
924 request->set_ledgerhash(hash.data(), hash.size());
926 server.msgHandler.processProofPathRequest(request));
927 BEAST_EXPECT(reply->has_error());
928 }
929
930 {
931 // good request
933 request->set_ledgerhash(l->header().hash.data(), l->header().hash.size());
934 request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE);
935 request->set_key(keylet::skip().key.data(), keylet::skip().key.size());
936 // generate response
938 server.msgHandler.processProofPathRequest(request));
939 BEAST_EXPECT(!reply->has_error());
940 BEAST_EXPECT(server.msgHandler.processProofPathResponse(reply));
941
942 {
943 // bad reply
944 // bad header
945 std::string r(reply->ledgerheader());
946 r.back()--;
947 reply->set_ledgerheader(r);
948 BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply));
949 r.back()++;
950 reply->set_ledgerheader(r);
951 BEAST_EXPECT(server.msgHandler.processProofPathResponse(reply));
952 // bad proof path
953 reply->mutable_path()->RemoveLast();
954 BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply));
955 }
956 }
957 }
958
959 void
961 {
962 testcase("ReplayDelta");
963 LedgerServer server(*this, {.initLedgers = 1});
964 auto const l = server.ledgerMaster.getClosedLedger();
965
966 {
967 // request, missing hash
970 server.msgHandler.processReplayDeltaRequest(request));
971 BEAST_EXPECT(reply->has_error());
972 BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply));
973 // request, wrong hash
974 uint256 hash(1234567);
975 request->set_ledgerhash(hash.data(), hash.size());
977 server.msgHandler.processReplayDeltaRequest(request));
978 BEAST_EXPECT(reply->has_error());
979 BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply));
980 }
981
982 {
983 // good request
985 request->set_ledgerhash(l->header().hash.data(), l->header().hash.size());
987 server.msgHandler.processReplayDeltaRequest(request));
988 BEAST_EXPECT(!reply->has_error());
989 BEAST_EXPECT(server.msgHandler.processReplayDeltaResponse(reply));
990
991 {
992 // bad reply
993 // bad header
994 std::string r(reply->ledgerheader());
995 r.back()--;
996 reply->set_ledgerheader(r);
997 BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply));
998 r.back()++;
999 reply->set_ledgerheader(r);
1000 BEAST_EXPECT(server.msgHandler.processReplayDeltaResponse(reply));
1001 // bad txns
1002 reply->mutable_transaction()->RemoveLast();
1003 BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply));
1004 }
1005 }
1006 }
1007
1008 void
1010 {
1011 testcase("TaskParameter");
1012
1013 auto makeSkipList = [](int count) -> std::vector<uint256> {
1015 sList.reserve(count);
1016 for (int i = 0; i < count; ++i)
1017 sList.emplace_back(i);
1018 return sList;
1019 };
1020
1022 BEAST_EXPECT(!tp10.update(uint256(777), 5, makeSkipList(10)));
1023 BEAST_EXPECT(!tp10.update(uint256(10), 5, makeSkipList(8)));
1024 BEAST_EXPECT(tp10.update(uint256(10), 10, makeSkipList(10)));
1025
1026 // can merge to self
1027 BEAST_EXPECT(tp10.canMergeInto(tp10));
1028
1029 // smaller task
1031
1032 BEAST_EXPECT(tp9.canMergeInto(tp10));
1033 BEAST_EXPECT(!tp10.canMergeInto(tp9));
1034
1035 tp9.totalLedgers++;
1036 BEAST_EXPECT(!tp9.canMergeInto(tp10));
1037 tp9.totalLedgers--;
1038 BEAST_EXPECT(tp9.canMergeInto(tp10));
1039
1041 BEAST_EXPECT(!tp9.canMergeInto(tp10));
1043 BEAST_EXPECT(tp9.canMergeInto(tp10));
1044
1045 tp9.finishHash = uint256(1234);
1046 BEAST_EXPECT(!tp9.canMergeInto(tp10));
1047 tp9.finishHash = uint256(9);
1048 BEAST_EXPECT(tp9.canMergeInto(tp10));
1049
1050 // larger task
1052 BEAST_EXPECT(tp20.update(uint256(20), 20, makeSkipList(20)));
1053 BEAST_EXPECT(tp10.canMergeInto(tp20));
1054 BEAST_EXPECT(tp9.canMergeInto(tp20));
1055 BEAST_EXPECT(!tp20.canMergeInto(tp10));
1056 BEAST_EXPECT(!tp20.canMergeInto(tp9));
1057 }
1058
1059 void
1061 {
1062 testcase("config test");
1063 {
1064 Config const c;
1065 BEAST_EXPECT(c.ledgerReplay == false);
1066 }
1067
1068 {
1069 Config c;
1070 std::string const toLoad(R"xrpldConfig(
1071[ledger_replay]
10721
1073)xrpldConfig");
1074 c.loadFromString(toLoad);
1075 BEAST_EXPECT(c.ledgerReplay == true);
1076 }
1077
1078 {
1079 Config c;
1080 std::string const toLoad = R"xrpldConfig(
1081[ledger_replay]
10820
1083)xrpldConfig";
1085 BEAST_EXPECT(c.ledgerReplay == false);
1086 }
1087 }
1088
1089 void
1091 {
1092 testcase("handshake test");
1093 auto handshake = [&](bool client, bool server, bool expecting) -> bool {
1094 auto request = xrpl::makeRequest(true, false, client, false, false);
1095 http_request_type httpRequest;
1096 httpRequest.version(request.version());
1097 httpRequest.base() = request.base();
1098 bool const serverResult = peerFeatureEnabled(httpRequest, kFeatureLedgerReplay, server);
1099 if (serverResult != expecting)
1100 return false;
1101
1102 beast::IP::Address const addr = boost::asio::ip::make_address("172.1.1.100");
1103 jtx::Env serverEnv(*this);
1104 serverEnv.app().config().ledgerReplay = server;
1105 auto httpResp = xrpl::makeResponse(
1106 true, httpRequest, addr, addr, uint256{1}, 1, {1, 0}, serverEnv.app());
1107 auto const clientResult = peerFeatureEnabled(httpResp, kFeatureLedgerReplay, client);
1108 return clientResult == expecting;
1109 };
1110
1111 BEAST_EXPECT(handshake(false, false, false));
1112 BEAST_EXPECT(handshake(false, true, false));
1113 BEAST_EXPECT(handshake(true, false, false));
1114 BEAST_EXPECT(handshake(true, true, true));
1115 }
1116
1117 void
1118 testAllLocal(int totalReplay)
1119 {
1120 testcase("local node has all the ledgers");
1121 auto psBhvr = PeerSetBehavior::DropAll;
1122 auto ilBhvr = InboundLedgersBehavior::DropAll;
1123 auto peerFeature = PeerFeature::None;
1124
1125 NetworkOfTwo net(*this, {.initLedgers = totalReplay + 1}, psBhvr, ilBhvr, peerFeature);
1126
1127 auto l = net.server.ledgerMaster.getClosedLedger();
1128 uint256 const finalHash = l->header().hash;
1129 for (int i = 0; i < totalReplay; ++i)
1130 {
1131 BEAST_EXPECT(l);
1132 if (l)
1133 {
1134 net.client.ledgerMaster.storeLedger(l);
1135 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1136 }
1137 else
1138 {
1139 break;
1140 }
1141 }
1142
1143 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1144
1145 std::vector<TaskStatus> const deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1146 BEAST_EXPECT(net.client.waitAndCheckStatus(
1147 finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses));
1148
1149 // sweep
1150 net.client.replayer.sweep();
1151 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1152 }
1153
1154 void
1155 testAllInboundLedgers(int totalReplay)
1156 {
1157 testcase("all the ledgers from InboundLedgers");
1158 NetworkOfTwo net(
1159 *this,
1160 {.initLedgers = totalReplay + 1},
1164
1165 auto l = net.server.ledgerMaster.getClosedLedger();
1166 uint256 const finalHash = l->header().hash;
1167 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1168
1169 std::vector<TaskStatus> const deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1170 BEAST_EXPECT(net.client.waitAndCheckStatus(
1171 finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses));
1172
1173 // sweep() cleans up skipLists_ and deltas_ by removing entries whose
1174 // weak_ptr can no longer be locked. Those weak_ptrs expire only when the
1175 // last shared_ptr holder releases the sub-task. The sole owner is the
1176 // LedgerReplayTask, but a JobQueue worker thread may still hold a
1177 // temporary shared_ptr to a sub-task (from wptr.lock()) while executing
1178 // the timer job that drove the task to completion. If sweep() runs before
1179 // that thread unwinds, the weak_ptr is still lockable and the map entry
1180 // is not removed. We retry until the worker thread finishes.
1181 auto waitForSweep = [&net]() {
1182 for (auto numAttempts = 0; numAttempts < 20; ++numAttempts)
1183 {
1184 net.client.replayer.sweep();
1185 if (net.client.countsAsExpected(0, 0, 0))
1186 {
1187 return true;
1188 }
1190 }
1191 return false;
1192 };
1193 BEAST_EXPECT(waitForSweep());
1194 }
1195
1196 void
1197 testPeerSetBehavior(PeerSetBehavior peerSetBehavior, int totalReplay = 4)
1198 {
1199 switch (peerSetBehavior)
1200 {
1202 testcase("good network");
1203 break;
1205 testcase("network drops 50% messages");
1206 break;
1208 testcase("network repeats all messages");
1209 break;
1210 default:
1211 return;
1212 }
1213
1214 NetworkOfTwo net(
1215 *this,
1216 {.initLedgers = totalReplay + 1},
1217 peerSetBehavior,
1220
1221 // feed client with start ledger since InboundLedgers drops all
1222 auto l = net.server.ledgerMaster.getClosedLedger();
1223 uint256 const finalHash = l->header().hash;
1224 for (int i = 0; i < totalReplay - 1; ++i)
1225 {
1226 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1227 }
1228 net.client.ledgerMaster.storeLedger(l);
1229
1230 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1231
1232 std::vector<TaskStatus> const deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1233 BEAST_EXPECT(net.client.waitAndCheckStatus(
1234 finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses));
1235 BEAST_EXPECT(net.client.waitForLedgers(finalHash, totalReplay));
1236
1237 // sweep
1238 net.client.replayer.sweep();
1239 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1240 }
1241
1242 void
1243 testStop()
1244 {
1245 testcase("stop before timeout");
1246 int const totalReplay = 3;
1247 NetworkOfTwo net(
1248 *this,
1249 {.initLedgers = totalReplay + 1},
1253
1254 auto l = net.server.ledgerMaster.getClosedLedger();
1255 uint256 const finalHash = l->header().hash;
1256 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1257
1258 std::vector<TaskStatus> const deltaStatuses;
1259 BEAST_EXPECT(net.client.checkStatus(
1260 finalHash, totalReplay, TaskStatus::NotDone, TaskStatus::NotDone, deltaStatuses));
1261
1262 BEAST_EXPECT(net.client.countsAsExpected(1, 1, 0));
1263 net.client.replayer.stop();
1264 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1265 }
1266
1267 void
1269 {
1270 testcase("SkipListAcquire bad reply");
1271 int const totalReplay = 3;
1272 NetworkOfTwo net(
1273 *this,
1274 {.initLedgers = totalReplay + 1 + 1},
1278
1279 auto l = net.server.ledgerMaster.getClosedLedger();
1280 uint256 const finalHash = l->header().hash;
1281 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1282
1283 auto skipList = net.client.findSkipListAcquire(finalHash);
1284
1285 std::uint8_t payload[55] = {0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08, 0xB2};
1286 auto item = makeShamapitem(uint256(12345), Slice(payload, sizeof(payload)));
1287 skipList->processData(l->seq(), item);
1288
1289 std::vector<TaskStatus> const deltaStatuses;
1290 BEAST_EXPECT(net.client.waitAndCheckStatus(
1291 finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses));
1292
1293 // add another task
1294 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay + 1);
1295 BEAST_EXPECT(net.client.waitAndCheckStatus(
1296 finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses));
1297 BEAST_EXPECT(net.client.countsAsExpected(2, 1, 0));
1298 }
1299
1300 void
1302 {
1303 testcase("LedgerDeltaAcquire bad reply");
1304 int const totalReplay = 3;
1305 NetworkOfTwo net(
1306 *this,
1307 {.initLedgers = totalReplay + 1},
1311
1312 auto l = net.server.ledgerMaster.getClosedLedger();
1313 uint256 const finalHash = l->header().hash;
1314 net.client.ledgerMaster.storeLedger(l);
1315 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1316
1317 auto delta = net.client.findLedgerDeltaAcquire(l->header().parentHash);
1318 delta->processData(
1319 l->header(), // wrong ledger info
1321 BEAST_EXPECT(net.client.taskStatus(delta) == TaskStatus::Failed);
1322 BEAST_EXPECT(
1323 net.client.taskStatus(net.client.findTask(finalHash, totalReplay)) ==
1325
1326 // add another task
1327 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay + 1);
1328 BEAST_EXPECT(
1329 net.client.taskStatus(net.client.findTask(finalHash, totalReplay + 1)) ==
1331 }
1332
1333 void
1335 {
1336 testcase("Overlap tasks");
1337 int const totalReplay = 5;
1338 NetworkOfTwo net(
1339 *this,
1340 {.initLedgers = (totalReplay * 3) + 1},
1344 auto l = net.server.ledgerMaster.getClosedLedger();
1345 uint256 const finalHash = l->header().hash;
1346 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1347 std::vector<TaskStatus> deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1348 BEAST_EXPECT(net.client.waitAndCheckStatus(
1349 finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses));
1350 BEAST_EXPECT(net.client.waitForLedgers(finalHash, totalReplay));
1351
1352 // same range, same reason
1353 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1354 BEAST_EXPECT(net.client.countsAsExpected(1, 1, totalReplay - 1));
1355 // same range, different reason
1356 net.client.replayer.replay(InboundLedger::Reason::CONSENSUS, finalHash, totalReplay);
1357 BEAST_EXPECT(net.client.countsAsExpected(2, 1, totalReplay - 1));
1358
1359 // no overlap
1360 for (int i = 0; i < totalReplay + 2; ++i)
1361 {
1362 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1363 }
1364 auto finalHashEarly = l->header().hash;
1365 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHashEarly, totalReplay);
1366 BEAST_EXPECT(net.client.waitAndCheckStatus(
1367 finalHashEarly,
1368 totalReplay,
1371 deltaStatuses)); // deltaStatuses no change
1372 BEAST_EXPECT(net.client.waitForLedgers(finalHashEarly, totalReplay));
1373 BEAST_EXPECT(net.client.countsAsExpected(3, 2, 2 * (totalReplay - 1)));
1374
1375 // partial overlap
1376 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1377 auto finalHashMoreEarly = l->header().parentHash;
1378 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHashMoreEarly, totalReplay);
1379 BEAST_EXPECT(net.client.waitAndCheckStatus(
1380 finalHashMoreEarly,
1381 totalReplay,
1384 deltaStatuses)); // deltaStatuses no change
1385 BEAST_EXPECT(net.client.waitForLedgers(finalHashMoreEarly, totalReplay));
1386 BEAST_EXPECT(net.client.countsAsExpected(4, 3, (2 * (totalReplay - 1)) + 2));
1387
1388 // cover
1389 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay * 3);
1390 deltaStatuses = std::vector<TaskStatus>((totalReplay * 3) - 1, TaskStatus::Completed);
1391 BEAST_EXPECT(net.client.waitAndCheckStatus(
1392 finalHash,
1393 totalReplay * 3,
1396 deltaStatuses)); // deltaStatuses changed
1397 BEAST_EXPECT(net.client.waitForLedgers(finalHash, totalReplay * 3));
1398 BEAST_EXPECT(net.client.countsAsExpected(5, 3, (totalReplay * 3) - 1));
1399
1400 // sweep
1401 net.client.replayer.sweep();
1402 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1403 }
1404
1405 void
1406 run() override
1407 {
1408 testProofPath();
1411 testConfig();
1412 testHandshake();
1413 testAllLocal(1);
1414 testAllLocal(3);
1421 testStop();
1425 }
1426};
1427
1429{
1430 void
1432 {
1433 testcase("SkipListAcquire timeout");
1434 int const totalReplay = 3;
1435 NetworkOfTwo net(
1436 *this,
1437 {.initLedgers = totalReplay + 1},
1441
1442 auto l = net.server.ledgerMaster.getClosedLedger();
1443 uint256 const finalHash = l->header().hash;
1444 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1445
1446 std::vector<TaskStatus> const deltaStatuses;
1447 BEAST_EXPECT(net.client.waitAndCheckStatus(
1448 finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses));
1449
1450 // sweep
1451 BEAST_EXPECT(net.client.countsAsExpected(1, 1, 0));
1452 net.client.replayer.sweep();
1453 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1454 }
1455
1456 void
1458 {
1459 testcase("LedgerDeltaAcquire timeout");
1460 int const totalReplay = 3;
1461 NetworkOfTwo net(
1462 *this,
1463 {.initLedgers = totalReplay + 1},
1467
1468 auto l = net.server.ledgerMaster.getClosedLedger();
1469 uint256 const finalHash = l->header().hash;
1470 net.client.ledgerMaster.storeLedger(l);
1471 net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay);
1472
1473 std::vector<TaskStatus> deltaStatuses(totalReplay - 1, TaskStatus::Failed);
1474 deltaStatuses.back() = TaskStatus::Completed; // in client ledgerMaster
1475 BEAST_EXPECT(net.client.waitAndCheckStatus(
1476 finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Completed, deltaStatuses));
1477
1478 // sweep
1479 BEAST_EXPECT(net.client.countsAsExpected(1, 1, totalReplay - 1));
1480 net.client.replayer.sweep();
1481 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1482 }
1483
1484 void
1485 run() override
1486 {
1489 }
1490};
1491
1493{
1494 void
1495 run() override
1496 {
1497 testcase("Acquire 1000 ledgers");
1498 int const totalReplay = 250;
1499 int const rounds = 4;
1500 NetworkOfTwo net(
1501 *this,
1502 {.initLedgers = (totalReplay * rounds) + 1},
1506
1507 std::vector<uint256> finishHashes;
1508 auto l = net.server.ledgerMaster.getClosedLedger();
1509 for (int i = 0; i < rounds; ++i)
1510 {
1511 finishHashes.push_back(l->header().hash);
1512 for (int j = 0; j < totalReplay; ++j)
1513 {
1514 l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash);
1515 }
1516 }
1517 BEAST_EXPECT(finishHashes.size() == rounds);
1518
1519 for (int i = 0; i < rounds; ++i)
1520 {
1521 net.client.replayer.replay(
1522 InboundLedger::Reason::GENERIC, finishHashes[i], totalReplay);
1523 }
1524
1525 std::vector<TaskStatus> const deltaStatuses(totalReplay - 1, TaskStatus::Completed);
1526 for (int i = 0; i < rounds; ++i)
1527 {
1528 BEAST_EXPECT(net.client.waitAndCheckStatus(
1529 finishHashes[i],
1530 totalReplay,
1533 deltaStatuses));
1534 }
1535
1536 BEAST_EXPECT(net.client.waitForLedgers(finishHashes[0], totalReplay * rounds));
1537 BEAST_EXPECT(net.client.countsAsExpected(rounds, rounds, rounds * (totalReplay - 1)));
1538
1539 // sweep
1540 net.client.replayer.sweep();
1541 BEAST_EXPECT(net.client.countsAsExpected(0, 0, 0));
1542 }
1543};
1544
1547BEAST_DEFINE_TESTSUITE(LedgerReplayerTimeout, app, xrpl);
1548BEAST_DEFINE_TESTSUITE_MANUAL(LedgerReplayerLong, app, xrpl);
1549
1550} // namespace xrpl::test
T back(T... args)
A version-independent IP address and port combination.
Definition IPEndpoint.h:17
A testsuite class.
Definition suite.h:50
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
Represents a JSON value.
Definition json_value.h:130
pointer data()
Definition base_uint.h:106
static constexpr std::size_t size()
Definition base_uint.h:530
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition Config.cpp:473
bool ledgerReplay
Definition Config.h:208
Manages the lifetime of inbound ledgers.
std::shared_ptr< Ledger const > getClosedLedger()
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
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.
beast::Severity threshold() const
Definition Log.cpp:143
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:9
virtual LedgerMaster & getLedgerMaster()=0
virtual Logs & getLogs()=0
Ledger replay client side.
LedgerReplayClient(beast::unit_test::Suite &suite, LedgerServer &server, PeerSetBehavior behavior=PeerSetBehavior::Good, InboundLedgersBehavior inboundBhvr=InboundLedgersBehavior::Good, PeerFeature peerFeature=PeerFeature::LedgerReplayEnabled)
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
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.
std::shared_ptr< Ledger const > acquire(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason) override
void acquireAsync(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason reason) override
bool gotLedgerData(LedgerHash const &ledgerHash, std::shared_ptr< Peer >, std::shared_ptr< protocol::TMLedgerData >) override
MagicInboundLedgers(LedgerMaster &ledgerSource, LedgerMaster &ledgerSink, InboundLedgersBehavior bhvr)
void onLedgerFetched() override
Called when a complete ledger is obtained.
std::shared_ptr< InboundLedger > find(LedgerHash const &hash) override
~MagicInboundLedgers() override=default
std::size_t fetchRate() override
Returns the rate of historical ledger fetches per minute.
void logFailure(uint256 const &h, std::uint32_t seq) override
bool isFailure(uint256 const &h) override
void gotStaleData(std::shared_ptr< protocol::TMLedgerData > packet) override
LedgerReplayMsgHandler & local_
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
A transaction testing environment.
Definition Env.h:143
Application & app()
Definition Env.h:280
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:133
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:296
beast::Journal const journal
Definition Env.h:184
Set the fee on a JTx.
Definition fee.h:15
Set the regular signature on a JTx.
Definition sig.h:13
T contains(T... args)
T emplace_back(T... args)
T find_if(T... args)
T insert(T... args)
T make_shared(T... args)
T make_unique(T... args)
boost::asio::ip::address Address
Definition IPAddress.h:19
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:11
STL namespace.
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition Indexes.cpp:198
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:14
XrpT const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:28
static AutofillT const kAutofill
Definition tags.h:15
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
void logAll(LedgerServer &server, LedgerReplayClient &client, beast::Severity level=Severity::Trace)
static uint256 ledgerHash(LedgerHeader const &info)
BEAST_DEFINE_TESTSUITE_MANUAL(AMMCalc, app, xrpl)
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, xrpl, 2)
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.
static constexpr char kFeatureLedgerReplay[]
Definition Handshake.h:124
auto makeRequest(bool crawlPublic, bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled) -> request_type
Make outbound http request.
boost::intrusive_ptr< SHAMapItem > makeShamapitem(uint256 const &tag, Slice data)
Definition SHAMapItem.h:139
uint256 LedgerHash
http_response_type makeResponse(bool crawlPublic, http_request_type const &req, beast::IP::Address publicIp, beast::IP::Address remoteIp, uint256 const &sharedValue, std::optional< std::uint32_t > networkID, ProtocolVersion protocol, Application &app)
Make http response.
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:13
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
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:12
BaseUInt< 256 > uint256
Definition base_uint.h:562
T reserve(T... args)
T size(T... args)
T sleep_for(T... args)
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)
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:12
T to_string(T... args)