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