rippled
Loading...
Searching...
No Matches
Application.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/consensus/RCLValidations.h>
21#include <xrpld/app/ledger/InboundLedgers.h>
22#include <xrpld/app/ledger/InboundTransactions.h>
23#include <xrpld/app/ledger/LedgerCleaner.h>
24#include <xrpld/app/ledger/LedgerMaster.h>
25#include <xrpld/app/ledger/LedgerReplayer.h>
26#include <xrpld/app/ledger/LedgerToJson.h>
27#include <xrpld/app/ledger/OpenLedger.h>
28#include <xrpld/app/ledger/OrderBookDB.h>
29#include <xrpld/app/ledger/PendingSaves.h>
30#include <xrpld/app/ledger/TransactionMaster.h>
31#include <xrpld/app/main/Application.h>
32#include <xrpld/app/main/BasicApp.h>
33#include <xrpld/app/main/DBInit.h>
34#include <xrpld/app/main/GRPCServer.h>
35#include <xrpld/app/main/LoadManager.h>
36#include <xrpld/app/main/NodeIdentity.h>
37#include <xrpld/app/main/NodeStoreScheduler.h>
38#include <xrpld/app/misc/AmendmentTable.h>
39#include <xrpld/app/misc/HashRouter.h>
40#include <xrpld/app/misc/LoadFeeTrack.h>
41#include <xrpld/app/misc/NetworkOPs.h>
42#include <xrpld/app/misc/SHAMapStore.h>
43#include <xrpld/app/misc/TxQ.h>
44#include <xrpld/app/misc/ValidatorKeys.h>
45#include <xrpld/app/misc/ValidatorSite.h>
46#include <xrpld/app/paths/PathRequests.h>
47#include <xrpld/app/rdb/RelationalDatabase.h>
48#include <xrpld/app/rdb/Wallet.h>
49#include <xrpld/app/tx/apply.h>
50#include <xrpld/core/DatabaseCon.h>
51#include <xrpld/overlay/Cluster.h>
52#include <xrpld/overlay/PeerReservationTable.h>
53#include <xrpld/overlay/PeerSet.h>
54#include <xrpld/overlay/make_Overlay.h>
55#include <xrpld/perflog/PerfLog.h>
56#include <xrpld/shamap/NodeFamily.h>
57
58#include <xrpl/basics/ByteUtilities.h>
59#include <xrpl/basics/ResolverAsio.h>
60#include <xrpl/basics/random.h>
61#include <xrpl/beast/asio/io_latency_probe.h>
62#include <xrpl/beast/core/LexicalCast.h>
63#include <xrpl/crypto/csprng.h>
64#include <xrpl/json/json_reader.h>
65#include <xrpl/nodestore/DummyScheduler.h>
66#include <xrpl/protocol/ApiVersion.h>
67#include <xrpl/protocol/BuildInfo.h>
68#include <xrpl/protocol/Feature.h>
69#include <xrpl/protocol/Protocol.h>
70#include <xrpl/protocol/STParsedJSON.h>
71#include <xrpl/resource/Fees.h>
72
73#include <boost/algorithm/string/predicate.hpp>
74#include <boost/asio/steady_timer.hpp>
75#include <boost/system/error_code.hpp>
76
77#include <date/date.h>
78
79#include <chrono>
80#include <condition_variable>
81#include <cstring>
82#include <fstream>
83#include <limits>
84#include <mutex>
85#include <optional>
86#include <utility>
87
88namespace ripple {
89
90static void
91fixConfigPorts(Config& config, Endpoints const& endpoints);
92
93// VFALCO TODO Move the function definitions into the class declaration
94class ApplicationImp : public Application, public BasicApp
95{
96private:
98 {
99 private:
104
105 public:
110 boost::asio::io_context& ios)
111 : m_event(ev)
113 , m_probe(interval, ios)
114 , lastSample_{}
115 {
116 }
117
118 void
120 {
121 m_probe.sample(std::ref(*this));
122 }
123
124 template <class Duration>
125 void
126 operator()(Duration const& elapsed)
127 {
128 using namespace std::chrono;
129 auto const lastSample = ceil<milliseconds>(elapsed);
130
131 lastSample_ = lastSample;
132
133 if (lastSample >= 10ms)
134 m_event.notify(lastSample);
135 if (lastSample >= 500ms)
136 {
137 JLOG(m_journal.warn())
138 << "io_context latency = " << lastSample.count();
139 }
140 }
141
143 get() const
144 {
145 return lastSample_.load();
146 }
147
148 void
150 {
151 m_probe.cancel();
152 }
153
154 void
156 {
158 }
159 };
160
161public:
165
167
171
172 // Required by the SHAMapStore
174
181
186
188
191 // VFALCO TODO Make OrderBookDB abstract
215 boost::asio::steady_timer sweepTimer_;
216 boost::asio::steady_timer entropyTimer_;
217
222
223 boost::asio::signal_set m_signals;
224
225 // Once we get C++20, we could use `std::atomic_flag` for `isTimeToStop`
226 // and eliminate the need for the condition variable and the mutex.
230
232
234
236
238
239 //--------------------------------------------------------------------------
240
241 static std::size_t
243 {
244#if RIPPLE_SINGLE_IO_SERVICE_THREAD
245 return 1;
246#else
247
248 if (config.IO_WORKERS > 0)
249 return config.IO_WORKERS;
250
251 auto const cores = std::thread::hardware_concurrency();
252
253 // Use a single thread when running on under-provisioned systems
254 // or if we are configured to use minimal resources.
255 if ((cores == 1) || ((config.NODE_SIZE == 0) && (cores == 2)))
256 return 1;
257
258 // Otherwise, prefer six threads.
259 return 6;
260#endif
261 }
262
263 //--------------------------------------------------------------------------
264
270 , config_(std::move(config))
271 , logs_(std::move(logs))
272 , timeKeeper_(std::move(timeKeeper))
274 1 +
275 rand_int(
276 crypto_prng(),
277 std::numeric_limits<std::uint64_t>::max() - 1))
278 , m_journal(logs_->journal("Application"))
279
280 // PerfLog must be started before any other threads are launched.
281 , perfLog_(perf::make_PerfLog(
282 perf::setup_PerfLog(
283 config_->section("perf"),
284 config_->CONFIG_DIR),
285 *this,
286 logs_->journal("PerfLog"),
287 [this] { signalStop("PerfLog"); }))
288
289 , m_txMaster(*this)
290
292 config_->section(SECTION_INSIGHT),
293 logs_->journal("Collector")))
294
298 return 1;
299
300 if (config->WORKERS)
301 return config->WORKERS;
302
303 auto count =
304 static_cast<int>(std::thread::hardware_concurrency());
305
306 // Be more aggressive about the number of threads to use
307 // for the job queue if the server is configured as
308 // "large" or "huge" if there are enough cores.
309 if (config->NODE_SIZE >= 4 && count >= 16)
310 count = 6 + std::min(count, 8);
311 else if (config->NODE_SIZE >= 3 && count >= 8)
312 count = 4 + std::min(count, 6);
313 else
314 count = 2 + std::min(count, 4);
315
316 return count;
317 }(config_),
318 m_collectorManager->group("jobq"),
319 logs_->journal("JobQueue"),
320 *logs_,
321 *perfLog_))
322
324
326 *this,
328 logs_->journal("SHAMapStore")))
329
331 "NodeCache",
332 16384,
334 stopwatch(),
335 logs_->journal("TaggedCache"))
336
337 , cachedSLEs_(
338 "Cached SLEs",
339 0,
341 stopwatch(),
342 logs_->journal("CachedSLEs"))
343
345
347 m_collectorManager->collector(),
348 logs_->journal("Resource")))
349
350 , m_nodeStore(m_shaMapStore->makeNodeStore(
351 config_->PREFETCH_WORKERS > 0 ? config_->PREFETCH_WORKERS : 4))
352
354
355 , m_orderBookDB(*this)
356
357 , m_pathRequests(std::make_unique<PathRequests>(
358 *this,
359 logs_->journal("PathRequest"),
360 m_collectorManager->collector()))
361
362 , m_ledgerMaster(std::make_unique<LedgerMaster>(
363 *this,
364 stopwatch(),
365 m_collectorManager->collector(),
366 logs_->journal("LedgerMaster")))
367
369 make_LedgerCleaner(*this, logs_->journal("LedgerCleaner")))
370
371 // VFALCO NOTE must come before NetworkOPs to prevent a crash due
372 // to dependencies in the destructor.
373 //
375 *this,
376 stopwatch(),
377 m_collectorManager->collector()))
378
380 *this,
381 m_collectorManager->collector(),
382 [this](std::shared_ptr<SHAMap> const& set, bool fromAcquire) {
383 gotTXSet(set, fromAcquire);
384 }))
385
387 *this,
389 make_PeerSetBuilder(*this)))
390
392 "AcceptedLedger",
393 4,
395 stopwatch(),
396 logs_->journal("TaggedCache"))
397
399 *this,
400 stopwatch(),
401 config_->standalone(),
402 config_->NETWORK_QUORUM,
403 config_->START_VALID,
404 *m_jobQueue,
408 logs_->journal("NetworkOPs"),
409 m_collectorManager->collector()))
410
411 , cluster_(std::make_unique<Cluster>(logs_->journal("Overlay")))
412
414 logs_->journal("PeerReservationTable")))
415
417 std::make_unique<ManifestCache>(logs_->journal("ManifestCache")))
418
420 std::make_unique<ManifestCache>(logs_->journal("ManifestCache")))
421
426 config_->legacy("database_path"),
427 logs_->journal("ValidatorList"),
428 config_->VALIDATION_QUORUM))
429
431
433 *this,
435 *m_jobQueue,
439
440 , mFeeTrack(
441 std::make_unique<LoadFeeTrack>(logs_->journal("LoadManager")))
442
445 stopwatch()))
446
447 , mValidations(
448 ValidationParms(),
449 stopwatch(),
450 *this,
451 logs_->journal("Validations"))
452
453 , m_loadManager(make_LoadManager(*this, logs_->journal("LoadManager")))
454
455 , txQ_(
456 std::make_unique<TxQ>(setup_TxQ(*config_), logs_->journal("TxQ")))
457
459
461
463
464 , checkSigs_(true)
465
466 , m_resolver(
467 ResolverAsio::New(get_io_context(), logs_->journal("Resolver")))
468
470 m_collectorManager->collector()->make_event("ios_latency"),
471 logs_->journal("Application"),
475 {
477
478 add(m_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 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
520 instanceID() const override
521 {
522 return instanceCookie_;
523 }
524
525 Logs&
526 logs() override
527 {
528 return *logs_;
529 }
530
531 Config&
532 config() override
533 {
534 return *config_;
535 }
536
539 {
540 return *m_collectorManager;
541 }
542
543 Family&
544 getNodeFamily() override
545 {
546 return nodeFamily_;
547 }
548
550 timeKeeper() override
551 {
552 return *timeKeeper_;
553 }
554
555 JobQueue&
556 getJobQueue() override
557 {
558 return *m_jobQueue;
559 }
560
562 nodeIdentity() override
563 {
564 if (nodeIdentity_)
565 return *nodeIdentity_;
566
568 "Accessing Application::nodeIdentity() before it is initialized.");
569 }
570
572 getValidationPublicKey() const override
573 {
574 if (!validatorKeys_.keys)
575 return {};
576
577 return validatorKeys_.keys->publicKey;
578 }
579
581 getOPs() override
582 {
583 return *m_networkOPs;
584 }
585
586 virtual ServerHandler&
588 {
589 XRPL_ASSERT(
591 "ripple::ApplicationImp::getServerHandler : non-null server "
592 "handle");
593 return *serverHandler_;
594 }
595
596 boost::asio::io_context&
597 getIOContext() override
598 {
599 return get_io_context();
600 }
601
603 getIOLatency() override
604 {
605 return m_io_latency_sampler.get();
606 }
607
610 {
611 return *m_ledgerMaster;
612 }
613
616 {
617 return *ledgerCleaner_;
618 }
619
622 {
623 return *m_ledgerReplayer;
624 }
625
628 {
629 return *m_inboundLedgers;
630 }
631
634 {
635 return *m_inboundTransactions;
636 }
637
640 {
642 }
643
644 void
645 gotTXSet(std::shared_ptr<SHAMap> const& set, bool fromAcquire)
646 {
647 if (set)
648 m_networkOPs->mapComplete(set, fromAcquire);
649 }
650
653 {
654 return m_txMaster;
655 }
656
658 getPerfLog() override
659 {
660 return *perfLog_;
661 }
662
663 NodeCache&
665 {
666 return m_tempNodeCache;
667 }
668
670 getNodeStore() override
671 {
672 return *m_nodeStore;
673 }
674
676 getMasterMutex() override
677 {
678 return m_masterMutex;
679 }
680
682 getLoadManager() override
683 {
684 return *m_loadManager;
685 }
686
689 {
690 return *m_resourceManager;
691 }
692
694 getOrderBookDB() override
695 {
696 return m_orderBookDB;
697 }
698
701 {
702 return *m_pathRequests;
703 }
704
706 cachedSLEs() override
707 {
708 return cachedSLEs_;
709 }
710
713 {
714 return *m_amendmentTable;
715 }
716
718 getFeeTrack() override
719 {
720 return *mFeeTrack;
721 }
722
724 getHashRouter() override
725 {
726 return *hashRouter_;
727 }
728
730 getValidations() override
731 {
732 return mValidations;
733 }
734
736 validators() override
737 {
738 return *validators_;
739 }
740
742 validatorSites() override
743 {
744 return *validatorSites_;
745 }
746
749 {
750 return *validatorManifests_;
751 }
752
755 {
756 return *publisherManifests_;
757 }
758
759 Cluster&
760 cluster() override
761 {
762 return *cluster_;
763 }
764
767 {
768 return *peerReservations_;
769 }
770
772 getSHAMapStore() override
773 {
774 return *m_shaMapStore;
775 }
776
778 pendingSaves() override
779 {
780 return pendingSaves_;
781 }
782
784 openLedger() override
785 {
786 return *openLedger_;
787 }
788
789 OpenLedger const&
790 openLedger() const override
791 {
792 return *openLedger_;
793 }
794
795 Overlay&
796 overlay() override
797 {
798 XRPL_ASSERT(
799 overlay_, "ripple::ApplicationImp::overlay : non-null overlay");
800 return *overlay_;
801 }
802
803 TxQ&
804 getTxQ() override
805 {
806 XRPL_ASSERT(
807 txQ_,
808 "ripple::ApplicationImp::getTxQ : non-null transaction queue");
809 return *txQ_;
810 }
811
814 {
815 XRPL_ASSERT(
817 "ripple::ApplicationImp::getRelationalDatabase : non-null "
818 "relational database");
819 return *mRelationalDatabase;
820 }
821
823 getWalletDB() override
824 {
825 XRPL_ASSERT(
826 mWalletDB,
827 "ripple::ApplicationImp::getWalletDB : non-null wallet database");
828 return *mWalletDB;
829 }
830
831 bool
832 serverOkay(std::string& reason) override;
833
835 journal(std::string const& name) override;
836
837 //--------------------------------------------------------------------------
838
839 bool
841 {
842 XRPL_ASSERT(
843 mWalletDB.get() == nullptr,
844 "ripple::ApplicationImp::initRelationalDatabase : null wallet "
845 "database");
846
847 try
848 {
851
852 // wallet database
854 setup.useGlobalPragma = false;
855
857 }
858 catch (std::exception const& e)
859 {
860 JLOG(m_journal.fatal())
861 << "Failed to initialize SQL databases: " << e.what();
862 return false;
863 }
864
865 return true;
866 }
867
868 bool
870 {
871 if (config_->doImport)
872 {
873 auto j = logs_->journal("NodeObject");
874 NodeStore::DummyScheduler dummyScheduler;
877 megabytes(config_->getValueFor(
879 dummyScheduler,
880 0,
882 j);
883
884 JLOG(j.warn()) << "Starting node import from '" << source->getName()
885 << "' to '" << m_nodeStore->getName() << "'.";
886
887 using namespace std::chrono;
888 auto const start = steady_clock::now();
889
890 m_nodeStore->importDatabase(*source);
891
892 auto const elapsed =
893 duration_cast<seconds>(steady_clock::now() - start);
894 JLOG(j.warn()) << "Node import from '" << source->getName()
895 << "' took " << elapsed.count() << " seconds.";
896 }
897
898 return true;
899 }
900
901 //--------------------------------------------------------------------------
902 //
903 // PropertyStream
904 //
905
906 void
908 {
909 }
910
911 //--------------------------------------------------------------------------
912
913 void
915 {
916 // Only start the timer if waitHandlerCounter_ is not yet joined.
917 if (auto optionalCountedHandler = waitHandlerCounter_.wrap(
918 [this](boost::system::error_code const& e) {
919 if (e.value() == boost::system::errc::success)
920 {
921 m_jobQueue->addJob(
922 jtSWEEP, "sweep", [this]() { doSweep(); });
923 }
924 // Recover as best we can if an unexpected error occurs.
925 if (e.value() != boost::system::errc::success &&
926 e.value() != boost::asio::error::operation_aborted)
927 {
928 // Try again later and hope for the best.
929 JLOG(m_journal.error())
930 << "Sweep timer got error '" << e.message()
931 << "'. Restarting timer.";
932 setSweepTimer();
933 }
934 }))
935 {
936 using namespace std::chrono;
937 sweepTimer_.expires_after(seconds{config_->SWEEP_INTERVAL.value_or(
938 config_->getValueFor(SizedItem::sweepInterval))});
939 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
940 }
941 }
942
943 void
945 {
946 // Only start the timer if waitHandlerCounter_ is not yet joined.
947 if (auto optionalCountedHandler = waitHandlerCounter_.wrap(
948 [this](boost::system::error_code const& e) {
949 if (e.value() == boost::system::errc::success)
950 {
951 crypto_prng().mix_entropy();
952 setEntropyTimer();
953 }
954 // Recover as best we can if an unexpected error occurs.
955 if (e.value() != boost::system::errc::success &&
956 e.value() != boost::asio::error::operation_aborted)
957 {
958 // Try again later and hope for the best.
959 JLOG(m_journal.error())
960 << "Entropy timer got error '" << e.message()
961 << "'. Restarting timer.";
962 setEntropyTimer();
963 }
964 }))
965 {
966 using namespace std::chrono_literals;
967 entropyTimer_.expires_after(5min);
968 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
969 }
970 }
971
972 void
974 {
975 if (!config_->standalone() &&
976 !getRelationalDatabase().transactionDbHasSpace(*config_))
977 {
978 signalStop("Out of transaction DB space");
979 }
980
981 // VFALCO NOTE Does the order of calls matter?
982 // VFALCO TODO fix the dependency inversion using an observer,
983 // have listeners register for "onSweep ()" notification.
984
985 {
986 std::shared_ptr<FullBelowCache const> const fullBelowCache =
987 nodeFamily_.getFullBelowCache();
988
989 std::shared_ptr<TreeNodeCache const> const treeNodeCache =
990 nodeFamily_.getTreeNodeCache();
991
992 std::size_t const oldFullBelowSize = fullBelowCache->size();
993 std::size_t const oldTreeNodeSize = treeNodeCache->size();
994
995 nodeFamily_.sweep();
996
997 JLOG(m_journal.debug())
998 << "NodeFamily::FullBelowCache sweep. Size before: "
999 << oldFullBelowSize
1000 << "; size after: " << fullBelowCache->size();
1001
1002 JLOG(m_journal.debug())
1003 << "NodeFamily::TreeNodeCache sweep. Size before: "
1004 << oldTreeNodeSize << "; size after: " << treeNodeCache->size();
1005 }
1006 {
1007 TaggedCache<uint256, Transaction> const& masterTxCache =
1008 getMasterTransaction().getCache();
1009
1010 std::size_t const oldMasterTxSize = masterTxCache.size();
1011
1012 getMasterTransaction().sweep();
1013
1014 JLOG(m_journal.debug())
1015 << "MasterTransaction sweep. Size before: " << oldMasterTxSize
1016 << "; size after: " << masterTxCache.size();
1017 }
1018 {
1019 // Does not appear to have an associated cache.
1020 getNodeStore().sweep();
1021 }
1022 {
1023 std::size_t const oldLedgerMasterCacheSize =
1024 getLedgerMaster().getFetchPackCacheSize();
1025
1026 getLedgerMaster().sweep();
1027
1028 JLOG(m_journal.debug())
1029 << "LedgerMaster sweep. Size before: "
1030 << oldLedgerMasterCacheSize << "; size after: "
1031 << getLedgerMaster().getFetchPackCacheSize();
1032 }
1033 {
1034 // NodeCache == TaggedCache<SHAMapHash, Blob>
1035 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1036
1037 getTempNodeCache().sweep();
1038
1039 JLOG(m_journal.debug())
1040 << "TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1041 << "; size after: " << getTempNodeCache().size();
1042 }
1043 {
1044 std::size_t const oldCurrentCacheSize =
1045 getValidations().sizeOfCurrentCache();
1046 std::size_t const oldSizeSeqEnforcesSize =
1047 getValidations().sizeOfSeqEnforcersCache();
1048 std::size_t const oldByLedgerSize =
1049 getValidations().sizeOfByLedgerCache();
1050 std::size_t const oldBySequenceSize =
1051 getValidations().sizeOfBySequenceCache();
1052
1053 getValidations().expire(m_journal);
1054
1055 JLOG(m_journal.debug())
1056 << "Validations Current expire. Size before: "
1057 << oldCurrentCacheSize
1058 << "; size after: " << getValidations().sizeOfCurrentCache();
1059
1060 JLOG(m_journal.debug())
1061 << "Validations SeqEnforcer expire. Size before: "
1062 << oldSizeSeqEnforcesSize << "; size after: "
1063 << getValidations().sizeOfSeqEnforcersCache();
1064
1065 JLOG(m_journal.debug())
1066 << "Validations ByLedger expire. Size before: "
1067 << oldByLedgerSize
1068 << "; size after: " << getValidations().sizeOfByLedgerCache();
1069
1070 JLOG(m_journal.debug())
1071 << "Validations BySequence expire. Size before: "
1072 << oldBySequenceSize
1073 << "; size after: " << getValidations().sizeOfBySequenceCache();
1074 }
1075 {
1076 std::size_t const oldInboundLedgersSize =
1077 getInboundLedgers().cacheSize();
1078
1079 getInboundLedgers().sweep();
1080
1081 JLOG(m_journal.debug())
1082 << "InboundLedgers sweep. Size before: "
1083 << oldInboundLedgersSize
1084 << "; size after: " << getInboundLedgers().cacheSize();
1085 }
1086 {
1087 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1088 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1089 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1090
1091 getLedgerReplayer().sweep();
1092
1093 JLOG(m_journal.debug())
1094 << "LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1095 << "; size after: " << getLedgerReplayer().tasksSize();
1096
1097 JLOG(m_journal.debug())
1098 << "LedgerReplayer deltas sweep. Size before: "
1099 << oldDeltasSize
1100 << "; size after: " << getLedgerReplayer().deltasSize();
1101
1102 JLOG(m_journal.debug())
1103 << "LedgerReplayer skipLists sweep. Size before: "
1104 << oldSkipListsSize
1105 << "; size after: " << getLedgerReplayer().skipListsSize();
1106 }
1107 {
1108 std::size_t const oldAcceptedLedgerSize =
1109 m_acceptedLedgerCache.size();
1110
1111 m_acceptedLedgerCache.sweep();
1112
1113 JLOG(m_journal.debug())
1114 << "AcceptedLedgerCache sweep. Size before: "
1115 << oldAcceptedLedgerSize
1116 << "; size after: " << m_acceptedLedgerCache.size();
1117 }
1118 {
1119 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1120
1121 cachedSLEs_.sweep();
1122
1123 JLOG(m_journal.debug())
1124 << "CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1125 << "; size after: " << cachedSLEs_.size();
1126 }
1127
1128 // Set timer to do another sweep later.
1129 setSweepTimer();
1130 }
1131
1134 {
1135 return maxDisallowedLedger_;
1136 }
1137
1138 virtual std::optional<uint256> const&
1139 trapTxID() const override
1140 {
1141 return trapTxID_;
1142 }
1143
1144private:
1145 // For a newly-started validator, this is the greatest persisted ledger
1146 // and new validations must be greater than this.
1147 std::atomic<LedgerIndex> maxDisallowedLedger_{0};
1148
1149 void
1150 startGenesisLedger();
1151
1153 getLastFullLedger();
1154
1156 loadLedgerFromFile(std::string const& ledgerID);
1157
1158 bool
1159 loadOldLedger(
1160 std::string const& ledgerID,
1161 bool replay,
1162 bool isFilename,
1163 std::optional<uint256> trapTxID);
1164
1165 void
1166 setMaxDisallowedLedger();
1167};
1168
1169//------------------------------------------------------------------------------
1170
1171// TODO Break this up into smaller, more digestible initialization segments.
1172bool
1173ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
1174{
1175 // We want to intercept CTRL-C and the standard termination signal SIGTERM
1176 // and terminate the process. This handler will NEVER be invoked twice.
1177 //
1178 // Note that async_wait is "one-shot": for each call, the handler will be
1179 // invoked exactly once, either when one of the registered signals in the
1180 // signal set occurs or the signal set is cancelled. Subsequent signals are
1181 // effectively ignored (technically, they are queued up, waiting for a call
1182 // to async_wait).
1183 m_signals.add(SIGINT);
1184 m_signals.add(SIGTERM);
1185 m_signals.async_wait(
1186 [this](boost::system::error_code const& ec, int signum) {
1187 // Indicates the signal handler has been aborted; do nothing
1188 if (ec == boost::asio::error::operation_aborted)
1189 return;
1190
1191 JLOG(m_journal.info()) << "Received signal " << signum;
1192
1193 if (signum == SIGTERM || signum == SIGINT)
1194 signalStop("Signal: " + to_string(signum));
1195 });
1196
1197 auto debug_log = config_->getDebugLogFile();
1198
1199 if (!debug_log.empty())
1200 {
1201 // Let debug messages go to the file but only WARNING or higher to
1202 // regular output (unless verbose)
1203
1204 if (!logs_->open(debug_log))
1205 std::cerr << "Can't open log file " << debug_log << '\n';
1206
1207 using namespace beast::severities;
1208 if (logs_->threshold() > kDebug)
1209 logs_->threshold(kDebug);
1210 }
1211
1212 JLOG(m_journal.info()) << "Process starting: "
1213 << BuildInfo::getFullVersionString()
1214 << ", Instance Cookie: " << instanceCookie_;
1215
1216 if (numberOfThreads(*config_) < 2)
1217 {
1218 JLOG(m_journal.warn()) << "Limited to a single I/O service thread by "
1219 "system configuration.";
1220 }
1221
1222 // Optionally turn off logging to console.
1223 logs_->silent(config_->silent());
1224
1225 if (!initRelationalDatabase() || !initNodeStore())
1226 return false;
1227
1228 if (!peerReservations_->load(getWalletDB()))
1229 {
1230 JLOG(m_journal.fatal()) << "Cannot find peer reservations!";
1231 return false;
1232 }
1233
1234 if (validatorKeys_.keys)
1235 setMaxDisallowedLedger();
1236
1237 // Configure the amendments the server supports
1238 {
1239 auto const supported = []() {
1240 auto const& amendments = detail::supportedAmendments();
1242 supported.reserve(amendments.size());
1243 for (auto const& [a, vote] : amendments)
1244 {
1245 auto const f = ripple::getRegisteredFeature(a);
1246 XRPL_ASSERT(
1247 f, "ripple::ApplicationImp::setup : registered feature");
1248 if (f)
1249 supported.emplace_back(a, *f, vote);
1250 }
1251 return supported;
1252 }();
1253 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1254
1255 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1256
1257 m_amendmentTable = make_AmendmentTable(
1258 *this,
1259 config().AMENDMENT_MAJORITY_TIME,
1260 supported,
1261 upVoted,
1262 downVoted,
1263 logs_->journal("Amendments"));
1264 }
1265
1266 Pathfinder::initPathTable();
1267
1268 auto const startUp = config_->START_UP;
1269 JLOG(m_journal.debug()) << "startUp: " << startUp;
1270 if (startUp == Config::FRESH)
1271 {
1272 JLOG(m_journal.info()) << "Starting new Ledger";
1273
1274 startGenesisLedger();
1275 }
1276 else if (
1277 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1278 startUp == Config::REPLAY)
1279 {
1280 JLOG(m_journal.info()) << "Loading specified Ledger";
1281
1282 if (!loadOldLedger(
1283 config_->START_LEDGER,
1284 startUp == Config::REPLAY,
1285 startUp == Config::LOAD_FILE,
1286 config_->TRAP_TX_HASH))
1287 {
1288 JLOG(m_journal.error())
1289 << "The specified ledger could not be loaded.";
1290 if (config_->FAST_LOAD)
1291 {
1292 // Fall back to syncing from the network, such as
1293 // when there's no existing data.
1294 startGenesisLedger();
1295 }
1296 else
1297 {
1298 return false;
1299 }
1300 }
1301 }
1302 else if (startUp == Config::NETWORK)
1303 {
1304 // This should probably become the default once we have a stable
1305 // network.
1306 if (!config_->standalone())
1307 m_networkOPs->setNeedNetworkLedger();
1308
1309 startGenesisLedger();
1310 }
1311 else
1312 {
1313 startGenesisLedger();
1314 }
1315
1316 if (auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1317 {
1318 m_ledgerMaster->setLedgerRangePresent(
1319 forcedRange->first, forcedRange->second);
1320 }
1321
1322 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1323
1324 nodeIdentity_ = getNodeIdentity(*this, cmdline);
1325
1326 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1327 {
1328 JLOG(m_journal.fatal()) << "Invalid entry in cluster configuration.";
1329 return false;
1330 }
1331
1332 {
1333 if (validatorKeys_.configInvalid())
1334 return false;
1335
1336 if (!validatorManifests_->load(
1337 getWalletDB(),
1338 "ValidatorManifests",
1339 validatorKeys_.manifest,
1340 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1341 {
1342 JLOG(m_journal.fatal()) << "Invalid configured validator manifest.";
1343 return false;
1344 }
1345
1346 publisherManifests_->load(getWalletDB(), "PublisherManifests");
1347
1348 // It is possible to have a valid ValidatorKeys object without
1349 // setting the signingKey or masterKey. This occurs if the
1350 // configuration file does not have either
1351 // SECTION_VALIDATOR_TOKEN or SECTION_VALIDATION_SEED section.
1352
1353 // masterKey for the configuration-file specified validator keys
1354 std::optional<PublicKey> localSigningKey;
1355 if (validatorKeys_.keys)
1356 localSigningKey = validatorKeys_.keys->publicKey;
1357
1358 // Setup trusted validators
1359 if (!validators_->load(
1360 localSigningKey,
1361 config().section(SECTION_VALIDATORS).values(),
1362 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1363 config().VALIDATOR_LIST_THRESHOLD))
1364 {
1365 JLOG(m_journal.fatal())
1366 << "Invalid entry in validator configuration.";
1367 return false;
1368 }
1369 }
1370
1371 if (!validatorSites_->load(
1372 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1373 {
1374 JLOG(m_journal.fatal())
1375 << "Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES << "]";
1376 return false;
1377 }
1378
1379 // Tell the AmendmentTable who the trusted validators are.
1380 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1381
1382 //----------------------------------------------------------------------
1383 //
1384 // Server
1385 //
1386 //----------------------------------------------------------------------
1387
1388 // VFALCO NOTE Unfortunately, in stand-alone mode some code still
1389 // foolishly calls overlay(). When this is fixed we can
1390 // move the instantiation inside a conditional:
1391 //
1392 // if (!config_.standalone())
1393 overlay_ = make_Overlay(
1394 *this,
1395 setup_Overlay(*config_),
1396 *serverHandler_,
1397 *m_resourceManager,
1398 *m_resolver,
1399 get_io_context(),
1400 *config_,
1401 m_collectorManager->collector());
1402 add(*overlay_); // add to PropertyStream
1403
1404 // start first consensus round
1405 if (!m_networkOPs->beginConsensus(
1406 m_ledgerMaster->getClosedLedger()->info().hash, {}))
1407 {
1408 JLOG(m_journal.fatal()) << "Unable to start consensus";
1409 return false;
1410 }
1411
1412 {
1413 try
1414 {
1415 auto setup = setup_ServerHandler(
1416 *config_, beast::logstream{m_journal.error()});
1417 setup.makeContexts();
1418 serverHandler_->setup(setup, m_journal);
1419 fixConfigPorts(*config_, serverHandler_->endpoints());
1420 }
1421 catch (std::exception const& e)
1422 {
1423 if (auto stream = m_journal.fatal())
1424 {
1425 stream << "Unable to setup server handler";
1426 if (std::strlen(e.what()) > 0)
1427 stream << ": " << e.what();
1428 }
1429 return false;
1430 }
1431 }
1432
1433 // Begin connecting to network.
1434 if (!config_->standalone())
1435 {
1436 // Should this message be here, conceptually? In theory this sort
1437 // of message, if displayed, should be displayed from PeerFinder.
1438 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1439 {
1440 JLOG(m_journal.warn())
1441 << "No outbound peer connections will be made";
1442 }
1443
1444 // VFALCO NOTE the state timer resets the deadlock detector.
1445 //
1446 m_networkOPs->setStateTimer();
1447 }
1448 else
1449 {
1450 JLOG(m_journal.warn()) << "Running in standalone mode";
1451
1452 m_networkOPs->setStandAlone();
1453 }
1454
1455 if (config_->canSign())
1456 {
1457 JLOG(m_journal.warn()) << "*** The server is configured to allow the "
1458 "'sign' and 'sign_for'";
1459 JLOG(m_journal.warn()) << "*** commands. These commands have security "
1460 "implications and have";
1461 JLOG(m_journal.warn()) << "*** been deprecated. They will be removed "
1462 "in a future release of";
1463 JLOG(m_journal.warn()) << "*** rippled.";
1464 JLOG(m_journal.warn()) << "*** If you do not use them to sign "
1465 "transactions please edit your";
1466 JLOG(m_journal.warn())
1467 << "*** configuration file and remove the [enable_signing] stanza.";
1468 JLOG(m_journal.warn()) << "*** If you do use them to sign transactions "
1469 "please migrate to a";
1470 JLOG(m_journal.warn())
1471 << "*** standalone signing solution as soon as possible.";
1472 }
1473
1474 //
1475 // Execute start up rpc commands.
1476 //
1477 for (auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1478 {
1479 Json::Reader jrReader;
1480 Json::Value jvCommand;
1481
1482 if (!jrReader.parse(cmd, jvCommand))
1483 {
1484 JLOG(m_journal.fatal()) << "Couldn't parse entry in ["
1485 << SECTION_RPC_STARTUP << "]: '" << cmd;
1486 }
1487
1488 if (!config_->quiet())
1489 {
1490 JLOG(m_journal.fatal())
1491 << "Startup RPC: " << jvCommand << std::endl;
1492 }
1493
1494 Resource::Charge loadType = Resource::feeReferenceRPC;
1496 RPC::JsonContext context{
1497 {journal("RPCHandler"),
1498 *this,
1499 loadType,
1500 getOPs(),
1501 getLedgerMaster(),
1502 c,
1503 Role::ADMIN,
1504 {},
1505 {},
1506 RPC::apiMaximumSupportedVersion},
1507 jvCommand};
1508
1509 Json::Value jvResult;
1510 RPC::doCommand(context, jvResult);
1511
1512 if (!config_->quiet())
1513 {
1514 JLOG(m_journal.fatal()) << "Result: " << jvResult << std::endl;
1515 }
1516 }
1517
1518 validatorSites_->start();
1519
1520 return true;
1521}
1522
1523void
1524ApplicationImp::start(bool withTimers)
1525{
1526 JLOG(m_journal.info()) << "Application starting. Version is "
1527 << BuildInfo::getVersionString();
1528
1529 if (withTimers)
1530 {
1531 setSweepTimer();
1532 setEntropyTimer();
1533 }
1534
1535 m_io_latency_sampler.start();
1536 m_resolver->start();
1537 m_loadManager->start();
1538 m_shaMapStore->start();
1539 if (overlay_)
1540 overlay_->start();
1541
1542 if (grpcServer_->start())
1544 *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1545
1546 ledgerCleaner_->start();
1547 perfLog_->start();
1548}
1549
1550void
1551ApplicationImp::run()
1552{
1553 if (!config_->standalone())
1554 {
1555 // VFALCO NOTE This seems unnecessary. If we properly refactor the load
1556 // manager then the stall detector can just always be
1557 // "armed"
1558 //
1559 getLoadManager().activateStallDetector();
1560 }
1561
1562 {
1563 std::unique_lock<std::mutex> lk{stoppingMutex_};
1564 stoppingCondition_.wait(lk, [this] { return isTimeToStop.load(); });
1565 }
1566
1567 JLOG(m_journal.debug()) << "Application stopping";
1568
1569 m_io_latency_sampler.cancel_async();
1570
1571 // VFALCO Enormous hack, we have to force the probe to cancel
1572 // before we stop the io_context queue or else it never
1573 // unblocks in its destructor. The fix is to make all
1574 // io_objects gracefully handle exit so that we can
1575 // naturally return from io_context::run() instead of
1576 // forcing a call to io_context::stop()
1577 m_io_latency_sampler.cancel();
1578
1579 m_resolver->stop_async();
1580
1581 // NIKB This is a hack - we need to wait for the resolver to
1582 // stop. before we stop the io_server_queue or weird
1583 // things will happen.
1584 m_resolver->stop();
1585
1586 {
1587 try
1588 {
1589 sweepTimer_.cancel();
1590 }
1591 catch (boost::system::system_error const& e)
1592 {
1593 JLOG(m_journal.error())
1594 << "Application: sweepTimer cancel error: " << e.what();
1595 }
1596
1597 try
1598 {
1599 entropyTimer_.cancel();
1600 }
1601 catch (boost::system::system_error const& e)
1602 {
1603 JLOG(m_journal.error())
1604 << "Application: entropyTimer cancel error: " << e.what();
1605 }
1606 }
1607
1608 // Make sure that any waitHandlers pending in our timers are done
1609 // before we declare ourselves stopped.
1610 using namespace std::chrono_literals;
1611
1612 waitHandlerCounter_.join("Application", 1s, m_journal);
1613
1614 mValidations.flush();
1615
1616 validatorSites_->stop();
1617
1618 // TODO Store manifests in manifests.sqlite instead of wallet.db
1619 validatorManifests_->save(
1620 getWalletDB(), "ValidatorManifests", [this](PublicKey const& pubKey) {
1621 return validators().listed(pubKey);
1622 });
1623
1624 publisherManifests_->save(
1625 getWalletDB(), "PublisherManifests", [this](PublicKey const& pubKey) {
1626 return validators().trustedPublisher(pubKey);
1627 });
1628
1629 // The order of these stop calls is delicate.
1630 // Re-ordering them risks undefined behavior.
1631 m_loadManager->stop();
1632 m_shaMapStore->stop();
1633 m_jobQueue->stop();
1634 if (overlay_)
1635 overlay_->stop();
1636 grpcServer_->stop();
1637 m_networkOPs->stop();
1638 serverHandler_->stop();
1639 m_ledgerReplayer->stop();
1640 m_inboundTransactions->stop();
1641 m_inboundLedgers->stop();
1642 ledgerCleaner_->stop();
1643 m_nodeStore->stop();
1644 perfLog_->stop();
1645
1646 JLOG(m_journal.info()) << "Done.";
1647}
1648
1649void
1650ApplicationImp::signalStop(std::string msg)
1651{
1652 if (!isTimeToStop.exchange(true))
1653 {
1654 if (msg.empty())
1655 JLOG(m_journal.warn()) << "Server stopping";
1656 else
1657 JLOG(m_journal.warn()) << "Server stopping: " << msg;
1658
1659 stoppingCondition_.notify_all();
1660 }
1661}
1662
1663bool
1664ApplicationImp::checkSigs() const
1665{
1666 return checkSigs_;
1667}
1668
1669void
1670ApplicationImp::checkSigs(bool check)
1671{
1672 checkSigs_ = check;
1673}
1674
1675bool
1676ApplicationImp::isStopping() const
1677{
1678 return isTimeToStop.load();
1679}
1680
1681int
1682ApplicationImp::fdRequired() const
1683{
1684 // Standard handles, config file, misc I/O etc:
1685 int needed = 128;
1686
1687 // 2x the configured peer limit for peer connections:
1688 if (overlay_)
1689 needed += 2 * overlay_->limit();
1690
1691 // the number of fds needed by the backend (internally
1692 // doubled if online delete is enabled).
1693 needed += std::max(5, m_shaMapStore->fdRequired());
1694
1695 // One fd per incoming connection a port can accept, or
1696 // if no limit is set, assume it'll handle 256 clients.
1697 for (auto const& p : serverHandler_->setup().ports)
1698 needed += std::max(256, p.limit);
1699
1700 // The minimum number of file descriptors we need is 1024:
1701 return std::max(1024, needed);
1702}
1703
1704//------------------------------------------------------------------------------
1705
1706void
1707ApplicationImp::startGenesisLedger()
1708{
1709 std::vector<uint256> const initialAmendments =
1710 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1712
1714 create_genesis, *config_, initialAmendments, nodeFamily_);
1715 m_ledgerMaster->storeLedger(genesis);
1716
1717 auto const next =
1718 std::make_shared<Ledger>(*genesis, timeKeeper().closeTime());
1719 next->updateSkipList();
1720 XRPL_ASSERT(
1721 next->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1722 next->read(keylet::fees()),
1723 "ripple::ApplicationImp::startGenesisLedger : valid ledger fees");
1724 next->setImmutable();
1725 openLedger_.emplace(next, cachedSLEs_, logs_->journal("OpenLedger"));
1726 m_ledgerMaster->storeLedger(next);
1727 m_ledgerMaster->switchLCL(next);
1728}
1729
1731ApplicationImp::getLastFullLedger()
1732{
1733 auto j = journal("Ledger");
1734
1735 try
1736 {
1737 auto const [ledger, seq, hash] = getLatestLedger(*this);
1738
1739 if (!ledger)
1740 return ledger;
1741
1742 XRPL_ASSERT(
1743 ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1744 ledger->read(keylet::fees()),
1745 "ripple::ApplicationImp::getLastFullLedger : valid ledger fees");
1746 ledger->setImmutable();
1747
1748 if (getLedgerMaster().haveLedger(seq))
1749 ledger->setValidated();
1750
1751 if (ledger->info().hash == hash)
1752 {
1753 JLOG(j.trace()) << "Loaded ledger: " << hash;
1754 return ledger;
1755 }
1756
1757 if (auto stream = j.error())
1758 {
1759 stream << "Failed on ledger";
1760 Json::Value p;
1761 addJson(p, {*ledger, nullptr, LedgerFill::full});
1762 stream << p;
1763 }
1764
1765 return {};
1766 }
1767 catch (SHAMapMissingNode const& mn)
1768 {
1769 JLOG(j.warn()) << "Ledger in database: " << mn.what();
1770 return {};
1771 }
1772}
1773
1775ApplicationImp::loadLedgerFromFile(std::string const& name)
1776{
1777 try
1778 {
1779 std::ifstream ledgerFile(name, std::ios::in);
1780
1781 if (!ledgerFile)
1782 {
1783 JLOG(m_journal.fatal()) << "Unable to open file '" << name << "'";
1784 return nullptr;
1785 }
1786
1787 Json::Reader reader;
1788 Json::Value jLedger;
1789
1790 if (!reader.parse(ledgerFile, jLedger))
1791 {
1792 JLOG(m_journal.fatal()) << "Unable to parse ledger JSON";
1793 return nullptr;
1794 }
1795
1797
1798 // accept a wrapped ledger
1799 if (ledger.get().isMember("result"))
1800 ledger = ledger.get()["result"];
1801
1802 if (ledger.get().isMember("ledger"))
1803 ledger = ledger.get()["ledger"];
1804
1805 std::uint32_t seq = 1;
1806 auto closeTime = timeKeeper().closeTime();
1807 using namespace std::chrono_literals;
1808 auto closeTimeResolution = 30s;
1809 bool closeTimeEstimated = false;
1810 std::uint64_t totalDrops = 0;
1811
1812 if (ledger.get().isMember("accountState"))
1813 {
1814 if (ledger.get().isMember(jss::ledger_index))
1815 {
1816 seq = ledger.get()[jss::ledger_index].asUInt();
1817 }
1818
1819 if (ledger.get().isMember("close_time"))
1820 {
1821 using tp = NetClock::time_point;
1822 using d = tp::duration;
1823 closeTime = tp{d{ledger.get()["close_time"].asUInt()}};
1824 }
1825 if (ledger.get().isMember("close_time_resolution"))
1826 {
1827 using namespace std::chrono;
1828 closeTimeResolution =
1829 seconds{ledger.get()["close_time_resolution"].asUInt()};
1830 }
1831 if (ledger.get().isMember("close_time_estimated"))
1832 {
1833 closeTimeEstimated =
1834 ledger.get()["close_time_estimated"].asBool();
1835 }
1836 if (ledger.get().isMember("total_coins"))
1837 {
1838 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1839 ledger.get()["total_coins"].asString());
1840 }
1841
1842 ledger = ledger.get()["accountState"];
1843 }
1844
1845 if (!ledger.get().isArrayOrNull())
1846 {
1847 JLOG(m_journal.fatal()) << "State nodes must be an array";
1848 return nullptr;
1849 }
1850
1851 auto loadLedger =
1852 std::make_shared<Ledger>(seq, closeTime, *config_, nodeFamily_);
1853 loadLedger->setTotalDrops(totalDrops);
1854
1855 for (Json::UInt index = 0; index < ledger.get().size(); ++index)
1856 {
1857 Json::Value& entry = ledger.get()[index];
1858
1859 if (!entry.isObjectOrNull())
1860 {
1861 JLOG(m_journal.fatal()) << "Invalid entry in ledger";
1862 return nullptr;
1863 }
1864
1865 uint256 uIndex;
1866
1867 if (!uIndex.parseHex(entry[jss::index].asString()))
1868 {
1869 JLOG(m_journal.fatal()) << "Invalid entry in ledger";
1870 return nullptr;
1871 }
1872
1873 entry.removeMember(jss::index);
1874
1875 STParsedJSONObject stp("sle", ledger.get()[index]);
1876
1877 if (!stp.object || uIndex.isZero())
1878 {
1879 JLOG(m_journal.fatal()) << "Invalid entry in ledger";
1880 return nullptr;
1881 }
1882
1883 // VFALCO TODO This is the only place that
1884 // constructor is used, try to remove it
1885 STLedgerEntry sle(*stp.object, uIndex);
1886
1887 if (!loadLedger->addSLE(sle))
1888 {
1889 JLOG(m_journal.fatal())
1890 << "Couldn't add serialized ledger: " << uIndex;
1891 return nullptr;
1892 }
1893 }
1894
1895 loadLedger->stateMap().flushDirty(hotACCOUNT_NODE);
1896
1897 XRPL_ASSERT(
1898 loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1899 loadLedger->read(keylet::fees()),
1900 "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1901 loadLedger->setAccepted(
1902 closeTime, closeTimeResolution, !closeTimeEstimated);
1903
1904 return loadLedger;
1905 }
1906 catch (std::exception const& x)
1907 {
1908 JLOG(m_journal.fatal()) << "Ledger contains invalid data: " << x.what();
1909 return nullptr;
1910 }
1911}
1912
1913bool
1914ApplicationImp::loadOldLedger(
1915 std::string const& ledgerID,
1916 bool replay,
1917 bool isFileName,
1918 std::optional<uint256> trapTxID)
1919{
1920 try
1921 {
1922 std::shared_ptr<Ledger const> loadLedger, replayLedger;
1923
1924 if (isFileName)
1925 {
1926 if (!ledgerID.empty())
1927 loadLedger = loadLedgerFromFile(ledgerID);
1928 }
1929 else if (ledgerID.length() == 64)
1930 {
1931 uint256 hash;
1932
1933 if (hash.parseHex(ledgerID))
1934 {
1935 loadLedger = loadByHash(hash, *this);
1936
1937 if (!loadLedger)
1938 {
1939 // Try to build the ledger from the back end
1941 *this,
1942 hash,
1943 0,
1944 InboundLedger::Reason::GENERIC,
1945 stopwatch(),
1946 make_DummyPeerSet(*this));
1947 if (il->checkLocal())
1948 loadLedger = il->getLedger();
1949 }
1950 }
1951 }
1952 else if (ledgerID.empty() || boost::iequals(ledgerID, "latest"))
1953 {
1954 loadLedger = getLastFullLedger();
1955 }
1956 else
1957 {
1958 // assume by sequence
1959 std::uint32_t index;
1960
1961 if (beast::lexicalCastChecked(index, ledgerID))
1962 loadLedger = loadByIndex(index, *this);
1963 }
1964
1965 if (!loadLedger)
1966 return false;
1967
1968 if (replay)
1969 {
1970 // Replay a ledger close with same prior ledger and transactions
1971
1972 // this ledger holds the transactions we want to replay
1973 replayLedger = loadLedger;
1974
1975 JLOG(m_journal.info()) << "Loading parent ledger";
1976
1977 loadLedger = loadByHash(replayLedger->info().parentHash, *this);
1978 if (!loadLedger)
1979 {
1980 JLOG(m_journal.info())
1981 << "Loading parent ledger from node store";
1982
1983 // Try to build the ledger from the back end
1985 *this,
1986 replayLedger->info().parentHash,
1987 0,
1988 InboundLedger::Reason::GENERIC,
1989 stopwatch(),
1990 make_DummyPeerSet(*this));
1991
1992 if (il->checkLocal())
1993 loadLedger = il->getLedger();
1994
1995 if (!loadLedger)
1996 {
1997 // LCOV_EXCL_START
1998 JLOG(m_journal.fatal()) << "Replay ledger missing/damaged";
1999 UNREACHABLE(
2000 "ripple::ApplicationImp::loadOldLedger : replay ledger "
2001 "missing/damaged");
2002 return false;
2003 // LCOV_EXCL_STOP
2004 }
2005 }
2006 }
2007 using namespace std::chrono_literals;
2008 using namespace date;
2009 static constexpr NetClock::time_point ledgerWarnTimePoint{
2010 sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}};
2011 if (loadLedger->info().closeTime < ledgerWarnTimePoint)
2012 {
2013 JLOG(m_journal.fatal())
2014 << "\n\n*** WARNING ***\n"
2015 "You are replaying a ledger from before "
2016 << to_string(ledgerWarnTimePoint)
2017 << " UTC.\n"
2018 "This replay will not handle your ledger as it was "
2019 "originally "
2020 "handled.\nConsider running an earlier version of rippled "
2021 "to "
2022 "get the older rules.\n*** CONTINUING ***\n";
2023 }
2024
2025 JLOG(m_journal.info()) << "Loading ledger " << loadLedger->info().hash
2026 << " seq:" << loadLedger->info().seq;
2027
2028 if (loadLedger->info().accountHash.isZero())
2029 {
2030 // LCOV_EXCL_START
2031 JLOG(m_journal.fatal()) << "Ledger is empty.";
2032 UNREACHABLE(
2033 "ripple::ApplicationImp::loadOldLedger : ledger is empty");
2034 return false;
2035 // LCOV_EXCL_STOP
2036 }
2037
2038 if (!loadLedger->walkLedger(journal("Ledger"), true))
2039 {
2040 // LCOV_EXCL_START
2041 JLOG(m_journal.fatal()) << "Ledger is missing nodes.";
2042 UNREACHABLE(
2043 "ripple::ApplicationImp::loadOldLedger : ledger is missing "
2044 "nodes");
2045 return false;
2046 // LCOV_EXCL_STOP
2047 }
2048
2049 if (!loadLedger->assertSensible(journal("Ledger")))
2050 {
2051 // LCOV_EXCL_START
2052 JLOG(m_journal.fatal()) << "Ledger is not sensible.";
2053 UNREACHABLE(
2054 "ripple::ApplicationImp::loadOldLedger : ledger is not "
2055 "sensible");
2056 return false;
2057 // LCOV_EXCL_STOP
2058 }
2059
2060 m_ledgerMaster->setLedgerRangePresent(
2061 loadLedger->info().seq, loadLedger->info().seq);
2062
2063 m_ledgerMaster->switchLCL(loadLedger);
2064 loadLedger->setValidated();
2065 m_ledgerMaster->setFullLedger(loadLedger, true, false);
2066 openLedger_.emplace(
2067 loadLedger, cachedSLEs_, logs_->journal("OpenLedger"));
2068
2069 if (replay)
2070 {
2071 // inject transaction(s) from the replayLedger into our open ledger
2072 // and build replay structure
2073 auto replayData =
2074 std::make_unique<LedgerReplay>(loadLedger, replayLedger);
2075
2076 for (auto const& [_, tx] : replayData->orderedTxns())
2077 {
2078 (void)_;
2079 auto txID = tx->getTransactionID();
2080 if (trapTxID == txID)
2081 {
2082 trapTxID_ = txID;
2083 JLOG(m_journal.debug()) << "Trap transaction set: " << txID;
2084 }
2085
2087 tx->add(*s);
2088
2089 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2090
2091 openLedger_->modify(
2092 [&txID, &s](OpenView& view, beast::Journal j) {
2093 view.rawTxInsert(txID, std::move(s), nullptr);
2094 return true;
2095 });
2096 }
2097
2098 m_ledgerMaster->takeReplay(std::move(replayData));
2099
2100 if (trapTxID && !trapTxID_)
2101 {
2102 JLOG(m_journal.fatal())
2103 << "Ledger " << replayLedger->info().seq
2104 << " does not contain the transaction hash " << *trapTxID;
2105 return false;
2106 }
2107 }
2108 }
2109 catch (SHAMapMissingNode const& mn)
2110 {
2111 JLOG(m_journal.fatal())
2112 << "While loading specified ledger: " << mn.what();
2113 return false;
2114 }
2115 catch (boost::bad_lexical_cast&)
2116 {
2117 JLOG(m_journal.fatal())
2118 << "Ledger specified '" << ledgerID << "' is not valid";
2119 return false;
2120 }
2121
2122 return true;
2123}
2124
2125bool
2126ApplicationImp::serverOkay(std::string& reason)
2127{
2128 if (!config().ELB_SUPPORT)
2129 return true;
2130
2131 if (isStopping())
2132 {
2133 reason = "Server is shutting down";
2134 return false;
2135 }
2136
2137 if (getOPs().isNeedNetworkLedger())
2138 {
2139 reason = "Not synchronized with network yet";
2140 return false;
2141 }
2142
2143 if (getOPs().isAmendmentBlocked())
2144 {
2145 reason = "Server version too old";
2146 return false;
2147 }
2148
2149 if (getOPs().isUNLBlocked())
2150 {
2151 reason = "No valid validator list available";
2152 return false;
2153 }
2154
2155 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2156 {
2157 reason = "Not synchronized with network";
2158 return false;
2159 }
2160
2161 if (!getLedgerMaster().isCaughtUp(reason))
2162 return false;
2163
2164 if (getFeeTrack().isLoadedLocal())
2165 {
2166 reason = "Too much load";
2167 return false;
2168 }
2169
2170 return true;
2171}
2172
2174ApplicationImp::journal(std::string const& name)
2175{
2176 return logs_->journal(name);
2177}
2178
2179void
2180ApplicationImp::setMaxDisallowedLedger()
2181{
2182 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2183 if (seq)
2184 maxDisallowedLedger_ = *seq;
2185
2186 JLOG(m_journal.trace())
2187 << "Max persisted ledger is " << maxDisallowedLedger_;
2188}
2189
2190//------------------------------------------------------------------------------
2191
2192Application::Application() : beast::PropertyStream::Source("app")
2193{
2194}
2195
2196//------------------------------------------------------------------------------
2197
2202 std::unique_ptr<TimeKeeper> timeKeeper)
2203{
2205 std::move(config), std::move(logs), std::move(timeKeeper));
2206}
2207
2208void
2209fixConfigPorts(Config& config, Endpoints const& endpoints)
2210{
2211 for (auto const& [name, ep] : endpoints)
2212 {
2213 if (!config.exists(name))
2214 continue;
2215
2216 auto& section = config[name];
2217 auto const optPort = section.get("port");
2218 if (optPort)
2219 {
2220 std::uint16_t const port =
2221 beast::lexicalCast<std::uint16_t>(*optPort);
2222 if (!port)
2223 section.set("port", std::to_string(ep.port()));
2224 }
2225 }
2226}
2227
2228} // namespace ripple
boost::asio::io_context & get_io_context()
Definition BasicApp.h:44
Unserialize a JSON document into a Value.
Definition json_reader.h:39
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Represents a JSON value.
Definition json_value.h:149
bool isObjectOrNull() const
Value removeMember(char const *key)
Remove and return the named member.
std::string asString() const
Returns the unquoted string value.
A generic endpoint for log messages.
Definition Journal.h:60
Stream fatal() const
Definition Journal.h:352
Stream warn() const
Definition Journal.h:340
std::string const & name() const
Returns the name of this source.
void add(Source &source)
Add a child source.
Abstract stream with RAII containers that produce a property tree.
A metric for reporting event timing.
Definition Event.h:41
void notify(std::chrono::duration< Rep, Period > const &value) const
Push an event notification.
Definition Event.h:64
Measures handler latency on an io_context queue.
void sample(Handler &&handler)
Initiate continuous i/o latency sampling.
void cancel()
Cancel all pending i/o.
The amendment table stores the list of enabled and potential amendments.
io_latency_sampler(beast::insight::Event ev, beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_context &ios)
std::atomic< std::chrono::milliseconds > lastSample_
beast::io_latency_probe< std::chrono::steady_clock > m_probe
std::chrono::milliseconds get() const
void operator()(Duration const &elapsed)
std::unique_ptr< TxQ > txQ_
RCLValidations & getValidations() override
virtual ServerHandler & getServerHandler() override
std::unique_ptr< Cluster > cluster_
Config & config() override
std::unique_ptr< ValidatorList > validators_
std::uint64_t const instanceCookie_
HashRouter & getHashRouter() override
OrderBookDB & getOrderBookDB() override
Logs & logs() override
std::unique_ptr< PeerReservationTable > peerReservations_
LoadFeeTrack & getFeeTrack() override
std::unique_ptr< Config > config_
Family & getNodeFamily() override
RCLValidations mValidations
std::optional< OpenLedger > openLedger_
std::unique_ptr< ResolverAsio > m_resolver
AmendmentTable & getAmendmentTable() override
io_latency_sampler m_io_latency_sampler
static std::size_t numberOfThreads(Config const &config)
bool isStopping() const override
LoadManager & getLoadManager() override
std::unique_ptr< LoadFeeTrack > mFeeTrack
boost::asio::steady_timer entropyTimer_
std::unique_ptr< LedgerCleaner > ledgerCleaner_
std::unique_ptr< NodeStore::Database > m_nodeStore
std::unique_ptr< PathRequests > m_pathRequests
std::unique_ptr< ManifestCache > validatorManifests_
LedgerIndex getMaxDisallowedLedger() override
Ensure that a newly-started validator does not sign proposals older than the last ledger it persisted...
ManifestCache & validatorManifests() override
OpenLedger const & openLedger() const override
std::unique_ptr< SHAMapStore > m_shaMapStore
std::unique_ptr< RelationalDatabase > mRelationalDatabase
std::pair< PublicKey, SecretKey > const & nodeIdentity() override
boost::asio::io_context & getIOContext() override
Overlay & overlay() override
ValidatorList & validators() override
ValidatorSite & validatorSites() override
virtual std::optional< uint256 > const & trapTxID() const override
PeerReservationTable & peerReservations() override
ManifestCache & publisherManifests() override
int fdRequired() const override
Application::MutexType & getMasterMutex() override
std::unique_ptr< LedgerMaster > m_ledgerMaster
TransactionMaster & getMasterTransaction() override
CollectorManager & getCollectorManager() override
NodeCache & getTempNodeCache() override
std::unique_ptr< InboundTransactions > m_inboundTransactions
std::unique_ptr< NetworkOPs > m_networkOPs
TransactionMaster m_txMaster
std::unique_ptr< InboundLedgers > m_inboundLedgers
std::unique_ptr< Overlay > overlay_
std::unique_ptr< HashRouter > hashRouter_
RelationalDatabase & getRelationalDatabase() override
bool serverOkay(std::string &reason) override
OpenLedger & openLedger() override
TimeKeeper & timeKeeper() override
std::optional< PublicKey const > getValidationPublicKey() const override
TxQ & getTxQ() override
std::unique_ptr< ValidatorSite > validatorSites_
beast::Journal m_journal
std::unique_ptr< CollectorManager > m_collectorManager
SHAMapStore & getSHAMapStore() override
InboundLedgers & getInboundLedgers() override
InboundTransactions & getInboundTransactions() override
ClosureCounter< void, boost::system::error_code const & > waitHandlerCounter_
void signalStop(std::string msg) override
Cluster & cluster() override
NodeStoreScheduler m_nodeStoreScheduler
LedgerReplayer & getLedgerReplayer() override
std::unique_ptr< ServerHandler > serverHandler_
LedgerMaster & getLedgerMaster() override
void gotTXSet(std::shared_ptr< SHAMap > const &set, bool fromAcquire)
void start(bool withTimers) override
std::unique_ptr< ManifestCache > publisherManifests_
boost::asio::signal_set m_signals
std::unique_ptr< LoadManager > m_loadManager
perf::PerfLog & getPerfLog() override
DatabaseCon & getWalletDB() override
Retrieve the "wallet database".
std::unique_ptr< GRPCServer > grpcServer_
Application::MutexType m_masterMutex
std::unique_ptr< perf::PerfLog > perfLog_
bool checkSigs() const override
std::unique_ptr< TimeKeeper > timeKeeper_
NodeStore::Database & getNodeStore() override
PendingSaves & pendingSaves() override
std::unique_ptr< AmendmentTable > m_amendmentTable
std::optional< uint256 > trapTxID_
ApplicationImp(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
std::unique_ptr< DatabaseCon > mWalletDB
beast::Journal journal(std::string const &name) override
PathRequests & getPathRequests() override
std::optional< std::pair< PublicKey, SecretKey > > nodeIdentity_
boost::asio::steady_timer sweepTimer_
std::uint64_t instanceID() const override
Returns a 64-bit instance identifier, generated at startup.
std::unique_ptr< Resource::Manager > m_resourceManager
std::unique_ptr< LedgerReplayer > m_ledgerReplayer
CachedSLEs & cachedSLEs() override
std::chrono::milliseconds getIOLatency() override
LedgerCleaner & getLedgerCleaner() override
JobQueue & getJobQueue() override
ValidatorKeys const validatorKeys_
std::condition_variable stoppingCondition_
std::unique_ptr< Logs > logs_
Resource::Manager & getResourceManager() override
std::unique_ptr< JobQueue > m_jobQueue
std::atomic< bool > checkSigs_
bool setup(boost::program_options::variables_map const &cmdline) override
std::atomic< bool > isTimeToStop
TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache() override
NetworkOPs & getOPs() override
void onWrite(beast::PropertyStream::Map &stream) override
Subclass override.
TaggedCache< uint256, AcceptedLedger > m_acceptedLedgerCache
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 FORCE_MULTI_THREAD
Definition Config.h:239
bool standalone() const
Definition Config.h:336
std::size_t NODE_SIZE
Definition Config.h:213
Routing table for objects identified by hash.
Definition HashRouter.h:97
Manages the lifetime of inbound ledgers.
Manages the acquisition and lifetime of transaction sets.
A pool of threads to perform work.
Definition JobQueue.h:58
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:46
Manages partitions for logging.
Definition Log.h:52
Remembers manifests with the highest sequence number.
Definition Manifest.h:256
Provides server functionality for clients.
Definition NetworkOPs.h:89
A NodeStore::Scheduler which uses the JobQueue.
Persistency layer for NodeObject.
Definition Database.h:51
Simple NodeStore Scheduler that just peforms the tasks synchronously.
virtual std::unique_ptr< Database > make_Database(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.
Represents the open ledger.
Definition OpenLedger.h:52
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:65
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
Manages the set of connected peers.
Definition Overlay.h:49
Keeps track of which ledgers haven't been fully saved.
A public key.
Definition PublicKey.h:62
static std::unique_ptr< RelationalDatabase > init(Application &app, Config const &config, JobQueue &jobQueue)
init Creates and returns an appropriate RelationalDatabase instance based on configuration.
static std::unique_ptr< ResolverAsio > New(boost::asio::io_context &, beast::Journal)
A consumption charge.
Definition Charge.h:30
An endpoint that consumes resources.
Definition Consumer.h:36
Tracks load and resource consumption.
class to create database, launch online delete thread, and related SQLite database
Definition SHAMapStore.h:38
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:45
std::size_t size() const
Returns the number of items in the container.
Manages various times used by the server.
Definition TimeKeeper.h:32
Transaction Queue.
Definition TxQ.h:61
Validator keys and manifest as set in configuration file.
std::optional< Keys > keys
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:503
bool isZero() const
Definition base_uint.h:540
Singleton class that maintains performance counters and optionally writes Json-formatted data to a di...
Definition PerfLog.h:52
T empty(T... args)
T endl(T... args)
T hardware_concurrency(T... args)
T is_same_v
T load(T... args)
T make_unique(T... args)
T max(T... args)
T min(T... args)
unsigned int UInt
A namespace for easy access to logging severity values.
Definition Journal.h:30
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
std::unique_ptr< Manager > make_Manager(beast::insight::Collector::ptr const &collector, beast::Journal journal)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
Definition Ledger.cpp:1108
std::unique_ptr< NetworkOPs > make_NetworkOPs(Application &app, NetworkOPs::clock_type &clock, bool standalone, std::size_t minPeerCount, bool startvalid, JobQueue &job_queue, LedgerMaster &ledgerMaster, ValidatorKeys const &validatorKeys, boost::asio::io_context &io_svc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
constexpr auto megabytes(T value) noexcept
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
std::unique_ptr< LedgerCleaner > make_LedgerCleaner(Application &app, beast::Journal journal)
TxQ::Setup setup_TxQ(Config const &config)
Build a TxQ::Setup object from application configuration.
Definition TxQ.cpp:1913
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
Definition Ledger.cpp:1118
std::unique_ptr< LoadManager > make_LoadManager(Application &app, beast::Journal journal)
std::unique_ptr< Application > make_Application(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
std::unordered_map< std::string, boost::asio::ip::tcp::endpoint > Endpoints
Definition ServerImpl.h:41
@ hotACCOUNT_NODE
Definition NodeObject.h:35
std::pair< PublicKey, SecretKey > getNodeIdentity(Application &app, boost::program_options::variables_map const &cmdline)
The cryptographic credentials identifying this server instance.
std::unique_ptr< PeerSet > make_DummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
Definition PeerSet.cpp:187
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
Definition PeerSet.cpp:144
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
Definition Ledger.cpp:1131
void addJson(Json::Value &json, LedgerFill const &fill)
Given a Ledger and options, fill a Json::Object or Json::Value with a description of the ledger.
std::unique_ptr< CollectorManager > make_CollectorManager(Section const &params, beast::Journal journal)
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
std::unique_ptr< InboundLedgers > make_InboundLedgers(Application &app, InboundLedgers::clock_type &clock, beast::insight::Collector::ptr const &collector)
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
HashRouter::Setup setup_HashRouter(Config const &config)
Stopwatch & stopwatch()
Returns an instance of a wall clock.
Definition chrono.h:119
std::optional< uint256 > getRegisteredFeature(std::string const &name)
Definition Feature.cpp:382
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
Definition Wallet.cpp:27
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
Definition apply.cpp:118
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, boost::asio::io_context &io_context, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
create_genesis_t const create_genesis
Definition Ledger.cpp:51
std::unique_ptr< Overlay > make_Overlay(Application &app, Overlay::Setup const &setup, ServerHandler &serverHandler, Resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_context &io_context, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
Creates the implementation of Overlay.
static void fixConfigPorts(Config &config, Endpoints const &endpoints)
std::unique_ptr< AmendmentTable > make_AmendmentTable(Application &app, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
Overlay::Setup setup_Overlay(BasicConfig const &config)
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
std::unique_ptr< SHAMapStore > make_SHAMapStore(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
STL namespace.
T ref(T... args)
T length(T... args)
T strlen(T... args)
static std::string importNodeDatabase()
T to_string(T... args)
T what(T... args)