xrpld
Loading...
Searching...
No Matches
Application.cpp
1#include <xrpld/app/main/Application.h>
2
3#include <xrpld/app/consensus/RCLValidations.h>
4#include <xrpld/app/ledger/InboundLedger.h>
5#include <xrpld/app/ledger/InboundLedgers.h>
6#include <xrpld/app/ledger/InboundTransactions.h>
7#include <xrpld/app/ledger/LedgerCleaner.h>
8#include <xrpld/app/ledger/LedgerMaster.h>
9#include <xrpld/app/ledger/LedgerPersistence.h>
10#include <xrpld/app/ledger/LedgerReplay.h>
11#include <xrpld/app/ledger/LedgerReplayer.h>
12#include <xrpld/app/ledger/LedgerToJson.h>
13#include <xrpld/app/ledger/OpenLedger.h>
14#include <xrpld/app/ledger/OrderBookDBImpl.h>
15#include <xrpld/app/ledger/TransactionMaster.h>
16#include <xrpld/app/main/BasicApp.h>
17#include <xrpld/app/main/CollectorManager.h>
18#include <xrpld/app/main/GRPCServer.h>
19#include <xrpld/app/main/LoadManager.h>
20#include <xrpld/app/main/NodeIdentity.h>
21#include <xrpld/app/main/NodeStoreScheduler.h>
22#include <xrpld/app/misc/SHAMapStore.h>
23#include <xrpld/app/misc/TxQ.h>
24#include <xrpld/app/misc/ValidatorKeys.h>
25#include <xrpld/app/misc/ValidatorSite.h>
26#include <xrpld/app/misc/make_NetworkOPs.h>
27#include <xrpld/app/misc/setup_HashRouter.h>
28#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
29#include <xrpld/core/Config.h>
30#include <xrpld/core/NetworkIDServiceImpl.h>
31#include <xrpld/overlay/Cluster.h>
32#include <xrpld/overlay/PeerSet.h>
33#include <xrpld/overlay/make_Overlay.h>
34#include <xrpld/rpc/Context.h>
35#include <xrpld/rpc/RPCHandler.h>
36#include <xrpld/rpc/Role.h>
37#include <xrpld/rpc/ServerHandler.h>
38#include <xrpld/rpc/detail/PathRequestManager.h>
39#include <xrpld/rpc/detail/Pathfinder.h>
40#include <xrpld/shamap/NodeFamily.h>
41
42#include <xrpl/basics/ByteUtilities.h>
43#include <xrpl/basics/Log.h>
44#include <xrpl/basics/MallocTrim.h>
45#include <xrpl/basics/ResolverAsio.h>
46#include <xrpl/basics/ToString.h>
47#include <xrpl/basics/base_uint.h>
48#include <xrpl/basics/chrono.h>
49#include <xrpl/basics/contract.h>
50#include <xrpl/basics/random.h>
51#include <xrpl/beast/asio/io_latency_probe.h>
52#include <xrpl/beast/core/LexicalCast.h>
53#include <xrpl/beast/insight/Event.h>
54#include <xrpl/beast/utility/Journal.h>
55#include <xrpl/beast/utility/PropertyStream.h>
56#include <xrpl/beast/utility/instrumentation.h>
57#include <xrpl/config/BasicConfig.h>
58#include <xrpl/config/Constants.h>
59#include <xrpl/core/ClosureCounter.h>
60#include <xrpl/core/HashRouter.h>
61#include <xrpl/core/Job.h>
62#include <xrpl/core/NetworkIDService.h>
63#include <xrpl/core/PeerReservationTable.h>
64#include <xrpl/core/PerfLog.h>
65#include <xrpl/core/StartUpType.h>
66#include <xrpl/crypto/csprng.h>
67#include <xrpl/json/json_forwards.h>
68#include <xrpl/json/json_reader.h>
69#include <xrpl/json/json_value.h>
70#include <xrpl/ledger/AmendmentTable.h>
71#include <xrpl/ledger/Ledger.h>
72#include <xrpl/ledger/OpenView.h>
73#include <xrpl/ledger/PendingSaves.h>
74#include <xrpl/nodestore/Database.h>
75#include <xrpl/nodestore/DummyScheduler.h>
76#include <xrpl/nodestore/NodeObject.h>
77#include <xrpl/protocol/AccountID.h>
78#include <xrpl/protocol/ApiVersion.h>
79#include <xrpl/protocol/BuildInfo.h>
80#include <xrpl/protocol/Feature.h>
81#include <xrpl/protocol/Indexes.h>
82#include <xrpl/protocol/Protocol.h>
83#include <xrpl/protocol/STParsedJSON.h>
84#include <xrpl/protocol/Serializer.h>
85#include <xrpl/protocol/SystemParameters.h>
86#include <xrpl/protocol/jss.h>
87#include <xrpl/rdb/DatabaseCon.h>
88#include <xrpl/resource/Charge.h>
89#include <xrpl/resource/Consumer.h>
90#include <xrpl/resource/Fees.h>
91#include <xrpl/resource/ResourceManager.h>
92#include <xrpl/server/LoadFeeTrack.h>
93#include <xrpl/server/NetworkOPs.h>
94#include <xrpl/server/Wallet.h>
95#include <xrpl/server/detail/ServerImpl.h>
96#include <xrpl/shamap/FullBelowCache.h>
97#include <xrpl/shamap/SHAMap.h>
98#include <xrpl/shamap/SHAMapMissingNode.h>
99#include <xrpl/shamap/TreeNodeCache.h>
100#include <xrpl/tx/apply.h>
101
102#include <boost/algorithm/string/predicate.hpp>
103#include <boost/asio/error.hpp>
104#include <boost/asio/io_context.hpp>
105#include <boost/asio/signal_set.hpp>
106#include <boost/asio/steady_timer.hpp>
107#include <boost/lexical_cast/bad_lexical_cast.hpp>
108#include <boost/program_options/variables_map.hpp>
109#include <boost/system/detail/errc.hpp>
110#include <boost/system/detail/error_code.hpp>
111#include <boost/system/system_error.hpp>
112
113#include <date/date.h>
114
115#include <algorithm>
116#include <atomic>
117#include <chrono>
118#include <csignal>
119#include <cstdint>
120#include <cstring>
121#include <exception>
122#include <fstream>
123#include <functional>
124#include <ios>
125#include <iostream>
126#include <limits>
127#include <memory>
128#include <optional>
129#include <ostream>
130#include <string>
131#include <thread>
132#include <utility>
133#include <vector>
134
135namespace xrpl {
136
137static void
138fixConfigPorts(Config& config, Endpoints const& endpoints);
139
140// VFALCO TODO Move the function definitions into the class declaration
141class ApplicationImp : public Application, public BasicApp
142{
143private:
145 {
146 private:
151
152 public:
155 beast::Journal journal,
157 boost::asio::io_context& ios)
158 : event_(std::move(ev)), journal_(journal), probe_(interval, ios)
159 {
160 }
161
162 void
164 {
165 probe_.sample(std::ref(*this));
166 }
167
168 template <class Duration>
169 void
170 operator()(Duration const& elapsed)
171 {
172 using namespace std::chrono;
173 auto const lastSample = ceil<milliseconds>(elapsed);
174
175 lastSample_ = lastSample;
176
177 if (lastSample >= 10ms)
178 event_.notify(lastSample);
179 if (lastSample >= 500ms)
180 {
181 JLOG(journal_.warn()) << "io_context latency = " << lastSample.count();
182 }
183 }
184
185 [[nodiscard]] std::chrono::milliseconds
186 get() const
187 {
188 return lastSample_.load();
189 }
190
191 void
193 {
194 probe_.cancel();
195 }
196
197 void
199 {
200 probe_.cancelAsync();
201 }
202 };
203
204public:
205 // NOLINTBEGIN(readability-identifier-naming)
209
211
215
216 // Required by the SHAMapStore
218
225
231
233
259 boost::asio::steady_timer sweepTimer_;
260 boost::asio::steady_timer entropyTimer_;
261
266
267 boost::asio::signal_set signals_;
268
270
272
274
276
278 // NOLINTEND(readability-identifier-naming)
279
280 //--------------------------------------------------------------------------
281
282 static std::size_t
284 {
285#if XRPL_SINGLE_IO_SERVICE_THREAD
286 return 1;
287#else
288
289 if (config.ioWorkers > 0)
290 return config.ioWorkers;
291
292 auto const cores = std::thread::hardware_concurrency();
293
294 // Use a single thread when running on under-provisioned systems
295 // or if we are configured to use minimal resources.
296 if ((cores == 1) || ((config.nodeSize == 0) && (cores == 2)))
297 return 1;
298
299 // Otherwise, prefer six threads.
300 return 6;
301#endif
302 }
303
304 //--------------------------------------------------------------------------
305
311 , config_(std::move(config))
312 , logs_(std::move(logs))
313 , timeKeeper_(std::move(timeKeeper))
315 , journal_(logs_->journal("Application"))
316 // PerfLog must be started before any other threads are launched.
317 , perfLog_(
318 perf::makePerfLog(
319 perf::setupPerfLog(config_->section(Sections::kPerf), config_->configDir),
320 *this,
321 logs_->journal("PerfLog"),
322 [this] { signalStop("PerfLog"); }))
323 , txMaster_(*this)
325 config_->section(Sections::kInsight),
326 logs_->journal("Collector")))
327 , jobQueue_(
331 return 1;
332
333 if (config->workers)
334 return config->workers;
335
336 auto count = static_cast<int>(std::thread::hardware_concurrency());
337
338 // Be more aggressive about the number of threads to use
339 // for the job queue if the server is configured as
340 // "large" or "huge" if there are enough cores.
341 if (config->nodeSize >= 4 && count >= 16)
342 {
343 count = 6 + std::min(count, 8);
344 }
345 else if (config->nodeSize >= 3 && count >= 8)
346 {
347 count = 4 + std::min(count, 6);
348 }
349 else
350 {
351 count = 2 + std::min(count, 4);
352 }
353
354 return count;
355 }(config_),
356 collectorManager_->group("jobq"),
357 logs_->journal("JobQueue"),
358 *logs_,
359 *perfLog_))
361 , shaMapStore_(makeSHAMapStore(*this, nodeStoreScheduler_, logs_->journal("SHAMapStore")))
363 "NodeCache",
364 16384,
365 std::chrono::seconds{90},
366 stopwatch(),
367 logs_->journal("TaggedCache"))
368 , cachedSLEs_(
369 "Cached SLEs",
370 0,
371 std::chrono::minutes(1),
372 stopwatch(),
373 logs_->journal("CachedSLEs"))
377 Resource::makeManager(collectorManager_->collector(), logs_->journal("Resource")))
378 , nodeStore_(shaMapStore_->makeNodeStore(
379 config_->prefetchWorkers > 0 ? config_->prefetchWorkers : 4))
382 *this,
383 {.pathSearchMax = config_->pathSearchMax, .standalone = config_->standalone()}))
386 *this,
387 logs_->journal("PathRequest"),
388 collectorManager_->collector()))
391 *this,
392 stopwatch(),
393 collectorManager_->collector(),
394 logs_->journal("LedgerMaster")))
395 , ledgerCleaner_(makeLedgerCleaner(*this, logs_->journal("LedgerCleaner")))
396
397 // VFALCO NOTE must come before NetworkOPs to prevent a crash due
398 // to dependencies in the destructor.
399 //
402 *this,
403 collectorManager_->collector(),
404 [this](std::shared_ptr<SHAMap> const& set, bool fromAcquire) {
405 gotTXSet(set, fromAcquire);
406 }))
410 "AcceptedLedger",
411 4,
412 std::chrono::minutes{1},
413 stopwatch(),
414 logs_->journal("TaggedCache"))
416 *this,
417 stopwatch(),
418 config_->standalone(),
419 config_->networkQuorum,
420 config_->startValid,
421 *jobQueue_,
424 getIoContext(),
425 logs_->journal("NetworkOPs"),
426 collectorManager_->collector()))
427 , cluster_(std::make_unique<Cluster>(logs_->journal("Overlay")))
429 std::make_unique<PeerReservationTable>(logs_->journal("PeerReservationTable")))
430 , validatorManifests_(std::make_unique<ManifestCache>(logs_->journal("ManifestCache")))
431 , publisherManifests_(std::make_unique<ManifestCache>(logs_->journal("ManifestCache")))
432 , validators_(
437 config_->legacy("database_path"),
438 logs_->journal("ValidatorList"),
439 config_->validationQuorum))
442 *this,
443 getIoContext(),
444 *jobQueue_,
448 , feeTrack_(std::make_unique<LoadFeeTrack>(logs_->journal("LoadManager")))
450 , validations_(ValidationParms(), stopwatch(), *this, logs_->journal("Validations"))
451 , loadManager_(makeLoadManager(*this, logs_->journal("LoadManager")))
452 , txQ_(std::make_unique<TxQ>(setupTxQ(*config_), logs_->journal("TxQ")))
456 , checkSigs_(true)
457 , resolver_(ResolverAsio::make(getIoContext(), logs_->journal("Resolver")))
459 collectorManager_->collector()->makeEvent("ios_latency"),
460 logs_->journal("Application"),
461 std::chrono::milliseconds(100),
462 getIoContext())
464 {
466
467 add(resourceManager_.get());
468
469 //
470 // VFALCO - READ THIS!
471 //
472 // Do not start threads, open sockets, or do any sort of "real work"
473 // inside the constructor. Put it in start instead. Or if you must,
474 // put it in setup (but everything in setup should be moved to start
475 // anyway.
476 //
477 // The reason is that the unit tests require an Application object to
478 // be created. But we don't actually start all the threads, sockets,
479 // and services when running the unit tests. Therefore anything which
480 // needs to be stopped will not get stopped correctly if it is
481 // started in this constructor.
482 //
483
484 add(ledgerCleaner_.get());
485 }
486
487 //--------------------------------------------------------------------------
488
489 bool
490 setup(boost::program_options::variables_map const& cmdline) override;
491 void
492 start(bool withTimers) override;
493 void
494 run() override;
495 void
496 signalStop(std::string const& msg) override;
497 bool
498 checkSigs() const override;
499 void
500 checkSigs(bool) override;
501 bool
502 isStopping() const override;
503 int
504 fdRequired() const override;
505
506 //--------------------------------------------------------------------------
507
508 std::uint64_t
509 instanceID() const override
510 {
511 return instanceCookie_;
512 }
513
514 Logs&
515 getLogs() override
516 {
517 return *logs_;
518 }
519
520 Config&
521 config() override
522 {
523 return *config_;
524 }
525
528 {
529 return *collectorManager_;
530 }
531
532 Family&
533 getNodeFamily() override
534 {
535 return nodeFamily_;
536 }
537
539 getTimeKeeper() override
540 {
541 return *timeKeeper_;
542 }
543
544 JobQueue&
545 getJobQueue() override
546 {
547 return *jobQueue_;
548 }
549
551 nodeIdentity() override
552 {
553 if (nodeIdentity_)
554 return *nodeIdentity_;
555
556 logicError("Accessing Application::nodeIdentity() before it is initialized.");
557 }
558
560 getValidationPublicKey() const override
561 {
562 if (!validatorKeys_.keys)
563 return {};
564
565 return validatorKeys_.keys->publicKey;
566 }
567
569 getOPs() override
570 {
571 return *networkOPs_;
572 }
573
576 {
577 XRPL_ASSERT(
579 "xrpl::ApplicationImp::getServerHandler : non-null server "
580 "handle");
581 return *serverHandler_;
582 }
583
584 boost::asio::io_context&
585 getIOContext() override
586 {
587 return getIoContext();
588 }
589
591 getIOLatency() override
592 {
593 return io_latency_sampler_.get();
594 }
595
598 {
599 return *ledgerMaster_;
600 }
601
604 {
605 return *ledgerCleaner_;
606 }
607
610 {
611 return *ledgerReplayer_;
612 }
613
616 {
617 return *inboundLedgers_;
618 }
619
622 {
623 return *inboundTransactions_;
624 }
625
628 {
630 }
631
632 void
633 gotTXSet(std::shared_ptr<SHAMap> const& set, bool fromAcquire) const
634 {
635 if (set)
636 networkOPs_->mapComplete(set, fromAcquire);
637 }
638
641 {
642 return txMaster_;
643 }
644
646 getPerfLog() override
647 {
648 return *perfLog_;
649 }
650
651 NodeCache&
653 {
654 return tempNodeCache_;
655 }
656
658 getNodeStore() override
659 {
660 return *nodeStore_;
661 }
662
664 getMasterMutex() override
665 {
666 return masterMutex_;
667 }
668
670 getLoadManager() override
671 {
672 return *loadManager_;
673 }
674
677 {
678 return *resourceManager_;
679 }
680
682 getOrderBookDB() override
683 {
684 return *orderBookDB_;
685 }
686
689 {
690 return *pathRequestManager_;
691 }
692
694 getCachedSLEs() override
695 {
696 return cachedSLEs_;
697 }
698
701 {
702 return *networkIDService_;
703 }
704
707 {
708 return *amendmentTable_;
709 }
710
712 getFeeTrack() override
713 {
714 return *feeTrack_;
715 }
716
718 getHashRouter() override
719 {
720 return *hashRouter_;
721 }
722
724 getValidations() override
725 {
726 return validations_;
727 }
728
730 getValidators() override
731 {
732 return *validators_;
733 }
734
737 {
738 return *validatorSites_;
739 }
740
743 {
744 return *validatorManifests_;
745 }
746
749 {
750 return *publisherManifests_;
751 }
752
753 Cluster&
754 getCluster() override
755 {
756 return *cluster_;
757 }
758
761 {
762 return *peerReservations_;
763 }
764
766 getSHAMapStore() override
767 {
768 return *shaMapStore_;
769 }
770
773 {
774 return pendingSaves_;
775 }
776
778 getOpenLedger() override
779 {
780 return *openLedger_; // NOLINT(bugprone-unchecked-optional-access) emplaced during
781 // initialization before any caller
782 }
783
784 OpenLedger const&
785 getOpenLedger() const override
786 {
787 return *openLedger_; // NOLINT(bugprone-unchecked-optional-access) emplaced during
788 // initialization before any caller
789 }
790
791 Overlay&
792 getOverlay() override
793 {
794 XRPL_ASSERT(overlay_, "xrpl::ApplicationImp::overlay : non-null overlay");
795 return *overlay_; // NOLINT(bugprone-unchecked-optional-access) assert above
796 }
797
798 TxQ&
799 getTxQ() override
800 {
801 XRPL_ASSERT(txQ_, "xrpl::ApplicationImp::getTxQ : non-null transaction queue");
802 return *txQ_; // NOLINT(bugprone-unchecked-optional-access) assert above
803 }
804
807 {
808 XRPL_ASSERT(
810 "xrpl::ApplicationImp::getRelationalDatabase : non-null relational database");
811 return *relationalDatabase_; // NOLINT(bugprone-unchecked-optional-access) assert above
812 }
813
815 getWalletDB() override
816 {
817 XRPL_ASSERT(walletDB_, "xrpl::ApplicationImp::getWalletDB : non-null wallet database");
818 return *walletDB_;
819 }
820
821 bool
822 serverOkay(std::string& reason) override;
823
825 getJournal(std::string const& name) override;
826
827 //--------------------------------------------------------------------------
828
829 bool
831 {
832 XRPL_ASSERT(
833 walletDB_.get() == nullptr,
834 "xrpl::ApplicationImp::initRelationalDatabase : null wallet "
835 "database");
836
837 try
838 {
840
841 // wallet database
843 setup.useGlobalPragma = false;
844
846 }
847 catch (std::exception const& e)
848 {
849 JLOG(journal_.fatal()) << "Failed to initialize SQL databases: " << e.what();
850 return false;
851 }
852
853 return true;
854 }
855
856 bool
858 {
859 if (config_->doImport)
860 {
861 auto j = logs_->journal("NodeObject");
862 NodeStore::DummyScheduler dummyScheduler;
865 megabytes(config_->getValueFor(SizedItem::BurstSize, std::nullopt)),
866 dummyScheduler,
867 0,
869 j);
870
871 JLOG(j.warn()) << "Starting node import from '" << source->getName() << "' to '"
872 << nodeStore_->getName() << "'.";
873
874 using namespace std::chrono;
875 auto const start = steady_clock::now();
876
877 nodeStore_->importDatabase(*source);
878
879 auto const elapsed = duration_cast<seconds>(steady_clock::now() - start);
880 JLOG(j.warn()) << "Node import from '" << source->getName() << "' took "
881 << elapsed.count() << " seconds.";
882 }
883
884 return true;
885 }
886
887 //--------------------------------------------------------------------------
888 //
889 // PropertyStream
890 //
891
892 void
894 {
895 }
896
897 //--------------------------------------------------------------------------
898
899 void
901 {
902 // Only start the timer if waitHandlerCounter_ is not yet joined.
903 if (auto optionalCountedHandler =
904 waitHandlerCounter_.wrap([this](boost::system::error_code const& e) {
905 if (e.value() == boost::system::errc::success)
906 {
907 jobQueue_->addJob(JtSweep, "sweep", [this]() { doSweep(); });
908 }
909 // Recover as best we can if an unexpected error occurs.
910 if (e.value() != boost::system::errc::success &&
911 e.value() != boost::asio::error::operation_aborted)
912 {
913 // Try again later and hope for the best.
914 JLOG(journal_.error())
915 << "Sweep timer got error '" << e.message() << "'. Restarting timer.";
916 setSweepTimer();
917 }
918 }))
919 {
920 using namespace std::chrono;
921 sweepTimer_.expires_after(
922 seconds{config_->sweepInterval.value_or(
923 config_->getValueFor(SizedItem::SweepInterval))});
924 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
925 }
926 }
927
928 void
930 {
931 // Only start the timer if waitHandlerCounter_ is not yet joined.
932 if (auto optionalCountedHandler =
933 waitHandlerCounter_.wrap([this](boost::system::error_code const& e) {
934 if (e.value() == boost::system::errc::success)
935 {
936 cryptoPrng().mixEntropy();
937 setEntropyTimer();
938 }
939 // Recover as best we can if an unexpected error occurs.
940 if (e.value() != boost::system::errc::success &&
941 e.value() != boost::asio::error::operation_aborted)
942 {
943 // Try again later and hope for the best.
944 JLOG(journal_.error()) << "Entropy timer got error '" << e.message()
945 << "'. Restarting timer.";
946 setEntropyTimer();
947 }
948 }))
949 {
950 using namespace std::chrono_literals;
951 entropyTimer_.expires_after(5min);
952 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
953 }
954 }
955
956 void
958 {
959 XRPL_ASSERT(
960 relationalDatabase_, "xrpl::ApplicationImp::doSweep : non-null relational database");
961 // NOLINTNEXTLINE(bugprone-unchecked-optional-access) assert above
962 if (!config_->standalone() && !relationalDatabase_->transactionDbHasSpace(*config_))
963 {
964 signalStop("Out of transaction DB space");
965 }
966
967 // VFALCO NOTE Does the order of calls matter?
968 // VFALCO TODO fix the dependency inversion using an observer,
969 // have listeners register for "onSweep ()" notification.
970
971 {
972 std::shared_ptr<FullBelowCache const> const fullBelowCache =
973 nodeFamily_.getFullBelowCache();
974
975 std::shared_ptr<TreeNodeCache const> const treeNodeCache =
976 nodeFamily_.getTreeNodeCache();
977
978 std::size_t const oldFullBelowSize = fullBelowCache->size();
979 std::size_t const oldTreeNodeSize = treeNodeCache->size();
980
981 nodeFamily_.sweep();
982
983 JLOG(journal_.debug())
984 << "NodeFamily::FullBelowCache sweep. Size before: " << oldFullBelowSize
985 << "; size after: " << fullBelowCache->size();
986
987 JLOG(journal_.debug())
988 << "NodeFamily::TreeNodeCache sweep. Size before: " << oldTreeNodeSize
989 << "; size after: " << treeNodeCache->size();
990 }
991 {
992 TaggedCache<uint256, Transaction> const& masterTxCache =
993 getMasterTransaction().getCache();
994
995 std::size_t const oldMasterTxSize = masterTxCache.size();
996
997 getMasterTransaction().sweep();
998
999 JLOG(journal_.debug()) << "MasterTransaction sweep. Size before: " << oldMasterTxSize
1000 << "; size after: " << masterTxCache.size();
1001 }
1002 {
1003 // Sweep NodeStore database cache(s), if enabled.
1004 getNodeStore().sweep();
1005 }
1006 {
1007 std::size_t const oldLedgerMasterCacheSize = getLedgerMaster().getFetchPackCacheSize();
1008
1009 getLedgerMaster().sweep();
1010
1011 JLOG(journal_.debug())
1012 << "LedgerMaster sweep. Size before: " << oldLedgerMasterCacheSize
1013 << "; size after: " << getLedgerMaster().getFetchPackCacheSize();
1014 }
1015 {
1016 // NodeCache == TaggedCache<SHAMapHash, Blob>
1017 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1018
1019 getTempNodeCache().sweep();
1020
1021 JLOG(journal_.debug()) << "TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1022 << "; size after: " << getTempNodeCache().size();
1023 }
1024 {
1025 std::size_t const oldCurrentCacheSize = getValidations().sizeOfCurrentCache();
1026 std::size_t const oldSizeSeqEnforcesSize = getValidations().sizeOfSeqEnforcersCache();
1027 std::size_t const oldByLedgerSize = getValidations().sizeOfByLedgerCache();
1028 std::size_t const oldBySequenceSize = getValidations().sizeOfBySequenceCache();
1029
1030 getValidations().expire(journal_);
1031
1032 JLOG(journal_.debug())
1033 << "Validations Current expire. Size before: " << oldCurrentCacheSize
1034 << "; size after: " << getValidations().sizeOfCurrentCache();
1035
1036 JLOG(journal_.debug())
1037 << "Validations SeqEnforcer expire. Size before: " << oldSizeSeqEnforcesSize
1038 << "; size after: " << getValidations().sizeOfSeqEnforcersCache();
1039
1040 JLOG(journal_.debug())
1041 << "Validations ByLedger expire. Size before: " << oldByLedgerSize
1042 << "; size after: " << getValidations().sizeOfByLedgerCache();
1043
1044 JLOG(journal_.debug())
1045 << "Validations BySequence expire. Size before: " << oldBySequenceSize
1046 << "; size after: " << getValidations().sizeOfBySequenceCache();
1047 }
1048 {
1049 std::size_t const oldInboundLedgersSize = getInboundLedgers().cacheSize();
1050
1051 getInboundLedgers().sweep();
1052
1053 JLOG(journal_.debug())
1054 << "InboundLedgers sweep. Size before: " << oldInboundLedgersSize
1055 << "; size after: " << getInboundLedgers().cacheSize();
1056 }
1057 {
1058 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1059 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1060 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1061
1062 getLedgerReplayer().sweep();
1063
1064 JLOG(journal_.debug()) << "LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1065 << "; size after: " << getLedgerReplayer().tasksSize();
1066
1067 JLOG(journal_.debug()) << "LedgerReplayer deltas sweep. Size before: " << oldDeltasSize
1068 << "; size after: " << getLedgerReplayer().deltasSize();
1069
1070 JLOG(journal_.debug())
1071 << "LedgerReplayer skipLists sweep. Size before: " << oldSkipListsSize
1072 << "; size after: " << getLedgerReplayer().skipListsSize();
1073 }
1074 {
1075 std::size_t const oldAcceptedLedgerSize = acceptedLedgerCache_.size();
1076
1077 acceptedLedgerCache_.sweep();
1078
1079 JLOG(journal_.debug())
1080 << "AcceptedLedgerCache sweep. Size before: " << oldAcceptedLedgerSize
1081 << "; size after: " << acceptedLedgerCache_.size();
1082 }
1083 {
1084 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1085
1086 cachedSLEs_.sweep();
1087
1088 JLOG(journal_.debug()) << "CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1089 << "; size after: " << cachedSLEs_.size();
1090 }
1091
1092 mallocTrim("doSweep", journal_);
1093
1094 // Set timer to do another sweep later.
1095 setSweepTimer();
1096 }
1097
1100 {
1101 return maxDisallowedLedger_;
1102 }
1103
1105 getTrapTxID() const override
1106 {
1107 return trapTxID_;
1108 }
1109
1110 size_t
1111 getNumberOfThreads() const override
1112 {
1114 }
1115
1116private:
1117 // For a newly-started validator, this is the greatest persisted ledger
1118 // and new validations must be greater than this.
1120
1121 void
1122 startGenesisLedger();
1123
1125 getLastFullLedger();
1126
1128 loadLedgerFromFile(std::string const& ledgerID);
1129
1130 bool
1131 loadOldLedger(
1132 std::string const& ledgerID,
1133 bool replay,
1134 bool isFilename,
1135 std::optional<uint256> trapTxID);
1136
1137 void
1138 setMaxDisallowedLedger();
1139
1141 getApp() override
1142 {
1143 return *this;
1144 }
1145};
1146
1147//------------------------------------------------------------------------------
1148
1149// TODO Break this up into smaller, more digestible initialization segments.
1150bool
1151ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
1152{
1153 // We want to intercept CTRL-C and the standard termination signal SIGTERM
1154 // and terminate the process. This handler will NEVER be invoked twice.
1155 //
1156 // Note that async_wait is "one-shot": for each call, the handler will be
1157 // invoked exactly once, either when one of the registered signals in the
1158 // signal set occurs or the signal set is cancelled. Subsequent signals are
1159 // effectively ignored (technically, they are queued up, waiting for a call
1160 // to async_wait).
1161 signals_.add(SIGINT);
1162 signals_.add(SIGTERM);
1163 signals_.async_wait([this](boost::system::error_code const& ec, int signum) {
1164 // Indicates the signal handler has been aborted; do nothing
1165 if (ec == boost::asio::error::operation_aborted)
1166 return;
1167
1168 JLOG(journal_.info()) << "Received signal " << signum;
1169
1170 if (signum == SIGTERM || signum == SIGINT)
1171 signalStop("Signal: " + to_string(signum));
1172 });
1173
1174 auto debugLog = config_->getDebugLogFile();
1175
1176 if (!debugLog.empty())
1177 {
1178 // Let debug messages go to the file but only WARNING or higher to
1179 // regular output (unless verbose)
1180
1181 if (!logs_->open(debugLog))
1182 std::cerr << "Can't open log file " << debugLog << '\n';
1183
1184 using beast::Severity;
1185 if (logs_->threshold() > Severity::Debug)
1186 logs_->threshold(Severity::Debug);
1187 }
1188
1189 JLOG(journal_.info()) << "Process starting: " << BuildInfo::getFullVersionString()
1190 << ", Instance Cookie: " << instanceCookie_;
1191
1192 if (numberOfThreads(*config_) < 2)
1193 {
1194 JLOG(journal_.warn()) << "Limited to a single I/O service thread by "
1195 "system configuration.";
1196 }
1197
1198 // Optionally turn off logging to console.
1199 logs_->silent(config_->silent());
1200
1202 return false;
1203
1204 if (!peerReservations_->load(getWalletDB()))
1205 {
1206 JLOG(journal_.fatal()) << "Cannot find peer reservations!";
1207 return false;
1208 }
1209
1210 if (validatorKeys_.keys)
1212
1213 // Configure the amendments the server supports
1214 {
1215 auto const supported = []() {
1216 auto const& amendments = detail::supportedAmendments();
1218 supported.reserve(amendments.size());
1219 for (auto const& [a, vote] : amendments)
1220 {
1221 auto const f = xrpl::getRegisteredFeature(a);
1222 XRPL_ASSERT(f, "xrpl::ApplicationImp::setup : registered feature");
1223 if (f)
1224 supported.emplace_back(a, *f, vote);
1225 }
1226 return supported;
1227 }();
1228 Section const& downVoted = config_->section(Sections::kVetoAmendments);
1229
1230 Section const& upVoted = config_->section(Sections::kAmendments);
1231
1233 *this,
1234 config().amendmentMajorityTime,
1235 supported,
1236 upVoted,
1237 downVoted,
1238 logs_->journal("Amendments"));
1239 }
1240
1242
1243 auto const startUp = config_->startUp;
1244 JLOG(journal_.debug()) << "startUp: " << startUp;
1245 if (startUp == StartUpType::Fresh)
1246 {
1247 JLOG(journal_.info()) << "Starting new Ledger";
1248
1250 }
1251 else if (
1252 startUp == StartUpType::Load || startUp == StartUpType::LoadFile ||
1253 startUp == StartUpType::Replay)
1254 {
1255 JLOG(journal_.info()) << "Loading specified Ledger";
1256
1257 if (!loadOldLedger(
1258 config_->startLedger,
1259 startUp == StartUpType::Replay,
1260 startUp == StartUpType::LoadFile,
1261 config_->trapTxHash))
1262 {
1263 JLOG(journal_.error()) << "The specified ledger could not be loaded.";
1264 if (config_->fastLoad)
1265 {
1266 // Fall back to syncing from the network, such as
1267 // when there's no existing data.
1269 }
1270 else
1271 {
1272 return false;
1273 }
1274 }
1275 }
1276 else if (startUp == StartUpType::Network)
1277 {
1278 // This should probably become the default once we have a stable
1279 // network.
1280 if (!config_->standalone())
1281 networkOPs_->setNeedNetworkLedger();
1282
1284 }
1285 else
1286 {
1288 }
1289
1290 if (auto const& forcedRange = config().forcedLedgerRangePresent)
1291 {
1292 ledgerMaster_->setLedgerRangePresent(forcedRange->first, forcedRange->second);
1293 }
1294
1295 orderBookDB_->setup(getLedgerMaster().getCurrentLedger());
1296
1297 nodeIdentity_ = getNodeIdentity(*this, cmdline);
1298
1299 if (!cluster_->load(config().section(Sections::kClusterNodes)))
1300 {
1301 JLOG(journal_.fatal()) << "Invalid entry in cluster configuration.";
1302 return false;
1303 }
1304
1305 {
1306 if (validatorKeys_.configInvalid())
1307 return false;
1308
1309 if (!validatorManifests_->load(
1310 getWalletDB(),
1311 "ValidatorManifests",
1312 validatorKeys_.manifest,
1313 config().section(Sections::kValidatorKeyRevocation).values()))
1314 {
1315 JLOG(journal_.fatal()) << "Invalid configured validator manifest.";
1316 return false;
1317 }
1318
1319 publisherManifests_->load(getWalletDB(), "PublisherManifests");
1320
1321 // It is possible to have a valid ValidatorKeys object without
1322 // setting the signingKey or masterKey. This occurs if the
1323 // configuration file does not have either
1324 // Sections::kValidatorToken or Sections::kValidationSeed section.
1325
1326 // masterKey for the configuration-file specified validator keys
1327 std::optional<PublicKey> localSigningKey;
1328 if (validatorKeys_.keys)
1329 localSigningKey = validatorKeys_.keys->publicKey;
1330
1331 // Setup trusted validators
1332 if (!validators_->load(
1333 localSigningKey,
1334 config().section(Sections::kValidators).values(),
1335 config().section(Sections::kValidatorListKeys).values(),
1336 config().validatorListThreshold))
1337 {
1338 JLOG(journal_.fatal()) << "Invalid entry in validator configuration.";
1339 return false;
1340 }
1341 }
1342
1343 if (!validatorSites_->load(config().section(Sections::kValidatorListSites).values()))
1344 {
1345 JLOG(journal_.fatal()) << "Invalid entry in [" << Sections::kValidatorListSites << "]";
1346 return false;
1347 }
1348
1349 // Tell the AmendmentTable who the trusted validators are.
1350 amendmentTable_->trustChanged(validators_->getQuorumKeys().second);
1351
1352 //----------------------------------------------------------------------
1353 //
1354 // Server
1355 //
1356 //----------------------------------------------------------------------
1357
1358 // VFALCO NOTE Unfortunately, in stand-alone mode some code still
1359 // foolishly calls overlay(). When this is fixed we can
1360 // move the instantiation inside a conditional:
1361 //
1362 // if (!config_.standalone())
1364 *this,
1368 *resolver_,
1369 getIoContext(),
1370 *config_,
1371 collectorManager_->collector());
1372 add(*overlay_); // add to PropertyStream
1373
1374 // start first consensus round
1375 if (!networkOPs_->beginConsensus(ledgerMaster_->getClosedLedger()->header().hash, {}))
1376 {
1377 JLOG(journal_.fatal()) << "Unable to start consensus";
1378 return false;
1379 }
1380
1381 {
1382 try
1383 {
1384 auto logStream = beast::logstream{journal_.error()};
1385 auto setup = setupServerHandler(*config_, logStream);
1386 setup.makeContexts();
1387 serverHandler_->setup(setup, journal_);
1388 fixConfigPorts(*config_, serverHandler_->endpoints());
1389 }
1390 catch (std::exception const& e)
1391 {
1392 if (auto stream = journal_.fatal())
1393 {
1394 stream << "Unable to setup server handler";
1395 if (std::strlen(e.what()) > 0)
1396 stream << ": " << e.what();
1397 }
1398 return false;
1399 }
1400 }
1401
1402 // Begin connecting to network.
1403 if (!config_->standalone())
1404 {
1405 // Should this message be here, conceptually? In theory this sort
1406 // of message, if displayed, should be displayed from PeerFinder.
1407 if (config_->peerPrivate && config_->ipsFixed.empty())
1408 {
1409 JLOG(journal_.warn()) << "No outbound peer connections will be made";
1410 }
1411
1412 // VFALCO NOTE the state timer resets the deadlock detector.
1413 //
1414 networkOPs_->setStateTimer();
1415 }
1416 else
1417 {
1418 JLOG(journal_.warn()) << "Running in standalone mode";
1419
1420 networkOPs_->setStandAlone();
1421 }
1422
1423 if (config_->canSign())
1424 {
1425 JLOG(journal_.warn()) << "*** The server is configured to allow the "
1426 "'sign' and 'sign_for'";
1427 JLOG(journal_.warn()) << "*** commands. These commands have security "
1428 "implications and have";
1429 JLOG(journal_.warn()) << "*** been deprecated. They will be removed "
1430 "in a future release of";
1431 JLOG(journal_.warn()) << "*** xrpld.";
1432 JLOG(journal_.warn()) << "*** If you do not use them to sign "
1433 "transactions please edit your";
1434 JLOG(journal_.warn()) << "*** configuration file and remove the [enable_signing] stanza.";
1435 JLOG(journal_.warn()) << "*** If you do use them to sign transactions "
1436 "please migrate to a";
1437 JLOG(journal_.warn()) << "*** standalone signing solution as soon as possible.";
1438 }
1439
1440 //
1441 // Execute start up rpc commands.
1442 //
1443 for (auto const& cmd : config_->section(Sections::kRpcStartup).lines())
1444 {
1445 json::Reader jrReader;
1446 json::Value jvCommand;
1447
1448 if (!jrReader.parse(cmd, jvCommand))
1449 {
1450 JLOG(journal_.fatal())
1451 << "Couldn't parse entry in [" << Sections::kRpcStartup << "]: '" << cmd;
1452 }
1453
1454 if (!config_->quiet())
1455 {
1456 JLOG(journal_.fatal()) << "Startup RPC: " << jvCommand << std::endl;
1457 }
1458
1461 RPC::JsonContext context{
1462 {.j = getJournal("RPCHandler"),
1463 .app = *this,
1464 .loadType = loadType,
1465 .netOps = getOPs(),
1466 .ledgerMaster = getLedgerMaster(),
1467 .consumer = c,
1468 .role = Role::ADMIN,
1469 .coro = {},
1470 .infoSub = {},
1471 .apiVersion = RPC::kApiMaximumSupportedVersion},
1472 jvCommand};
1473
1474 json::Value jvResult;
1475 RPC::doCommand(context, jvResult);
1476
1477 if (!config_->quiet())
1478 {
1479 JLOG(journal_.fatal()) << "Result: " << jvResult << std::endl;
1480 }
1481 }
1482
1483 validatorSites_->start();
1484
1485 return true;
1486}
1487
1488void
1490{
1491 JLOG(journal_.info()) << "Application starting. Version is " << BuildInfo::getVersionString();
1492
1493 if (withTimers)
1494 {
1495 setSweepTimer();
1497 }
1498
1499 io_latency_sampler_.start();
1500 resolver_->start();
1501 loadManager_->start();
1502 shaMapStore_->start();
1503 if (overlay_)
1504 overlay_->start();
1505
1506 if (grpcServer_->start())
1508
1509 ledgerCleaner_->start();
1510 perfLog_->start();
1511}
1512
1513void
1515{
1516 if (!config_->standalone())
1517 {
1518 // VFALCO NOTE This seems unnecessary. If we properly refactor the load
1519 // manager then the stall detector can just always be
1520 // "armed"
1521 //
1522 getLoadManager().activateStallDetector();
1523 }
1524
1525 isTimeToStop.wait(false, std::memory_order_relaxed);
1526
1527 JLOG(journal_.debug()) << "Application stopping";
1528
1529 io_latency_sampler_.cancelAsync();
1530
1531 // VFALCO Enormous hack, we have to force the probe to cancel
1532 // before we stop the io_context queue or else it never
1533 // unblocks in its destructor. The fix is to make all
1534 // io_objects gracefully handle exit so that we can
1535 // naturally return from io_context::run() instead of
1536 // forcing a call to io_context::stop()
1537 io_latency_sampler_.cancel();
1538
1539 resolver_->stopAsync();
1540
1541 // NIKB This is a hack - we need to wait for the resolver to
1542 // stop. before we stop the io_server_queue or weird
1543 // things will happen.
1544 resolver_->stop();
1545
1546 {
1547 try
1548 {
1549 sweepTimer_.cancel();
1550 }
1551 catch (boost::system::system_error const& e)
1552 {
1553 JLOG(journal_.error()) << "Application: sweepTimer cancel error: " << e.what();
1554 }
1555
1556 try
1557 {
1558 entropyTimer_.cancel();
1559 }
1560 catch (boost::system::system_error const& e)
1561 {
1562 JLOG(journal_.error()) << "Application: entropyTimer cancel error: " << e.what();
1563 }
1564 }
1565
1566 // Make sure that any waitHandlers pending in our timers are done
1567 // before we declare ourselves stopped.
1568 using namespace std::chrono_literals;
1569
1570 waitHandlerCounter_.join("Application", 1s, journal_);
1571
1572 validations_.flush();
1573
1574 validatorSites_->stop();
1575
1576 // TODO Store manifests in manifests.sqlite instead of wallet.db
1577 validatorManifests_->save(getWalletDB(), "ValidatorManifests", [this](PublicKey const& pubKey) {
1578 return getValidators().listed(pubKey);
1579 });
1580
1581 publisherManifests_->save(getWalletDB(), "PublisherManifests", [this](PublicKey const& pubKey) {
1582 return getValidators().trustedPublisher(pubKey);
1583 });
1584
1585 // The order of these stop calls is delicate.
1586 // Re-ordering them risks undefined behavior.
1587 loadManager_->stop();
1588 shaMapStore_->stop();
1589 jobQueue_->stop();
1590 if (overlay_)
1591 overlay_->stop();
1592 grpcServer_->stop();
1593 networkOPs_->stop();
1594 serverHandler_->stop();
1595 ledgerReplayer_->stop();
1596 inboundTransactions_->stop();
1597 inboundLedgers_->stop();
1598 ledgerCleaner_->stop();
1599 nodeStore_->stop();
1600 perfLog_->stop();
1601
1602 JLOG(journal_.info()) << "Done.";
1603}
1604
1605void
1607{
1608 if (!isTimeToStop.test_and_set(std::memory_order_acquire))
1609 {
1610 if (msg.empty())
1611 {
1612 JLOG(journal_.warn()) << "Server stopping";
1613 }
1614 else
1615 {
1616 JLOG(journal_.warn()) << "Server stopping: " << msg;
1617 }
1618
1619 isTimeToStop.notify_all();
1620 }
1621}
1622
1623bool
1625{
1626 return checkSigs_;
1627}
1628
1629void
1631{
1632 checkSigs_ = check;
1633}
1634
1635bool
1637{
1638 return isTimeToStop.test(std::memory_order_relaxed);
1639}
1640
1641int
1643{
1644 // Standard handles, config file, misc I/O etc:
1645 int needed = 128;
1646
1647 // 2x the configured peer limit for peer connections:
1648 if (overlay_)
1649 needed += 2 * overlay_->limit();
1650
1651 // the number of fds needed by the backend (internally
1652 // doubled if online delete is enabled).
1653 needed += std::max(5, shaMapStore_->fdRequired());
1654
1655 // One fd per incoming connection a port can accept, or
1656 // if no limit is set, assume it'll handle 256 clients.
1657 for (auto const& p : serverHandler_->setup().ports)
1658 needed += std::max(256, p.limit);
1659
1660 // The minimum number of file descriptors we need is 1024:
1661 return std::max(1024, needed);
1662}
1663
1664//------------------------------------------------------------------------------
1665
1666void
1668{
1669 std::vector<uint256> const initialAmendments = (config_->startUp == StartUpType::Fresh)
1670 ? amendmentTable_->getDesired()
1672
1675 Rules{config_->features},
1676 config_->fees.toFees(),
1677 initialAmendments,
1678 nodeFamily_);
1679 ledgerMaster_->storeLedger(genesis);
1680
1681 auto const next = std::make_shared<Ledger>(*genesis, getTimeKeeper().closeTime());
1682 next->updateSkipList();
1683 XRPL_ASSERT(
1684 next->header().seq < kXrpLedgerEarliestFees || next->read(keylet::feeSettings()),
1685 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1686 next->setImmutable();
1687 openLedger_.emplace(next, cachedSLEs_, logs_->journal("OpenLedger"));
1688 ledgerMaster_->storeLedger(next);
1689 ledgerMaster_->switchLCL(next);
1690}
1691
1694{
1695 auto j = getJournal("Ledger");
1696
1697 try
1698 {
1699 auto const [ledger, seq, hash] =
1700 getLatestLedger(Rules{config_->features}, config_->fees.toFees(), *this);
1701
1702 if (!ledger)
1703 return ledger;
1704
1705 XRPL_ASSERT(
1706 ledger->header().seq < kXrpLedgerEarliestFees || ledger->read(keylet::feeSettings()),
1707 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1708 ledger->setImmutable();
1709
1710 if (getLedgerMaster().haveLedger(seq))
1711 ledger->setValidated();
1712
1713 if (ledger->header().hash == hash)
1714 {
1715 JLOG(j.trace()) << "Loaded ledger: " << hash;
1716 return ledger;
1717 }
1718
1719 if (auto stream = j.error())
1720 {
1721 stream << "Failed on ledger";
1722 json::Value p;
1723 addJson(p, {*ledger, nullptr, static_cast<int>(LedgerFill::Options::Full)});
1724 stream << p;
1725 }
1726
1727 return {};
1728 }
1729 catch (SHAMapMissingNode const& mn)
1730 {
1731 JLOG(j.warn()) << "Ledger in database: " << mn.what();
1732 return {};
1733 }
1734}
1735
1738{
1739 try
1740 {
1741 std::ifstream ledgerFile(name, std::ios::in);
1742
1743 if (!ledgerFile)
1744 {
1745 JLOG(journal_.fatal()) << "Unable to open file '" << name << "'";
1746 return nullptr;
1747 }
1748
1749 json::Reader reader;
1750 json::Value jLedger;
1751
1752 if (!reader.parse(ledgerFile, jLedger))
1753 {
1754 JLOG(journal_.fatal()) << "Unable to parse ledger JSON";
1755 return nullptr;
1756 }
1757
1759
1760 // accept a wrapped ledger
1761 if (ledger.get().isMember("result"))
1762 ledger = ledger.get()["result"];
1763
1764 if (ledger.get().isMember("ledger"))
1765 ledger = ledger.get()["ledger"];
1766
1767 std::uint32_t seq = 1;
1768 auto closeTime = getTimeKeeper().closeTime();
1769 using namespace std::chrono_literals;
1770 auto closeTimeResolution = 30s;
1771 bool closeTimeEstimated = false;
1772 std::uint64_t totalDrops = 0;
1773
1774 if (ledger.get().isMember("accountState"))
1775 {
1776 if (ledger.get().isMember(jss::ledger_index))
1777 {
1778 seq = ledger.get()[jss::ledger_index].asUInt();
1779 }
1780
1781 if (ledger.get().isMember("close_time"))
1782 {
1783 using tp = NetClock::time_point;
1784 using d = tp::duration;
1785 closeTime = tp{d{ledger.get()["close_time"].asUInt()}};
1786 }
1787 if (ledger.get().isMember("close_time_resolution"))
1788 {
1789 using namespace std::chrono;
1790 closeTimeResolution = seconds{ledger.get()["close_time_resolution"].asUInt()};
1791 }
1792 if (ledger.get().isMember("close_time_estimated"))
1793 {
1794 closeTimeEstimated = ledger.get()["close_time_estimated"].asBool();
1795 }
1796 if (ledger.get().isMember("total_coins"))
1797 {
1798 totalDrops =
1799 beast::lexicalCastThrow<std::uint64_t>(ledger.get()["total_coins"].asString());
1800 }
1801
1802 ledger = ledger.get()["accountState"];
1803 }
1804
1805 if (!ledger.get().isArrayOrNull())
1806 {
1807 JLOG(journal_.fatal()) << "State nodes must be an array";
1808 return nullptr;
1809 }
1810
1811 auto loadLedger = std::make_shared<Ledger>(
1812 seq, closeTime, Rules{config_->features}, config_->fees.toFees(), nodeFamily_);
1813 loadLedger->setTotalDrops(totalDrops);
1814
1815 for (json::UInt index = 0; index < ledger.get().size(); ++index)
1816 {
1817 json::Value& entry = ledger.get()[index];
1818
1819 if (!entry.isObjectOrNull())
1820 {
1821 JLOG(journal_.fatal()) << "Invalid entry in ledger";
1822 return nullptr;
1823 }
1824
1825 uint256 uIndex;
1826
1827 if (!uIndex.parseHex(entry[jss::index].asString()))
1828 {
1829 JLOG(journal_.fatal()) << "Invalid entry in ledger";
1830 return nullptr;
1831 }
1832
1833 entry.removeMember(jss::index);
1834
1835 STParsedJSONObject stp("sle", ledger.get()[index]);
1836
1837 if (!stp.object || uIndex.isZero())
1838 {
1839 JLOG(journal_.fatal()) << "Invalid entry in ledger";
1840 return nullptr;
1841 }
1842
1843 // VFALCO TODO This is the only place that
1844 // constructor is used, try to remove it
1845 STLedgerEntry const sle(*stp.object, uIndex);
1846
1847 if (!loadLedger->addSLE(sle))
1848 {
1849 JLOG(journal_.fatal()) << "Couldn't add serialized ledger: " << uIndex;
1850 return nullptr;
1851 }
1852 }
1853
1854 loadLedger->stateMap().flushDirty(NodeObjectType::AccountNode);
1855
1856 XRPL_ASSERT(
1857 loadLedger->header().seq < kXrpLedgerEarliestFees ||
1858 loadLedger->read(keylet::feeSettings()),
1859 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1860 loadLedger->setAccepted(closeTime, closeTimeResolution, !closeTimeEstimated);
1861
1862 return loadLedger;
1863 }
1864 catch (std::exception const& x)
1865 {
1866 JLOG(journal_.fatal()) << "Ledger contains invalid data: " << x.what();
1867 return nullptr;
1868 }
1869}
1870
1871bool
1873 std::string const& ledgerID,
1874 bool replay,
1875 bool isFileName,
1876 std::optional<uint256> trapTxID)
1877{
1878 try
1879 {
1880 std::shared_ptr<Ledger const> loadLedger, replayLedger;
1881
1882 if (isFileName)
1883 {
1884 if (!ledgerID.empty())
1885 loadLedger = loadLedgerFromFile(ledgerID);
1886 }
1887 else if (ledgerID.length() == 64)
1888 {
1889 uint256 hash;
1890
1891 if (hash.parseHex(ledgerID))
1892 {
1893 loadLedger =
1894 loadByHash(hash, Rules{config_->features}, config_->fees.toFees(), *this);
1895
1896 if (!loadLedger)
1897 {
1898 // Try to build the ledger from the back end
1900 *this,
1901 hash,
1902 0,
1904 stopwatch(),
1905 makeDummyPeerSet(*this));
1906 if (il->checkLocal())
1907 loadLedger = il->getLedger();
1908 }
1909 }
1910 }
1911 else if (ledgerID.empty() || boost::iequals(ledgerID, "latest"))
1912 {
1913 loadLedger = getLastFullLedger();
1914 }
1915 else
1916 {
1917 // assume by sequence
1918 std::uint32_t index = 0;
1919
1920 if (beast::lexicalCastChecked(index, ledgerID))
1921 {
1922 loadLedger =
1923 loadByIndex(index, Rules{config_->features}, config_->fees.toFees(), *this);
1924 }
1925 }
1926
1927 if (!loadLedger)
1928 return false;
1929
1930 if (replay)
1931 {
1932 // Replay a ledger close with same prior ledger and transactions
1933
1934 // this ledger holds the transactions we want to replay
1935 replayLedger = loadLedger;
1936
1937 JLOG(journal_.info()) << "Loading parent ledger";
1938
1939 loadLedger = loadByHash(
1940 replayLedger->header().parentHash,
1941 Rules{config_->features},
1942 config_->fees.toFees(),
1943 *this);
1944 if (!loadLedger)
1945 {
1946 JLOG(journal_.info()) << "Loading parent ledger from node store";
1947
1948 // Try to build the ledger from the back end
1950 *this,
1951 replayLedger->header().parentHash,
1952 0,
1954 stopwatch(),
1955 makeDummyPeerSet(*this));
1956
1957 if (il->checkLocal())
1958 loadLedger = il->getLedger();
1959
1960 if (!loadLedger)
1961 {
1962 // LCOV_EXCL_START
1963 JLOG(journal_.fatal()) << "Replay ledger missing/damaged";
1964 UNREACHABLE(
1965 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1966 "missing/damaged");
1967 return false;
1968 // LCOV_EXCL_STOP
1969 }
1970 }
1971 }
1972 using namespace std::chrono_literals;
1973 using namespace date;
1974 static constexpr NetClock::time_point kLedgerWarnTimePoint{
1975 sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}};
1976 if (loadLedger->header().closeTime < kLedgerWarnTimePoint)
1977 {
1978 JLOG(journal_.fatal()) << "\n\n*** WARNING ***\n"
1979 "You are replaying a ledger from before "
1980 << to_string(kLedgerWarnTimePoint)
1981 << " UTC.\n"
1982 "This replay will not handle your ledger as it was "
1983 "originally "
1984 "handled.\nConsider running an earlier version of xrpld "
1985 "to "
1986 "get the older rules.\n*** CONTINUING ***\n";
1987 }
1988
1989 JLOG(journal_.info()) << "Loading ledger " << loadLedger->header().hash
1990 << " seq:" << loadLedger->header().seq;
1991
1992 if (loadLedger->header().accountHash.isZero())
1993 {
1994 // LCOV_EXCL_START
1995 JLOG(journal_.fatal()) << "Ledger is empty.";
1996 UNREACHABLE("xrpl::ApplicationImp::loadOldLedger : ledger is empty");
1997 return false;
1998 // LCOV_EXCL_STOP
1999 }
2000
2001 if (!loadLedger->walkLedger(getJournal("Ledger"), true))
2002 {
2003 // LCOV_EXCL_START
2004 JLOG(journal_.fatal()) << "Ledger is missing nodes.";
2005 UNREACHABLE(
2006 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
2007 "nodes");
2008 return false;
2009 // LCOV_EXCL_STOP
2010 }
2011
2012 if (!loadLedger->isSensible())
2013 {
2014 // LCOV_EXCL_START
2015 json::Value j = getJson({*loadLedger, {}});
2016 j[jss::accountTreeHash] = to_string(loadLedger->header().accountHash);
2017 j[jss::transTreeHash] = to_string(loadLedger->header().txHash);
2018 JLOG(journal_.fatal()) << "Ledger is not sensible: " << j;
2019 UNREACHABLE(
2020 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
2021 "sensible");
2022 return false;
2023 // LCOV_EXCL_STOP
2024 }
2025
2026 ledgerMaster_->setLedgerRangePresent(loadLedger->header().seq, loadLedger->header().seq);
2027
2028 ledgerMaster_->switchLCL(loadLedger);
2029 loadLedger->setValidated();
2030 ledgerMaster_->setFullLedger(loadLedger, true, false);
2031 openLedger_.emplace(loadLedger, cachedSLEs_, logs_->journal("OpenLedger"));
2032
2033 if (replay)
2034 {
2035 // inject transaction(s) from the replayLedger into our open ledger
2036 // and build replay structure
2037 auto replayData = std::make_unique<LedgerReplay>(loadLedger, replayLedger);
2038
2039 for (auto const& [_, tx] : replayData->orderedTxns())
2040 {
2041 (void)_;
2042 auto txID = tx->getTransactionID();
2043 if (trapTxID == txID)
2044 {
2045 trapTxID_ = txID;
2046 JLOG(journal_.debug()) << "Trap transaction set: " << txID;
2047 }
2048
2050 tx->add(*s);
2051
2053
2054 // emplaced during initialization before any caller
2055 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
2056 openLedger_->modify([&txID, &s](OpenView& view, beast::Journal j) {
2057 view.rawTxInsert(txID, std::move(s), nullptr);
2058 return true;
2059 });
2060 }
2061
2062 ledgerMaster_->takeReplay(std::move(replayData));
2063
2064 if (trapTxID && !trapTxID_)
2065 {
2066 JLOG(journal_.fatal()) << "Ledger " << replayLedger->header().seq
2067 << " does not contain the transaction hash " << *trapTxID;
2068 return false;
2069 }
2070 }
2071 }
2072 catch (SHAMapMissingNode const& mn)
2073 {
2074 JLOG(journal_.fatal()) << "While loading specified ledger: " << mn.what();
2075 return false;
2076 }
2077 catch (boost::bad_lexical_cast&)
2078 {
2079 JLOG(journal_.fatal()) << "Ledger specified '" << ledgerID << "' is not valid";
2080 return false;
2081 }
2082
2083 return true;
2084}
2085
2086bool
2088{
2089 if (!config().elbSupport)
2090 return true;
2091
2092 if (isStopping())
2093 {
2094 reason = "Server is shutting down";
2095 return false;
2096 }
2097
2098 if (getOPs().isNeedNetworkLedger())
2099 {
2100 reason = "Not synchronized with network yet";
2101 return false;
2102 }
2103
2104 if (getOPs().isAmendmentBlocked())
2105 {
2106 reason = "Server version too old";
2107 return false;
2108 }
2109
2110 if (getOPs().isUNLBlocked())
2111 {
2112 reason = "No valid validator list available";
2113 return false;
2114 }
2115
2116 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2117 {
2118 reason = "Not synchronized with network";
2119 return false;
2120 }
2121
2122 if (!getLedgerMaster().isCaughtUp(reason))
2123 return false;
2124
2125 if (getFeeTrack().isLoadedLocal())
2126 {
2127 reason = "Too much load";
2128 return false;
2129 }
2130
2131 return true;
2132}
2133
2136{
2137 return logs_->journal(name);
2138}
2139
2140void
2142{
2143 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2144 if (seq)
2145 maxDisallowedLedger_ = *seq;
2146
2147 JLOG(journal_.trace()) << "Max persisted ledger is " << maxDisallowedLedger_;
2148}
2149
2150//------------------------------------------------------------------------------
2151
2152Application::Application() : beast::PropertyStream::Source("app")
2153{
2154}
2155
2156//------------------------------------------------------------------------------
2157
2162 std::unique_ptr<TimeKeeper> timeKeeper)
2163{
2165 std::move(config), std::move(logs), std::move(timeKeeper));
2166}
2167
2168void
2169fixConfigPorts(Config& config, Endpoints const& endpoints)
2170{
2171 for (auto const& [name, ep] : endpoints)
2172 {
2173 if (!config.exists(name))
2174 continue;
2175
2176 auto& section = config[name];
2177 auto const optPort = section.get(Keys::kPort);
2178 if (optPort)
2179 {
2180 std::uint16_t const port = beast::lexicalCast<std::uint16_t>(*optPort);
2181 if (port == 0u)
2182 section.set(Keys::kPort, std::to_string(ep.port()));
2183 }
2184 }
2185}
2186
2187} // namespace xrpl
T ceil(T... args)
size_t getNumberOfThreads() const
Definition BasicApp.h:28
BasicApp(std::size_t numberOfThreads)
Definition BasicApp.cpp:10
boost::asio::io_context & getIoContext()
Definition BasicApp.h:22
Measures handler latency on an io_context queue.
A generic endpoint for log messages.
Definition Journal.h:38
std::string const & name() const
Returns the name of this source.
void add(Source &source)
Add a child source.
A metric for reporting event timing.
Definition Event.h:21
Unserialize a JSON document into a Value.
Definition json_reader.h:17
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Represents a JSON value.
Definition json_value.h:130
Value removeMember(char const *key)
Remove and return the named member.
std::string asString() const
Returns the unquoted string value.
bool isObjectOrNull() const
The amendment table stores the list of enabled and potential amendments.
beast::IOLatencyProbe< std::chrono::steady_clock > probe_
std::chrono::milliseconds get() const
void operator()(Duration const &elapsed)
std::atomic< std::chrono::milliseconds > lastSample_
IOLatencySampler(beast::insight::Event ev, beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_context &ios)
LedgerReplayer & getLedgerReplayer() override
Application::MutexType & getMasterMutex() override
std::optional< std::pair< PublicKey, SecretKey > > nodeIdentity_
InboundLedgers & getInboundLedgers() override
ValidatorList & getValidators() override
std::unique_ptr< SHAMapStore > shaMapStore_
TimeKeeper & getTimeKeeper() override
std::unique_ptr< LedgerCleaner > ledgerCleaner_
void start(bool withTimers) override
LoadFeeTrack & getFeeTrack() override
std::unique_ptr< perf::PerfLog > perfLog_
std::unique_ptr< HashRouter > hashRouter_
std::optional< OpenLedger > openLedger_
RCLValidations & getValidations() override
void run() override
std::unique_ptr< ResolverAsio > resolver_
Application::MutexType masterMutex_
Resource::Manager & getResourceManager() override
std::unique_ptr< InboundTransactions > inboundTransactions_
ClosureCounter< void, boost::system::error_code const & > waitHandlerCounter_
NodeStoreScheduler nodeStoreScheduler_
RelationalDatabase & getRelationalDatabase() override
OpenLedger & getOpenLedger() override
TransactionMaster & getMasterTransaction() override
std::chrono::milliseconds getIOLatency() override
boost::asio::io_context & getIOContext() override
std::unique_ptr< PathRequestManager > pathRequestManager_
std::optional< PublicKey const > getValidationPublicKey() const override
HashRouter & getHashRouter() override
LoadManager & getLoadManager() override
size_t getNumberOfThreads() const override
Returns the number of io_context (I/O worker) threads used by the application.
PendingSaves pendingSaves_
ManifestCache & getValidatorManifests() override
std::atomic< bool > checkSigs_
bool checkSigs() const override
ManifestCache & getPublisherManifests() override
void signalStop(std::string const &msg) override
bool serverOkay(std::string &reason) override
bool loadOldLedger(std::string const &ledgerID, bool replay, bool isFilename, std::optional< uint256 > trapTxID)
InboundTransactions & getInboundTransactions() override
SHAMapStore & getSHAMapStore() override
boost::asio::steady_timer sweepTimer_
boost::asio::signal_set signals_
boost::asio::steady_timer entropyTimer_
std::unique_ptr< Overlay > overlay_
bool setup(boost::program_options::variables_map const &cmdline) override
std::unique_ptr< OrderBookDB > orderBookDB_
std::unique_ptr< Config > config_
std::unique_ptr< ManifestCache > validatorManifests_
std::unique_ptr< LoadFeeTrack > feeTrack_
CollectorManager & getCollectorManager() override
std::unique_ptr< NetworkOPs > networkOPs_
std::optional< uint256 > trapTxID_
NetworkOPs & getOPs() override
std::unique_ptr< ValidatorList > validators_
std::unique_ptr< TxQ > txQ_
std::unique_ptr< NodeStore::Database > nodeStore_
static std::size_t numberOfThreads(Config const &config)
std::unique_ptr< ManifestCache > publisherManifests_
CachedSLEs & getCachedSLEs() override
LedgerIndex getMaxDisallowedLedger() override
Ensure that a newly-started validator does not sign proposals older than the last ledger it persisted...
NodeCache & getTempNodeCache() override
ApplicationImp(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
std::unique_ptr< PeerReservationTable > peerReservations_
Cluster & getCluster() override
std::pair< PublicKey, SecretKey > const & nodeIdentity() override
std::unique_ptr< Logs > logs_
NetworkIDService & getNetworkIDService() override
std::atomic_flag isTimeToStop
std::optional< SQLiteDatabase > relationalDatabase_
OpenLedger const & getOpenLedger() const override
std::shared_ptr< Ledger > getLastFullLedger()
std::unique_ptr< GRPCServer > grpcServer_
std::unique_ptr< ServerHandler > serverHandler_
Application & getApp() override
std::unique_ptr< Resource::Manager > resourceManager_
ValidatorKeys const validatorKeys_
std::uint64_t instanceID() const override
Returns a 64-bit instance identifier, generated at startup.
OrderBookDB & getOrderBookDB() override
Family & getNodeFamily() override
RCLValidations validations_
PeerReservationTable & getPeerReservations() override
Config & config() override
DatabaseCon & getWalletDB() override
Retrieve the "wallet database".
bool isStopping() const override
std::unique_ptr< TimeKeeper > timeKeeper_
std::unique_ptr< LedgerMaster > ledgerMaster_
void gotTXSet(std::shared_ptr< SHAMap > const &set, bool fromAcquire) const
beast::Journal journal_
std::unique_ptr< ValidatorSite > validatorSites_
Logs & getLogs() override
std::unique_ptr< CollectorManager > collectorManager_
std::shared_ptr< Ledger > loadLedgerFromFile(std::string const &ledgerID)
PathRequestManager & getPathRequestManager() override
std::uint64_t const instanceCookie_
IOLatencySampler io_latency_sampler_
LedgerCleaner & getLedgerCleaner() override
std::unique_ptr< AmendmentTable > amendmentTable_
std::atomic< LedgerIndex > maxDisallowedLedger_
AmendmentTable & getAmendmentTable() override
std::unique_ptr< JobQueue > jobQueue_
int fdRequired() const override
beast::Journal getJournal(std::string const &name) override
TaggedCache< uint256, AcceptedLedger > acceptedLedgerCache_
bool initNodeStore() const
TransactionMaster txMaster_
std::unique_ptr< LedgerReplayer > ledgerReplayer_
LedgerMaster & getLedgerMaster() override
NodeStore::Database & getNodeStore() override
std::unique_ptr< DatabaseCon > walletDB_
ValidatorSite & getValidatorSites() override
std::unique_ptr< Cluster > cluster_
std::unique_ptr< InboundLedgers > inboundLedgers_
std::optional< uint256 > const & getTrapTxID() const override
PendingSaves & getPendingSaves() override
std::unique_ptr< LoadManager > loadManager_
Overlay & getOverlay() override
JobQueue & getJobQueue() override
ServerHandler & getServerHandler() override
void onWrite(beast::PropertyStream::Map &stream) override
Subclass override.
TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache() override
perf::PerfLog & getPerfLog() override
std::unique_ptr< NetworkIDService > networkIDService_
TxQ & getTxQ() override
std::recursive_mutex MutexType
Definition Application.h:99
bool isZero() const
Definition base_uint.h:544
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:507
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
The role of a ClosureCounter is to assist in shutdown by letting callers wait for the completion of c...
Provides the beast::insight::Collector service.
bool standalone() const
Definition Config.h:316
bool forceMultiThread
Definition Config.h:224
std::size_t nodeSize
Definition Config.h:198
int workers
Definition Config.h:219
Routing table for objects identified by hash.
Definition HashRouter.h:77
Manages the lifetime of inbound ledgers.
Manages the acquisition and lifetime of transaction sets.
A pool of threads to perform work.
Definition JobQueue.h:43
Check the ledger/transaction databases to make sure they have continuity.
Manages the lifetime of ledger replay tasks.
Manages the current fee schedule.
Manages load sources.
Definition LoadManager.h:27
Manages partitions for logging.
Definition Log.h:20
Remembers manifests with the highest sequence number.
Definition Manifest.h:236
std::chrono::time_point< NetClock > time_point
Definition chrono.h:46
Service that provides access to the network ID.
Provides server functionality for clients.
Definition NetworkOPs.h:71
A NodeStore::Scheduler which uses the JobQueue.
Persistency layer for NodeObject.
Definition Database.h:32
Simple NodeStore Scheduler that just performs the tasks synchronously.
static Manager & instance()
Returns the instance of the manager singleton.
virtual std::unique_ptr< Database > makeDatabase(std::size_t burstSize, Scheduler &scheduler, int readThreads, Section const &backendParameters, beast::Journal journal)=0
Construct a NodeStore database.
Represents the open ledger.
Definition OpenLedger.h:33
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:45
void rawTxInsert(key_type const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData) override
Add a transaction to the tx map.
Definition OpenView.cpp:259
Tracks order books in the ledger.
Definition OrderBookDB.h:29
Manages the set of connected peers.
Definition Overlay.h:25
static void initPathTable()
Keeps track of which ledgers haven't been fully saved.
A public key.
Definition PublicKey.h:42
static std::unique_ptr< ResolverAsio > make(boost::asio::io_context &, beast::Journal)
A consumption charge.
Definition Charge.h:9
An endpoint that consumes resources.
Definition Consumer.h:15
Tracks load and resource consumption.
Rules controlling protocol behavior.
Definition Rules.h:33
class to create database, launch online delete thread, and related SQLite database
Definition SHAMapStore.h:19
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
Holds a collection of configuration values.
Definition BasicConfig.h:24
Map/cache combination.
Definition TaggedCache.h:59
std::size_t size() const
Returns the number of items in the container.
Manages various times used by the server.
Definition TimeKeeper.h:12
Transaction Queue.
Definition TxQ.h:40
Validator keys and manifest as set in configuration file.
Singleton class that maintains performance counters and optionally writes Json-formatted data to a di...
Definition PerfLog.h:31
T count(T... args)
T duration_cast(T... args)
T emplace_back(T... args)
T empty(T... args)
T endl(T... args)
T hardware_concurrency(T... args)
T make_shared(T... args)
T make_unique(T... args)
T max(T... args)
T min(T... args)
Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:11
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
BasicLogstream< char > logstream
Definition Journal.h:427
unsigned int UInt
STL namespace.
std::string const & getFullVersionString()
Full server version string.
Definition BuildInfo.cpp:82
std::string const & getVersionString()
Server version.
Definition BuildInfo.cpp:68
static constexpr auto kApiMaximumSupportedVersion
Definition ApiVersion.h:42
Status doCommand(RPC::JsonContext &context, json::Value &result)
Execute an RPC command and store the results in a json::Value.
std::unique_ptr< Manager > makeManager(beast::insight::Collector::ptr const &collector, beast::Journal journal)
Charge const kFeeReferenceRpc
std::map< std::string, VoteBehavior > const & supportedAmendments()
Amendments that this server supports and the default voting behavior.
Keylet const & feeSettings() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:221
Dummy class for unit tests.
Definition Workers.h:14
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::unique_ptr< CollectorManager > makeCollectorManager(Section const &params, beast::Journal journal)
std::unique_ptr< InboundTransactions > makeInboundTransactions(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Rules const &rules, Fees const &fees, ServiceRegistry &registry)
Fetch the ledger with the highest sequence contained in the database.
std::unordered_map< std::string, boost::asio::ip::tcp::endpoint > Endpoints
Definition ServerImpl.h:20
std::unique_ptr< AmendmentTable > makeAmendmentTable(ServiceRegistry &registry, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
ServerHandler::Setup setupServerHandler(Config const &config, std::ostream &log)
@ SigGoodOnly
Signature is good, but local checks fail.
Definition apply.h:23
beast::Journal debugLog()
Returns a debug journal.
Definition Log.cpp:399
std::uint32_t LedgerIndex
A ledger index.
Definition Protocol.h:259
CreateGenesisT const kCreateGenesis
Stopwatch & stopwatch()
Returns an instance of a wall clock.
Definition chrono.h:94
void addJson(json::Value &json, LedgerFill const &fill)
Given a Ledger and options, fill a json::Value with a description of the ledger.
std::enable_if_t< std::is_integral_v< Integral > &&detail::is_engine< Engine >::value, Integral > randInt(Engine &engine, Integral min, Integral max)
Return a uniformly distributed random integer.
std::unique_ptr< ServerHandler > makeServerHandler(Application &app, boost::asio::io_context &ioContext, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
std::pair< PublicKey, SecretKey > getNodeIdentity(soci::session &session)
Returns a stable public and private key for this node.
Definition Wallet.cpp:138
CsprngEngine & cryptoPrng()
The default cryptographically secure PRNG.
std::unique_ptr< SHAMapStore > makeSHAMapStore(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Rules const &rules, Fees const &fees, ServiceRegistry &registry, bool acquire)
Load a ledger by its sequence number.
@ AccountIdCacheSize
Definition Config.h:40
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
void logicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
static constexpr std::uint32_t kXrpLedgerEarliestFees
The XRP Ledger mainnet's earliest ledger with a FeeSettings object.
@ ADMIN
Definition Role.h:24
std::unique_ptr< LedgerCleaner > makeLedgerCleaner(Application &app, beast::Journal journal)
constexpr auto megabytes(T value) noexcept
static void fixConfigPorts(Config &config, Endpoints const &endpoints)
std::unique_ptr< PeerSetBuilder > makePeerSetBuilder(Application &app)
Definition PeerSet.cpp:137
std::unique_ptr< InboundLedgers > makeInboundLedgers(Application &app, InboundLedgers::clock_type &clock, beast::insight::Collector::ptr const &collector)
std::unique_ptr< Overlay > makeOverlay(Application &app, Overlay::Setup const &setup, ServerHandler &serverHandler, Resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_context &ioContext, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
Creates the implementation of Overlay.
std::unique_ptr< NetworkOPs > makeNetworkOPs(ServiceRegistry &registry, NetworkOPs::clock_type &clock, bool standalone, std::size_t minPeerCount, bool startValid, JobQueue &jobQueue, LedgerMaster &ledgerMaster, ValidatorKeys const &validatorKeys, boost::asio::io_context &ioSvc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
json::Value getJson(LedgerFill const &fill)
Return a new json::Value representing the ledger with given options.
Validations< RCLValidationsAdaptor > RCLValidations
Alias for RCL-specific instantiation of generic Validations.
TaggedCache< uint256, SLE const > CachedSLEs
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
Definition Wallet.cpp:39
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
Definition AccountID.cpp:86
std::unique_ptr< Application > makeApplication(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
MallocTrimReport mallocTrim(std::string_view tag, beast::Journal journal)
Attempt to return freed memory to the operating system.
std::unique_ptr< PeerSet > makeDummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
Definition PeerSet.cpp:180
std::unique_ptr< LoadManager > makeLoadManager(Application &app, beast::Journal journal)
DatabaseCon::Setup setupDatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
Definition Config.cpp:1219
TaggedCache< SHAMapHash, Blob > NodeCache
HashRouter::Setup setupHashRouter(Config const &config)
Create HashRouter setup from configuration.
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
Definition apply.cpp:112
@ SYNCING
fallen slightly behind
Definition NetworkOPs.h:53
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Rules const &rules, Fees const &fees, ServiceRegistry &registry, bool acquire)
Load a ledger by its hash.
Overlay::Setup setupOverlay(BasicConfig const &config, beast::Journal j)
SQLiteDatabase setupRelationalDatabase(ServiceRegistry &registry, Config const &config, JobQueue &jobQueue)
setupRelationalDatabase Creates and returns a SQLiteDatabase instance based on configuration.
std::optional< uint256 > getRegisteredFeature(std::string const &name)
TxQ::Setup setupTxQ(Config const &config)
Build a TxQ::Setup object from application configuration.
Definition TxQ.cpp:1872
BaseUInt< 256 > uint256
Definition base_uint.h:562
std::unique_ptr< OrderBookDB > makeOrderBookDb(ServiceRegistry &registry, OrderBookDBConfig const &config)
Create an OrderBookDB instance.
T next(T... args)
T ref(T... args)
T reserve(T... args)
T size(T... args)
T strlen(T... args)
static constexpr auto kPort
Definition Constants.h:142
static constexpr auto kValidators
Definition Constants.h:73
static constexpr auto kValidatorListKeys
Definition Constants.h:69
static constexpr auto kImportNodeDatabase
Definition Constants.h:20
static constexpr auto kAmendments
Definition Constants.h:7
static constexpr auto kRpcStartup
Definition Constants.h:54
static constexpr auto kValidatorKeyRevocation
Definition Constants.h:68
static constexpr auto kPortGrpc
Definition Constants.h:44
static constexpr auto kVetoAmendments
Definition Constants.h:75
static constexpr auto kClusterNodes
Definition Constants.h:10
static constexpr auto kInsight
Definition Constants.h:21
static constexpr auto kValidatorListSites
Definition Constants.h:70
T to_string(T... args)
T what(T... args)