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