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/nodestore/DummyScheduler.h>
52#include <xrpld/overlay/Cluster.h>
53#include <xrpld/overlay/PeerReservationTable.h>
54#include <xrpld/overlay/PeerSet.h>
55#include <xrpld/overlay/make_Overlay.h>
56#include <xrpld/perflog/PerfLog.h>
57#include <xrpld/rpc/detail/RPCHelpers.h>
58#include <xrpld/shamap/NodeFamily.h>
59#include <xrpl/basics/ByteUtilities.h>
60#include <xrpl/basics/ResolverAsio.h>
61#include <xrpl/basics/random.h>
62#include <xrpl/beast/asio/io_latency_probe.h>
63#include <xrpl/beast/core/LexicalCast.h>
64#include <xrpl/crypto/csprng.h>
65#include <xrpl/json/json_reader.h>
66#include <xrpl/protocol/BuildInfo.h>
67#include <xrpl/protocol/Feature.h>
68#include <xrpl/protocol/Protocol.h>
69#include <xrpl/protocol/STParsedJSON.h>
70#include <xrpl/resource/Fees.h>
71
72#include <boost/algorithm/string/predicate.hpp>
73#include <boost/asio/steady_timer.hpp>
74#include <boost/system/error_code.hpp>
75#include <date/date.h>
76
77#include <chrono>
78#include <condition_variable>
79#include <cstring>
80#include <iostream>
81#include <limits>
82#include <mutex>
83#include <optional>
84#include <sstream>
85#include <utility>
86
87namespace ripple {
88
89static void
90fixConfigPorts(Config& config, Endpoints const& endpoints);
91
92// VFALCO TODO Move the function definitions into the class declaration
93class ApplicationImp : public Application, public BasicApp
94{
95private:
97 {
98 private:
103
104 public:
109 boost::asio::io_service& ios)
110 : m_event(ev)
112 , m_probe(interval, ios)
113 , lastSample_{}
114 {
115 }
116
117 void
119 {
120 m_probe.sample(std::ref(*this));
121 }
122
123 template <class Duration>
124 void
125 operator()(Duration const& elapsed)
126 {
127 using namespace std::chrono;
128 auto const lastSample = ceil<milliseconds>(elapsed);
129
130 lastSample_ = lastSample;
131
132 if (lastSample >= 10ms)
133 m_event.notify(lastSample);
134 if (lastSample >= 500ms)
135 {
136 JLOG(m_journal.warn())
137 << "io_service latency = " << lastSample.count();
138 }
139 }
140
142 get() const
143 {
144 return lastSample_.load();
145 }
146
147 void
149 {
150 m_probe.cancel();
151 }
152
153 void
155 {
157 }
158 };
159
160public:
164
166
170
171 // Required by the SHAMapStore
173
180
185
187
190 // VFALCO TODO Make OrderBookDB abstract
214 boost::asio::steady_timer sweepTimer_;
215 boost::asio::steady_timer entropyTimer_;
216
221
222 boost::asio::signal_set m_signals;
223
224 // Once we get C++20, we could use `std::atomic_flag` for `isTimeToStop`
225 // and eliminate the need for the condition variable and the mutex.
229
231
233
235
237
238 //--------------------------------------------------------------------------
239
240 static std::size_t
242 {
243#if RIPPLE_SINGLE_IO_SERVICE_THREAD
244 return 1;
245#else
246
247 if (config.IO_WORKERS > 0)
248 return config.IO_WORKERS;
249
250 auto const cores = std::thread::hardware_concurrency();
251
252 // Use a single thread when running on under-provisioned systems
253 // or if we are configured to use minimal resources.
254 if ((cores == 1) || ((config.NODE_SIZE == 0) && (cores == 2)))
255 return 1;
256
257 // Otherwise, prefer two threads.
258 return 2;
259#endif
260 }
261
262 //--------------------------------------------------------------------------
263
269 , config_(std::move(config))
270 , logs_(std::move(logs))
271 , timeKeeper_(std::move(timeKeeper))
273 1 +
274 rand_int(
275 crypto_prng(),
276 std::numeric_limits<std::uint64_t>::max() - 1))
277 , m_journal(logs_->journal("Application"))
278
279 // PerfLog must be started before any other threads are launched.
280 , perfLog_(perf::make_PerfLog(
281 perf::setup_PerfLog(
282 config_->section("perf"),
283 config_->CONFIG_DIR),
284 *this,
285 logs_->journal("PerfLog"),
286 [this] { signalStop(); }))
287
288 , m_txMaster(*this)
289
291 config_->section(SECTION_INSIGHT),
292 logs_->journal("Collector")))
293
294 , m_jobQueue(std::make_unique<JobQueue>(
297 return 1;
298
299 if (config->WORKERS)
300 return config->WORKERS;
301
302 auto count =
303 static_cast<int>(std::thread::hardware_concurrency());
304
305 // Be more aggressive about the number of threads to use
306 // for the job queue if the server is configured as "large"
307 // or "huge" if there are enough cores.
308 if (config->NODE_SIZE >= 4 && count >= 16)
309 count = 6 + std::min(count, 8);
310 else if (config->NODE_SIZE >= 3 && count >= 8)
311 count = 4 + std::min(count, 6);
312 else
313 count = 2 + std::min(count, 4);
314
315 return count;
316 }(config_),
317 m_collectorManager->group("jobq"),
318 logs_->journal("JobQueue"),
319 *logs_,
320 *perfLog_))
321
323
325 *this,
327 logs_->journal("SHAMapStore")))
328
330 "NodeCache",
331 16384,
333 stopwatch(),
334 logs_->journal("TaggedCache"))
335
336 , cachedSLEs_(
337 "Cached SLEs",
338 0,
340 stopwatch(),
341 logs_->journal("CachedSLEs"))
342
344
346 m_collectorManager->collector(),
347 logs_->journal("Resource")))
348
349 , m_nodeStore(m_shaMapStore->makeNodeStore(
350 config_->PREFETCH_WORKERS > 0 ? config_->PREFETCH_WORKERS : 4))
351
353
354 , m_orderBookDB(*this)
355
356 , m_pathRequests(std::make_unique<PathRequests>(
357 *this,
358 logs_->journal("PathRequest"),
359 m_collectorManager->collector()))
360
361 , m_ledgerMaster(std::make_unique<LedgerMaster>(
362 *this,
363 stopwatch(),
364 m_collectorManager->collector(),
365 logs_->journal("LedgerMaster")))
366
368 make_LedgerCleaner(*this, logs_->journal("LedgerCleaner")))
369
370 // VFALCO NOTE must come before NetworkOPs to prevent a crash due
371 // to dependencies in the destructor.
372 //
374 *this,
375 stopwatch(),
376 m_collectorManager->collector()))
377
379 *this,
380 m_collectorManager->collector(),
381 [this](std::shared_ptr<SHAMap> const& set, bool fromAcquire) {
382 gotTXSet(set, fromAcquire);
383 }))
384
385 , m_ledgerReplayer(std::make_unique<LedgerReplayer>(
386 *this,
388 make_PeerSetBuilder(*this)))
389
391 "AcceptedLedger",
392 4,
394 stopwatch(),
395 logs_->journal("TaggedCache"))
396
398 *this,
399 stopwatch(),
400 config_->standalone(),
401 config_->NETWORK_QUORUM,
402 config_->START_VALID,
403 *m_jobQueue,
407 logs_->journal("NetworkOPs"),
408 m_collectorManager->collector()))
409
410 , cluster_(std::make_unique<Cluster>(logs_->journal("Overlay")))
411
412 , peerReservations_(std::make_unique<PeerReservationTable>(
413 logs_->journal("PeerReservationTable")))
414
416 std::make_unique<ManifestCache>(logs_->journal("ManifestCache")))
417
419 std::make_unique<ManifestCache>(logs_->journal("ManifestCache")))
420
421 , validators_(std::make_unique<ValidatorList>(
425 config_->legacy("database_path"),
426 logs_->journal("ValidatorList"),
427 config_->VALIDATION_QUORUM))
428
429 , validatorSites_(std::make_unique<ValidatorSite>(*this))
430
432 *this,
434 *m_jobQueue,
438
439 , mFeeTrack(
440 std::make_unique<LoadFeeTrack>(logs_->journal("LoadManager")))
441
442 , hashRouter_(std::make_unique<HashRouter>(
443 stopwatch(),
445
446 , mValidations(
447 ValidationParms(),
448 stopwatch(),
449 *this,
450 logs_->journal("Validations"))
451
452 , m_loadManager(make_LoadManager(*this, logs_->journal("LoadManager")))
453
454 , txQ_(
455 std::make_unique<TxQ>(setup_TxQ(*config_), logs_->journal("TxQ")))
456
458
460
462
463 , checkSigs_(true)
464
465 , m_resolver(
466 ResolverAsio::New(get_io_service(), logs_->journal("Resolver")))
467
469 m_collectorManager->collector()->make_event("ios_latency"),
470 logs_->journal("Application"),
473 , grpcServer_(std::make_unique<GRPCServer>(*this))
474 {
476
477 add(m_resourceManager.get());
478
479 //
480 // VFALCO - READ THIS!
481 //
482 // Do not start threads, open sockets, or do any sort of "real work"
483 // inside the constructor. Put it in start instead. Or if you must,
484 // put it in setup (but everything in setup should be moved to start
485 // anyway.
486 //
487 // The reason is that the unit tests require an Application object to
488 // be created. But we don't actually start all the threads, sockets,
489 // and services when running the unit tests. Therefore anything which
490 // needs to be stopped will not get stopped correctly if it is
491 // started in this constructor.
492 //
493
494 add(ledgerCleaner_.get());
495 }
496
497 //--------------------------------------------------------------------------
498
499 bool
500 setup(boost::program_options::variables_map const& cmdline) override;
501 void
502 start(bool withTimers) override;
503 void
504 run() override;
505 void
506 signalStop(std::string msg = "") override;
507 bool
508 checkSigs() const override;
509 void
510 checkSigs(bool) override;
511 bool
512 isStopping() const override;
513 int
514 fdRequired() const override;
515
516 //--------------------------------------------------------------------------
517
519 instanceID() const override
520 {
521 return instanceCookie_;
522 }
523
524 Logs&
525 logs() override
526 {
527 return *logs_;
528 }
529
530 Config&
531 config() override
532 {
533 return *config_;
534 }
535
538 {
539 return *m_collectorManager;
540 }
541
542 Family&
543 getNodeFamily() override
544 {
545 return nodeFamily_;
546 }
547
549 timeKeeper() override
550 {
551 return *timeKeeper_;
552 }
553
554 JobQueue&
555 getJobQueue() override
556 {
557 return *m_jobQueue;
558 }
559
561 nodeIdentity() override
562 {
563 if (nodeIdentity_)
564 return *nodeIdentity_;
565
567 "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 *m_networkOPs;
583 }
584
585 virtual ServerHandler&
587 {
588 XRPL_ASSERT(
590 "ripple::ApplicationImp::getServerHandler : non-null server "
591 "handle");
592 return *serverHandler_;
593 }
594
595 boost::asio::io_service&
596 getIOService() override
597 {
598 return get_io_service();
599 }
600
602 getIOLatency() override
603 {
604 return m_io_latency_sampler.get();
605 }
606
609 {
610 return *m_ledgerMaster;
611 }
612
615 {
616 return *ledgerCleaner_;
617 }
618
621 {
622 return *m_ledgerReplayer;
623 }
624
627 {
628 return *m_inboundLedgers;
629 }
630
633 {
634 return *m_inboundTransactions;
635 }
636
639 {
641 }
642
643 void
644 gotTXSet(std::shared_ptr<SHAMap> const& set, bool fromAcquire)
645 {
646 if (set)
647 m_networkOPs->mapComplete(set, fromAcquire);
648 }
649
652 {
653 return m_txMaster;
654 }
655
657 getPerfLog() override
658 {
659 return *perfLog_;
660 }
661
662 NodeCache&
664 {
665 return m_tempNodeCache;
666 }
667
669 getNodeStore() override
670 {
671 return *m_nodeStore;
672 }
673
675 getMasterMutex() override
676 {
677 return m_masterMutex;
678 }
679
681 getLoadManager() override
682 {
683 return *m_loadManager;
684 }
685
688 {
689 return *m_resourceManager;
690 }
691
693 getOrderBookDB() override
694 {
695 return m_orderBookDB;
696 }
697
700 {
701 return *m_pathRequests;
702 }
703
705 cachedSLEs() override
706 {
707 return cachedSLEs_;
708 }
709
712 {
713 return *m_amendmentTable;
714 }
715
717 getFeeTrack() override
718 {
719 return *mFeeTrack;
720 }
721
723 getHashRouter() override
724 {
725 return *hashRouter_;
726 }
727
729 getValidations() override
730 {
731 return mValidations;
732 }
733
735 validators() override
736 {
737 return *validators_;
738 }
739
741 validatorSites() override
742 {
743 return *validatorSites_;
744 }
745
748 {
749 return *validatorManifests_;
750 }
751
754 {
755 return *publisherManifests_;
756 }
757
758 Cluster&
759 cluster() override
760 {
761 return *cluster_;
762 }
763
766 {
767 return *peerReservations_;
768 }
769
771 getSHAMapStore() override
772 {
773 return *m_shaMapStore;
774 }
775
777 pendingSaves() override
778 {
779 return pendingSaves_;
780 }
781
783 openLedger() override
784 {
785 return *openLedger_;
786 }
787
788 OpenLedger const&
789 openLedger() const override
790 {
791 return *openLedger_;
792 }
793
794 Overlay&
795 overlay() override
796 {
797 XRPL_ASSERT(
798 overlay_, "ripple::ApplicationImp::overlay : non-null overlay");
799 return *overlay_;
800 }
801
802 TxQ&
803 getTxQ() override
804 {
805 XRPL_ASSERT(
806 txQ_,
807 "ripple::ApplicationImp::getTxQ : non-null transaction queue");
808 return *txQ_;
809 }
810
813 {
814 XRPL_ASSERT(
816 "ripple::ApplicationImp::getRelationalDatabase : non-null "
817 "relational database");
818 return *mRelationalDatabase;
819 }
820
822 getWalletDB() override
823 {
824 XRPL_ASSERT(
825 mWalletDB,
826 "ripple::ApplicationImp::getWalletDB : non-null wallet database");
827 return *mWalletDB;
828 }
829
830 bool
831 serverOkay(std::string& reason) override;
832
834 journal(std::string const& name) override;
835
836 //--------------------------------------------------------------------------
837
838 bool
840 {
841 XRPL_ASSERT(
842 mWalletDB.get() == nullptr,
843 "ripple::ApplicationImp::initRelationalDatabase : null wallet "
844 "database");
845
846 try
847 {
850
851 // wallet database
853 setup.useGlobalPragma = false;
854
856 }
857 catch (std::exception const& e)
858 {
859 JLOG(m_journal.fatal())
860 << "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 NodeStore::DummyScheduler dummyScheduler;
876 megabytes(config_->getValueFor(
877 SizedItem::burstSize, std::nullopt)),
878 dummyScheduler,
879 0,
881 j);
882
883 JLOG(j.warn()) << "Starting node import from '" << source->getName()
884 << "' to '" << m_nodeStore->getName() << "'.";
885
886 using namespace std::chrono;
887 auto const start = steady_clock::now();
888
889 m_nodeStore->importDatabase(*source);
890
891 auto const elapsed =
892 duration_cast<seconds>(steady_clock::now() - start);
893 JLOG(j.warn()) << "Node import from '" << source->getName()
894 << "' took " << elapsed.count() << " seconds.";
895 }
896
897 return true;
898 }
899
900 //--------------------------------------------------------------------------
901 //
902 // PropertyStream
903 //
904
905 void
907 {
908 }
909
910 //--------------------------------------------------------------------------
911
912 void
914 {
915 // Only start the timer if waitHandlerCounter_ is not yet joined.
916 if (auto optionalCountedHandler = waitHandlerCounter_.wrap(
917 [this](boost::system::error_code const& e) {
918 if (e.value() == boost::system::errc::success)
919 {
920 m_jobQueue->addJob(
921 jtSWEEP, "sweep", [this]() { doSweep(); });
922 }
923 // Recover as best we can if an unexpected error occurs.
924 if (e.value() != boost::system::errc::success &&
925 e.value() != boost::asio::error::operation_aborted)
926 {
927 // Try again later and hope for the best.
928 JLOG(m_journal.error())
929 << "Sweep timer got error '" << e.message()
930 << "'. Restarting timer.";
931 setSweepTimer();
932 }
933 }))
934 {
935 using namespace std::chrono;
936 sweepTimer_.expires_from_now(
937 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_from_now(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();
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 const std::optional<uint256>&
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();
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_service(),
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 deadlock detector can just always be
1557 // "armed"
1558 //
1559 getLoadManager().activateDeadlockDetector();
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_service 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_service::run() instead of
1576 // forcing a call to io_service::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 boost::system::error_code ec;
1588 sweepTimer_.cancel(ec);
1589 if (ec)
1590 {
1591 JLOG(m_journal.error())
1592 << "Application: sweepTimer cancel error: " << ec.message();
1593 }
1594
1595 ec.clear();
1596 entropyTimer_.cancel(ec);
1597 if (ec)
1598 {
1599 JLOG(m_journal.error())
1600 << "Application: entropyTimer cancel error: " << ec.message();
1601 }
1602 }
1603
1604 // Make sure that any waitHandlers pending in our timers are done
1605 // before we declare ourselves stopped.
1606 using namespace std::chrono_literals;
1607
1608 waitHandlerCounter_.join("Application", 1s, m_journal);
1609
1610 mValidations.flush();
1611
1612 validatorSites_->stop();
1613
1614 // TODO Store manifests in manifests.sqlite instead of wallet.db
1615 validatorManifests_->save(
1616 getWalletDB(), "ValidatorManifests", [this](PublicKey const& pubKey) {
1617 return validators().listed(pubKey);
1618 });
1619
1620 publisherManifests_->save(
1621 getWalletDB(), "PublisherManifests", [this](PublicKey const& pubKey) {
1622 return validators().trustedPublisher(pubKey);
1623 });
1624
1625 // The order of these stop calls is delicate.
1626 // Re-ordering them risks undefined behavior.
1627 m_loadManager->stop();
1628 m_shaMapStore->stop();
1629 m_jobQueue->stop();
1630 if (overlay_)
1631 overlay_->stop();
1632 grpcServer_->stop();
1633 m_networkOPs->stop();
1634 serverHandler_->stop();
1635 m_ledgerReplayer->stop();
1636 m_inboundTransactions->stop();
1637 m_inboundLedgers->stop();
1638 ledgerCleaner_->stop();
1639 m_nodeStore->stop();
1640 perfLog_->stop();
1641
1642 JLOG(m_journal.info()) << "Done.";
1643}
1644
1645void
1646ApplicationImp::signalStop(std::string msg)
1647{
1648 if (!isTimeToStop.exchange(true))
1649 {
1650 if (msg.empty())
1651 JLOG(m_journal.warn()) << "Server stopping";
1652 else
1653 JLOG(m_journal.warn()) << "Server stopping: " << msg;
1654
1655 stoppingCondition_.notify_all();
1656 }
1657}
1658
1659bool
1660ApplicationImp::checkSigs() const
1661{
1662 return checkSigs_;
1663}
1664
1665void
1666ApplicationImp::checkSigs(bool check)
1667{
1668 checkSigs_ = check;
1669}
1670
1671bool
1672ApplicationImp::isStopping() const
1673{
1674 return isTimeToStop.load();
1675}
1676
1677int
1678ApplicationImp::fdRequired() const
1679{
1680 // Standard handles, config file, misc I/O etc:
1681 int needed = 128;
1682
1683 // 2x the configured peer limit for peer connections:
1684 if (overlay_)
1685 needed += 2 * overlay_->limit();
1686
1687 // the number of fds needed by the backend (internally
1688 // doubled if online delete is enabled).
1689 needed += std::max(5, m_shaMapStore->fdRequired());
1690
1691 // One fd per incoming connection a port can accept, or
1692 // if no limit is set, assume it'll handle 256 clients.
1693 for (auto const& p : serverHandler_->setup().ports)
1694 needed += std::max(256, p.limit);
1695
1696 // The minimum number of file descriptors we need is 1024:
1697 return std::max(1024, needed);
1698}
1699
1700//------------------------------------------------------------------------------
1701
1702void
1703ApplicationImp::startGenesisLedger()
1704{
1705 std::vector<uint256> const initialAmendments =
1706 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1708
1709 std::shared_ptr<Ledger> const genesis = std::make_shared<Ledger>(
1710 create_genesis, *config_, initialAmendments, nodeFamily_);
1711 m_ledgerMaster->storeLedger(genesis);
1712
1713 auto const next =
1714 std::make_shared<Ledger>(*genesis, timeKeeper().closeTime());
1715 next->updateSkipList();
1716 XRPL_ASSERT(
1717 next->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1718 next->read(keylet::fees()),
1719 "ripple::ApplicationImp::startGenesisLedger : valid ledger fees");
1720 next->setImmutable();
1721 openLedger_.emplace(next, cachedSLEs_, logs_->journal("OpenLedger"));
1722 m_ledgerMaster->storeLedger(next);
1723 m_ledgerMaster->switchLCL(next);
1724}
1725
1727ApplicationImp::getLastFullLedger()
1728{
1729 auto j = journal("Ledger");
1730
1731 try
1732 {
1733 auto const [ledger, seq, hash] = getLatestLedger(*this);
1734
1735 if (!ledger)
1736 return ledger;
1737
1738 XRPL_ASSERT(
1739 ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1740 ledger->read(keylet::fees()),
1741 "ripple::ApplicationImp::getLastFullLedger : valid ledger fees");
1742 ledger->setImmutable();
1743
1744 if (getLedgerMaster().haveLedger(seq))
1745 ledger->setValidated();
1746
1747 if (ledger->info().hash == hash)
1748 {
1749 JLOG(j.trace()) << "Loaded ledger: " << hash;
1750 return ledger;
1751 }
1752
1753 if (auto stream = j.error())
1754 {
1755 stream << "Failed on ledger";
1756 Json::Value p;
1757 addJson(p, {*ledger, nullptr, LedgerFill::full});
1758 stream << p;
1759 }
1760
1761 return {};
1762 }
1763 catch (SHAMapMissingNode const& mn)
1764 {
1765 JLOG(j.warn()) << "Ledger in database: " << mn.what();
1766 return {};
1767 }
1768}
1769
1771ApplicationImp::loadLedgerFromFile(std::string const& name)
1772{
1773 try
1774 {
1775 std::ifstream ledgerFile(name, std::ios::in);
1776
1777 if (!ledgerFile)
1778 {
1779 JLOG(m_journal.fatal()) << "Unable to open file '" << name << "'";
1780 return nullptr;
1781 }
1782
1783 Json::Reader reader;
1784 Json::Value jLedger;
1785
1786 if (!reader.parse(ledgerFile, jLedger))
1787 {
1788 JLOG(m_journal.fatal()) << "Unable to parse ledger JSON";
1789 return nullptr;
1790 }
1791
1793
1794 // accept a wrapped ledger
1795 if (ledger.get().isMember("result"))
1796 ledger = ledger.get()["result"];
1797
1798 if (ledger.get().isMember("ledger"))
1799 ledger = ledger.get()["ledger"];
1800
1801 std::uint32_t seq = 1;
1802 auto closeTime = timeKeeper().closeTime();
1803 using namespace std::chrono_literals;
1804 auto closeTimeResolution = 30s;
1805 bool closeTimeEstimated = false;
1806 std::uint64_t totalDrops = 0;
1807
1808 if (ledger.get().isMember("accountState"))
1809 {
1810 if (ledger.get().isMember(jss::ledger_index))
1811 {
1812 seq = ledger.get()[jss::ledger_index].asUInt();
1813 }
1814
1815 if (ledger.get().isMember("close_time"))
1816 {
1817 using tp = NetClock::time_point;
1818 using d = tp::duration;
1819 closeTime = tp{d{ledger.get()["close_time"].asUInt()}};
1820 }
1821 if (ledger.get().isMember("close_time_resolution"))
1822 {
1823 using namespace std::chrono;
1824 closeTimeResolution =
1825 seconds{ledger.get()["close_time_resolution"].asUInt()};
1826 }
1827 if (ledger.get().isMember("close_time_estimated"))
1828 {
1829 closeTimeEstimated =
1830 ledger.get()["close_time_estimated"].asBool();
1831 }
1832 if (ledger.get().isMember("total_coins"))
1833 {
1834 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1835 ledger.get()["total_coins"].asString());
1836 }
1837
1838 ledger = ledger.get()["accountState"];
1839 }
1840
1841 if (!ledger.get().isArrayOrNull())
1842 {
1843 JLOG(m_journal.fatal()) << "State nodes must be an array";
1844 return nullptr;
1845 }
1846
1847 auto loadLedger =
1848 std::make_shared<Ledger>(seq, closeTime, *config_, nodeFamily_);
1849 loadLedger->setTotalDrops(totalDrops);
1850
1851 for (Json::UInt index = 0; index < ledger.get().size(); ++index)
1852 {
1853 Json::Value& entry = ledger.get()[index];
1854
1855 if (!entry.isObjectOrNull())
1856 {
1857 JLOG(m_journal.fatal()) << "Invalid entry in ledger";
1858 return nullptr;
1859 }
1860
1861 uint256 uIndex;
1862
1863 if (!uIndex.parseHex(entry[jss::index].asString()))
1864 {
1865 JLOG(m_journal.fatal()) << "Invalid entry in ledger";
1866 return nullptr;
1867 }
1868
1869 entry.removeMember(jss::index);
1870
1871 STParsedJSONObject stp("sle", ledger.get()[index]);
1872
1873 if (!stp.object || uIndex.isZero())
1874 {
1875 JLOG(m_journal.fatal()) << "Invalid entry in ledger";
1876 return nullptr;
1877 }
1878
1879 // VFALCO TODO This is the only place that
1880 // constructor is used, try to remove it
1881 STLedgerEntry sle(*stp.object, uIndex);
1882
1883 if (!loadLedger->addSLE(sle))
1884 {
1885 JLOG(m_journal.fatal())
1886 << "Couldn't add serialized ledger: " << uIndex;
1887 return nullptr;
1888 }
1889 }
1890
1891 loadLedger->stateMap().flushDirty(hotACCOUNT_NODE);
1892
1893 XRPL_ASSERT(
1894 loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1895 loadLedger->read(keylet::fees()),
1896 "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1897 loadLedger->setAccepted(
1898 closeTime, closeTimeResolution, !closeTimeEstimated);
1899
1900 return loadLedger;
1901 }
1902 catch (std::exception const& x)
1903 {
1904 JLOG(m_journal.fatal()) << "Ledger contains invalid data: " << x.what();
1905 return nullptr;
1906 }
1907}
1908
1909bool
1910ApplicationImp::loadOldLedger(
1911 std::string const& ledgerID,
1912 bool replay,
1913 bool isFileName,
1914 std::optional<uint256> trapTxID)
1915{
1916 try
1917 {
1918 std::shared_ptr<Ledger const> loadLedger, replayLedger;
1919
1920 if (isFileName)
1921 {
1922 if (!ledgerID.empty())
1923 loadLedger = loadLedgerFromFile(ledgerID);
1924 }
1925 else if (ledgerID.length() == 64)
1926 {
1927 uint256 hash;
1928
1929 if (hash.parseHex(ledgerID))
1930 {
1931 loadLedger = loadByHash(hash, *this);
1932
1933 if (!loadLedger)
1934 {
1935 // Try to build the ledger from the back end
1936 auto il = std::make_shared<InboundLedger>(
1937 *this,
1938 hash,
1939 0,
1940 InboundLedger::Reason::GENERIC,
1941 stopwatch(),
1942 make_DummyPeerSet(*this));
1943 if (il->checkLocal())
1944 loadLedger = il->getLedger();
1945 }
1946 }
1947 }
1948 else if (ledgerID.empty() || boost::iequals(ledgerID, "latest"))
1949 {
1950 loadLedger = getLastFullLedger();
1951 }
1952 else
1953 {
1954 // assume by sequence
1955 std::uint32_t index;
1956
1957 if (beast::lexicalCastChecked(index, ledgerID))
1958 loadLedger = loadByIndex(index, *this);
1959 }
1960
1961 if (!loadLedger)
1962 return false;
1963
1964 if (replay)
1965 {
1966 // Replay a ledger close with same prior ledger and transactions
1967
1968 // this ledger holds the transactions we want to replay
1969 replayLedger = loadLedger;
1970
1971 JLOG(m_journal.info()) << "Loading parent ledger";
1972
1973 loadLedger = loadByHash(replayLedger->info().parentHash, *this);
1974 if (!loadLedger)
1975 {
1976 JLOG(m_journal.info())
1977 << "Loading parent ledger from node store";
1978
1979 // Try to build the ledger from the back end
1980 auto il = std::make_shared<InboundLedger>(
1981 *this,
1982 replayLedger->info().parentHash,
1983 0,
1984 InboundLedger::Reason::GENERIC,
1985 stopwatch(),
1986 make_DummyPeerSet(*this));
1987
1988 if (il->checkLocal())
1989 loadLedger = il->getLedger();
1990
1991 if (!loadLedger)
1992 {
1993 JLOG(m_journal.fatal()) << "Replay ledger missing/damaged";
1994 UNREACHABLE(
1995 "ripple::ApplicationImp::loadOldLedger : replay ledger "
1996 "missing/damaged");
1997 return false;
1998 }
1999 }
2000 }
2001 using namespace std::chrono_literals;
2002 using namespace date;
2003 static constexpr NetClock::time_point ledgerWarnTimePoint{
2004 sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}};
2005 if (loadLedger->info().closeTime < ledgerWarnTimePoint)
2006 {
2007 JLOG(m_journal.fatal())
2008 << "\n\n*** WARNING ***\n"
2009 "You are replaying a ledger from before "
2010 << to_string(ledgerWarnTimePoint)
2011 << " UTC.\n"
2012 "This replay will not handle your ledger as it was "
2013 "originally "
2014 "handled.\nConsider running an earlier version of rippled "
2015 "to "
2016 "get the older rules.\n*** CONTINUING ***\n";
2017 }
2018
2019 JLOG(m_journal.info()) << "Loading ledger " << loadLedger->info().hash
2020 << " seq:" << loadLedger->info().seq;
2021
2022 if (loadLedger->info().accountHash.isZero())
2023 {
2024 JLOG(m_journal.fatal()) << "Ledger is empty.";
2025 UNREACHABLE(
2026 "ripple::ApplicationImp::loadOldLedger : ledger is empty");
2027 return false;
2028 }
2029
2030 if (!loadLedger->walkLedger(journal("Ledger"), true))
2031 {
2032 JLOG(m_journal.fatal()) << "Ledger is missing nodes.";
2033 UNREACHABLE(
2034 "ripple::ApplicationImp::loadOldLedger : ledger is missing "
2035 "nodes");
2036 return false;
2037 }
2038
2039 if (!loadLedger->assertSensible(journal("Ledger")))
2040 {
2041 JLOG(m_journal.fatal()) << "Ledger is not sensible.";
2042 UNREACHABLE(
2043 "ripple::ApplicationImp::loadOldLedger : ledger is not "
2044 "sensible");
2045 return false;
2046 }
2047
2048 m_ledgerMaster->setLedgerRangePresent(
2049 loadLedger->info().seq, loadLedger->info().seq);
2050
2051 m_ledgerMaster->switchLCL(loadLedger);
2052 loadLedger->setValidated();
2053 m_ledgerMaster->setFullLedger(loadLedger, true, false);
2054 openLedger_.emplace(
2055 loadLedger, cachedSLEs_, logs_->journal("OpenLedger"));
2056
2057 if (replay)
2058 {
2059 // inject transaction(s) from the replayLedger into our open ledger
2060 // and build replay structure
2061 auto replayData =
2062 std::make_unique<LedgerReplay>(loadLedger, replayLedger);
2063
2064 for (auto const& [_, tx] : replayData->orderedTxns())
2065 {
2066 (void)_;
2067 auto txID = tx->getTransactionID();
2068 if (trapTxID == txID)
2069 {
2070 trapTxID_ = txID;
2071 JLOG(m_journal.debug()) << "Trap transaction set: " << txID;
2072 }
2073
2074 auto s = std::make_shared<Serializer>();
2075 tx->add(*s);
2076
2077 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2078
2079 openLedger_->modify(
2080 [&txID, &s](OpenView& view, beast::Journal j) {
2081 view.rawTxInsert(txID, std::move(s), nullptr);
2082 return true;
2083 });
2084 }
2085
2086 m_ledgerMaster->takeReplay(std::move(replayData));
2087
2088 if (trapTxID && !trapTxID_)
2089 {
2090 JLOG(m_journal.fatal())
2091 << "Ledger " << replayLedger->info().seq
2092 << " does not contain the transaction hash " << *trapTxID;
2093 return false;
2094 }
2095 }
2096 }
2097 catch (SHAMapMissingNode const& mn)
2098 {
2099 JLOG(m_journal.fatal())
2100 << "While loading specified ledger: " << mn.what();
2101 return false;
2102 }
2103 catch (boost::bad_lexical_cast&)
2104 {
2105 JLOG(m_journal.fatal())
2106 << "Ledger specified '" << ledgerID << "' is not valid";
2107 return false;
2108 }
2109
2110 return true;
2111}
2112
2113bool
2114ApplicationImp::serverOkay(std::string& reason)
2115{
2116 if (!config().ELB_SUPPORT)
2117 return true;
2118
2119 if (isStopping())
2120 {
2121 reason = "Server is shutting down";
2122 return false;
2123 }
2124
2125 if (getOPs().isNeedNetworkLedger())
2126 {
2127 reason = "Not synchronized with network yet";
2128 return false;
2129 }
2130
2131 if (getOPs().isAmendmentBlocked())
2132 {
2133 reason = "Server version too old";
2134 return false;
2135 }
2136
2137 if (getOPs().isUNLBlocked())
2138 {
2139 reason = "No valid validator list available";
2140 return false;
2141 }
2142
2143 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2144 {
2145 reason = "Not synchronized with network";
2146 return false;
2147 }
2148
2149 if (!getLedgerMaster().isCaughtUp(reason))
2150 return false;
2151
2152 if (getFeeTrack().isLoadedLocal())
2153 {
2154 reason = "Too much load";
2155 return false;
2156 }
2157
2158 return true;
2159}
2160
2162ApplicationImp::journal(std::string const& name)
2163{
2164 return logs_->journal(name);
2165}
2166
2167void
2168ApplicationImp::setMaxDisallowedLedger()
2169{
2170 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2171 if (seq)
2172 maxDisallowedLedger_ = *seq;
2173
2174 JLOG(m_journal.trace())
2175 << "Max persisted ledger is " << maxDisallowedLedger_;
2176}
2177
2178//------------------------------------------------------------------------------
2179
2180Application::Application() : beast::PropertyStream::Source("app")
2181{
2182}
2183
2184//------------------------------------------------------------------------------
2185
2190 std::unique_ptr<TimeKeeper> timeKeeper)
2191{
2192 return std::make_unique<ApplicationImp>(
2193 std::move(config), std::move(logs), std::move(timeKeeper));
2194}
2195
2196void
2197fixConfigPorts(Config& config, Endpoints const& endpoints)
2198{
2199 for (auto const& [name, ep] : endpoints)
2200 {
2201 if (!config.exists(name))
2202 continue;
2203
2204 auto& section = config[name];
2205 auto const optPort = section.get("port");
2206 if (optPort)
2207 {
2208 std::uint16_t const port =
2209 beast::lexicalCast<std::uint16_t>(*optPort);
2210 if (!port)
2211 section.set("port", std::to_string(ep.port()));
2212 }
2213 }
2214}
2215
2216} // namespace ripple
boost::asio::io_service & get_io_service()
Definition: BasicApp.h:42
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.
Definition: json_reader.cpp:78
Represents a JSON value.
Definition: json_value.h:148
bool isObjectOrNull() const
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:922
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:475
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_service 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.
std::atomic< std::chrono::milliseconds > lastSample_
io_latency_sampler(beast::insight::Event ev, beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_service &ios)
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
void signalStop(std::string msg="") 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
virtual const std::optional< uint256 > & trapTxID() const override
Overlay & overlay() override
ValidatorList & validators() override
ValidatorSite & validatorSites() 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_
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
boost::asio::io_service & getIOService() override
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_
PendingSaves pendingSaves_
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.
int IO_WORKERS
Definition: Config.h:235
bool FORCE_MULTI_THREAD
Definition: Config.h:239
bool standalone() const
Definition: Config.h:337
std::size_t NODE_SIZE
Definition: Config.h:213
Routing table for objects identified by hash.
Definition: HashRouter.h:54
static std::chrono::seconds getDefaultHoldTime()
Definition: HashRouter.h:139
Manages the lifetime of inbound ledgers.
Manages the acquisition and lifetime of transaction sets.
A pool of threads to perform work.
Definition: JobQueue.h:55
Check the ledger/transaction databases to make sure they have continuity.
Definition: LedgerCleaner.h:32
Manages the lifetime of ledger replay tasks.
Manages the current fee schedule.
Definition: LoadFeeTrack.h:45
Manages load sources.
Definition: LoadManager.h:46
Manages partitions for logging.
Definition: Log.h:51
Remembers manifests with the highest sequence number.
Definition: Manifest.h:256
Provides server functionality for clients.
Definition: NetworkOPs.h:87
A NodeStore::Scheduler which uses the JobQueue.
Persistency layer for NodeObject.
Definition: Database.h:50
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.
Definition: ManagerImp.cpp:116
Represents the open ledger.
Definition: OpenLedger.h:51
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:56
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:261
Manages the set of connected peers.
Definition: Overlay.h:48
Keeps track of which ledgers haven't been fully saved.
Definition: PendingSaves.h:38
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_service &, beast::Journal)
A consumption charge.
Definition: Charge.h:31
An endpoint that consumes resources.
Definition: Consumer.h:35
Tracks load and resource consumption.
class to create database, launch online delete thread, and related SQLite database
Definition: SHAMapStore.h:37
Holds the serialized result of parsing an input JSON object.
Definition: STParsedJSON.h:33
std::optional< STObject > object
The STObject if the parse was successful.
Definition: STParsedJSON.h:51
Holds a collection of configuration values.
Definition: BasicConfig.h:45
std::size_t size() const
Returns the number of items in the container.
Definition: TaggedCache.h:99
Manages various times used by the server.
Definition: TimeKeeper.h:32
Transaction Queue.
Definition: TxQ.h:60
Validator keys and manifest as set in configuration file.
Definition: ValidatorKeys.h:38
std::optional< Keys > keys
Definition: ValidatorKeys.h:63
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:51
T empty(T... args)
T endl(T... args)
T hardware_concurrency(T... args)
T load(T... args)
T max(T... args)
T min(T... args)
unsigned int UInt
Definition: json_forwards.h:27
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.
Definition: LexicalCast.h:202
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:26
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
Definition: Ledger.cpp:1102
constexpr auto megabytes(T value) noexcept
Definition: ByteUtilities.h:34
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:1914
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
Definition: Ledger.cpp:1112
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)
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, boost::asio::io_service &io_service, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
Definition: AccountID.cpp:107
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_service &io_svc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
std::unordered_map< std::string, boost::asio::ip::tcp::endpoint > Endpoints
Definition: ServerImpl.h:39
@ 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.
Definition: csprng.cpp:103
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:1125
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)
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:89
create_genesis_t const create_genesis
Definition: Ledger.cpp:50
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.
Definition: contract.cpp:50
std::unique_ptr< Overlay > make_Overlay(Application &app, Overlay::Setup const &setup, ServerHandler &serverHandler, Resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_service &io_service, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
Creates the implementation of Overlay.
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)